Merge "Add shell commands and dump information for Translation" into sc-dev
diff --git a/Android.bp b/Android.bp
index 240d803..df8b15f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -60,6 +60,44 @@
 //
 // READ ME: ########################################################
 
+package {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+        "SPDX-license-identifier-BSD",
+        "SPDX-license-identifier-CC-BY",
+        "SPDX-license-identifier-CPL-1.0",
+        "SPDX-license-identifier-GPL",
+        "SPDX-license-identifier-GPL-2.0",
+        "SPDX-license-identifier-MIT",
+        "SPDX-license-identifier-Unicode-DFS",
+        "SPDX-license-identifier-W3C",
+        "legacy_unencumbered",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 filegroup {
     name: "framework-core-sources",
     srcs: [
@@ -306,8 +344,8 @@
 genrule {
     name: "statslog-telephony-common-java-gen",
     tools: ["stats-log-api-gen"],
-    cmd: "$(location stats-log-api-gen) --java $(out) --module telephony_common"
-        + " --javaPackage com.android.internal.telephony --javaClass TelephonyCommonStatsLog",
+    cmd: "$(location stats-log-api-gen) --java $(out) --module telephony_common" +
+        " --javaPackage com.android.internal.telephony --javaClass TelephonyCommonStatsLog",
     out: ["com/android/internal/telephony/TelephonyCommonStatsLog.java"],
 }
 
@@ -333,7 +371,6 @@
     srcs: [
         // Java/AIDL sources under frameworks/base
         ":framework-blobstore-sources",
-        ":framework-connectivity-sources", // framework-connectivity is not yet a module
         ":framework-core-sources",
         ":framework-drm-sources",
         ":framework-graphics-nonupdatable-sources",
@@ -384,6 +421,7 @@
         ":resourcemanager_aidl",
         ":storaged_aidl",
         ":vold_aidl",
+        ":deviceproductinfoconstants_aidl",
 
         // For the generated R.java and Manifest.java
         ":framework-res{.aapt.srcjar}",
@@ -399,6 +437,7 @@
     name: "framework-updatable-sources",
     srcs: [
         ":framework-appsearch-sources",
+        ":framework-connectivity-sources",
         ":framework-graphics-srcs",
         ":framework-mediaprovider-sources",
         ":framework-permission-sources",
@@ -544,6 +583,7 @@
         "android.hardware.vibrator-V1.3-java",
         "android.security.apc-java",
         "android.security.authorization-java",
+        "android.security.usermanager-java",
         "android.system.keystore2-V1-java",
         "android.system.suspend.control.internal-java",
         "cameraprotosnano",
@@ -600,6 +640,7 @@
     defaults: ["framework-aidl-export-defaults"],
     srcs: [
         ":framework-non-updatable-sources",
+        ":framework-connectivity-sources",
         "core/java/**/*.logtags",
     ],
     // See comment on framework-atb-backward-compatibility module below
@@ -661,6 +702,8 @@
     apex_available: ["//apex_available:platform"],
     visibility: [
         "//frameworks/base",
+        // TODO: remove when framework-connectivity can build against API
+        "//frameworks/base/packages/Connectivity/framework",
         // TODO(b/147128803) remove the below lines
         "//frameworks/base/apex/appsearch/framework",
         "//frameworks/base/apex/blobstore/framework",
@@ -707,8 +750,8 @@
 }
 
 platform_compat_config {
-   name: "framework-platform-compat-config",
-   src: ":framework-minus-apex",
+    name: "framework-platform-compat-config",
+    src: ":framework-minus-apex",
 }
 
 // A temporary build target that is conditionally included on the bootclasspath if
@@ -729,7 +772,7 @@
     name: "statslog-framework-java-gen",
     tools: ["stats-log-api-gen"],
     cmd: "$(location stats-log-api-gen) --java $(out) --module framework" +
-         " --javaPackage com.android.internal.util --javaClass FrameworkStatsLog --worksource",
+        " --javaPackage com.android.internal.util --javaClass FrameworkStatsLog --worksource",
     out: ["com/android/internal/util/FrameworkStatsLog.java"],
 }
 
@@ -838,7 +881,7 @@
 
 java_library {
     name: "framework-annotations-lib",
-    srcs: [ ":framework-annotations" ],
+    srcs: [":framework-annotations"],
     sdk_version: "core_current",
 }
 
@@ -1116,7 +1159,6 @@
     },
 }
 
-
 // This is the full proto version of libplatformprotos. It may only
 // be used by test code that is not shipped on the device.
 cc_library {
@@ -1182,68 +1224,58 @@
     path: "core/java",
 }
 
-aidl_interface {
-    name: "libincremental_aidl",
-    unstable: true,
+cc_defaults {
+    name: "incremental_default",
+    host_supported: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Wextra-semi",
+        "-Werror",
+        "-Wzero-as-null-pointer-constant",
+        "-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION",
+    ],
+    shared_libs: [
+        "libbinder",
+        "libutils",
+    ],
+    aidl: {
+        include_dirs: [
+            "frameworks/native/aidl/binder",
+        ],
+        export_aidl_headers: true,
+    },
+}
+
+cc_library {
+    name: "libincremental_aidl-cpp",
     srcs: [
         ":incremental_aidl",
     ],
-    backend: {
-        java: {
-            sdk_version: "28",
-        },
-        cpp: {
-            enabled: true,
-        },
-        ndk: {
-            enabled: true,
-        },
-    },
+    defaults: ["incremental_default"],
 }
 
-aidl_interface {
-    name: "libdataloader_aidl",
-    unstable: true,
+cc_library {
+    name: "libdataloader_aidl-cpp",
     srcs: [
         ":dataloader_aidl",
     ],
-    imports: [
-        "libincremental_aidl",
+    defaults: ["incremental_default"],
+    shared_libs: [
+        "libincremental_aidl-cpp",
     ],
-    backend: {
-        java: {
-            sdk_version: "28",
-        },
-        cpp: {
-            enabled: true,
-        },
-        ndk: {
-            enabled: false,
-        },
-    },
 }
 
-aidl_interface {
-    name: "libincremental_manager_aidl",
-    unstable: true,
+cc_library {
+    name: "libincremental_manager_aidl-cpp",
     srcs: [
         ":incremental_manager_aidl",
     ],
-    imports: [
-        "libincremental_aidl",
-        "libdataloader_aidl",
+    defaults: ["incremental_default"],
+    shared_libs: [
+        "libincremental_aidl-cpp",
+        "libdataloader_aidl-cpp",
     ],
-    backend: {
-        java: {
-            sdk_version: "28",
-        },
-        cpp: {
-            enabled: true,
-        },
-        ndk: {
-            enabled: false,
-        },
-    },
 }
 
 // TODO(b/77285514): remove this once the last few hidl interfaces have been
@@ -1272,7 +1304,7 @@
         "core/java/android/os/RemoteException.java",
         "core/java/android/util/AndroidException.java",
     ],
-    libs: [ "unsupportedappusage" ],
+    libs: ["unsupportedappusage"],
 
     dxflags: ["--core-library"],
     installable: false,
@@ -1413,6 +1445,7 @@
     ],
     libs: [
         "framework-annotations-lib",
+        "framework-connectivity",
         "unsupportedappusage",
     ],
     visibility: [
@@ -1490,4 +1523,5 @@
         ":protolog-common-src",
     ],
 }
+
 // protolog end
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 30ed7de..175fb38 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -1,5 +1,6 @@
 [Builtin Hooks]
 clang_format = true
+bpfmt = true
 
 [Builtin Hooks Options]
 # Only turn on clang-format check for the following subfolders.
@@ -15,7 +16,7 @@
                services/incremental/
                tests/
                tools/
-
+bpfmt = -d
 [Hook Scripts]
 checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT}
 
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 4bd524f..bff222e 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -58,6 +58,9 @@
         local_include_dirs: [
             "apex/media/aidl/stable",
             "media/aidl",
+            // TODO: move to include-dirs for packages/modules/Connectivity when this moves out of
+            // frameworks/base
+            "packages/Connectivity/framework/aidl-export",
             "telephony/java",
         ],
         include_dirs: ["frameworks/av/aidl"],
@@ -310,6 +313,7 @@
         "art.module.public.api.stubs",
         "conscrypt.module.public.api.stubs",
         "framework-appsearch.stubs",
+        "framework-connectivity.stubs",
         "framework-graphics.stubs",
         "framework-media.stubs",
         "framework-mediaprovider.stubs",
@@ -334,6 +338,7 @@
         "art.module.public.api.stubs",
         "conscrypt.module.public.api.stubs",
         "framework-appsearch.stubs.system",
+        "framework-connectivity.stubs.system",
         "framework-graphics.stubs.system",
         "framework-media.stubs.system",
         "framework-mediaprovider.stubs.system",
@@ -374,6 +379,7 @@
         "art.module.public.api.stubs",
         "conscrypt.module.public.api.stubs",
         "framework-appsearch.stubs.system",
+        "framework-connectivity.stubs.system",
         "framework-graphics.stubs.system",
         "framework-media.stubs.system",
         "framework-mediaprovider.stubs.system",
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 6c265bc..d08c527 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -39,6 +39,20 @@
       ]
     },
     {
+      "name": "FrameworkPermissionTests",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        },
+        {
+          "exclude-annotation": "org.junit.Ignore"
+        }
+      ]
+    },
+    {
       "name": "FrameworksServicesTests",
       "options": [
         {
diff --git a/apct-tests/perftests/autofill/Android.bp b/apct-tests/perftests/autofill/Android.bp
index 79176ff..84145be 100644
--- a/apct-tests/perftests/autofill/Android.bp
+++ b/apct-tests/perftests/autofill/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "AutofillPerfTests",
     srcs: ["src/**/*.java"],
diff --git a/apct-tests/perftests/blobstore/Android.bp b/apct-tests/perftests/blobstore/Android.bp
index be700a2..25c42507 100644
--- a/apct-tests/perftests/blobstore/Android.bp
+++ b/apct-tests/perftests/blobstore/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
   name: "BlobStorePerfTests",
   srcs: ["src/**/*.java"],
@@ -26,4 +35,4 @@
   platform_apis: true,
   test_suites: ["device-tests"],
   certificate: "platform",
-}
\ No newline at end of file
+}
diff --git a/apct-tests/perftests/contentcapture/Android.bp b/apct-tests/perftests/contentcapture/Android.bp
index 19a66ad..638403d 100644
--- a/apct-tests/perftests/contentcapture/Android.bp
+++ b/apct-tests/perftests/contentcapture/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ContentCapturePerfTests",
     srcs: ["src/**/*.java"],
diff --git a/apct-tests/perftests/core/Android.bp b/apct-tests/perftests/core/Android.bp
index c541963..2182f0b 100644
--- a/apct-tests/perftests/core/Android.bp
+++ b/apct-tests/perftests/core/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "CorePerfTests",
 
diff --git a/apct-tests/perftests/core/apps/overlay/Android.bp b/apct-tests/perftests/core/apps/overlay/Android.bp
index 7bee30e..6465307 100644
--- a/apct-tests/perftests/core/apps/overlay/Android.bp
+++ b/apct-tests/perftests/core/apps/overlay/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "Overlay0",
     aaptflags: [
@@ -185,4 +194,4 @@
         ":LargeOverlay8",
         ":LargeOverlay9",
     ],
-}
\ No newline at end of file
+}
diff --git a/apct-tests/perftests/core/apps/reources_manager/Android.bp b/apct-tests/perftests/core/apps/reources_manager/Android.bp
index 4516132..85dd0c4 100644
--- a/apct-tests/perftests/core/apps/reources_manager/Android.bp
+++ b/apct-tests/perftests/core/apps/reources_manager/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "LargeResourcesCompressed",
     static_libs: [ "androidx.appcompat_appcompat" ],
@@ -31,4 +40,4 @@
         ":LargeResourcesCompressed",
         ":LargeResourcesUncompressed",
     ],
-}
\ No newline at end of file
+}
diff --git a/apct-tests/perftests/core/jni/Android.bp b/apct-tests/perftests/core/jni/Android.bp
index d160d48..1e4405de 100644
--- a/apct-tests/perftests/core/jni/Android.bp
+++ b/apct-tests/perftests/core/jni/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_library_shared {
     name: "libperftestscore_jni",
     sdk_version: "21",
diff --git a/apct-tests/perftests/inputmethod/Android.bp b/apct-tests/perftests/inputmethod/Android.bp
index 463ac9b..f2f1f75 100644
--- a/apct-tests/perftests/inputmethod/Android.bp
+++ b/apct-tests/perftests/inputmethod/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ImePerfTests",
     srcs: ["src/**/*.java"],
diff --git a/apct-tests/perftests/multiuser/Android.bp b/apct-tests/perftests/multiuser/Android.bp
index fc45d4a..917753e 100644
--- a/apct-tests/perftests/multiuser/Android.bp
+++ b/apct-tests/perftests/multiuser/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "MultiUserPerfTests",
     srcs: ["src/**/*.java"],
diff --git a/apct-tests/perftests/multiuser/apps/dummyapp/Android.bp b/apct-tests/perftests/multiuser/apps/dummyapp/Android.bp
index 08c54a6..892c140 100644
--- a/apct-tests/perftests/multiuser/apps/dummyapp/Android.bp
+++ b/apct-tests/perftests/multiuser/apps/dummyapp/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "MultiUserPerfDummyApp",
 
diff --git a/apct-tests/perftests/packagemanager/Android.bp b/apct-tests/perftests/packagemanager/Android.bp
index c15b641..0e76488 100644
--- a/apct-tests/perftests/packagemanager/Android.bp
+++ b/apct-tests/perftests/packagemanager/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "PackageManagerPerfTests",
 
diff --git a/apct-tests/perftests/packagemanager/apps/query-all/Android.bp b/apct-tests/perftests/packagemanager/apps/query-all/Android.bp
index 3cb1589..b2339d5 100644
--- a/apct-tests/perftests/packagemanager/apps/query-all/Android.bp
+++ b/apct-tests/perftests/packagemanager/apps/query-all/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "QueriesAll0",
     aaptflags: [
diff --git a/apct-tests/perftests/textclassifier/Android.bp b/apct-tests/perftests/textclassifier/Android.bp
index c40e025..1011267 100644
--- a/apct-tests/perftests/textclassifier/Android.bp
+++ b/apct-tests/perftests/textclassifier/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "TextClassifierPerfTests",
     srcs: ["src/**/*.java"],
diff --git a/apct-tests/perftests/utils/Android.bp b/apct-tests/perftests/utils/Android.bp
index be85816..6c46a9b 100644
--- a/apct-tests/perftests/utils/Android.bp
+++ b/apct-tests/perftests/utils/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library {
     name: "apct-perftests-utils",
     static_libs: [
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfRunPreconditionBase.java b/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfRunPreconditionBase.java
index 8d2ac02..330a19e0 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfRunPreconditionBase.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfRunPreconditionBase.java
@@ -89,7 +89,7 @@
                         navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
                         break;
                 }
-                executeShellCommand("cmd overlay enable-exclusive " + navOverlay);
+                executeShellCommand("cmd overlay enable-exclusive --category " + navOverlay);
             });
 
     /** It only executes once before all tests. */
diff --git a/apct-tests/perftests/windowmanager/Android.bp b/apct-tests/perftests/windowmanager/Android.bp
index dbfe6ab..365824e 100644
--- a/apct-tests/perftests/windowmanager/Android.bp
+++ b/apct-tests/perftests/windowmanager/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "WmPerfTests",
     srcs: ["src/**/*.java"],
diff --git a/apex/Android.bp b/apex/Android.bp
index 8310ba7..f3a9362 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -14,4 +14,10 @@
 
 package {
     default_visibility: [":__subpackages__"],
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
 }
diff --git a/apex/appsearch/Android.bp b/apex/appsearch/Android.bp
index b014fdc..87f65a9 100644
--- a/apex/appsearch/Android.bp
+++ b/apex/appsearch/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 apex {
     name: "com.android.appsearch",
     manifest: "apex_manifest.json",
@@ -21,6 +30,7 @@
     ],
     key: "com.android.appsearch.key",
     certificate: ":com.android.appsearch.certificate",
+    updatable: false,
 }
 
 apex_key {
diff --git a/apex/appsearch/framework/Android.bp b/apex/appsearch/framework/Android.bp
index 8ba7954..5def55f 100644
--- a/apex/appsearch/framework/Android.bp
+++ b/apex/appsearch/framework/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "framework-appsearch-sources",
     srcs: [
diff --git a/apex/appsearch/framework/api/current.txt b/apex/appsearch/framework/api/current.txt
index 905000a..168c7c2 100644
--- a/apex/appsearch/framework/api/current.txt
+++ b/apex/appsearch/framework/api/current.txt
@@ -2,6 +2,7 @@
 package android.app.appsearch {
 
   public final class AppSearchBatchResult<KeyType, ValueType> {
+    method @NonNull public java.util.Map<KeyType,android.app.appsearch.AppSearchResult<ValueType>> getAll();
     method @NonNull public java.util.Map<KeyType,android.app.appsearch.AppSearchResult<ValueType>> getFailures();
     method @NonNull public java.util.Map<KeyType,ValueType> getSuccesses();
     method public boolean isSuccess();
@@ -146,8 +147,8 @@
     method public void put(@NonNull android.app.appsearch.PutDocumentsRequest, @NonNull java.util.concurrent.Executor, @NonNull android.app.appsearch.BatchResultCallback<java.lang.String,java.lang.Void>);
     method public void remove(@NonNull android.app.appsearch.RemoveByUriRequest, @NonNull java.util.concurrent.Executor, @NonNull android.app.appsearch.BatchResultCallback<java.lang.String,java.lang.Void>);
     method public void remove(@NonNull String, @NonNull android.app.appsearch.SearchSpec, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<java.lang.Void>>);
-    method @NonNull public void reportUsage(@NonNull android.app.appsearch.ReportUsageRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<java.lang.Void>>);
-    method @NonNull public android.app.appsearch.SearchResults search(@NonNull String, @NonNull android.app.appsearch.SearchSpec, @NonNull java.util.concurrent.Executor);
+    method public void reportUsage(@NonNull android.app.appsearch.ReportUsageRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<java.lang.Void>>);
+    method @NonNull public android.app.appsearch.SearchResults search(@NonNull String, @NonNull android.app.appsearch.SearchSpec);
     method public void setSchema(@NonNull android.app.appsearch.SetSchemaRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<android.app.appsearch.SetSchemaResponse>>);
   }
 
@@ -216,7 +217,7 @@
 
   public class GlobalSearchSession implements java.io.Closeable {
     method public void close();
-    method @NonNull public android.app.appsearch.SearchResults search(@NonNull String, @NonNull android.app.appsearch.SearchSpec, @NonNull java.util.concurrent.Executor);
+    method @NonNull public android.app.appsearch.SearchResults search(@NonNull String, @NonNull android.app.appsearch.SearchSpec);
   }
 
   public class PackageIdentifier {
@@ -286,7 +287,7 @@
 
   public class SearchResults implements java.io.Closeable {
     method public void close();
-    method public void getNextPage(@NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<java.util.List<android.app.appsearch.SearchResult>>>);
+    method public void getNextPage(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<java.util.List<android.app.appsearch.SearchResult>>>);
   }
 
   public final class SearchSpec {
@@ -358,7 +359,6 @@
     method @NonNull public java.util.Set<java.lang.String> getIncompatibleTypes();
     method @NonNull public java.util.Set<java.lang.String> getMigratedTypes();
     method @NonNull public java.util.List<android.app.appsearch.SetSchemaResponse.MigrationFailure> getMigrationFailures();
-    method public boolean isSuccess();
   }
 
   public static class SetSchemaResponse.MigrationFailure {
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.java
index cd75b14..31ab259 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.java
@@ -28,11 +28,19 @@
 import java.util.Map;
 
 /**
- * Provides access to multiple {@link AppSearchResult}s from a batch operation accepting multiple
- * inputs.
+ * Provides results for AppSearch batch operations which encompass multiple documents.
  *
- * @param <KeyType> The type of the keys for {@link #getSuccesses} and {@link #getFailures}.
- * @param <ValueType> The type of result objects associated with the keys.
+ * <p>Individual results of a batch operation are separated into two maps: one for successes and one
+ * for failures. For successes, {@link #getSuccesses()} will return a map of keys to instances of
+ * the value type. For failures, {@link #getFailures()} will return a map of keys to {@link
+ * AppSearchResult} objects.
+ *
+ * <p>Alternatively, {@link #getAll()} returns a map of keys to {@link AppSearchResult} objects for
+ * both successes and failures.
+ *
+ * @see AppSearchSession#put
+ * @see AppSearchSession#getByUri
+ * @see AppSearchSession#remove
  */
 public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelable {
     @NonNull private final Map<KeyType, ValueType> mSuccesses;
@@ -75,8 +83,11 @@
     }
 
     /**
-     * Returns a {@link Map} of all successful keys mapped to the successful {@link
-     * AppSearchResult}s they produced.
+     * Returns a {@link Map} of keys mapped to instances of the value type for all successful
+     * individual results.
+     *
+     * <p>Example: {@link AppSearchSession#getByUri} returns an {@link AppSearchBatchResult}. Each
+     * key (a URI of {@code String} type) will map to a {@link GenericDocument} object.
      *
      * <p>The values of the {@link Map} will not be {@code null}.
      */
@@ -86,8 +97,8 @@
     }
 
     /**
-     * Returns a {@link Map} of all failed keys mapped to the failed {@link AppSearchResult}s they
-     * produced.
+     * Returns a {@link Map} of keys mapped to instances of {@link AppSearchResult} for all failed
+     * individual results.
      *
      * <p>The values of the {@link Map} will not be {@code null}.
      */
@@ -97,10 +108,10 @@
     }
 
     /**
-     * Returns a {@link Map} of all keys mapped to the {@link AppSearchResult}s they produced.
+     * Returns a {@link Map} of keys mapped to instances of {@link AppSearchResult} for all
+     * individual results.
      *
      * <p>The values of the {@link Map} will not be {@code null}.
-     * @hide
      */
     @NonNull
     public Map<KeyType, AppSearchResult<ValueType>> getAll() {
@@ -150,8 +161,8 @@
     /**
      * Builder for {@link AppSearchBatchResult} objects.
      *
-     * @param <KeyType> The type of keys.
-     * @param <ValueType> The type of result objects associated with the keys.
+     * <p>Once {@link #build} is called, the instance can no longer be used.
+     *
      * @hide
      */
     public static final class Builder<KeyType, ValueType> {
@@ -161,9 +172,11 @@
         private boolean mBuilt = false;
 
         /**
-         * Associates the {@code key} with the given successful return value.
+         * Associates the {@code key} with the provided successful return value.
          *
          * <p>Any previous mapping for a key, whether success or failure, is deleted.
+         *
+         * @throws IllegalStateException if the builder has already been used.
          */
         @NonNull
         public Builder<KeyType, ValueType> setSuccess(
@@ -174,9 +187,11 @@
         }
 
         /**
-         * Associates the {@code key} with the given failure code and error message.
+         * Associates the {@code key} with the provided failure code and error message.
          *
          * <p>Any previous mapping for a key, whether success or failure, is deleted.
+         *
+         * @throws IllegalStateException if the builder has already been used.
          */
         @NonNull
         public Builder<KeyType, ValueType> setFailure(
@@ -189,9 +204,11 @@
         }
 
         /**
-         * Associates the {@code key} with the given {@code result}.
+         * Associates the {@code key} with the provided {@code result}.
          *
          * <p>Any previous mapping for a key, whether success or failure, is deleted.
+         *
+         * @throws IllegalStateException if the builder has already been used.
          */
         @NonNull
         public Builder<KeyType, ValueType> setResult(
@@ -210,7 +227,11 @@
             return this;
         }
 
-        /** Builds an {@link AppSearchBatchResult} from the contents of this {@link Builder}. */
+        /**
+         * Builds an {@link AppSearchBatchResult} object from the contents of this {@link Builder}.
+         *
+         * @throws IllegalStateException if the builder has already been used.
+         */
         @NonNull
         public AppSearchBatchResult<KeyType, ValueType> build() {
             Preconditions.checkState(!mBuilt, "Builder has already been used");
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
index 69d4e53..6a5975e 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
@@ -36,12 +36,89 @@
 import java.util.function.Consumer;
 
 /**
- * This class provides access to the centralized AppSearch index maintained by the system.
+ * Provides access to the centralized AppSearch index maintained by the system.
  *
- * <p>Apps can index structured text documents with AppSearch, which can then be retrieved through
- * the query API.
+ * <p>AppSearch is a search library for managing structured data featuring:
+ * <ul>
+ *     <li>A fully offline on-device solution
+ *     <li>A set of APIs for applications to index documents and retrieve them via full-text search
+ *     <li>APIs for applications to allow the System to display their content on system UI surfaces
+ *     <li>Similarly, APIs for applications to allow the System to share their content with other
+ *     specified applications.
+ * </ul>
+ *
+ * <p>Applications create a database by opening an {@link AppSearchSession}.
+ *
+ * <p>Example:
+ * <pre>
+ * AppSearchManager appSearchManager = context.getSystemService(AppSearchManager.class);
+ *
+ * AppSearchManager.SearchContext searchContext = new AppSearchManager.SearchContext.Builder().
+ *    setDatabaseName(dbName).build());
+ * appSearchManager.createSearchSession(searchContext, mExecutor, appSearchSessionResult -&gt; {
+ *      mAppSearchSession = appSearchSessionResult.getResultValue();
+ * });</pre>
+ *
+ * <p>After opening the session, a schema must be set in order to define the organizational
+ * structure of data. The schema is set by calling {@link AppSearchSession#setSchema}. The schema
+ * is composed of a collection of {@link AppSearchSchema} objects, each of which defines a unique
+ * type of data.
+ *
+ * <p>Example:
+ * <pre>
+ * AppSearchSchema emailSchemaType = new AppSearchSchema.Builder("Email")
+ *     .addProperty(new StringPropertyConfig.Builder("subject")
+ *        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ *        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+ *        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+ *    .build()
+ * ).build();
+ *
+ * SetSchemaRequest request = new SetSchemaRequest.Builder().addSchema(emailSchemaType).build();
+ * mAppSearchSession.set(request, mExecutor, appSearchResult -&gt; {
+ *      if (appSearchResult.isSuccess()) {
+ *           //Schema has been successfully set.
+ *      }
+ * });</pre>
+ *
+ * <p>The basic unit of data in AppSearch is represented as a {@link GenericDocument} object,
+ * containing a URI, namespace, time-to-live, score, and properties. A namespace organizes a
+ * logical group of documents. For example, a namespace can be created to group documents on a
+ * per-account basis. A URI identifies a single document within a namespace. The combination
+ * of URI and namespace uniquely identifies a {@link GenericDocument} in the database.
+ *
+ * <p>Once the schema has been set, {@link GenericDocument} objects can be put into the database
+ * and indexed by calling {@link AppSearchSession#put}.
+ *
+ * <p>Example:
+ * <pre>
+ * // Although for this example we use GenericDocument directly, we recommend extending
+ * // GenericDocument to create specific types (i.e. Email) with specific setters/getters.
+ * GenericDocument email = new GenericDocument.Builder<>(URI, EMAIL_SCHEMA_TYPE)
+ *     .setNamespace(NAMESPACE)
+ *     .setPropertyString(“subject”, EMAIL_SUBJECT)
+ *     .setScore(EMAIL_SCORE)
+ *     .build();
+ *
+ * PutDocumentsRequest request = new PutDocumentsRequest.Builder().addGenericDocuments(email)
+ *     .build();
+ * mAppSearchSession.put(request, mExecutor, appSearchBatchResult -&gt; {
+ *      if (appSearchBatchResult.isSuccess()) {
+ *           //All documents have been successfully indexed.
+ *      }
+ * });</pre>
+ *
+ * <p>Searching within the database is done by calling {@link AppSearchSession#search} and providing
+ * the query string to search for, as well as a {@link SearchSpec}.
+ *
+ * <p>Alternatively, {@link AppSearchSession#getByUri} can be called to retrieve documents by URI
+ * and namespace.
+ *
+ * <p>Document removal is done either by time-to-live expiration, or explicitly calling a remove
+ * operation. Remove operations can be done by URI and namespace via
+ * {@link AppSearchSession#remove(RemoveByUriRequest, Executor, BatchResultCallback)},
+ * or by query via {@link AppSearchSession#remove(String, SearchSpec, Executor, Consumer)}.
  */
-// TODO(b/148046169): This class header needs a detailed example/tutorial.
 @SystemService(Context.APP_SEARCH_SERVICE)
 public class AppSearchManager {
     /**
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
index 73ca0cc..24cc60e 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
@@ -41,7 +41,7 @@
  * Represents a connection to an AppSearch storage system where {@link GenericDocument}s can be
  * placed and queried.
  *
- * This class is thread safe.
+ * <p>This class is thread safe.
  */
 public final class AppSearchSession implements Closeable {
     private static final String TAG = "AppSearchSession";
@@ -102,92 +102,23 @@
     }
 
     /**
-     * Sets the schema that will be used by documents provided to the {@link #put} method.
+     * Sets the schema that represents the organizational structure of data within the AppSearch
+     * database.
      *
-     * <p>The schema provided here is compared to the stored copy of the schema previously supplied
-     * to {@link #setSchema}, if any, to determine how to treat existing documents. The following
-     * types of schema modifications are always safe and are made without deleting any existing
-     * documents:
+     * <p>Upon creating an {@link AppSearchSession}, {@link #setSchema} should be called. If the
+     * schema needs to be updated, or it has not been previously set, then the provided schema will
+     * be saved and persisted to disk. Otherwise, {@link #setSchema} is handled efficiently as a
+     * no-op call.
      *
-     * <ul>
-     *   <li>Addition of new types
-     *   <li>Addition of new {@link AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL OPTIONAL} or
-     *       {@link AppSearchSchema.PropertyConfig#CARDINALITY_REPEATED REPEATED} properties to a
-     *       type
-     *   <li>Changing the cardinality of a data type to be less restrictive (e.g. changing an {@link
-     *       AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL OPTIONAL} property into a {@link
-     *       AppSearchSchema.PropertyConfig#CARDINALITY_REPEATED REPEATED} property.
-     * </ul>
-     *
-     * <p>The following types of schema changes are not backwards-compatible:
-     *
-     * <ul>
-     *   <li>Removal of an existing type
-     *   <li>Removal of a property from a type
-     *   <li>Changing the data type ({@code boolean}, {@code long}, etc.) of an existing property
-     *   <li>For properties of {@code Document} type, changing the schema type of {@code Document}s
-     *       of that property
-     *   <li>Changing the cardinality of a data type to be more restrictive (e.g. changing an {@link
-     *       AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL OPTIONAL} property into a {@link
-     *       AppSearchSchema.PropertyConfig#CARDINALITY_REQUIRED REQUIRED} property).
-     *   <li>Adding a {@link AppSearchSchema.PropertyConfig#CARDINALITY_REQUIRED REQUIRED} property.
-     * </ul>
-     *
-     * <p>Supplying a schema with such changes will, by default, result in this call completing its
-     * future with an {@link android.app.appsearch.exceptions.AppSearchException} with a code of
-     * {@link AppSearchResult#RESULT_INVALID_SCHEMA} and a message describing the incompatibility.
-     * In this case the previously set schema will remain active.
-     *
-     * <p>If you need to make non-backwards-compatible changes as described above, you can either:
-     *
-     * <ul>
-     *   <li>Set the {@link SetSchemaRequest.Builder#setForceOverride} method to {@code true}. In
-     *       this case, instead of completing its future with an {@link
-     *       android.app.appsearch.exceptions.AppSearchException} with the {@link
-     *       AppSearchResult#RESULT_INVALID_SCHEMA} error code, all documents which are not
-     *       compatible with the new schema will be deleted and the incompatible schema will be
-     *       applied. Incompatible types and deleted types will be set into {@link
-     *       SetSchemaResponse#getIncompatibleTypes()} and {@link
-     *       SetSchemaResponse#getDeletedTypes()}, respectively.
-     *   <li>Add a {@link android.app.appsearch.AppSearchSchema.Migrator} for each incompatible type
-     *       and make no deletion. The migrator will migrate documents from it's old schema version
-     *       to the new version. Migrated types will be set into both {@link
-     *       SetSchemaResponse#getIncompatibleTypes()} and {@link
-     *       SetSchemaResponse#getMigratedTypes()}. See the migration section below.
-     * </ul>
-     *
-     * <p>It is a no-op to set the same schema as has been previously set; this is handled
-     * efficiently.
-     *
-     * <p>By default, documents are visible on platform surfaces. To opt out, call {@code
-     * SetSchemaRequest.Builder#setPlatformSurfaceable} with {@code surfaceable} as false. Any
-     * visibility settings apply only to the schemas that are included in the {@code request}.
-     * Visibility settings for a schema type do not apply or persist across {@link
-     * SetSchemaRequest}s.
-     *
-     * <p>Migration: make non-backwards-compatible changes will delete all stored documents in old
-     * schema. You can save your documents by setting {@link
-     * android.app.appsearch.AppSearchSchema.Migrator} via the {@link
-     * SetSchemaRequest.Builder#setMigrator} for each type you want to save.
-     *
-     * <p>{@link android.app.appsearch.AppSearchSchema.Migrator#onDowngrade} or {@link
-     * android.app.appsearch.AppSearchSchema.Migrator#onUpgrade} will be triggered if the version
-     * number of the schema stored in AppSearch is different with the version in the request.
-     *
-     * <p>If any error or Exception occurred in the {@link
-     * android.app.appsearch.AppSearchSchema.Migrator#onDowngrade}, {@link
-     * android.app.appsearch.AppSearchSchema.Migrator#onUpgrade} or {@link
-     * android.app.appsearch.AppSearchMigrationHelper.Transformer#transform}, the migration will be
-     * terminated, the setSchema request will be rejected unless the schema changes are
-     * backwards-compatible, and stored documents won't have any observable changes.
-     *
-     * @param request The schema update request.
+     * @param request the schema to set or update the AppSearch database to.
      * @param executor Executor on which to invoke the callback.
      * @param callback Callback to receive errors resulting from setting the schema. If the
      *                 operation succeeds, the callback will be invoked with {@code null}.
      * @see android.app.appsearch.AppSearchSchema.Migrator
      * @see android.app.appsearch.AppSearchMigrationHelper.Transformer
      */
+    // TODO(b/169883602): Change @code references to @link when setPlatformSurfaceable APIs are
+    //  exposed.
     public void setSchema(
             @NonNull SetSchemaRequest request,
             @NonNull @CallbackExecutor Executor executor,
@@ -280,12 +211,13 @@
     }
 
     /**
-     * Indexes documents into AppSearch.
+     * Indexes documents into the {@link AppSearchSession} database.
      *
-     * <p>Each {@link GenericDocument}'s {@code schemaType} field must be set to the name of a
-     * schema type previously registered via the {@link #setSchema} method.
+     * <p>Each {@link GenericDocument} object must have a {@code schemaType} field set to an {@link
+     * AppSearchSchema} type that has been previously registered by calling the {@link #setSchema}
+     * method.
      *
-     * @param request {@link PutDocumentsRequest} containing documents to be indexed
+     * @param request containing documents to be indexed.
      * @param executor Executor on which to invoke the callback.
      * @param callback Callback to receive pending result of performing this operation. The keys
      *                 of the returned {@link AppSearchBatchResult} are the URIs of the input
@@ -463,21 +395,15 @@
      * @param queryExpression query string to search.
      * @param searchSpec spec for setting document filters, adding projection, setting term match
      *     type, etc.
-     * @param executor        Executor on which to invoke the callback of the following request
-     *                        {@link SearchResults#getNextPage}.
      * @return a {@link SearchResults} object for retrieved matched documents.
      */
     @NonNull
-    public SearchResults search(
-            @NonNull String queryExpression,
-            @NonNull SearchSpec searchSpec,
-            @NonNull @CallbackExecutor Executor executor) {
+    public SearchResults search(@NonNull String queryExpression, @NonNull SearchSpec searchSpec) {
         Objects.requireNonNull(queryExpression);
         Objects.requireNonNull(searchSpec);
-        Objects.requireNonNull(executor);
         Preconditions.checkState(!mIsClosed, "AppSearchSession has already been closed");
         return new SearchResults(mService, mPackageName, mDatabaseName, queryExpression,
-                searchSpec, mUserId, executor);
+                searchSpec, mUserId);
     }
 
     /**
@@ -497,7 +423,6 @@
      * @param callback Callback to receive errors. If the operation succeeds, the callback will be
      *                 invoked with {@code null}.
      */
-    @NonNull
     public void reportUsage(
             @NonNull ReportUsageRequest request,
             @NonNull @CallbackExecutor Executor executor,
diff --git a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java
index 09bca4f..8dd9dc1 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java
@@ -98,8 +98,7 @@
      * <p>Document access can also be granted to system UIs by specifying {@link
      * SetSchemaRequest.Builder#setSchemaTypeVisibilityForSystemUi} when building a schema.
      *
-     * <p>See {@link AppSearchSession#search} for a detailed explanation on
-     * forming a query string.
+     * <p>See {@link AppSearchSession#search} for a detailed explanation on forming a query string.
      *
      * <p>This method is lightweight. The heavy work will be done in {@link
      * SearchResults#getNextPage}.
@@ -107,21 +106,15 @@
      * @param queryExpression query string to search.
      * @param searchSpec spec for setting document filters, adding projection, setting term match
      *     type, etc.
-     * @param executor        Executor on which to invoke the callback of the following request
-     *                        {@link SearchResults#getNextPage}.
      * @return a {@link SearchResults} object for retrieved matched documents.
      */
     @NonNull
-    public SearchResults search(
-            @NonNull String queryExpression,
-            @NonNull SearchSpec searchSpec,
-            @NonNull @CallbackExecutor Executor executor) {
+    public SearchResults search(@NonNull String queryExpression, @NonNull SearchSpec searchSpec) {
         Objects.requireNonNull(queryExpression);
         Objects.requireNonNull(searchSpec);
-        Objects.requireNonNull(executor);
         Preconditions.checkState(!mIsClosed, "GlobalSearchSession has already been closed");
         return new SearchResults(mService, mPackageName, /*databaseName=*/null, queryExpression,
-                searchSpec, mUserId, executor);
+                searchSpec, mUserId);
     }
 
     /** Closes the {@link GlobalSearchSession}. */
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
index a63e015..531c984 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
@@ -33,12 +33,16 @@
 import java.util.function.Consumer;
 
 /**
- * SearchResults are a returned object from a query API.
+ * Encapsulates results of a search operation.
  *
- * <p>Each {@link SearchResult} contains a document and may contain other fields like snippets based
- * on request.
+ * <p>Each {@link AppSearchSession#search} operation returns a list of {@link SearchResult} objects,
+ * referred to as a "page", limited by the size configured by {@link
+ * SearchSpec.Builder#setResultCountPerPage}.
  *
- * <p>Should close this object after finish fetching results.
+ * <p>To fetch a page of results, call {@link #getNextPage}.
+ *
+ * <p>All instances of {@link SearchResults} must call {@link SearchResults#close()} after the
+ * results are fetched.
  *
  * <p>This class is not thread safe.
  */
@@ -61,8 +65,6 @@
     @UserIdInt
     private final int mUserId;
 
-    private final Executor mExecutor;
-
     private long mNextPageToken;
 
     private boolean mIsFirstLoad = true;
@@ -75,28 +77,31 @@
             @Nullable String databaseName,
             @NonNull String queryExpression,
             @NonNull SearchSpec searchSpec,
-            @UserIdInt int userId,
-            @NonNull @CallbackExecutor Executor executor) {
+            @UserIdInt int userId) {
         mService = Objects.requireNonNull(service);
         mPackageName = packageName;
         mDatabaseName = databaseName;
         mQueryExpression = Objects.requireNonNull(queryExpression);
         mSearchSpec = Objects.requireNonNull(searchSpec);
         mUserId = userId;
-        mExecutor = Objects.requireNonNull(executor);
     }
 
     /**
-     * Gets a whole page of {@link SearchResult}s.
+     * Retrieves the next page of {@link SearchResult} objects.
      *
-     * <p>Re-call this method to get next page of {@link SearchResult}, until it returns an empty
-     * list.
+     * <p>The page size is configured by {@link SearchSpec.Builder#setResultCountPerPage}.
      *
-     * <p>The page size is set by {@link SearchSpec.Builder#setResultCountPerPage}.
+     * <p>Continue calling this method to access results until it returns an empty list, signifying
+     * there are no more results.
      *
+     * @param executor Executor on which to invoke the callback.
      * @param callback Callback to receive the pending result of performing this operation.
      */
-    public void getNextPage(@NonNull Consumer<AppSearchResult<List<SearchResult>>> callback) {
+    public void getNextPage(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull Consumer<AppSearchResult<List<SearchResult>>> callback) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
         Preconditions.checkState(!mIsClosed, "SearchResults has already been closed");
         try {
             if (mIsFirstLoad) {
@@ -104,14 +109,14 @@
                 if (mDatabaseName == null) {
                     // Global query, there's no one package-database combination to check.
                     mService.globalQuery(mPackageName, mQueryExpression,
-                            mSearchSpec.getBundle(), mUserId, wrapCallback(callback));
+                            mSearchSpec.getBundle(), mUserId, wrapCallback(executor, callback));
                 } else {
                     // Normal local query, pass in specified database.
                     mService.query(mPackageName, mDatabaseName, mQueryExpression,
-                            mSearchSpec.getBundle(), mUserId, wrapCallback(callback));
+                            mSearchSpec.getBundle(), mUserId, wrapCallback(executor, callback));
                 }
             } else {
-                mService.getNextPage(mNextPageToken, mUserId, wrapCallback(callback));
+                mService.getNextPage(mNextPageToken, mUserId, wrapCallback(executor, callback));
             }
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -131,10 +136,11 @@
     }
 
     private IAppSearchResultCallback wrapCallback(
+            @NonNull @CallbackExecutor Executor executor,
             @NonNull Consumer<AppSearchResult<List<SearchResult>>> callback) {
         return new IAppSearchResultCallback.Stub() {
             public void onResult(AppSearchResult result) {
-                mExecutor.execute(() -> invokeCallback(result, callback));
+                executor.execute(() -> invokeCallback(result, callback));
             }
         };
     }
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java b/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java
index 138eb23..72bb9f3 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java
@@ -583,9 +583,9 @@
          * @param schemaType the {@link AppSearchSchema} type of the {@link GenericDocument}. The
          *     provided {@code schemaType} must be defined using {@link AppSearchSession#setSchema}
          *     prior to inserting a document of this {@code schemaType} into the AppSearch index
-         *     using {@link AppSearchSession#put}. Otherwise, the document will
-         *     be rejected by {@link AppSearchSession#put} with result code
-         *     {@link AppSearchResult#RESULT_NOT_FOUND}.
+         *     using {@link AppSearchSession#put}. Otherwise, the document will be rejected by
+         *     {@link AppSearchSession#put} with result code {@link
+         *     AppSearchResult#RESULT_NOT_FOUND}.
          */
         @SuppressWarnings("unchecked")
         public Builder(@NonNull String uri, @NonNull String schemaType) {
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/PutDocumentsRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/PutDocumentsRequest.java
index 05b2128..01473be 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/PutDocumentsRequest.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/PutDocumentsRequest.java
@@ -28,9 +28,9 @@
 import java.util.List;
 
 /**
- * Encapsulates a request to index a document into an {@link AppSearchSession} database.
+ * Encapsulates a request to index documents into an {@link AppSearchSession} database.
  *
- * <p>@see AppSearchSession#putDocuments
+ * @see AppSearchSession#put
  */
 public final class PutDocumentsRequest {
     private final List<GenericDocument> mDocuments;
@@ -39,7 +39,7 @@
         mDocuments = documents;
     }
 
-    /** Returns the documents that are part of this request. */
+    /** Returns a list of {@link GenericDocument} objects that are part of this request. */
     @NonNull
     public List<GenericDocument> getGenericDocuments() {
         return Collections.unmodifiableList(mDocuments);
@@ -54,14 +54,22 @@
         private final List<GenericDocument> mDocuments = new ArrayList<>();
         private boolean mBuilt = false;
 
-        /** Adds one or more {@link GenericDocument} objects to the request. */
+        /**
+         * Adds one or more {@link GenericDocument} objects to the request.
+         *
+         * @throws IllegalStateException if the builder has already been used.
+         */
         @NonNull
         public Builder addGenericDocuments(@NonNull GenericDocument... documents) {
             Preconditions.checkNotNull(documents);
             return addGenericDocuments(Arrays.asList(documents));
         }
 
-        /** Adds a collection of {@link GenericDocument} objects to the request. */
+        /**
+         * Adds a collection of {@link GenericDocument} objects to the request.
+         *
+         * @throws IllegalStateException if the builder has already been used.
+         */
         @NonNull
         public Builder addGenericDocuments(
                 @NonNull Collection<? extends GenericDocument> documents) {
@@ -71,7 +79,11 @@
             return this;
         }
 
-        /** Creates a new {@link PutDocumentsRequest} object. */
+        /**
+         * Creates a new {@link PutDocumentsRequest} object.
+         *
+         * @throws IllegalStateException if the builder has already been used.
+         */
         @NonNull
         public PutDocumentsRequest build() {
             Preconditions.checkState(!mBuilt, "Builder has already been used");
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java
index 2caa94a5e..426a903 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java
@@ -32,6 +32,41 @@
 /**
  * Encapsulates a request to update the schema of an {@link AppSearchSession} database.
  *
+ * <p>The schema is composed of a collection of {@link AppSearchSchema} objects, each of which
+ * defines a unique type of data.
+ *
+ * <p>The first call to SetSchemaRequest will set the provided schema and store it within the {@link
+ * AppSearchSession} database.
+ *
+ * <p>Subsequent calls will compare the provided schema to the previously saved schema, to determine
+ * how to treat existing documents.
+ *
+ * <p>The following types of schema modifications are always safe and are made without deleting any
+ * existing documents:
+ *
+ * <ul>
+ *   <li>Addition of new {@link AppSearchSchema} types
+ *   <li>Addition of new properties to an existing {@link AppSearchSchema} type
+ *   <li>Changing the cardinality of a property to be less restrictive
+ * </ul>
+ *
+ * <p>The following types of schema changes are not backwards compatible:
+ *
+ * <ul>
+ *   <li>Removal of an existing {@link AppSearchSchema} type
+ *   <li>Removal of a property from an existing {@link AppSearchSchema} type
+ *   <li>Changing the data type of an existing property
+ *   <li>Changing the cardinality of a property to be more restrictive
+ * </ul>
+ *
+ * <p>Providing a schema with incompatible changes, will throw an {@link
+ * android.app.appsearch.exceptions.AppSearchException}, with a message describing the
+ * incompatibility. As a result, the previously set schema will remain unchanged.
+ *
+ * <p>Backward incompatible changes can be made by setting {@link
+ * SetSchemaRequest.Builder#setForceOverride} method to {@code true}. This deletes all documents
+ * that are incompatible with the new schema. The new schema is then saved and persisted to disk.
+ *
  * @see AppSearchSession#setSchema
  */
 public final class SetSchemaRequest {
@@ -54,14 +89,15 @@
         mForceOverride = forceOverride;
     }
 
-    /** Returns the schemas that are part of this request. */
+    /** Returns the {@link AppSearchSchema} types that are part of this request. */
     @NonNull
     public Set<AppSearchSchema> getSchemas() {
         return Collections.unmodifiableSet(mSchemas);
     }
 
     /**
-     * Returns the set of schema types that have opted out of being visible on system UI surfaces.
+     * Returns all the schema types that are opted out of being displayed and visible on any system
+     * UI surface.
      */
     @NonNull
     public Set<String> getSchemasNotVisibleToSystemUi() {
@@ -70,10 +106,9 @@
 
     /**
      * Returns a mapping of schema types to the set of packages that have access to that schema
-     * type. Each package is represented by a {@link PackageIdentifier}. name and byte[]
-     * certificate.
+     * type.
      *
-     * <p>This method is inefficient to call repeatedly.
+     * <p>It’s inefficient to call this method repeatedly.
      */
     @NonNull
     public Map<String, Set<PackageIdentifier>> getSchemasVisibleToPackages() {
@@ -91,9 +126,8 @@
     }
 
     /**
-     * Returns a mapping of schema types to the set of packages that have access to that schema
-     * type. Each package is represented by a {@link PackageIdentifier}. name and byte[]
-     * certificate.
+     * Returns a mapping of {@link AppSearchSchema} types to the set of packages that have access to
+     * that schema type.
      *
      * <p>A more efficient version of {@link #getSchemasVisibleToPackages}, but it returns a
      * modifiable map. This is not meant to be unhidden and should only be used by internal classes.
@@ -110,7 +144,11 @@
         return mForceOverride;
     }
 
-    /** Builder for {@link SetSchemaRequest} objects. */
+    /**
+     * Builder for {@link SetSchemaRequest} objects.
+     *
+     * <p>Once {@link #build} is called, the instance can no longer be used.
+     */
     public static final class Builder {
         private final Set<AppSearchSchema> mSchemas = new ArraySet<>();
         private final Set<String> mSchemasNotVisibleToSystemUi = new ArraySet<>();
@@ -121,9 +159,11 @@
         private boolean mBuilt = false;
 
         /**
-         * Adds one or more types to the schema.
+         * Adds one or more {@link AppSearchSchema} types to the schema.
          *
-         * <p>Any documents of these types will be visible on system UI surfaces by default.
+         * <p>An {@link AppSearchSchema} object represents one type of structured data.
+         *
+         * @throws IllegalStateException if the builder has already been used.
          */
         @NonNull
         public Builder addSchemas(@NonNull AppSearchSchema... schemas) {
@@ -132,9 +172,11 @@
         }
 
         /**
-         * Adds one or more types to the schema.
+         * Adds a collection of {@link AppSearchSchema} objects to the schema.
          *
-         * <p>Any documents of these types will be visible on system UI surfaces by default.
+         * <p>An {@link AppSearchSchema} object represents one type of structured data.
+         *
+         * @throws IllegalStateException if the builder has already been used.
          */
         @NonNull
         public Builder addSchemas(@NonNull Collection<AppSearchSchema> schemas) {
@@ -145,10 +187,17 @@
         }
 
         /**
-         * Sets visibility on system UI surfaces for the given {@code schemaType}.
+         * Sets whether or not documents from the provided {@code schemaType} will be displayed and
+         * visible on any system UI surface.
+         *
+         * <p>This setting applies to the provided {@code schemaType} only, and does not persist
+         * across {@link AppSearchSession#setSchema} calls.
+         *
+         * <p>By default, documents are displayed and visible on system UI surfaces.
          *
          * @param schemaType The schema type to set visibility on.
          * @param visible Whether the {@code schemaType} will be visible or not.
+         * @throws IllegalStateException if the builder has already been used.
          */
         // Merged list available from getSchemasNotVisibleToSystemUi
         @SuppressLint("MissingGetterMatchingBuilder")
@@ -167,11 +216,25 @@
         }
 
         /**
-         * Sets visibility for a package for the given {@code schemaType}.
+         * Sets whether or not documents from the provided {@code schemaType} can be read by the
+         * specified package.
+         *
+         * <p>Each package is represented by a {@link PackageIdentifier}, containing a package name
+         * and a byte array of type {@link android.content.pm.PackageManager#CERT_INPUT_SHA256}.
+         *
+         * <p>To opt into one-way data sharing with another application, the developer will need to
+         * explicitly grant the other application’s package name and certificate Read access to its
+         * data.
+         *
+         * <p>For two-way data sharing, both applications need to explicitly grant Read access to
+         * one another.
+         *
+         * <p>By default, data sharing between applications is disabled.
          *
          * @param schemaType The schema type to set visibility on.
          * @param visible Whether the {@code schemaType} will be visible or not.
          * @param packageIdentifier Represents the package that will be granted visibility.
+         * @throws IllegalStateException if the builder has already been used.
          */
         // Merged list available from getSchemasVisibleToPackages
         @SuppressLint("MissingGetterMatchingBuilder")
@@ -224,13 +287,15 @@
         }
 
         /**
-         * Configures the {@link SetSchemaRequest} to delete any existing documents that don't
-         * follow the new schema.
+         * Sets whether or not to override the current schema in the {@link AppSearchSession}
+         * database.
          *
-         * <p>By default, this is {@code false} and schema incompatibility causes the {@link
-         * AppSearchSession#setSchema} call to fail.
+         * <p>Call this method whenever backward incompatible changes need to be made by setting
+         * {@code forceOverride} to {@code true}. As a result, during execution of the setSchema
+         * operation, all documents that are incompatible with the new schema will be deleted and
+         * the new schema will be saved and persisted.
          *
-         * @see AppSearchSession#setSchema
+         * <p>By default, this is {@code false}.
          */
         @NonNull
         public Builder setForceOverride(boolean forceOverride) {
@@ -239,10 +304,11 @@
         }
 
         /**
-         * Builds a new {@link SetSchemaRequest}.
+         * Builds a new {@link SetSchemaRequest} object.
          *
-         * @throws IllegalArgumentException If schema types were referenced, but the corresponding
-         *     {@link AppSearchSchema} was never added.
+         * @throws IllegalArgumentException if schema types were referenced, but the corresponding
+         *     {@link AppSearchSchema} type was never added.
+         * @throws IllegalStateException if the builder has already been used.
          */
         @NonNull
         public SetSchemaRequest build() {
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java
index bc99d4f..a146006 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java
@@ -79,12 +79,6 @@
         return mBundle;
     }
 
-    /** TODO(b/177266929): Remove this deprecated method */
-    //@Deprecated
-    public boolean isSuccess() {
-        return true;
-    }
-
     /**
      * Returns a {@link List} of all failed {@link MigrationFailure}.
      *
diff --git a/apex/appsearch/service/Android.bp b/apex/appsearch/service/Android.bp
index 2fd5c73..57ee1ec 100644
--- a/apex/appsearch/service/Android.bp
+++ b/apex/appsearch/service/Android.bp
@@ -11,6 +11,15 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library {
     name: "service-appsearch",
     installable: true,
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/VisibilityStore.java b/apex/appsearch/service/java/com/android/server/appsearch/VisibilityStore.java
index babcd25..7c92456 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/VisibilityStore.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/VisibilityStore.java
@@ -218,9 +218,23 @@
      * @throws AppSearchException AppSearchException on AppSearchImpl error.
      */
     public void initialize() throws AppSearchException {
-        if (!mAppSearchImpl.hasSchemaTypeLocked(PACKAGE_NAME, DATABASE_NAME, VISIBILITY_TYPE)
-                || !mAppSearchImpl.hasSchemaTypeLocked(
-                        PACKAGE_NAME, DATABASE_NAME, PACKAGE_ACCESSIBLE_TYPE)) {
+        List<AppSearchSchema> schemas = mAppSearchImpl.getSchema(PACKAGE_NAME, DATABASE_NAME);
+        boolean hasVisibilityType = false;
+        boolean hasPackageAccessibleType = false;
+        for (int i = 0; i < schemas.size(); i++) {
+            AppSearchSchema schema = schemas.get(i);
+            if (schema.getSchemaType().equals(VISIBILITY_TYPE)) {
+                hasVisibilityType = true;
+            } else if (schema.getSchemaType().equals(PACKAGE_ACCESSIBLE_TYPE)) {
+                hasPackageAccessibleType = true;
+            }
+
+            if (hasVisibilityType && hasPackageAccessibleType) {
+                // Found both our types, can exit early.
+                break;
+            }
+        }
+        if (!hasVisibilityType || !hasPackageAccessibleType) {
             // Schema type doesn't exist yet. Add it.
             mAppSearchImpl.setSchema(
                     PACKAGE_NAME,
@@ -250,10 +264,11 @@
                                 /*typePropertyPaths=*/ Collections.emptyMap());
 
                 // Update platform visibility settings
-                String[] schemas =
+                String[] notPlatformSurfaceableSchemas =
                         document.getPropertyStringArray(NOT_PLATFORM_SURFACEABLE_PROPERTY);
-                if (schemas != null) {
-                    mNotPlatformSurfaceableMap.put(prefix, new ArraySet<>(Arrays.asList(schemas)));
+                if (notPlatformSurfaceableSchemas != null) {
+                    mNotPlatformSurfaceableMap.put(
+                            prefix, new ArraySet<>(Arrays.asList(notPlatformSurfaceableSchemas)));
                 }
 
                 // Update 3p package visibility settings
@@ -333,7 +348,7 @@
                 schemasPackageAccessible.entrySet()) {
             for (int i = 0; i < entry.getValue().size(); i++) {
                 GenericDocument packageAccessibleDocument =
-                        new GenericDocument.Builder(/*uri=*/"", PACKAGE_ACCESSIBLE_TYPE)
+                        new GenericDocument.Builder(/*uri=*/ "", PACKAGE_ACCESSIBLE_TYPE)
                                 .setNamespace(NAMESPACE)
                                 .setPropertyString(
                                         PACKAGE_NAME_PROPERTY,
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
index 6c2e30e..e2c211b 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
@@ -654,6 +654,35 @@
         }
     }
 
+    /**
+     * Returns a mapping of package names to all the databases owned by that package.
+     *
+     * <p>This method is inefficient to call repeatedly.
+     */
+    @NonNull
+    public Map<String, Set<String>> getPackageToDatabases() {
+        mReadWriteLock.readLock().lock();
+        try {
+            Map<String, Set<String>> packageToDatabases = new ArrayMap<>();
+            for (String prefix : mSchemaMapLocked.keySet()) {
+                String packageName = getPackageName(prefix);
+
+                Set<String> databases = packageToDatabases.get(packageName);
+                if (databases == null) {
+                    databases = new ArraySet<>();
+                    packageToDatabases.put(packageName, databases);
+                }
+
+                String databaseName = getDatabaseName(prefix);
+                databases.add(databaseName);
+            }
+
+            return packageToDatabases;
+        } finally {
+            mReadWriteLock.readLock().unlock();
+        }
+    }
+
     @GuardedBy("mReadWriteLock")
     private SearchResultPage doQueryLocked(
             @NonNull Set<String> prefixes,
@@ -1211,26 +1240,8 @@
         return schemaProto.getSchema();
     }
 
-    /**
-     * Returns true if the {@code packageName} and {@code databaseName} has the {@code schemaType}
-     */
-    @GuardedBy("mReadWriteLock")
-    boolean hasSchemaTypeLocked(
-            @NonNull String packageName, @NonNull String databaseName, @NonNull String schemaType) {
-        Preconditions.checkNotNull(packageName);
-        Preconditions.checkNotNull(databaseName);
-        Preconditions.checkNotNull(schemaType);
-
-        String prefix = createPrefix(packageName, databaseName);
-        Set<String> schemaTypes = mSchemaMapLocked.get(prefix);
-        if (schemaTypes == null) {
-            return false;
-        }
-
-        return schemaTypes.contains(prefix + schemaType);
-    }
-
     /** Returns a set of all prefixes AppSearchImpl knows about. */
+    // TODO(b/180058203): Remove this method once platform has switched away from using this method.
     @GuardedBy("mReadWriteLock")
     @NonNull
     Set<String> getPrefixesLocked() {
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLogger.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLogger.java
new file mode 100644
index 0000000..0f23d92
--- /dev/null
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLogger.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appsearch.external.localstorage;
+
+import android.annotation.NonNull;
+import android.app.appsearch.exceptions.AppSearchException;
+
+import com.android.server.appsearch.external.localstorage.stats.CallStats;
+import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
+
+/**
+ * An interface for implementing client-defined logging AppSearch operations stats.
+ *
+ * <p>Any implementation needs to provide general information on how to log all the stats types.
+ * (e.g. {@link CallStats})
+ *
+ * <p>All implementations of this interface must be thread safe.
+ *
+ * @hide
+ */
+public interface AppSearchLogger {
+    /** Logs {@link CallStats} */
+    void logStats(@NonNull CallStats stats) throws AppSearchException;
+
+    /** Logs {@link PutDocumentStats} */
+    void logStats(@NonNull PutDocumentStats stats) throws AppSearchException;
+
+    // TODO(b/173532925) Add remaining logStats once we add all the stats.
+}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchMigrationHelperImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchMigrationHelperImpl.java
index a501e99..a7f1cc4 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchMigrationHelperImpl.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchMigrationHelperImpl.java
@@ -76,7 +76,7 @@
         int currentVersion = mCurrentVersionMap.get(schemaType);
         int finalVersion = mFinalVersionMap.get(schemaType);
         try (FileOutputStream outputStream = new FileOutputStream(mFile)) {
-            // TODO(b/177266929) change the output stream so that we can use it in platform
+            // TODO(b/151178558) change the output stream so that we can use it in platform
             CodedOutputStream codedOutputStream = CodedOutputStream.newInstance(outputStream);
             SearchResultPage searchResultPage =
                     mAppSearchImpl.query(
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/CallStats.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/CallStats.java
new file mode 100644
index 0000000..81a5067
--- /dev/null
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/CallStats.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appsearch.external.localstorage.stats;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A class for setting basic information to log for all function calls.
+ *
+ * <p>This class can set which stats to log for both batch and non-batch {@link
+ * android.app.appsearch.AppSearchSession} calls.
+ *
+ * <p>Some function calls like {@link android.app.appsearch.AppSearchSession#setSchema} have their
+ * own detailed stats class {@link placeholder}. However, {@link CallStats} can still be used along
+ * with the detailed stats class for easy aggregation/analysis with other function calls.
+ *
+ * @hide
+ */
+public class CallStats {
+    @IntDef(
+            value = {
+                CALL_TYPE_UNKNOWN,
+                CALL_TYPE_INITIALIZE,
+                CALL_TYPE_SET_SCHEMA,
+                CALL_TYPE_PUT_DOCUMENTS,
+                CALL_TYPE_GET_DOCUMENTS,
+                CALL_TYPE_REMOVE_DOCUMENTS,
+                CALL_TYPE_PUT_DOCUMENT,
+                CALL_TYPE_GET_DOCUMENT,
+                CALL_TYPE_REMOVE_DOCUMENT,
+                CALL_TYPE_QUERY,
+                CALL_TYPE_OPTIMIZE,
+                CALL_TYPE_FLUSH,
+            })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface CallType {}
+
+    public static final int CALL_TYPE_UNKNOWN = 0;
+    public static final int CALL_TYPE_INITIALIZE = 1;
+    public static final int CALL_TYPE_SET_SCHEMA = 2;
+    public static final int CALL_TYPE_PUT_DOCUMENTS = 3;
+    public static final int CALL_TYPE_GET_DOCUMENTS = 4;
+    public static final int CALL_TYPE_REMOVE_DOCUMENTS = 5;
+    public static final int CALL_TYPE_PUT_DOCUMENT = 6;
+    public static final int CALL_TYPE_GET_DOCUMENT = 7;
+    public static final int CALL_TYPE_REMOVE_DOCUMENT = 8;
+    public static final int CALL_TYPE_QUERY = 9;
+    public static final int CALL_TYPE_OPTIMIZE = 10;
+    public static final int CALL_TYPE_FLUSH = 11;
+
+    @NonNull private final GeneralStats mGeneralStats;
+    @CallType private final int mCallType;
+    private final int mEstimatedBinderLatencyMillis;
+    private final int mNumOperationsSucceeded;
+    private final int mNumOperationsFailed;
+
+    CallStats(@NonNull Builder builder) {
+        Preconditions.checkNotNull(builder);
+        mGeneralStats = Preconditions.checkNotNull(builder.mGeneralStats);
+        mCallType = builder.mCallType;
+        mEstimatedBinderLatencyMillis = builder.mEstimatedBinderLatencyMillis;
+        mNumOperationsSucceeded = builder.mNumOperationsSucceeded;
+        mNumOperationsFailed = builder.mNumOperationsFailed;
+    }
+
+    /** Returns general information for the call. */
+    @NonNull
+    public GeneralStats getGeneralStats() {
+        return mGeneralStats;
+    }
+
+    /** Returns type of the call. */
+    @CallType
+    public int getCallType() {
+        return mCallType;
+    }
+
+    /** Returns estimated binder latency, in milliseconds */
+    public int getEstimatedBinderLatencyMillis() {
+        return mEstimatedBinderLatencyMillis;
+    }
+
+    /**
+     * Returns number of operations succeeded.
+     *
+     * <p>For example, for {@link android.app.appsearch.AppSearchSession#put}, it is the total
+     * number of individual successful put operations. In this case, how many documents are
+     * successfully indexed.
+     *
+     * <p>For non-batch calls such as {@link android.app.appsearch.AppSearchSession#setSchema}, the
+     * sum of {@link CallStats#getNumOperationsSucceeded()} and {@link
+     * CallStats#getNumOperationsFailed()} is always 1 since there is only one operation.
+     */
+    public int getNumOperationsSucceeded() {
+        return mNumOperationsSucceeded;
+    }
+
+    /**
+     * Returns number of operations failed.
+     *
+     * <p>For example, for {@link android.app.appsearch.AppSearchSession#put}, it is the total
+     * number of individual failed put operations. In this case, how many documents are failed to be
+     * indexed.
+     *
+     * <p>For non-batch calls such as {@link android.app.appsearch.AppSearchSession#setSchema}, the
+     * sum of {@link CallStats#getNumOperationsSucceeded()} and {@link
+     * CallStats#getNumOperationsFailed()} is always 1 since there is only one operation.
+     */
+    public int getNumOperationsFailed() {
+        return mNumOperationsFailed;
+    }
+
+    /** Builder for {@link CallStats}. */
+    public static class Builder {
+        @NonNull final GeneralStats mGeneralStats;
+        @CallType int mCallType;
+        int mEstimatedBinderLatencyMillis;
+        int mNumOperationsSucceeded;
+        int mNumOperationsFailed;
+
+        /** Builder takes {@link GeneralStats} to hold general stats. */
+        public Builder(@NonNull GeneralStats generalStats) {
+            mGeneralStats = Preconditions.checkNotNull(generalStats);
+        }
+
+        /** Sets type of the call. */
+        @NonNull
+        public Builder setCallType(@CallType int callType) {
+            mCallType = callType;
+            return this;
+        }
+
+        /** Sets estimated binder latency, in milliseconds. */
+        @NonNull
+        public Builder setEstimatedBinderLatencyMillis(int estimatedBinderLatencyMillis) {
+            mEstimatedBinderLatencyMillis = estimatedBinderLatencyMillis;
+            return this;
+        }
+
+        /**
+         * Sets number of operations succeeded.
+         *
+         * <p>For example, for {@link android.app.appsearch.AppSearchSession#put}, it is the total
+         * number of individual successful put operations. In this case, how many documents are
+         * successfully indexed.
+         *
+         * <p>For non-batch calls such as {@link android.app.appsearch.AppSearchSession#setSchema},
+         * the sum of {@link CallStats#getNumOperationsSucceeded()} and {@link
+         * CallStats#getNumOperationsFailed()} is always 1 since there is only one operation.
+         */
+        @NonNull
+        public Builder setNumOperationsSucceeded(int numOperationsSucceeded) {
+            mNumOperationsSucceeded = numOperationsSucceeded;
+            return this;
+        }
+
+        /**
+         * Sets number of operations failed.
+         *
+         * <p>For example, for {@link android.app.appsearch.AppSearchSession#put}, it is the total
+         * number of individual failed put operations. In this case, how many documents are failed
+         * to be indexed.
+         *
+         * <p>For non-batch calls such as {@link android.app.appsearch.AppSearchSession#setSchema},
+         * the sum of {@link CallStats#getNumOperationsSucceeded()} and {@link
+         * CallStats#getNumOperationsFailed()} is always 1 since there is only one operation.
+         */
+        @NonNull
+        public Builder setNumOperationsFailed(int numOperationsFailed) {
+            mNumOperationsFailed = numOperationsFailed;
+            return this;
+        }
+
+        /** Creates {@link CallStats} object from {@link Builder} instance. */
+        @NonNull
+        public CallStats build() {
+            return new CallStats(/* builder= */ this);
+        }
+    }
+}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/GeneralStats.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/GeneralStats.java
new file mode 100644
index 0000000..d2a45d5
--- /dev/null
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/GeneralStats.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appsearch.external.localstorage.stats;
+
+import android.annotation.NonNull;
+import android.app.appsearch.AppSearchResult;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * A class for holding general logging information.
+ *
+ * <p>This class cannot be logged by {@link
+ * com.android.server.appsearch.external.localstorage.AppSearchLogger} directly. It is used for
+ * defining general logging information that is shared across different stats classes.
+ *
+ * @see PutDocumentStats
+ * @see CallStats
+ * @hide
+ */
+public final class GeneralStats {
+    /** Package name of the application. */
+    @NonNull private final String mPackageName;
+
+    /** Database name within AppSearch. */
+    @NonNull private final String mDatabase;
+
+    /**
+     * The status code returned by {@link AppSearchResult#getResultCode()} for the call or internal
+     * state.
+     */
+    @AppSearchResult.ResultCode private final int mStatusCode;
+
+    private final int mTotalLatencyMillis;
+
+    GeneralStats(@NonNull Builder builder) {
+        Preconditions.checkNotNull(builder);
+        mPackageName = Preconditions.checkNotNull(builder.mPackageName);
+        mDatabase = Preconditions.checkNotNull(builder.mDatabase);
+        mStatusCode = builder.mStatusCode;
+        mTotalLatencyMillis = builder.mTotalLatencyMillis;
+    }
+
+    /** Returns package name. */
+    @NonNull
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    /** Returns database name. */
+    @NonNull
+    public String getDatabase() {
+        return mDatabase;
+    }
+
+    /** Returns result code from {@link AppSearchResult#getResultCode()} */
+    @AppSearchResult.ResultCode
+    public int getStatusCode() {
+        return mStatusCode;
+    }
+
+    /** Returns total latency, in milliseconds. */
+    public int getTotalLatencyMillis() {
+        return mTotalLatencyMillis;
+    }
+
+    /** Builder for {@link GeneralStats}. */
+    public static class Builder {
+        @NonNull final String mPackageName;
+        @NonNull final String mDatabase;
+        @AppSearchResult.ResultCode int mStatusCode;
+        int mTotalLatencyMillis;
+
+        /**
+         * Constructor
+         *
+         * @param packageName name of the package logging stats
+         * @param dataBase name of the database logging stats
+         */
+        public Builder(@NonNull String packageName, @NonNull String dataBase) {
+            mPackageName = Preconditions.checkNotNull(packageName);
+            mDatabase = Preconditions.checkNotNull(dataBase);
+        }
+
+        /** Sets status code returned from {@link AppSearchResult#getResultCode()} */
+        @NonNull
+        public Builder setStatusCode(@AppSearchResult.ResultCode int statusCode) {
+            mStatusCode = statusCode;
+            return this;
+        }
+
+        /** Sets total latency, in milliseconds. */
+        @NonNull
+        public Builder setTotalLatencyMillis(int totalLatencyMillis) {
+            mTotalLatencyMillis = totalLatencyMillis;
+            return this;
+        }
+
+        /**
+         * Creates a new {@link GeneralStats} object from the contents of this {@link Builder}
+         * instance.
+         */
+        @NonNull
+        public GeneralStats build() {
+            return new GeneralStats(/* builder= */ this);
+        }
+    }
+}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/PutDocumentStats.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/PutDocumentStats.java
new file mode 100644
index 0000000..b1b643b
--- /dev/null
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/PutDocumentStats.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appsearch.external.localstorage.stats;
+
+import android.annotation.NonNull;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * A class for holding detailed stats to log for each individual document put by a {@link
+ * android.app.appsearch.AppSearchSession#put} call.
+ *
+ * @hide
+ */
+public final class PutDocumentStats {
+    /** {@link GeneralStats} holds the general stats. */
+    @NonNull private final GeneralStats mGeneralStats;
+
+    /** Time used to generate a document proto from a Bundle. */
+    private final int mGenerateDocumentProtoLatencyMillis;
+
+    /** Time used to rewrite types and namespaces in the document. */
+    private final int mRewriteDocumentTypesLatencyMillis;
+
+    /** Overall time used for the native function call. */
+    private final int mNativeLatencyMillis;
+
+    /** Time used to store the document. */
+    private final int mNativeDocumentStoreLatencyMillis;
+
+    /** Time used to index the document. It doesn't include the time to merge indices. */
+    private final int mNativeIndexLatencyMillis;
+
+    /** Time used to merge the indices. */
+    private final int mNativeIndexMergeLatencyMillis;
+
+    /** Document size in bytes. */
+    private final int mNativeDocumentSizeBytes;
+
+    /** Number of tokens added to the index. */
+    private final int mNativeNumTokensIndexed;
+
+    /** Number of tokens clipped for exceeding the max number. */
+    private final int mNativeNumTokensClipped;
+
+    PutDocumentStats(@NonNull Builder builder) {
+        Preconditions.checkNotNull(builder);
+        mGeneralStats = Preconditions.checkNotNull(builder.mGeneralStats);
+        mGenerateDocumentProtoLatencyMillis = builder.mGenerateDocumentProtoLatencyMillis;
+        mRewriteDocumentTypesLatencyMillis = builder.mRewriteDocumentTypesLatencyMillis;
+        mNativeLatencyMillis = builder.mNativeLatencyMillis;
+        mNativeDocumentStoreLatencyMillis = builder.mNativeDocumentStoreLatencyMillis;
+        mNativeIndexLatencyMillis = builder.mNativeIndexLatencyMillis;
+        mNativeIndexMergeLatencyMillis = builder.mNativeIndexMergeLatencyMillis;
+        mNativeDocumentSizeBytes = builder.mNativeDocumentSizeBytes;
+        mNativeNumTokensIndexed = builder.mNativeNumTokensIndexed;
+        mNativeNumTokensClipped = builder.mNativeNumTokensClipped;
+    }
+
+    /** Returns the {@link GeneralStats} object attached to this instance. */
+    @NonNull
+    public GeneralStats getGeneralStats() {
+        return mGeneralStats;
+    }
+
+    /** Returns time spent on generating document proto, in milliseconds. */
+    public int getGenerateDocumentProtoLatencyMillis() {
+        return mGenerateDocumentProtoLatencyMillis;
+    }
+
+    /** Returns time spent on rewriting types and namespaces in document, in milliseconds. */
+    public int getRewriteDocumentTypesLatencyMillis() {
+        return mRewriteDocumentTypesLatencyMillis;
+    }
+
+    /** Returns time spent in native, in milliseconds. */
+    public int getNativeLatencyMillis() {
+        return mNativeLatencyMillis;
+    }
+
+    /** Returns time spent on document store, in milliseconds. */
+    public int getNativeDocumentStoreLatencyMillis() {
+        return mNativeDocumentStoreLatencyMillis;
+    }
+
+    /** Returns time spent on indexing, in milliseconds. */
+    public int getNativeIndexLatencyMillis() {
+        return mNativeIndexLatencyMillis;
+    }
+
+    /** Returns time spent on merging indices, in milliseconds. */
+    public int getNativeIndexMergeLatencyMillis() {
+        return mNativeIndexMergeLatencyMillis;
+    }
+
+    /** Returns document size, in bytes. */
+    public int getNativeDocumentSizeBytes() {
+        return mNativeDocumentSizeBytes;
+    }
+
+    /** Returns number of tokens indexed. */
+    public int getNativeNumTokensIndexed() {
+        return mNativeNumTokensIndexed;
+    }
+
+    /** Returns number of tokens clipped for exceeding the max number. */
+    public int getNativeNumTokensClipped() {
+        return mNativeNumTokensClipped;
+    }
+
+    /** Builder for {@link PutDocumentStats}. */
+    public static class Builder {
+        @NonNull final GeneralStats mGeneralStats;
+        int mGenerateDocumentProtoLatencyMillis;
+        int mRewriteDocumentTypesLatencyMillis;
+        int mNativeLatencyMillis;
+        int mNativeDocumentStoreLatencyMillis;
+        int mNativeIndexLatencyMillis;
+        int mNativeIndexMergeLatencyMillis;
+        int mNativeDocumentSizeBytes;
+        int mNativeNumTokensIndexed;
+        int mNativeNumTokensClipped;
+
+        /** Builder takes {@link GeneralStats} to hold general stats. */
+        public Builder(@NonNull GeneralStats generalStats) {
+            mGeneralStats = Preconditions.checkNotNull(generalStats);
+        }
+
+        /** Sets how much time we spend for generating document proto, in milliseconds. */
+        @NonNull
+        public Builder setGenerateDocumentProtoLatencyMillis(
+                int generateDocumentProtoLatencyMillis) {
+            mGenerateDocumentProtoLatencyMillis = generateDocumentProtoLatencyMillis;
+            return this;
+        }
+
+        /**
+         * Sets how much time we spend for rewriting types and namespaces in document, in
+         * milliseconds.
+         */
+        @NonNull
+        public Builder setRewriteDocumentTypesLatencyMillis(int rewriteDocumentTypesLatencyMillis) {
+            mRewriteDocumentTypesLatencyMillis = rewriteDocumentTypesLatencyMillis;
+            return this;
+        }
+
+        /** Sets the native latency, in milliseconds. */
+        @NonNull
+        public Builder setNativeLatencyMillis(int nativeLatencyMillis) {
+            mNativeLatencyMillis = nativeLatencyMillis;
+            return this;
+        }
+
+        /** Sets how much time we spend on document store, in milliseconds. */
+        @NonNull
+        public Builder setNativeDocumentStoreLatencyMillis(int nativeDocumentStoreLatencyMillis) {
+            mNativeDocumentStoreLatencyMillis = nativeDocumentStoreLatencyMillis;
+            return this;
+        }
+
+        /** Sets the native index latency, in milliseconds. */
+        @NonNull
+        public Builder setNativeIndexLatencyMillis(int nativeIndexLatencyMillis) {
+            mNativeIndexLatencyMillis = nativeIndexLatencyMillis;
+            return this;
+        }
+
+        /** Sets how much time we spend on merging indices, in milliseconds. */
+        @NonNull
+        public Builder setNativeIndexMergeLatencyMillis(int nativeIndexMergeLatencyMillis) {
+            mNativeIndexMergeLatencyMillis = nativeIndexMergeLatencyMillis;
+            return this;
+        }
+
+        /** Sets document size, in bytes. */
+        @NonNull
+        public Builder setNativeDocumentSizeBytes(int nativeDocumentSizeBytes) {
+            mNativeDocumentSizeBytes = nativeDocumentSizeBytes;
+            return this;
+        }
+
+        /** Sets number of tokens indexed in native. */
+        @NonNull
+        public Builder setNativeNumTokensIndexed(int nativeNumTokensIndexed) {
+            mNativeNumTokensIndexed = nativeNumTokensIndexed;
+            return this;
+        }
+
+        /** Sets number of tokens clipped for exceeding the max number. */
+        @NonNull
+        public Builder setNativeNumTokensClipped(int nativeNumTokensClipped) {
+            mNativeNumTokensClipped = nativeNumTokensClipped;
+            return this;
+        }
+
+        /**
+         * Creates a new {@link PutDocumentStats} object from the contents of this {@link Builder}
+         * instance.
+         */
+        @NonNull
+        public PutDocumentStats build() {
+            return new PutDocumentStats(/* builder= */ this);
+        }
+    }
+}
diff --git a/apex/appsearch/synced_jetpack_changeid.txt b/apex/appsearch/synced_jetpack_changeid.txt
index d076db3..2c9477a 100644
--- a/apex/appsearch/synced_jetpack_changeid.txt
+++ b/apex/appsearch/synced_jetpack_changeid.txt
@@ -1 +1 @@
-Ia9a8daef1a6d7d9432f7808d440abd64f4797701
+I593dfd22279739e5f578e07d36a55cf02ee942c5
diff --git a/apex/appsearch/testing/Android.bp b/apex/appsearch/testing/Android.bp
index 54d5039..eb072af 100644
--- a/apex/appsearch/testing/Android.bp
+++ b/apex/appsearch/testing/Android.bp
@@ -11,6 +11,15 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library {
     name: "AppSearchTestUtils",
     srcs: ["java/**/*.java"],
diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/AppSearchSessionShimImpl.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/AppSearchSessionShimImpl.java
index afa633a..9ef6e0b 100644
--- a/apex/appsearch/testing/java/com/android/server/appsearch/testing/AppSearchSessionShimImpl.java
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/AppSearchSessionShimImpl.java
@@ -124,8 +124,7 @@
     @NonNull
     public SearchResultsShim search(
             @NonNull String queryExpression, @NonNull SearchSpec searchSpec) {
-        SearchResults searchResults =
-                mAppSearchSession.search(queryExpression, searchSpec, mExecutor);
+        SearchResults searchResults = mAppSearchSession.search(queryExpression, searchSpec);
         return new SearchResultsShimImpl(searchResults, mExecutor);
     }
 
diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/GlobalSearchSessionShimImpl.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/GlobalSearchSessionShimImpl.java
index 6595d8d..69a4c18 100644
--- a/apex/appsearch/testing/java/com/android/server/appsearch/testing/GlobalSearchSessionShimImpl.java
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/GlobalSearchSessionShimImpl.java
@@ -75,8 +75,7 @@
     @Override
     public SearchResultsShim search(
             @NonNull String queryExpression, @NonNull SearchSpec searchSpec) {
-        SearchResults searchResults =
-                mGlobalSearchSession.search(queryExpression, searchSpec, mExecutor);
+        SearchResults searchResults = mGlobalSearchSession.search(queryExpression, searchSpec);
         return new SearchResultsShimImpl(searchResults, mExecutor);
     }
 
diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/SearchResultsShimImpl.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/SearchResultsShimImpl.java
index 75add81..5f26e8c 100644
--- a/apex/appsearch/testing/java/com/android/server/appsearch/testing/SearchResultsShimImpl.java
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/SearchResultsShimImpl.java
@@ -47,7 +47,7 @@
     @NonNull
     public ListenableFuture<List<SearchResult>> getNextPage() {
         SettableFuture<AppSearchResult<List<SearchResult>>> future = SettableFuture.create();
-        mSearchResults.getNextPage(future::set);
+        mSearchResults.getNextPage(mExecutor, future::set);
         return Futures.transform(future, AppSearchResult::getResultValue, mExecutor);
     }
 
diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchSessionShim.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchSessionShim.java
index ea21e19..1428fb1 100644
--- a/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchSessionShim.java
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchSessionShim.java
@@ -33,91 +33,19 @@
 public interface AppSearchSessionShim extends Closeable {
 
     /**
-     * Sets the schema that will be used by documents provided to the {@link #put} method.
+     * Sets the schema that represents the organizational structure of data within the AppSearch
+     * database.
      *
-     * <p>The schema provided here is compared to the stored copy of the schema previously supplied
-     * to {@link #setSchema}, if any, to determine how to treat existing documents. The following
-     * types of schema modifications are always safe and are made without deleting any existing
-     * documents:
+     * <p>Upon creating an {@link AppSearchSessionShim}, {@link #setSchema} should be called. If the
+     * schema needs to be updated, or it has not been previously set, then the provided schema will
+     * be saved and persisted to disk. Otherwise, {@link #setSchema} is handled efficiently as a
+     * no-op call.
      *
-     * <ul>
-     *   <li>Addition of new types
-     *   <li>Addition of new {@link AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL OPTIONAL} or
-     *       {@link AppSearchSchema.PropertyConfig#CARDINALITY_REPEATED REPEATED} properties to a
-     *       type
-     *   <li>Changing the cardinality of a data type to be less restrictive (e.g. changing an {@link
-     *       AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL OPTIONAL} property into a {@link
-     *       AppSearchSchema.PropertyConfig#CARDINALITY_REPEATED REPEATED} property.
-     * </ul>
-     *
-     * <p>The following types of schema changes are not backwards-compatible:
-     *
-     * <ul>
-     *   <li>Removal of an existing type
-     *   <li>Removal of a property from a type
-     *   <li>Changing the data type ({@code boolean}, {@code long}, etc.) of an existing property
-     *   <li>For properties of {@code Document} type, changing the schema type of {@code Document}s
-     *       of that property
-     *   <li>Changing the cardinality of a data type to be more restrictive (e.g. changing an {@link
-     *       AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL OPTIONAL} property into a {@link
-     *       AppSearchSchema.PropertyConfig#CARDINALITY_REQUIRED REQUIRED} property).
-     *   <li>Adding a {@link AppSearchSchema.PropertyConfig#CARDINALITY_REQUIRED REQUIRED} property.
-     * </ul>
-     *
-     * <p>Supplying a schema with such changes will, by default, result in this call completing its
-     * future with an {@link android.app.appsearch.exceptions.AppSearchException} with a code of
-     * {@link AppSearchResult#RESULT_INVALID_SCHEMA} and a message describing the incompatibility.
-     * In this case the previously set schema will remain active.
-     *
-     * <p>If you need to make non-backwards-compatible changes as described above, you can either:
-     *
-     * <ul>
-     *   <li>Set the {@link SetSchemaRequest.Builder#setForceOverride} method to {@code true}. In
-     *       this case, instead of completing its future with an {@link
-     *       android.app.appsearch.exceptions.AppSearchException} with the {@link
-     *       AppSearchResult#RESULT_INVALID_SCHEMA} error code, all documents which are not
-     *       compatible with the new schema will be deleted and the incompatible schema will be
-     *       applied. Incompatible types and deleted types will be set into {@link
-     *       SetSchemaResponse#getIncompatibleTypes()} and {@link
-     *       SetSchemaResponse#getDeletedTypes()}, respectively.
-     *   <li>Add a {@link android.app.appsearch.AppSearchSchema.Migrator} for each incompatible type
-     *       and make no deletion. The migrator will migrate documents from it's old schema version
-     *       to the new version. Migrated types will be set into both {@link
-     *       SetSchemaResponse#getIncompatibleTypes()} and {@link
-     *       SetSchemaResponse#getMigratedTypes()}. See the migration section below.
-     * </ul>
-     *
-     * <p>It is a no-op to set the same schema as has been previously set; this is handled
-     * efficiently.
-     *
-     * <p>By default, documents are visible on platform surfaces. To opt out, call
-     * {@link SetSchemaRequest.Builder#setSchemaTypeVisibilityForSystemUi} with {@code visible} as
-     * false. Any visibility settings apply only to the schemas that are included in the
-     * {@code request}. Visibility settings for a schema type do not persist across
-     * {@link #setSchema} calls.
-     *
-     * <p>Migration: make non-backwards-compatible changes will delete all stored documents in old
-     * schema. You can save your documents by setting {@link
-     * android.app.appsearch.AppSearchSchema.Migrator} via the {@link
-     * SetSchemaRequest.Builder#setMigrator} for each type you want to save.
-     *
-     * <p>{@link android.app.appsearch.AppSearchSchema.Migrator#onDowngrade} or {@link
-     * android.app.appsearch.AppSearchSchema.Migrator#onUpgrade} will be triggered if the version
-     * number of the schema stored in AppSearch is different with the version in the request.
-     *
-     * <p>If any error or Exception occurred in the {@link
-     * android.app.appsearch.AppSearchSchema.Migrator#onDowngrade}, {@link
-     * android.app.appsearch.AppSearchSchema.Migrator#onUpgrade} or {@link
-     * android.app.appsearch.AppSearchMigrationHelper.Transformer#transform}, the migration will be
-     * terminated, the setSchema request will be rejected unless the schema changes are
-     * backwards-compatible, and stored documents won't have any observable changes.
-     *
-     * @param request The schema update request.
-     * @return A {@link ListenableFuture} with exception if we hit any error. Or the pending {@link
-     *     SetSchemaResponse} of performing this operation, if the schema has been successfully set.
-     * @see android.app.appsearch.AppSearchSchema.Migrator
-     * @see android.app.appsearch.AppSearchMigrationHelper.Transformer
+     * @param request the schema to set or update the AppSearch database to.
+     * @return a {@link ListenableFuture} which resolves to a {@link SetSchemaResponse} object.
      */
+    // TODO(b/169883602): Change @code references to @link when setPlatformSurfaceable APIs are
+    //  exposed.
     @NonNull
     ListenableFuture<SetSchemaResponse> setSchema(@NonNull SetSchemaRequest request);
 
@@ -132,15 +60,17 @@
     ListenableFuture<Set<AppSearchSchema>> getSchema();
 
     /**
-     * Indexes documents into AppSearch.
+     * Indexes documents into the {@link AppSearchSessionShim} database.
      *
-     * <p>Each {@link GenericDocument}'s {@code schemaType} field must be set to the name of a
-     * schema type previously registered via the {@link #setSchema} method.
+     * <p>Each {@link GenericDocument} object must have a {@code schemaType} field set to an {@link
+     * AppSearchSchema} type that has been previously registered by calling the {@link #setSchema}
+     * method.
      *
-     * @param request {@link PutDocumentsRequest} containing documents to be indexed
-     * @return The pending result of performing this operation. The keys of the returned {@link
-     *     AppSearchBatchResult} are the URIs of the input documents. The values are {@code null} if
-     *     they were successfully indexed, or a failed {@link AppSearchResult} otherwise.
+     * @param request containing documents to be indexed.
+     * @return a {@link ListenableFuture} which resolves to an {@link AppSearchBatchResult}. The
+     *     keys of the returned {@link AppSearchBatchResult} are the URIs of the input documents.
+     *     The values are either {@code null} if the corresponding document was successfully
+     *     indexed, or a failed {@link AppSearchResult} otherwise.
      */
     @NonNull
     ListenableFuture<AppSearchBatchResult<String, Void>> put(@NonNull PutDocumentsRequest request);
@@ -213,7 +143,7 @@
      * adding projection, can be set by calling the corresponding {@link SearchSpec.Builder} setter.
      *
      * <p>This method is lightweight. The heavy work will be done in {@link
-     * SearchResultsShim#getNextPage()}.
+     * SearchResultsShim#getNextPage}.
      *
      * @param queryExpression query string to search.
      * @param searchSpec spec for setting document filters, adding projection, setting term match
diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/GlobalSearchSessionShim.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/GlobalSearchSessionShim.java
index 31c934f..d912c08 100644
--- a/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/GlobalSearchSessionShim.java
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/GlobalSearchSessionShim.java
@@ -37,11 +37,11 @@
      * SetSchemaRequest.Builder#setSchemaTypeVisibilityForSystemUi}, or {@link
      * SetSchemaRequest.Builder#setDocumentClassVisibilityForSystemUi} when building a schema.
      *
-     * <p>See {@link AppSearchSessionShim#search(String, SearchSpec)} for a detailed explanation on
-     * forming a query string.
+     * <p>See {@link AppSearchSessionShim#search} for a detailed explanation on forming a query
+     * string.
      *
      * <p>This method is lightweight. The heavy work will be done in {@link
-     * SearchResultsShim#getNextPage()}.
+     * SearchResultsShim#getNextPage}.
      *
      * @param queryExpression query string to search.
      * @param searchSpec spec for setting document filters, adding projection, setting term match
diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/SearchResultsShim.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/SearchResultsShim.java
index 328c65c..38f61f8 100644
--- a/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/SearchResultsShim.java
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/SearchResultsShim.java
@@ -24,25 +24,29 @@
 import java.util.List;
 
 /**
- * SearchResultsShim are a returned object from a query API.
+ * Encapsulates results of a search operation.
  *
- * <p>Each {@link SearchResult} contains a document and may contain other fields like snippets based
- * on request.
+ * <p>Each {@link AppSearchSessionShim#search} operation returns a list of {@link SearchResult}
+ * objects, referred to as a "page", limited by the size configured by {@link
+ * SearchSpec.Builder#setResultCountPerPage}.
  *
- * <p>Should close this object after finish fetching results.
+ * <p>To fetch a page of results, call {@link #getNextPage()}.
+ *
+ * <p>All instances of {@link SearchResultsShim} must call {@link SearchResultsShim#close()} after
+ * the results are fetched.
  *
  * <p>This class is not thread safe.
  */
 public interface SearchResultsShim extends Closeable {
     /**
-     * Gets a whole page of {@link SearchResult}s.
+     * Retrieves the next page of {@link SearchResult} objects.
      *
-     * <p>Re-call this method to get next page of {@link SearchResult}, until it returns an empty
-     * list.
+     * <p>The page size is configured by {@link SearchSpec.Builder#setResultCountPerPage}.
      *
-     * <p>The page size is set by {@link SearchSpec.Builder#setResultCountPerPage}.
+     * <p>Continue calling this method to access results until it returns an empty list, signifying
+     * there are no more results.
      *
-     * @return The pending result of performing this operation.
+     * @return a {@link ListenableFuture} which resolves to a list of {@link SearchResult} objects.
      */
     @NonNull
     ListenableFuture<List<SearchResult>> getNextPage();
diff --git a/apex/blobstore/framework/Android.bp b/apex/blobstore/framework/Android.bp
index 3499553..1cb295b 100644
--- a/apex/blobstore/framework/Android.bp
+++ b/apex/blobstore/framework/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "framework-blobstore-sources",
     srcs: [
diff --git a/apex/blobstore/service/Android.bp b/apex/blobstore/service/Android.bp
index f6cbac1..49cfd07 100644
--- a/apex/blobstore/service/Android.bp
+++ b/apex/blobstore/service/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library {
     name: "service-blobstore",
     installable: true,
diff --git a/apex/jobscheduler/framework/Android.bp b/apex/jobscheduler/framework/Android.bp
index 6650e67..b51c2aa 100644
--- a/apex/jobscheduler/framework/Android.bp
+++ b/apex/jobscheduler/framework/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "framework-jobscheduler-sources",
     srcs: [
@@ -22,6 +31,7 @@
         ],
     },
     libs: [
+        "app-compat-annotations",
         "framework-minus-apex",
         "unsupportedappusage",
     ],
diff --git a/apex/jobscheduler/framework/java/android/app/AlarmManager.java b/apex/jobscheduler/framework/java/android/app/AlarmManager.java
index 7851087..77146e0 100644
--- a/apex/jobscheduler/framework/java/android/app/AlarmManager.java
+++ b/apex/jobscheduler/framework/java/android/app/AlarmManager.java
@@ -16,11 +16,14 @@
 
 package android.app;
 
+import android.Manifest;
 import android.annotation.IntDef;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
@@ -183,6 +186,25 @@
     @UnsupportedAppUsage
     public static final int FLAG_IDLE_UNTIL = 1<<4;
 
+    /**
+     * Flag for alarms: Used to provide backwards compatibility for apps with targetSdkVersion less
+     * than {@link Build.VERSION_CODES#S}
+     * @hide
+     */
+    public static final int FLAG_ALLOW_WHILE_IDLE_COMPAT = 1 << 5;
+
+    /**
+     * For apps targeting {@link Build.VERSION_CODES#S} or above, APIs
+     * {@link #setExactAndAllowWhileIdle(int, long, PendingIntent)} and
+     * {@link #setAlarmClock(AlarmClockInfo, PendingIntent)} will require holding a new
+     * permission {@link android.Manifest.permission#SCHEDULE_EXACT_ALARM}
+     *
+     * @hide
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S)
+    public static final long REQUIRE_EXACT_ALARM_PERMISSION = 171306433L;
+
     @UnsupportedAppUsage
     private final IAlarmManager mService;
     private final Context mContext;
@@ -588,6 +610,11 @@
      * This method is like {@link #setExact(int, long, PendingIntent)}, but implies
      * {@link #RTC_WAKEUP}.
      *
+     * <p>
+     * Starting from API {@link Build.VERSION_CODES#S}, using this method requires the
+     * {@link Manifest.permission#SCHEDULE_EXACT_ALARM} permission. Alarms scheduled via this API
+     * will be allowed to start a foreground service even if the app is in the background.
+     *
      * @param info
      * @param operation Action to perform when the alarm goes off;
      *        typically comes from {@link PendingIntent#getBroadcast
@@ -603,6 +630,7 @@
      * @see android.content.Context#registerReceiver
      * @see android.content.Intent#filterEquals
      */
+    @RequiresPermission(Manifest.permission.SCHEDULE_EXACT_ALARM)
     public void setAlarmClock(AlarmClockInfo info, PendingIntent operation) {
         setImpl(RTC_WAKEUP, info.getTriggerTime(), WINDOW_EXACT, 0, 0, operation,
                 null, null, null, null, info);
@@ -876,6 +904,12 @@
      * device is idle it may take even more liberties with scheduling in order to optimize
      * for battery life.</p>
      *
+     * <p>
+     * Starting from API {@link Build.VERSION_CODES#S}, using this method requires the
+     * {@link Manifest.permission#SCHEDULE_EXACT_ALARM} permission, unless the app is exempt from
+     * battery restrictions. Alarms scheduled via this API will be allowed to start a foreground
+     * service even if the app is in the background.
+     *
      * @param type type of alarm.
      * @param triggerAtMillis time in milliseconds that the alarm should go
      *        off, using the appropriate clock (depending on the alarm type).
@@ -895,6 +929,7 @@
      * @see #RTC
      * @see #RTC_WAKEUP
      */
+    @RequiresPermission(value = Manifest.permission.SCHEDULE_EXACT_ALARM, conditional = true)
     public void setExactAndAllowWhileIdle(@AlarmType int type, long triggerAtMillis,
             PendingIntent operation) {
         setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, FLAG_ALLOW_WHILE_IDLE, operation,
@@ -1018,6 +1053,18 @@
     }
 
     /**
+     * Called to check if the caller has permission to use alarms set via {@link }
+     * @return
+     */
+    public boolean canScheduleExactAlarms() {
+        try {
+            return mService.canScheduleExactAlarms();
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Gets information about the next alarm clock currently scheduled.
      *
      * The alarm clocks considered are those scheduled by any application
diff --git a/apex/jobscheduler/framework/java/android/app/IAlarmManager.aidl b/apex/jobscheduler/framework/java/android/app/IAlarmManager.aidl
index 2c51935..2f21ce3 100644
--- a/apex/jobscheduler/framework/java/android/app/IAlarmManager.aidl
+++ b/apex/jobscheduler/framework/java/android/app/IAlarmManager.aidl
@@ -41,4 +41,5 @@
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
     AlarmManager.AlarmClockInfo getNextAlarmClock(int userId);
     long currentNetworkTimeMillis();
+    boolean canScheduleExactAlarms();
 }
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
index 930415f..b7a3f10 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
@@ -59,6 +59,12 @@
  * constraint on the JobInfo object that you are creating. Otherwise, the builder would throw an
  * exception when building. From Android version {@link Build.VERSION_CODES#Q} and onwards, it is
  * valid to schedule jobs with no constraints.
+ * <p> In Android version {@link Build.VERSION_CODES#LOLLIPOP}, jobs had a maximum execution time
+ * of one minute. Starting with Android version {@link Build.VERSION_CODES#M} and ending with
+ * Android version {@link Build.VERSION_CODES#R}, jobs had a maximum execution time of 10 minutes.
+ * Starting from Android version {@link Build.VERSION_CODES#S}, jobs will still be stopped after
+ * 10 minutes if the system is busy or needs the resources, but if not, jobs may continue running
+ * longer than 10 minutes.
  */
 public class JobInfo implements Parcelable {
     private static String TAG = "JobInfo";
@@ -1461,11 +1467,13 @@
          * possible with stronger guarantees than regular jobs. These "expedited" jobs will:
          * <ol>
          *     <li>Run as soon as possible</li>
-         *     <li>Be exempted from Doze and battery saver restrictions</li>
+         *     <li>Be less restricted during Doze and battery saver</li>
          *     <li>Have network access</li>
-         *     <li>Less likely to be killed than regular jobs</li>
+         *     <li>Be less likely to be killed than regular jobs</li>
+         *     <li>Be subject to background location throttling</li>
          * </ol>
          *
+         * <p>
          * Since these jobs have stronger guarantees than regular jobs, they will be subject to
          * stricter quotas. As long as an app has available expedited quota, jobs scheduled with
          * this set to true will run with these guarantees. If an app has run out of available
@@ -1475,9 +1483,18 @@
          * will immediately return {@link JobScheduler#RESULT_FAILURE} if the app does not have
          * available quota (and the job will not be successfully scheduled).
          *
+         * <p>
          * Expedited jobs may only set network, storage-not-low, and persistence constraints.
          * No other constraints are allowed.
          *
+         * <p>
+         * Assuming all constraints remain satisfied (including ideal system load conditions),
+         * expedited jobs are guaranteed to have a minimum allowed runtime of 1 minute. If your
+         * app has remaining expedited job quota, then the expedited job <i>may</i> potentially run
+         * longer until remaining quota is used up. Just like with regular jobs, quota is not
+         * consumed while the app is on top and visible to the user.
+         *
+         * <p>
          * Note: Even though expedited jobs are meant to run as soon as possible, they may be
          * deferred if the system is under heavy load or requested constraints are not satisfied.
          *
diff --git a/apex/jobscheduler/framework/java/android/os/IDeviceIdleController.aidl b/apex/jobscheduler/framework/java/android/os/IDeviceIdleController.aidl
index 5693abe..43d4873 100644
--- a/apex/jobscheduler/framework/java/android/os/IDeviceIdleController.aidl
+++ b/apex/jobscheduler/framework/java/android/os/IDeviceIdleController.aidl
@@ -43,10 +43,10 @@
     boolean isPowerSaveWhitelistApp(String name);
     @UnsupportedAppUsage(maxTargetSdk = 30,
      publicAlternatives = "Use SystemApi {@code PowerWhitelistManager#whitelistAppTemporarily(String, int, String)}.")
-    void addPowerSaveTempWhitelistApp(String name, long duration, int userId, String reason);
-    long addPowerSaveTempWhitelistAppForMms(String name, int userId, String reason);
-    long addPowerSaveTempWhitelistAppForSms(String name, int userId, String reason);
-    long whitelistAppTemporarily(String name, int userId, String reason);
+    void addPowerSaveTempWhitelistApp(String name, long duration, int userId, int reasonCode, String reason);
+    long addPowerSaveTempWhitelistAppForMms(String name, int userId, int reasonCode, String reason);
+    long addPowerSaveTempWhitelistAppForSms(String name, int userId, int reasonCode, String reason);
+    long whitelistAppTemporarily(String name, int userId, int reasonCode, String reason);
     void exitIdle(String reason);
     int setPreIdleTimeoutMode(int Mode);
     void resetPreIdleTimeoutMode();
diff --git a/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java b/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java
index 283e933..df690d0 100644
--- a/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java
+++ b/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java
@@ -16,8 +16,16 @@
 
 package android.os;
 
+import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
+import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
+import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT;
+import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT_UI;
+import static android.app.ActivityManager.PROCESS_STATE_TOP;
+
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
@@ -87,13 +95,246 @@
      * The list of temp allowlist types.
      * @hide
      */
-    @IntDef(flag = true, prefix = { "TEMPORARY_ALLOW_TYPE_" }, value = {
+    @IntDef(flag = true, prefix = { "TEMPORARY_ALLOWLIST_TYPE_" }, value = {
             TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
             TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface TempAllowListType {}
 
+    /* Reason code for BG-FGS-launch. */
+    /**
+     * BG-FGS-launch is denied.
+     * @hide
+     */
+    public static final int REASON_DENIED = -1;
+    /**
+     * The default reason code if reason is unknown.
+     */
+    public static final int REASON_UNKNOWN = 0;
+    /**
+     * Use REASON_OTHER if there is no better choice.
+     */
+    public static final int REASON_OTHER = 1;
+    /** @hide */
+    public static final int REASON_PROC_STATE_PERSISTENT = 10;
+    /** @hide */
+    public static final int REASON_PROC_STATE_PERSISTENT_UI = 11;
+    /** @hide */
+    public static final int REASON_PROC_STATE_TOP = 12;
+    /** @hide */
+    public static final int REASON_PROC_STATE_BTOP = 13;
+    /** @hide */
+    public static final int REASON_PROC_STATE_FGS = 14;
+    /** @hide */
+    public static final int REASON_PROC_STATE_BFGS = 15;
+    /** @hide */
+    public static final int REASON_UID_VISIBLE = 50;
+    /** @hide */
+    public static final int REASON_SYSTEM_UID = 51;
+    /** @hide */
+    public static final int REASON_ACTIVITY_STARTER = 52;
+    /** @hide */
+    public static final int REASON_START_ACTIVITY_FLAG = 53;
+    /** @hide */
+    public static final int REASON_FGS_BINDING = 54;
+    /** @hide */
+    public static final int REASON_DEVICE_OWNER = 55;
+    /** @hide */
+    public static final int REASON_PROFILE_OWNER = 56;
+    /** @hide */
+    public static final int REASON_COMPANION_DEVICE_MANAGER = 57;
+    /**
+     * START_ACTIVITIES_FROM_BACKGROUND permission.
+     * @hide
+     */
+    public static final int REASON_BACKGROUND_ACTIVITY_PERMISSION = 58;
+    /**
+     * START_FOREGROUND_SERVICES_FROM_BACKGROUND permission.
+     * @hide
+     */
+    public static final int REASON_BACKGROUND_FGS_PERMISSION = 59;
+    /** @hide */
+    public static final int REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION = 60;
+    /** @hide */
+    public static final int REASON_INSTR_BACKGROUND_FGS_PERMISSION = 61;
+    /** @hide */
+    public static final int REASON_SYSTEM_ALERT_WINDOW_PERMISSION = 62;
+    /** @hide */
+    public static final int REASON_DEVICE_DEMO_MODE = 63;
+    /** @hide */
+    public static final int REASON_EXEMPTED_PACKAGE = 64;
+    /** @hide */
+    public static final int REASON_ALLOWLISTED_PACKAGE  = 65;
+    /**
+     * If it's because of a role,
+     * @hide
+     */
+    public static final int REASON_APPOP = 66;
+
+    /* BG-FGS-launch is allowed by temp-allowlist or system-allowlist.
+    Reason code for temp and system allowlist starts here.
+    */
+    public static final int REASON_GEOFENCING = 100;
+    public static final int REASON_PUSH_MESSAGING = 101;
+    public static final int REASON_ACTIVITY_RECOGNITION = 102;
+
+    /**
+     * Broadcast ACTION_BOOT_COMPLETED.
+     * @hide
+     */
+    public static final int REASON_BOOT_COMPLETED = 103;
+    /**
+     * Broadcast ACTION_PRE_BOOT_COMPLETED.
+     * @hide
+     */
+    public static final int REASON_PRE_BOOT_COMPLETED = 104;
+
+    /**
+     * Broadcast ACTION_LOCKED_BOOT_COMPLETED.
+     * @hide
+     */
+    public static final int REASON_LOCKED_BOOT_COMPLETED = 105;
+    /**
+     * Device idle system allowlist, including EXCEPT-IDLE
+     * @hide
+     */
+    public static final int REASON_SYSTEM_ALLOW_LISTED  = 106;
+    /** @hide */
+    public static final int REASON_ALARM_MANAGER_ALARM_CLOCK = 107;
+    /**
+     * AlarmManagerService.
+     * @hide
+     */
+    public static final int REASON_ALARM_MANAGER_WHILE_IDLE = 108;
+    /**
+     * ActiveServices.
+     * @hide
+     */
+    public static final int REASON_SERVICE_LAUNCH = 109;
+    /**
+     * KeyChainSystemService.
+     * @hide
+     */
+    public static final int REASON_KEY_CHAIN = 110;
+    /**
+     * PackageManagerService.
+     * @hide
+     */
+    public static final int REASON_PACKAGE_VERIFIER = 111;
+    /**
+     * SyncManager.
+     * @hide
+     */
+    public static final int REASON_SYNC_MANAGER = 112;
+    /**
+     * DomainVerificationProxyV1.
+     * @hide
+     */
+    public static final int REASON_DOMAIN_VERIFICATION_V1 = 113;
+    /**
+     * DomainVerificationProxyV2.
+     * @hide
+     */
+    public static final int REASON_DOMAIN_VERIFICATION_V2 = 114;
+    /** @hide */
+    public static final int REASON_VPN = 115;
+    /**
+     * NotificationManagerService.
+     * @hide
+     */
+    public static final int REASON_NOTIFICATION_SERVICE = 116;
+    /**
+     * Broadcast ACTION_MY_PACKAGE_REPLACED.
+     * @hide
+     */
+    public static final int REASON_PACKAGE_REPLACED = 117;
+    /**
+     * LocationProviderManager.
+     * @hide
+     */
+    public static final int REASON_LOCATION_PROVIDER = 118;
+    /**
+     * MediaButtonReceiver.
+     * @hide
+     */
+    public static final int REASON_MEDIA_BUTTON = 119;
+    /**
+     * InboundSmsHandler.
+     * @hide
+     */
+    public static final int REASON_EVENT_SMS = 120;
+    /**
+     * InboundSmsHandler.
+     * @hide
+     */
+    public static final int REASON_EVENT_MMS = 121;
+    /**
+     * Shell app.
+     * @hide
+     */
+    public static final int REASON_SHELL = 122;
+
+    /**
+     * The list of BG-FGS-Launch and temp-allowlist reason code.
+     * @hide
+     */
+    @IntDef(flag = true, prefix = { "REASON_" }, value = {
+            // BG-FGS-Launch reasons.
+            REASON_DENIED,
+            REASON_UNKNOWN,
+            REASON_OTHER,
+            REASON_PROC_STATE_PERSISTENT,
+            REASON_PROC_STATE_PERSISTENT_UI,
+            REASON_PROC_STATE_TOP,
+            REASON_PROC_STATE_BTOP,
+            REASON_PROC_STATE_FGS,
+            REASON_PROC_STATE_BFGS,
+            REASON_UID_VISIBLE,
+            REASON_SYSTEM_UID,
+            REASON_ACTIVITY_STARTER,
+            REASON_START_ACTIVITY_FLAG,
+            REASON_FGS_BINDING,
+            REASON_DEVICE_OWNER,
+            REASON_PROFILE_OWNER,
+            REASON_COMPANION_DEVICE_MANAGER,
+            REASON_BACKGROUND_ACTIVITY_PERMISSION,
+            REASON_BACKGROUND_FGS_PERMISSION,
+            REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION,
+            REASON_INSTR_BACKGROUND_FGS_PERMISSION,
+            REASON_SYSTEM_ALERT_WINDOW_PERMISSION,
+            REASON_DEVICE_DEMO_MODE,
+            REASON_EXEMPTED_PACKAGE,
+            REASON_ALLOWLISTED_PACKAGE,
+            REASON_APPOP,
+            // temp and system allowlist reasons.
+            REASON_GEOFENCING,
+            REASON_PUSH_MESSAGING,
+            REASON_ACTIVITY_RECOGNITION,
+            REASON_BOOT_COMPLETED,
+            REASON_PRE_BOOT_COMPLETED,
+            REASON_LOCKED_BOOT_COMPLETED,
+            REASON_SYSTEM_ALLOW_LISTED,
+            REASON_ALARM_MANAGER_ALARM_CLOCK,
+            REASON_ALARM_MANAGER_WHILE_IDLE,
+            REASON_SERVICE_LAUNCH,
+            REASON_KEY_CHAIN,
+            REASON_PACKAGE_VERIFIER,
+            REASON_SYNC_MANAGER,
+            REASON_DOMAIN_VERIFICATION_V1,
+            REASON_DOMAIN_VERIFICATION_V2,
+            REASON_VPN,
+            REASON_NOTIFICATION_SERVICE,
+            REASON_PACKAGE_REPLACED,
+            REASON_LOCATION_PROVIDER,
+            REASON_MEDIA_BUTTON,
+            REASON_EVENT_SMS,
+            REASON_EVENT_MMS,
+            REASON_SHELL,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ReasonCode {}
+
     /**
      * @hide
      */
@@ -184,19 +425,34 @@
      *
      * @param packageName The package to add to the temp whitelist
      * @param durationMs  How long to keep the app on the temp whitelist for (in milliseconds)
+     * @param reasonCode one of {@link ReasonCode}, use {@link #REASON_UNKNOWN} if not sure.
+     * @param reason a optional human readable reason string, could be null or empty string.
      */
     @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST)
-    public void whitelistAppTemporarily(@NonNull String packageName, long durationMs) {
-        String reason = "from:" + UserHandle.formatUid(Binder.getCallingUid());
+    public void whitelistAppTemporarily(@NonNull String packageName, long durationMs,
+            @ReasonCode int reasonCode, @Nullable String reason) {
         try {
             mService.addPowerSaveTempWhitelistApp(packageName, durationMs, mContext.getUserId(),
-                    reason);
+                    reasonCode, reason);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
     /**
+     * Add an app to the temporary whitelist for a short amount of time.
+     *
+     * @param packageName The package to add to the temp whitelist
+     * @param durationMs  How long to keep the app on the temp whitelist for (in milliseconds)
+     * @deprecated Use {@link #whitelistAppTemporarily(String, long, int, String)} instead
+     */
+    @Deprecated
+    @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST)
+    public void whitelistAppTemporarily(@NonNull String packageName, long durationMs) {
+        whitelistAppTemporarily(packageName, durationMs, REASON_UNKNOWN, packageName);
+    }
+
+    /**
      * Add an app to the temporary whitelist for a short amount of time for a specific reason. The
      * temporary whitelist is kept separately from the permanent whitelist and apps are
      * automatically removed from the temporary whitelist after a predetermined amount of time.
@@ -204,27 +460,179 @@
      * @param packageName The package to add to the temp whitelist
      * @param event       The reason to add the app to the temp whitelist
      * @param reason      A human-readable reason explaining why the app is temp whitelisted. Only
-     *                    used for logging purposes
+     *                    used for logging purposes. Could be null or empty string.
+     * @return The duration (in milliseconds) that the app is whitelisted for
+     * @deprecated Use {@link #whitelistAppTemporarilyForEvent(String, int, int, String)} instead
+     */
+    @Deprecated
+    @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST)
+    public long whitelistAppTemporarilyForEvent(@NonNull String packageName,
+            @WhitelistEvent int event, @Nullable String reason) {
+        return whitelistAppTemporarilyForEvent(packageName, event, REASON_UNKNOWN, reason);
+    }
+
+    /**
+     * Add an app to the temporary whitelist for a short amount of time for a specific reason. The
+     * temporary whitelist is kept separately from the permanent whitelist and apps are
+     * automatically removed from the temporary whitelist after a predetermined amount of time.
+     *
+     * @param packageName The package to add to the temp whitelist
+     * @param event       The reason to add the app to the temp whitelist
+     * @param reasonCode  one of {@link ReasonCode}, use {@link #REASON_UNKNOWN} if not sure.
+     * @param reason      A human-readable reason explaining why the app is temp whitelisted. Only
+     *                    used for logging purposes. Could be null or empty string.
      * @return The duration (in milliseconds) that the app is whitelisted for
      */
     @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST)
     public long whitelistAppTemporarilyForEvent(@NonNull String packageName,
-            @WhitelistEvent int event, @NonNull String reason) {
+            @WhitelistEvent int event, @ReasonCode int reasonCode, @Nullable String reason) {
         try {
             switch (event) {
                 case EVENT_MMS:
                     return mService.addPowerSaveTempWhitelistAppForMms(
-                            packageName, mContext.getUserId(), reason);
+                            packageName, mContext.getUserId(), reasonCode, reason);
                 case EVENT_SMS:
                     return mService.addPowerSaveTempWhitelistAppForSms(
-                            packageName, mContext.getUserId(), reason);
+                            packageName, mContext.getUserId(), reasonCode, reason);
                 case EVENT_UNSPECIFIED:
                 default:
                     return mService.whitelistAppTemporarily(
-                            packageName, mContext.getUserId(), reason);
+                            packageName, mContext.getUserId(), reasonCode, reason);
             }
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * @hide
+     */
+    public static @ReasonCode int getReasonCodeFromProcState(int procState) {
+        if (procState <= PROCESS_STATE_PERSISTENT) {
+            return REASON_PROC_STATE_PERSISTENT;
+        } else if (procState <= PROCESS_STATE_PERSISTENT_UI) {
+            return REASON_PROC_STATE_PERSISTENT_UI;
+        } else if (procState <= PROCESS_STATE_TOP) {
+            return REASON_PROC_STATE_TOP;
+        } else if (procState <= PROCESS_STATE_BOUND_TOP) {
+            return REASON_PROC_STATE_BTOP;
+        } else if (procState <= PROCESS_STATE_FOREGROUND_SERVICE) {
+            return REASON_PROC_STATE_FGS;
+        } else if (procState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
+            return REASON_PROC_STATE_BFGS;
+        } else {
+            return REASON_DENIED;
+        }
+    }
+
+    /**
+     * Return string name of the integer reason code.
+     * @hide
+     * @param reasonCode
+     * @return string name of the reason code.
+     */
+    public static String reasonCodeToString(@ReasonCode int reasonCode) {
+        switch (reasonCode) {
+            case REASON_DENIED:
+                return "DENIED";
+            case REASON_UNKNOWN:
+                return "UNKNOWN";
+            case REASON_OTHER:
+                return "OTHER";
+            case REASON_PROC_STATE_PERSISTENT:
+                return "PROC_STATE_PERSISTENT";
+            case REASON_PROC_STATE_PERSISTENT_UI:
+                return "PROC_STATE_PERSISTENT_UI";
+            case REASON_PROC_STATE_TOP:
+                return "PROC_STATE_TOP";
+            case REASON_PROC_STATE_BTOP:
+                return "PROC_STATE_BTOP";
+            case REASON_PROC_STATE_FGS:
+                return "PROC_STATE_FGS";
+            case REASON_PROC_STATE_BFGS:
+                return "PROC_STATE_BFGS";
+            case REASON_UID_VISIBLE:
+                return "UID_VISIBLE";
+            case REASON_SYSTEM_UID:
+                return "SYSTEM_UID";
+            case REASON_ACTIVITY_STARTER:
+                return "ACTIVITY_STARTER";
+            case REASON_START_ACTIVITY_FLAG:
+                return "START_ACTIVITY_FLAG";
+            case REASON_FGS_BINDING:
+                return "FGS_BINDING";
+            case REASON_DEVICE_OWNER:
+                return "DEVICE_OWNER";
+            case REASON_PROFILE_OWNER:
+                return "PROFILE_OWNER";
+            case REASON_COMPANION_DEVICE_MANAGER:
+                return "COMPANION_DEVICE_MANAGER";
+            case REASON_BACKGROUND_ACTIVITY_PERMISSION:
+                return "BACKGROUND_ACTIVITY_PERMISSION";
+            case REASON_BACKGROUND_FGS_PERMISSION:
+                return "BACKGROUND_FGS_PERMISSION";
+            case REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION:
+                return "INSTR_BACKGROUND_ACTIVITY_PERMISSION";
+            case REASON_INSTR_BACKGROUND_FGS_PERMISSION:
+                return "INSTR_BACKGROUND_FGS_PERMISSION";
+            case REASON_SYSTEM_ALERT_WINDOW_PERMISSION:
+                return "SYSTEM_ALERT_WINDOW_PERMISSION";
+            case REASON_DEVICE_DEMO_MODE:
+                return "DEVICE_DEMO_MODE";
+            case REASON_EXEMPTED_PACKAGE:
+                return "EXEMPTED_PACKAGE";
+            case REASON_ALLOWLISTED_PACKAGE:
+                return "ALLOWLISTED_PACKAGE";
+            case REASON_APPOP:
+                return "APPOP";
+            case REASON_GEOFENCING:
+                return "GEOFENCING";
+            case REASON_PUSH_MESSAGING:
+                return "PUSH_MESSAGING";
+            case REASON_ACTIVITY_RECOGNITION:
+                return "ACTIVITY_RECOGNITION";
+            case REASON_BOOT_COMPLETED:
+                return "BOOT_COMPLETED";
+            case REASON_PRE_BOOT_COMPLETED:
+                return "PRE_BOOT_COMPLETED";
+            case REASON_LOCKED_BOOT_COMPLETED:
+                return "LOCKED_BOOT_COMPLETED";
+            case REASON_SYSTEM_ALLOW_LISTED:
+                return "SYSTEM_ALLOW_LISTED";
+            case REASON_ALARM_MANAGER_ALARM_CLOCK:
+                return "ALARM_MANAGER_ALARM_CLOCK";
+            case REASON_ALARM_MANAGER_WHILE_IDLE:
+                return "ALARM_MANAGER_WHILE_IDLE";
+            case REASON_SERVICE_LAUNCH:
+                return "SERVICE_LAUNCH";
+            case REASON_KEY_CHAIN:
+                return "KEY_CHAIN";
+            case REASON_PACKAGE_VERIFIER:
+                return "PACKAGE_VERIFIER";
+            case REASON_SYNC_MANAGER:
+                return "SYNC_MANAGER";
+            case REASON_DOMAIN_VERIFICATION_V1:
+                return "DOMAIN_VERIFICATION_V1";
+            case REASON_DOMAIN_VERIFICATION_V2:
+                return "DOMAIN_VERIFICATION_V2";
+            case REASON_VPN:
+                return "VPN";
+            case REASON_NOTIFICATION_SERVICE:
+                return "NOTIFICATION_SERVICE";
+            case REASON_PACKAGE_REPLACED:
+                return "PACKAGE_REPLACED";
+            case REASON_LOCATION_PROVIDER:
+                return "LOCATION_PROVIDER";
+            case REASON_MEDIA_BUTTON:
+                return "MEDIA_BUTTON";
+            case REASON_EVENT_SMS:
+                return "EVENT_SMS";
+            case REASON_EVENT_MMS:
+                return "EVENT_MMS";
+            case REASON_SHELL:
+                return "SHELL";
+            default:
+                return  "(unknown:" + reasonCode + ")";
+        }
+    }
 }
diff --git a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java
index e045b0f..5e5717d11 100644
--- a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java
+++ b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java
@@ -16,6 +16,8 @@
 
 package com.android.server;
 
+import android.annotation.Nullable;
+import android.os.PowerWhitelistManager.ReasonCode;
 import android.os.PowerWhitelistManager.TempAllowListType;
 
 import com.android.server.deviceidle.IDeviceIdleConstraint;
@@ -34,6 +36,10 @@
     void addPowerSaveTempWhitelistApp(int callingUid, String packageName,
             long duration, int userId, boolean sync, String reason);
 
+    void addPowerSaveTempWhitelistApp(int callingUid, String packageName,
+            long duration, int userId, boolean sync, @ReasonCode int reasonCode,
+            @Nullable String reason);
+
     /**
      * Called by ActivityManagerService to directly add UID to DeviceIdleController's temp
      * allowlist.
@@ -41,11 +47,12 @@
      * @param duration duration in milliseconds
      * @param type temp allowlist type defined at {@link TempAllowListType}
      * @param sync
+     * @param reasonCode one of {@link ReasonCode}
      * @param reason
      */
     void addPowerSaveTempWhitelistAppDirect(int uid, long duration,
-            @TempAllowListType int type, boolean sync,
-            String reason);
+            @TempAllowListType int type, boolean sync, @ReasonCode int reasonCode,
+            @Nullable String reason);
 
     // duration in milliseconds
     long getNotificationAllowlistDuration();
diff --git a/apex/jobscheduler/service/Android.bp b/apex/jobscheduler/service/Android.bp
index 35bd317..a4a0b4b 100644
--- a/apex/jobscheduler/service/Android.bp
+++ b/apex/jobscheduler/service/Android.bp
@@ -1,5 +1,14 @@
 // Job Scheduler Service jar, which will eventually be put in the jobscheduler mainline apex.
 // service-jobscheduler needs to be added to PRODUCT_SYSTEM_SERVER_JARS.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library {
     name: "service-jobscheduler",
     installable: true,
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 8f7f705..ac28e82 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -16,12 +16,17 @@
 
 package com.android.server;
 
+import static android.os.PowerWhitelistManager.REASON_SHELL;
+import static android.os.PowerWhitelistManager.REASON_UNKNOWN;
+import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+import static android.os.Process.INVALID_UID;
+
 import android.Manifest;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
 import android.app.AlarmManager;
-import android.app.BroadcastOptions;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -56,6 +61,7 @@
 import android.os.PowerManager;
 import android.os.PowerManager.ServiceType;
 import android.os.PowerManagerInternal;
+import android.os.PowerWhitelistManager.ReasonCode;
 import android.os.PowerWhitelistManager.TempAllowListType;
 import android.os.Process;
 import android.os.RemoteException;
@@ -1838,31 +1844,34 @@
         }
 
         @Override
-        public long whitelistAppTemporarily(String packageName, int userId, String reason)
-                throws RemoteException {
+        public long whitelistAppTemporarily(String packageName, int userId,
+                @ReasonCode int reasonCode, @Nullable String reason) throws RemoteException {
             // At least 10 seconds.
             long durationMs = Math.max(10_000L, mConstants.MAX_TEMP_APP_ALLOWLIST_DURATION_MS / 2);
-            addPowerSaveTempAllowlistAppChecked(packageName, durationMs, userId, reason);
+            addPowerSaveTempAllowlistAppChecked(packageName, durationMs, userId, reasonCode,
+                    reason);
             return durationMs;
         }
 
         @Override
-        public void addPowerSaveTempWhitelistApp(String packageName, long duration,
-                int userId, String reason) throws RemoteException {
-            addPowerSaveTempAllowlistAppChecked(packageName, duration, userId, reason);
+        public void addPowerSaveTempWhitelistApp(String packageName, long duration, int userId,
+                @ReasonCode int reasonCode, @Nullable String reason) throws RemoteException {
+            addPowerSaveTempAllowlistAppChecked(packageName, duration, userId, reasonCode, reason);
         }
 
-        @Override public long addPowerSaveTempWhitelistAppForMms(String packageName,
-                int userId, String reason) throws RemoteException {
+        @Override public long addPowerSaveTempWhitelistAppForMms(String packageName, int userId,
+                @ReasonCode int reasonCode, @Nullable String reason) throws RemoteException {
             long durationMs = mConstants.MMS_TEMP_APP_ALLOWLIST_DURATION_MS;
-            addPowerSaveTempAllowlistAppChecked(packageName, durationMs, userId, reason);
+            addPowerSaveTempAllowlistAppChecked(packageName, durationMs, userId, reasonCode,
+                    reason);
             return durationMs;
         }
 
-        @Override public long addPowerSaveTempWhitelistAppForSms(String packageName,
-                int userId, String reason) throws RemoteException {
+        @Override public long addPowerSaveTempWhitelistAppForSms(String packageName, int userId,
+                @ReasonCode int reasonCode, @Nullable String reason) throws RemoteException {
             long durationMs = mConstants.SMS_TEMP_APP_ALLOWLIST_DURATION_MS;
-            addPowerSaveTempAllowlistAppChecked(packageName, durationMs, userId, reason);
+            addPowerSaveTempAllowlistAppChecked(packageName, durationMs, userId, reasonCode,
+                    reason);
             return durationMs;
         }
 
@@ -1934,18 +1943,29 @@
         }
 
         // duration in milliseconds
+        @Deprecated
         @Override
         public void addPowerSaveTempWhitelistApp(int callingUid, String packageName,
-                long duration, int userId, boolean sync, String reason) {
+                long duration, int userId, boolean sync, @Nullable String reason) {
             addPowerSaveTempAllowlistAppInternal(callingUid, packageName, duration,
-                    userId, sync, reason);
+                    userId, sync, REASON_UNKNOWN, reason);
+        }
+
+        @Override
+        public void addPowerSaveTempWhitelistApp(int callingUid, String packageName,
+                long duration, int userId, boolean sync, @ReasonCode int reasonCode,
+                @Nullable String reason) {
+            addPowerSaveTempAllowlistAppInternal(callingUid, packageName, duration,
+                    userId, sync, reasonCode, reason);
         }
 
         // duration in milliseconds
         @Override
         public void addPowerSaveTempWhitelistAppDirect(int uid, long duration,
-                @TempAllowListType int type, boolean sync, String reason) {
-            addPowerSaveTempWhitelistAppDirectInternal(0, uid, duration, type, sync, reason);
+                @TempAllowListType int type, boolean sync, @ReasonCode int reasonCode,
+                @Nullable String reason) {
+            addPowerSaveTempWhitelistAppDirectInternal(0, uid, duration, type, sync,
+                    reasonCode, reason);
         }
 
         // duration in milliseconds
@@ -2293,7 +2313,7 @@
                 filter.addAction(Intent.ACTION_SCREEN_ON);
                 getContext().registerReceiver(mInteractivityReceiver, filter);
 
-                mLocalActivityManager.setDeviceIdleWhitelist(
+                mLocalActivityManager.setDeviceIdleAllowlist(
                         mPowerSaveWhitelistAllAppIdArray, mPowerSaveWhitelistExceptIdleAppIdArray);
                 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
 
@@ -2671,7 +2691,8 @@
     }
 
     void addPowerSaveTempAllowlistAppChecked(String packageName, long duration,
-            int userId, String reason) throws RemoteException {
+            int userId, @ReasonCode int reasonCode, @Nullable String reason)
+            throws RemoteException {
         getContext().enforceCallingPermission(
                 Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
                 "No permission to change device idle whitelist");
@@ -2686,7 +2707,7 @@
         final long token = Binder.clearCallingIdentity();
         try {
             addPowerSaveTempAllowlistAppInternal(callingUid,
-                    packageName, duration, userId, true, reason);
+                    packageName, duration, userId, true, reasonCode, reason);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -2718,12 +2739,12 @@
      * app an exemption to access network and acquire wakelocks.
      */
     void addPowerSaveTempAllowlistAppInternal(int callingUid, String packageName,
-            long duration, int userId, boolean sync, String reason) {
+            long duration, int userId, boolean sync, @ReasonCode int reasonCode,
+            @Nullable String reason) {
         try {
             int uid = getContext().getPackageManager().getPackageUidAsUser(packageName, userId);
             addPowerSaveTempWhitelistAppDirectInternal(callingUid, uid, duration,
-                    BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED, sync,
-                    reason);
+                    TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, sync, reasonCode, reason);
         } catch (NameNotFoundException e) {
         }
     }
@@ -2733,7 +2754,8 @@
      * app an exemption to access network and acquire wakelocks.
      */
     void addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int uid,
-            long duration, @TempAllowListType int type, boolean sync, String reason) {
+            long duration, @TempAllowListType int type, boolean sync, @ReasonCode int reasonCode,
+            @Nullable String reason) {
         final long timeNow = SystemClock.elapsedRealtime();
         boolean informWhitelistChanged = false;
         int appId = UserHandle.getAppId(uid);
@@ -2765,7 +2787,8 @@
                 } catch (RemoteException e) {
                 }
                 postTempActiveTimeoutMessage(uid, duration);
-                updateTempWhitelistAppIdsLocked(uid, true, duration, type);
+                updateTempWhitelistAppIdsLocked(uid, true, duration, type, reasonCode,
+                        reason, callingUid);
                 if (sync) {
                     informWhitelistChanged = true;
                 } else {
@@ -2844,12 +2867,13 @@
     }
 
     @GuardedBy("this")
-    private void onAppRemovedFromTempWhitelistLocked(int uid, String reason) {
+    private void onAppRemovedFromTempWhitelistLocked(int uid, @Nullable String reason) {
         if (DEBUG) {
             Slog.d(TAG, "Removing uid " + uid + " from temp whitelist");
         }
         final int appId = UserHandle.getAppId(uid);
-        updateTempWhitelistAppIdsLocked(uid, false, 0, 0);
+        updateTempWhitelistAppIdsLocked(uid, false, 0, 0, REASON_UNKNOWN,
+                reason, INVALID_UID);
         mHandler.obtainMessage(MSG_REPORT_TEMP_APP_WHITELIST_CHANGED_TO_NPMS, appId, 0)
                 .sendToTarget();
         reportTempWhitelistChangedLocked(uid, false);
@@ -3860,7 +3884,7 @@
         mPowerSaveWhitelistUserAppIdArray = buildAppIdArray(null,
                 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistUserAppIds);
         if (mLocalActivityManager != null) {
-            mLocalActivityManager.setDeviceIdleWhitelist(
+            mLocalActivityManager.setDeviceIdleAllowlist(
                     mPowerSaveWhitelistAllAppIdArray, mPowerSaveWhitelistExceptIdleAppIdArray);
         }
         if (mLocalPowerManager != null) {
@@ -3880,9 +3904,14 @@
      * @param durationMs duration in milliseconds to add to temp allowlist, only valid when
      *                   param adding is true.
      * @param type temp allowlist type defined at {@link TempAllowListType}
+     * @prama reasonCode one of {@Link ReasonCode}
+     * @param reason A human-readable reason for logging purposes.
+     * @param callingUid the callingUid that setup this temp-allowlist, only valid when param adding
+     *                   is true.
      */
     private void updateTempWhitelistAppIdsLocked(int uid, boolean adding, long durationMs,
-            @TempAllowListType int type) {
+            @TempAllowListType int type, @ReasonCode int reasonCode, @Nullable String reason,
+            int callingUid) {
         final int size = mTempWhitelistAppIdEndTimes.size();
         if (mTempWhitelistAppIdArray.length != size) {
             mTempWhitelistAppIdArray = new int[size];
@@ -3895,8 +3924,8 @@
                 Slog.d(TAG, "Setting activity manager temp whitelist to "
                         + Arrays.toString(mTempWhitelistAppIdArray));
             }
-            mLocalActivityManager.updateDeviceIdleTempWhitelist(mTempWhitelistAppIdArray, uid,
-                    adding, durationMs, type);
+            mLocalActivityManager.updateDeviceIdleTempAllowlist(mTempWhitelistAppIdArray, uid,
+                    adding, durationMs, type, reasonCode, reason, callingUid);
         }
         if (mLocalPowerManager != null) {
             if (DEBUG) {
@@ -4428,7 +4457,8 @@
                     if (removePkg) {
                         removePowerSaveTempAllowlistAppChecked(arg, shell.userId);
                     } else {
-                        addPowerSaveTempAllowlistAppChecked(arg, duration, shell.userId, "shell");
+                        addPowerSaveTempAllowlistAppChecked(arg, duration, shell.userId,
+                                REASON_SHELL, "shell");
                     }
                 } catch (Exception e) {
                     pw.println("Failed: " + e);
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java b/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java
index 657c368..3bc7b30 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java
@@ -26,6 +26,7 @@
 import android.app.AlarmManager;
 import android.app.IAlarmListener;
 import android.app.PendingIntent;
+import android.os.Bundle;
 import android.os.WorkSource;
 import android.util.IndentingPrintWriter;
 import android.util.TimeUtils;
@@ -92,10 +93,12 @@
     private long mWhenElapsed;
     private long mMaxWhenElapsed;
     public AlarmManagerService.PriorityClass priorityClass;
+    /** Broadcast options to use when delivering this alarm */
+    public Bundle mIdleOptions;
 
     Alarm(int type, long when, long requestedWhenElapsed, long windowLength, long interval,
             PendingIntent op, IAlarmListener rec, String listenerTag, WorkSource ws, int flags,
-            AlarmManager.AlarmClockInfo info, int uid, String pkgName) {
+            AlarmManager.AlarmClockInfo info, int uid, String pkgName, Bundle idleOptions) {
         this.type = type;
         origWhen = when;
         wakeup = type == AlarmManager.ELAPSED_REALTIME_WAKEUP
@@ -115,6 +118,7 @@
         alarmClock = info;
         this.uid = uid;
         packageName = pkgName;
+        mIdleOptions = idleOptions;
         sourcePackage = (operation != null) ? operation.getCreatorPackage() : packageName;
         creatorUid = (operation != null) ? operation.getCreatorUid() : this.uid;
     }
@@ -303,6 +307,10 @@
             ipw.print("listener=");
             ipw.println(listener.asBinder());
         }
+        if (mIdleOptions != null) {
+            ipw.print("idle-options=");
+            ipw.println(mIdleOptions.toString());
+        }
     }
 
     public void dumpDebug(ProtoOutputStream proto, long fieldId, long nowElapsed) {
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index f6a1b8a..2b2918c 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -20,11 +20,17 @@
 import static android.app.AlarmManager.ELAPSED_REALTIME;
 import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
 import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE;
+import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE_COMPAT;
 import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
 import static android.app.AlarmManager.FLAG_IDLE_UNTIL;
+import static android.app.AlarmManager.FLAG_WAKE_FROM_IDLE;
+import static android.app.AlarmManager.INTERVAL_HOUR;
 import static android.app.AlarmManager.RTC;
 import static android.app.AlarmManager.RTC_WAKEUP;
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
+import static android.os.PowerWhitelistManager.REASON_ALARM_MANAGER_WHILE_IDLE;
+import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED;
 import static android.os.UserHandle.USER_SYSTEM;
 
 import static com.android.server.alarm.Alarm.APP_STANDBY_POLICY_INDEX;
@@ -32,6 +38,7 @@
 import static com.android.server.alarm.Alarm.DEVICE_IDLE_POLICY_INDEX;
 import static com.android.server.alarm.Alarm.REQUESTER_POLICY_INDEX;
 
+import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
 import android.app.Activity;
@@ -43,12 +50,14 @@
 import android.app.IAlarmListener;
 import android.app.IAlarmManager;
 import android.app.PendingIntent;
+import android.app.compat.CompatChanges;
 import android.app.usage.UsageStatsManager;
 import android.app.usage.UsageStatsManagerInternal;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.PermissionChecker;
 import android.content.pm.PackageManagerInternal;
 import android.net.Uri;
 import android.os.BatteryManager;
@@ -65,6 +74,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
+import android.os.ServiceManager;
 import android.os.ShellCallback;
 import android.os.ShellCommand;
 import android.os.SystemClock;
@@ -95,6 +105,8 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.IAppOpsCallback;
+import com.android.internal.app.IAppOpsService;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.util.LocalLog;
@@ -177,6 +189,7 @@
     final LocalLog mLog = new LocalLog(TAG);
 
     AppOpsManager mAppOps;
+    IAppOpsService mAppOpsService;
     DeviceIdleInternal mLocalDeviceIdleController;
     private UsageStatsManagerInternal mUsageStatsManagerInternal;
     private ActivityManagerInternal mActivityManagerInternal;
@@ -253,10 +266,8 @@
             "REORDER_ALARMS_FOR_STANDBY",
     });
 
-    /**
-     * Broadcast options to use for FLAG_ALLOW_WHILE_IDLE.
-     */
-    Bundle mIdleOptions;
+    BroadcastOptions mOptsWithFgs = BroadcastOptions.makeBasic();
+    BroadcastOptions mOptsWithoutFgs = BroadcastOptions.makeBasic();
 
     // TODO(b/172085676): Move inside alarm store.
     private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser =
@@ -410,6 +421,12 @@
         @VisibleForTesting
         static final String KEY_ALLOW_WHILE_IDLE_QUOTA = "allow_while_idle_quota";
 
+        @VisibleForTesting
+        static final String KEY_ALLOW_WHILE_IDLE_COMPAT_QUOTA = "allow_while_idle_compat_quota";
+        private static final String KEY_ALLOW_WHILE_IDLE_WINDOW = "allow_while_idle_window";
+
+        private static final String KEY_CRASH_NON_CLOCK_APPS = "crash_non_clock_apps";
+
         private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
         private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
         private static final long DEFAULT_MAX_INTERVAL = 365 * DateUtils.DAY_IN_MILLIS;
@@ -433,8 +450,16 @@
         private static final boolean DEFAULT_LAZY_BATCHING = true;
         private static final boolean DEFAULT_TIME_TICK_ALLOWED_WHILE_IDLE = true;
 
-        private static final int DEFAULT_ALLOW_WHILE_IDLE_QUOTA = 7;
-        public static final long ALLOW_WHILE_IDLE_WINDOW = 60 * 60 * 1000; // 1 hour.
+        /**
+         * Default quota for pre-S apps. Enough to accommodate the existing policy of an alarm
+         * every ALLOW_WHILE_IDLE_LONG_DELAY, which was 9 minutes.
+         */
+        private static final int DEFAULT_ALLOW_WHILE_IDLE_COMPAT_QUOTA = 7;
+        private static final int DEFAULT_ALLOW_WHILE_IDLE_QUOTA = 72;
+
+        private static final long DEFAULT_ALLOW_WHILE_IDLE_WINDOW = 60 * 60 * 1000; // 1 hour.
+        // TODO (b/171306433): Change to true by default.
+        private static final boolean DEFAULT_CRASH_NON_CLOCK_APPS = false;
 
         // Minimum futurity of a new alarm
         public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;
@@ -463,6 +488,26 @@
 
         public int ALLOW_WHILE_IDLE_QUOTA = DEFAULT_ALLOW_WHILE_IDLE_QUOTA;
 
+        /**
+         * Used to provide backwards compatibility to pre-S apps with a quota equivalent to the
+         * earlier delay throttling mechanism.
+         */
+        public int ALLOW_WHILE_IDLE_COMPAT_QUOTA = DEFAULT_ALLOW_WHILE_IDLE_COMPAT_QUOTA;
+
+        /**
+         * The window used for enforcing {@link #ALLOW_WHILE_IDLE_QUOTA} and
+         * {@link #ALLOW_WHILE_IDLE_COMPAT_QUOTA}. Can be configured, but only recommended for
+         * testing.
+         */
+        public long ALLOW_WHILE_IDLE_WINDOW = DEFAULT_ALLOW_WHILE_IDLE_WINDOW;
+
+        /**
+         * Whether or not to crash callers that use setExactAndAllowWhileIdle or setAlarmClock
+         * but don't hold the required permission. This is useful to catch broken
+         * apps and reverting to a softer failure in case of broken apps.
+         */
+        public boolean CRASH_NON_CLOCK_APPS = DEFAULT_CRASH_NON_CLOCK_APPS;
+
         private long mLastAllowWhileIdleWhitelistDuration = -1;
 
         Constants() {
@@ -480,9 +525,13 @@
         public void updateAllowWhileIdleWhitelistDurationLocked() {
             if (mLastAllowWhileIdleWhitelistDuration != ALLOW_WHILE_IDLE_WHITELIST_DURATION) {
                 mLastAllowWhileIdleWhitelistDuration = ALLOW_WHILE_IDLE_WHITELIST_DURATION;
-                BroadcastOptions opts = BroadcastOptions.makeBasic();
-                opts.setTemporaryAppWhitelistDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION);
-                mIdleOptions = opts.toBundle();
+
+                mOptsWithFgs.setTemporaryAppAllowlist(ALLOW_WHILE_IDLE_WHITELIST_DURATION,
+                        TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+                        REASON_ALARM_MANAGER_WHILE_IDLE, "");
+                mOptsWithoutFgs.setTemporaryAppAllowlist(ALLOW_WHILE_IDLE_WHITELIST_DURATION,
+                        TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED,
+                        REASON_ALARM_MANAGER_WHILE_IDLE, "");
             }
         }
 
@@ -516,6 +565,27 @@
                                 ALLOW_WHILE_IDLE_QUOTA = 1;
                             }
                             break;
+                        case KEY_ALLOW_WHILE_IDLE_COMPAT_QUOTA:
+                            ALLOW_WHILE_IDLE_COMPAT_QUOTA = properties.getInt(
+                                    KEY_ALLOW_WHILE_IDLE_COMPAT_QUOTA,
+                                    DEFAULT_ALLOW_WHILE_IDLE_COMPAT_QUOTA);
+                            if (ALLOW_WHILE_IDLE_COMPAT_QUOTA <= 0) {
+                                Slog.w(TAG, "Cannot have quota lower than 1.");
+                                ALLOW_WHILE_IDLE_COMPAT_QUOTA = 1;
+                            }
+                            break;
+                        case KEY_ALLOW_WHILE_IDLE_WINDOW:
+                            ALLOW_WHILE_IDLE_WINDOW = properties.getLong(
+                                    KEY_ALLOW_WHILE_IDLE_WINDOW, DEFAULT_ALLOW_WHILE_IDLE_WINDOW);
+                            if (ALLOW_WHILE_IDLE_WINDOW > DEFAULT_ALLOW_WHILE_IDLE_WINDOW) {
+                                Slog.w(TAG, "Cannot have allow_while_idle_window > "
+                                        + DEFAULT_ALLOW_WHILE_IDLE_WINDOW);
+                                ALLOW_WHILE_IDLE_WINDOW = DEFAULT_ALLOW_WHILE_IDLE_WINDOW;
+                            } else if (ALLOW_WHILE_IDLE_WINDOW < DEFAULT_ALLOW_WHILE_IDLE_WINDOW) {
+                                Slog.w(TAG, "Using a non-default allow_while_idle_window = "
+                                        + ALLOW_WHILE_IDLE_WINDOW);
+                            }
+                            break;
                         case KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION:
                             ALLOW_WHILE_IDLE_WHITELIST_DURATION = properties.getLong(
                                     KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION,
@@ -552,6 +622,10 @@
                                     KEY_TIME_TICK_ALLOWED_WHILE_IDLE,
                                     DEFAULT_TIME_TICK_ALLOWED_WHILE_IDLE);
                             break;
+                        case KEY_CRASH_NON_CLOCK_APPS:
+                            CRASH_NON_CLOCK_APPS = properties.getBoolean(KEY_CRASH_NON_CLOCK_APPS,
+                                    DEFAULT_CRASH_NON_CLOCK_APPS);
+                            break;
                         default:
                             if (name.startsWith(KEY_PREFIX_STANDBY_QUOTA) && !standbyQuotaUpdated) {
                                 // The quotas need to be updated in order, so we can't just rely
@@ -643,10 +717,14 @@
             TimeUtils.formatDuration(LISTENER_TIMEOUT, pw);
             pw.println();
 
-            pw.print("allow_while_idle_window=");
+            pw.print(KEY_ALLOW_WHILE_IDLE_WINDOW);
+            pw.print("=");
             TimeUtils.formatDuration(ALLOW_WHILE_IDLE_WINDOW, pw);
             pw.println();
 
+            pw.print(KEY_ALLOW_WHILE_IDLE_COMPAT_QUOTA, ALLOW_WHILE_IDLE_COMPAT_QUOTA);
+            pw.println();
+
             pw.print(KEY_ALLOW_WHILE_IDLE_QUOTA, ALLOW_WHILE_IDLE_QUOTA);
             pw.println();
 
@@ -682,6 +760,9 @@
             pw.print(KEY_TIME_TICK_ALLOWED_WHILE_IDLE, TIME_TICK_ALLOWED_WHILE_IDLE);
             pw.println();
 
+            pw.print(KEY_CRASH_NON_CLOCK_APPS, CRASH_NON_CLOCK_APPS);
+            pw.println();
+
             pw.decreaseIndent();
         }
 
@@ -830,7 +911,15 @@
         if (futurity < MIN_FUZZABLE_INTERVAL) {
             futurity = 0;
         }
-        return clampPositive(triggerAtTime + (long) (.75 * futurity));
+        long maxElapsed = triggerAtTime + (long) (0.75 * futurity);
+        // For non-repeating alarms, window is capped at a maximum of one hour from the requested
+        // delivery time. This allows for inexact-while-idle alarms to be slightly more reliable.
+        // In practice, the delivery window should generally be much smaller than that
+        // when the device is not idling.
+        if (interval == 0) {
+            maxElapsed = Math.min(maxElapsed, triggerAtTime + INTERVAL_HOUR);
+        }
+        return clampPositive(maxElapsed);
     }
 
     // The RTC clock has moved arbitrarily, so we need to recalculate all the RTC alarm deliveries.
@@ -998,7 +1087,7 @@
                 setImplLocked(alarm.type, alarm.origWhen + delta, nextElapsed,
                         nextMaxElapsed - nextElapsed, alarm.repeatInterval, alarm.operation, null,
                         null, alarm.flags, alarm.workSource, alarm.alarmClock, alarm.uid,
-                        alarm.packageName);
+                        alarm.packageName, null);
                 // Kernel alarms will be rescheduled as needed in setImplLocked
             }
         }
@@ -1241,7 +1330,8 @@
             mAlarmStore.setAlarmClockRemovalListener(mAlarmClockUpdater);
 
             mAppWakeupHistory = new AppWakeupHistory(Constants.DEFAULT_APP_STANDBY_WINDOW);
-            mAllowWhileIdleHistory = new AppWakeupHistory(Constants.ALLOW_WHILE_IDLE_WINDOW);
+            mAllowWhileIdleHistory = new AppWakeupHistory(
+                    Constants.DEFAULT_ALLOW_WHILE_IDLE_WINDOW);
 
             mNextWakeup = mNextNonWakeup = 0;
 
@@ -1327,6 +1417,28 @@
             synchronized (mLock) {
                 mConstants.start();
                 mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
+                mAppOpsService = mInjector.getAppOpsService();
+                try {
+                    mAppOpsService.startWatchingMode(AppOpsManager.OP_SCHEDULE_EXACT_ALARM, null,
+                            new IAppOpsCallback.Stub() {
+                                @Override
+                                public void opChanged(int op, int uid, String packageName)
+                                        throws RemoteException {
+                                    if (op != AppOpsManager.OP_SCHEDULE_EXACT_ALARM) {
+                                        return;
+                                    }
+                                    final int mode = mAppOpsService.checkOperation(op, uid,
+                                            packageName);
+                                    if (mode != AppOpsManager.MODE_ALLOWED
+                                            && mode != AppOpsManager.MODE_DEFAULT) {
+                                        mHandler.obtainMessage(AlarmHandler.REMOVE_EXACT_ALARMS,
+                                                uid, 0, packageName).sendToTarget();
+                                    }
+                                }
+                            });
+                } catch (RemoteException e) {
+                }
+
                 mLocalDeviceIdleController =
                         LocalServices.getService(DeviceIdleInternal.class);
                 mUsageStatsManagerInternal =
@@ -1428,7 +1540,7 @@
     void setImpl(int type, long triggerAtTime, long windowLength, long interval,
             PendingIntent operation, IAlarmListener directReceiver, String listenerTag,
             int flags, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock,
-            int callingUid, String callingPackage) {
+            int callingUid, String callingPackage, Bundle idleOptions) {
         if ((operation == null && directReceiver == null)
                 || (operation != null && directReceiver != null)) {
             Slog.w(TAG, "Alarms must either supply a PendingIntent or an AlarmReceiver");
@@ -1519,17 +1631,18 @@
             }
             setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, interval, operation,
                     directReceiver, listenerTag, flags, workSource, alarmClock, callingUid,
-                    callingPackage);
+                    callingPackage, idleOptions);
         }
     }
 
     private void setImplLocked(int type, long when, long whenElapsed, long windowLength,
             long interval, PendingIntent operation, IAlarmListener directReceiver,
             String listenerTag, int flags, WorkSource workSource,
-            AlarmManager.AlarmClockInfo alarmClock, int callingUid, String callingPackage) {
+            AlarmManager.AlarmClockInfo alarmClock, int callingUid, String callingPackage,
+            Bundle idleOptions) {
         final Alarm a = new Alarm(type, when, whenElapsed, windowLength, interval,
                 operation, directReceiver, listenerTag, workSource, flags, alarmClock,
-                callingUid, callingPackage);
+                callingUid, callingPackage, idleOptions);
         if (mActivityManagerInternal.isAppStartModeDisabled(callingUid, callingPackage)) {
             Slog.w(TAG, "Not setting alarm from " + callingUid + ":" + a
                     + " -- package not allowed to start");
@@ -1605,19 +1718,21 @@
             return false;
         }
 
-        if (!(mAppStateTracker != null && mAppStateTracker.areAlarmsRestrictedByBatterySaver(
-                alarm.creatorUid, alarm.sourcePackage))) {
+        if (mAppStateTracker == null || !mAppStateTracker.areAlarmsRestrictedByBatterySaver(
+                alarm.creatorUid, alarm.sourcePackage)) {
             return alarm.setPolicyElapsed(BATTERY_SAVER_POLICY_INDEX, nowElapsed);
         }
 
         final long batterySaverPolicyElapsed;
-        if ((alarm.flags & (AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED)) != 0) {
+        if ((alarm.flags & (FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED)) != 0) {
             // Unrestricted.
             batterySaverPolicyElapsed = nowElapsed;
-        } else if ((alarm.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
+        } else if (isAllowedWhileIdleRestricted(alarm)) {
             // Allowed but limited.
             final int userId = UserHandle.getUserId(alarm.creatorUid);
-            final int quota = mConstants.ALLOW_WHILE_IDLE_QUOTA;
+            final int quota = ((alarm.flags & FLAG_ALLOW_WHILE_IDLE) != 0)
+                    ? mConstants.ALLOW_WHILE_IDLE_QUOTA
+                    : mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA;
             final int dispatchesInWindow = mAllowWhileIdleHistory.getTotalWakeupsInWindow(
                     alarm.sourcePackage, userId);
             if (dispatchesInWindow < quota) {
@@ -1625,7 +1740,7 @@
                 batterySaverPolicyElapsed = nowElapsed;
             } else {
                 batterySaverPolicyElapsed = mAllowWhileIdleHistory.getNthLastWakeupForPackage(
-                        alarm.sourcePackage, userId, quota) + Constants.ALLOW_WHILE_IDLE_WINDOW;
+                        alarm.sourcePackage, userId, quota) + mConstants.ALLOW_WHILE_IDLE_WINDOW;
             }
         } else {
             // Not allowed.
@@ -1635,6 +1750,16 @@
     }
 
     /**
+     * Returns {@code true} if the given alarm has the flag
+     * {@link AlarmManager#FLAG_ALLOW_WHILE_IDLE} or
+     * {@link AlarmManager#FLAG_ALLOW_WHILE_IDLE_COMPAT}
+     *
+     */
+    private static boolean isAllowedWhileIdleRestricted(Alarm a) {
+        return (a.flags & (FLAG_ALLOW_WHILE_IDLE | FLAG_ALLOW_WHILE_IDLE_COMPAT)) != 0;
+    }
+
+    /**
      * Adjusts the delivery time of the alarm based on device_idle (doze) rules.
      *
      * @param alarm The alarm to adjust
@@ -1647,14 +1772,15 @@
         }
 
         final long deviceIdlePolicyTime;
-        if ((alarm.flags & (AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED
-                | AlarmManager.FLAG_WAKE_FROM_IDLE)) != 0) {
+        if ((alarm.flags & (FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED | FLAG_WAKE_FROM_IDLE)) != 0) {
             // Unrestricted.
             deviceIdlePolicyTime = nowElapsed;
-        } else if ((alarm.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
+        } else if (isAllowedWhileIdleRestricted(alarm)) {
             // Allowed but limited.
             final int userId = UserHandle.getUserId(alarm.creatorUid);
-            final int quota = mConstants.ALLOW_WHILE_IDLE_QUOTA;
+            final int quota = ((alarm.flags & FLAG_ALLOW_WHILE_IDLE) != 0)
+                    ? mConstants.ALLOW_WHILE_IDLE_QUOTA
+                    : mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA;
             final int dispatchesInWindow = mAllowWhileIdleHistory.getTotalWakeupsInWindow(
                     alarm.sourcePackage, userId);
             if (dispatchesInWindow < quota) {
@@ -1662,7 +1788,7 @@
                 deviceIdlePolicyTime = nowElapsed;
             } else {
                 final long whenInQuota = mAllowWhileIdleHistory.getNthLastWakeupForPackage(
-                        alarm.sourcePackage, userId, quota) + Constants.ALLOW_WHILE_IDLE_WINDOW;
+                        alarm.sourcePackage, userId, quota) + mConstants.ALLOW_WHILE_IDLE_WINDOW;
                 deviceIdlePolicyTime = Math.min(whenInQuota, mPendingIdleUntil.getWhenElapsed());
             }
         } else {
@@ -1749,7 +1875,7 @@
         } else if (mPendingIdleUntil != null) {
             adjustDeliveryTimeBasedOnDeviceIdle(a);
         }
-        if ((a.flags & AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
+        if ((a.flags & FLAG_WAKE_FROM_IDLE) != 0) {
             if (mNextWakeFromIdle == null || mNextWakeFromIdle.getWhenElapsed()
                     > a.getWhenElapsed()) {
                 mNextWakeFromIdle = a;
@@ -1810,6 +1936,15 @@
     }
 
     /**
+     * Returns true if the given uid does not require SCHEDULE_EXACT_ALARM to set exact,
+     * allow-while-idle alarms.
+     */
+    boolean isExemptFromPermission(int uid) {
+        return (UserHandle.isSameApp(mSystemUiUid, uid) || mLocalDeviceIdleController == null
+                || mLocalDeviceIdleController.isAppOnWhitelist(UserHandle.getAppId(uid)));
+    }
+
+    /**
      * Public-facing binder interface
      */
     private final IBinder mService = new IAlarmManager.Stub() {
@@ -1824,6 +1959,60 @@
             // wakelock time spent in alarm delivery
             mAppOps.checkPackage(callingUid, callingPackage);
 
+            final boolean allowWhileIdle = (flags & FLAG_ALLOW_WHILE_IDLE) != 0;
+
+            Bundle idleOptions = null;
+            if (alarmClock != null || allowWhileIdle) {
+                // make sure the caller is allowed to use the requested kind of alarm, and also
+                // decide what broadcast options to use.
+                final boolean needsPermission;
+                boolean lowQuota;
+                if (CompatChanges.isChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION,
+                        callingPackage, UserHandle.getUserHandleForUid(callingUid))) {
+                    if (windowLength != AlarmManager.WINDOW_EXACT) {
+                        needsPermission = false;
+                        lowQuota = true;
+                        idleOptions = isExemptFromPermission(callingUid) ? mOptsWithFgs.toBundle()
+                                : mOptsWithoutFgs.toBundle();
+                    } else if (alarmClock != null) {
+                        needsPermission = true;
+                        lowQuota = false;
+                        idleOptions = mOptsWithFgs.toBundle();
+                    } else {
+                        needsPermission = true;
+                        lowQuota = false;
+                        idleOptions = mOptsWithFgs.toBundle();
+                    }
+                } else {
+                    needsPermission = false;
+                    lowQuota = allowWhileIdle;
+                    idleOptions = allowWhileIdle ? mOptsWithFgs.toBundle() : null;
+                }
+                if (needsPermission && !canScheduleExactAlarms()) {
+                    if (alarmClock == null && isExemptFromPermission(callingUid)) {
+                        // If the app is on the full system allow-list (not except-idle), we still
+                        // allow the alarms, but with a lower quota to keep pre-S compatibility.
+                        lowQuota = true;
+                    } else {
+                        final String errorMessage = "Caller " + callingPackage + " needs to hold "
+                                + Manifest.permission.SCHEDULE_EXACT_ALARM + " to set "
+                                + ((allowWhileIdle) ? "exact, allow-while-idle" : "alarm-clock")
+                                + " alarms.";
+                        if (mConstants.CRASH_NON_CLOCK_APPS) {
+                            throw new SecurityException(errorMessage);
+                        } else {
+                            Slog.wtf(TAG, errorMessage);
+                            idleOptions = mOptsWithoutFgs.toBundle();
+                            lowQuota = allowWhileIdle;
+                        }
+                    }
+                }
+                if (lowQuota) {
+                    flags &= ~FLAG_ALLOW_WHILE_IDLE;
+                    flags |= FLAG_ALLOW_WHILE_IDLE_COMPAT;
+                }
+            }
+
             // Repeating alarms must use PendingIntent, not direct listener
             if (interval != 0) {
                 if (directReceiver != null) {
@@ -1840,8 +2029,7 @@
 
             // No incoming callers can request either WAKE_FROM_IDLE or
             // ALLOW_WHILE_IDLE_UNRESTRICTED -- we will apply those later as appropriate.
-            flags &= ~(AlarmManager.FLAG_WAKE_FROM_IDLE
-                    | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED);
+            flags &= ~(FLAG_WAKE_FROM_IDLE | FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED);
 
             // Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm
             // manager when to come out of idle mode, which is only for DeviceIdleController.
@@ -1857,22 +2045,32 @@
             // If this alarm is for an alarm clock, then it must be standalone and we will
             // use it to wake early from idle if needed.
             if (alarmClock != null) {
-                flags |= AlarmManager.FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE;
+                flags |= FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE;
 
             // If the caller is a core system component or on the user's whitelist, and not calling
             // to do work on behalf of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.
             // This means we will allow these alarms to go off as normal even while idle, with no
             // timing restrictions.
-            } else if (workSource == null && (callingUid < Process.FIRST_APPLICATION_UID
+            } else if (workSource == null && (UserHandle.isCore(callingUid)
                     || UserHandle.isSameApp(callingUid, mSystemUiUid)
                     || ((mAppStateTracker != null)
                         && mAppStateTracker.isUidPowerSaveUserExempt(callingUid)))) {
-                flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
-                flags &= ~AlarmManager.FLAG_ALLOW_WHILE_IDLE;
+                flags |= FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
+                flags &= ~FLAG_ALLOW_WHILE_IDLE;
+                flags &= ~FLAG_ALLOW_WHILE_IDLE_COMPAT;
+                idleOptions = null;
             }
 
             setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver,
-                    listenerTag, flags, workSource, alarmClock, callingUid, callingPackage);
+                    listenerTag, flags, workSource, alarmClock, callingUid, callingPackage,
+                    idleOptions);
+        }
+
+        @Override
+        public boolean canScheduleExactAlarms() {
+            return PermissionChecker.checkCallingOrSelfPermissionForPreflight(getContext(),
+                    Manifest.permission.SCHEDULE_EXACT_ALARM)
+                    == PermissionChecker.PERMISSION_GRANTED;
         }
 
         @Override
@@ -2755,6 +2953,77 @@
         }
     }
 
+    /**
+     * Called when an app loses {@link Manifest.permission#SCHEDULE_EXACT_ALARM} to remove alarms
+     * that the app is no longer eligible to use.
+     * TODO (b/179541791): Revisit and write tests once UX is final.
+     */
+    void removeExactAlarmsOnPermissionRevokedLocked(int uid, String packageName) {
+        if (UserHandle.isCore(uid) || uid == mSystemUiUid) {
+            return;
+        }
+        if (isExemptFromPermission(uid)) {
+            return;
+        }
+        if (!CompatChanges.isChangeEnabled(
+                AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION,
+                packageName, UserHandle.getUserHandleForUid(uid))) {
+            return;
+        }
+
+        final Predicate<Alarm> whichAlarms =
+                a -> (a.uid == uid && a.packageName.equals(packageName)
+                        && ((a.flags & FLAG_ALLOW_WHILE_IDLE) != 0 || a.alarmClock != null));
+        final ArrayList<Alarm> removed = mAlarmStore.remove(whichAlarms);
+        final boolean didRemove = !removed.isEmpty();
+        if (didRemove) {
+            decrementAlarmCount(uid, removed.size());
+        }
+
+        for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i--) {
+            final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.valueAt(i);
+            for (int j = alarmsForUid.size() - 1; j >= 0; j--) {
+                final Alarm alarm = alarmsForUid.get(j);
+                if (whichAlarms.test(alarm)) {
+                    // Don't set didRemove, since this doesn't impact the scheduled alarms.
+                    alarmsForUid.remove(j);
+                    decrementAlarmCount(alarm.uid, 1);
+                }
+            }
+            if (alarmsForUid.size() == 0) {
+                mPendingBackgroundAlarms.removeAt(i);
+            }
+        }
+        for (int i = mPendingNonWakeupAlarms.size() - 1; i >= 0; i--) {
+            final Alarm a = mPendingNonWakeupAlarms.get(i);
+            if (whichAlarms.test(a)) {
+                // Don't set didRemove, since this doesn't impact the scheduled alarms.
+                mPendingNonWakeupAlarms.remove(i);
+                decrementAlarmCount(a.uid, 1);
+            }
+        }
+
+        if (didRemove) {
+            if (mNextWakeFromIdle != null && whichAlarms.test(mNextWakeFromIdle)) {
+                mNextWakeFromIdle = mAlarmStore.getNextWakeFromIdleAlarm();
+                if (mPendingIdleUntil != null) {
+                    final boolean idleUntilUpdated = mAlarmStore.updateAlarmDeliveries(alarm -> {
+                        if (alarm != mPendingIdleUntil) {
+                            return false;
+                        }
+                        return adjustIdleUntilTime(alarm);
+                    });
+                    if (idleUntilUpdated) {
+                        mAlarmStore.updateAlarmDeliveries(
+                                alarm -> adjustDeliveryTimeBasedOnDeviceIdle(alarm));
+                    }
+                }
+            }
+            rescheduleKernelAlarmsLocked();
+            updateNextAlarmClockLocked();
+        }
+    }
+
     void removeLocked(PendingIntent operation, IAlarmListener directReceiver) {
         if (operation == null && directReceiver == null) {
             if (localLOGV) {
@@ -3082,7 +3351,7 @@
         }
     }
 
-    private boolean isExemptFromBatterySaver(Alarm alarm) {
+    private static boolean isExemptFromBatterySaver(Alarm alarm) {
         if (alarm.alarmClock != null) {
             return true;
         }
@@ -3142,7 +3411,7 @@
 
             alarm.count = 1;
             triggerList.add(alarm);
-            if ((alarm.flags & AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
+            if ((alarm.flags & FLAG_WAKE_FROM_IDLE) != 0) {
                 EventLogTags.writeDeviceIdleWakeFromIdle(mPendingIdleUntil != null ? 1 : 0,
                         alarm.statsTag);
             }
@@ -3180,7 +3449,7 @@
                 setImplLocked(alarm.type, alarm.origWhen + delta, nextElapsed,
                         nextMaxElapsed - nextElapsed, alarm.repeatInterval, alarm.operation, null,
                         null, alarm.flags, alarm.workSource, alarm.alarmClock, alarm.uid,
-                        alarm.packageName);
+                        alarm.packageName, null);
             }
 
             if (alarm.wakeup) {
@@ -3257,7 +3526,6 @@
         mLastAlarmDeliveryTime = nowELAPSED;
         for (int i = 0; i < triggerList.size(); i++) {
             Alarm alarm = triggerList.get(i);
-            final boolean allowWhileIdle = (alarm.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0;
             if (alarm.wakeup) {
                 Trace.traceBegin(Trace.TRACE_TAG_POWER,
                         "Dispatch wakeup alarm to " + alarm.packageName);
@@ -3273,7 +3541,7 @@
                     mActivityManagerInternal.noteAlarmStart(alarm.operation, alarm.workSource,
                             alarm.uid, alarm.statsTag);
                 }
-                mDeliveryTracker.deliverLocked(alarm, nowELAPSED, allowWhileIdle);
+                mDeliveryTracker.deliverLocked(alarm, nowELAPSED);
             } catch (RuntimeException e) {
                 Slog.w(TAG, "Failure sending alarm.", e);
             }
@@ -3282,9 +3550,10 @@
         }
     }
 
-    private boolean isExemptFromAppStandby(Alarm a) {
+    @VisibleForTesting
+    static boolean isExemptFromAppStandby(Alarm a) {
         return a.alarmClock != null || UserHandle.isCore(a.creatorUid)
-                || (a.flags & FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED) != 0;
+                || (a.flags & (FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED | FLAG_ALLOW_WHILE_IDLE)) != 0;
     }
 
     @VisibleForTesting
@@ -3368,6 +3637,11 @@
                     MATCH_SYSTEM_ONLY, USER_SYSTEM);
         }
 
+        IAppOpsService getAppOpsService() {
+            return IAppOpsService.Stub.asInterface(
+                    ServiceManager.getService(Context.APP_OPS_SERVICE));
+        }
+
         ClockReceiver getClockReceiver(AlarmManagerService service) {
             return service.new ClockReceiver();
         }
@@ -3566,6 +3840,7 @@
         public static final int APP_STANDBY_BUCKET_CHANGED = 5;
         public static final int CHARGING_STATUS_CHANGED = 6;
         public static final int REMOVE_FOR_CANCELED = 7;
+        public static final int REMOVE_EXACT_ALARMS = 8;
 
         AlarmHandler() {
             super(Looper.myLooper());
@@ -3645,6 +3920,14 @@
                     }
                     break;
 
+                case REMOVE_EXACT_ALARMS:
+                    final int uid = msg.arg1;
+                    final String packageName = (String) msg.obj;
+                    synchronized (mLock) {
+                        removeExactAlarmsOnPermissionRevokedLocked(uid, packageName);
+                    }
+                    break;
+
                 default:
                     // nope, just ignore it
                     break;
@@ -3720,7 +4003,7 @@
 
             setImpl(ELAPSED_REALTIME, mInjector.getElapsedRealtime() + tickEventDelay, 0,
                     0, null, mTimeTickTrigger, TIME_TICK_TAG, flags, workSource, null,
-                    Process.myUid(), "android");
+                    Process.myUid(), "android", null);
 
             // Finally, remember when we set the tick alarm
             synchronized (mLock) {
@@ -3740,7 +4023,7 @@
             final WorkSource workSource = null; // Let system take blame for date change events.
             setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, null, null,
                     AlarmManager.FLAG_STANDALONE, workSource, null,
-                    Process.myUid(), "android");
+                    Process.myUid(), "android", null);
         }
     }
 
@@ -4112,7 +4395,7 @@
          * Deliver an alarm and set up the post-delivery handling appropriately
          */
         @GuardedBy("mLock")
-        public void deliverLocked(Alarm alarm, long nowELAPSED, boolean allowWhileIdle) {
+        public void deliverLocked(Alarm alarm, long nowELAPSED) {
             final long workSourceToken = ThreadLocalWorkSource.setUid(
                     getAlarmAttributionUid(alarm));
             try {
@@ -4122,10 +4405,8 @@
 
                     try {
                         alarm.operation.send(getContext(), 0,
-                                mBackgroundIntent.putExtra(
-                                        Intent.EXTRA_ALARM_COUNT, alarm.count),
-                                mDeliveryTracker, mHandler, null,
-                                allowWhileIdle ? mIdleOptions : null);
+                                mBackgroundIntent.putExtra(Intent.EXTRA_ALARM_COUNT, alarm.count),
+                                mDeliveryTracker, mHandler, null, alarm.mIdleOptions);
                     } catch (PendingIntent.CanceledException e) {
                         if (alarm.repeatInterval > 0) {
                             // This IntentSender is no longer valid, but this
@@ -4194,7 +4475,7 @@
             if (inflight.isBroadcast()) {
                 notifyBroadcastAlarmPendingLocked(alarm.uid);
             }
-            if (allowWhileIdle) {
+            if (isAllowedWhileIdleRestricted(alarm)) {
                 final boolean doze = (mPendingIdleUntil != null);
                 final boolean batterySaver = (mAppStateTracker != null
                         && mAppStateTracker.isForceAllAppsStandbyEnabled());
@@ -4204,8 +4485,7 @@
                     mAllowWhileIdleHistory.recordAlarmForPackage(alarm.sourcePackage,
                             UserHandle.getUserId(alarm.creatorUid), nowELAPSED);
                     mAlarmStore.updateAlarmDeliveries(a -> {
-                        if (a.creatorUid != alarm.creatorUid
-                                || (a.flags & FLAG_ALLOW_WHILE_IDLE) == 0) {
+                        if (a.creatorUid != alarm.creatorUid || !isAllowedWhileIdleRestricted(a)) {
                             return false;
                         }
                         return (doze && adjustDeliveryTimeBasedOnDeviceIdle(a))
diff --git a/apex/jobscheduler/service/java/com/android/server/job/GrantedUriPermissions.java b/apex/jobscheduler/service/java/com/android/server/job/GrantedUriPermissions.java
index b7e8cf6..7f191d4 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/GrantedUriPermissions.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/GrantedUriPermissions.java
@@ -26,6 +26,7 @@
 import android.os.UserHandle;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
+
 import com.android.server.LocalServices;
 import com.android.server.uri.UriGrantsManagerInternal;
 
@@ -144,13 +145,13 @@
     }
 
     // Dumpsys infrastructure
-    public void dump(PrintWriter pw, String prefix) {
-        pw.print(prefix); pw.print("mGrantFlags=0x"); pw.print(Integer.toHexString(mGrantFlags));
+    public void dump(PrintWriter pw) {
+        pw.print("mGrantFlags=0x"); pw.print(Integer.toHexString(mGrantFlags));
         pw.print(" mSourceUserId="); pw.println(mSourceUserId);
-        pw.print(prefix); pw.print("mTag="); pw.println(mTag);
-        pw.print(prefix); pw.print("mPermissionOwner="); pw.println(mPermissionOwner);
+        pw.print("mTag="); pw.println(mTag);
+        pw.print("mPermissionOwner="); pw.println(mPermissionOwner);
         for (int i = 0; i < mUris.size(); i++) {
-            pw.print(prefix); pw.print("#"); pw.print(i); pw.print(": ");
+            pw.print("#"); pw.print(i); pw.print(": ");
             pw.println(mUris.get(i));
         }
     }
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
index 164781a..e8e2c27 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
@@ -20,6 +20,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
 import android.app.UserSwitchObserver;
@@ -80,6 +81,8 @@
     static final int WORK_TYPE_BGUSER = 1 << 3;
     @VisibleForTesting
     static final int NUM_WORK_TYPES = 4;
+    private static final int ALL_WORK_TYPES =
+            WORK_TYPE_TOP | WORK_TYPE_EJ | WORK_TYPE_BG | WORK_TYPE_BGUSER;
 
     @IntDef(prefix = {"WORK_TYPE_"}, flag = true, value = {
             WORK_TYPE_NONE,
@@ -92,6 +95,23 @@
     public @interface WorkType {
     }
 
+    private static String workTypeToString(@WorkType int workType) {
+        switch (workType) {
+            case WORK_TYPE_NONE:
+                return "NONE";
+            case WORK_TYPE_TOP:
+                return "TOP";
+            case WORK_TYPE_EJ:
+                return "EJ";
+            case WORK_TYPE_BG:
+                return "BG";
+            case WORK_TYPE_BGUSER:
+                return "BGUSER";
+            default:
+                return "WORK(" + workType + ")";
+        }
+    }
+
     private final Object mLock;
     private final JobSchedulerService mService;
     private final Context mContext;
@@ -182,10 +202,16 @@
 
     int[] mRecycledWorkTypeForContext = new int[MAX_JOB_CONTEXTS_COUNT];
 
+    String[] mRecycledPreemptReasonForContext = new String[MAX_JOB_CONTEXTS_COUNT];
+
+    String[] mRecycledShouldStopJobReason = new String[MAX_JOB_CONTEXTS_COUNT];
+
     private final ArraySet<JobStatus> mRunningJobs = new ArraySet<>();
 
     private final WorkCountTracker mWorkCountTracker = new WorkCountTracker();
 
+    private WorkTypeConfig mWorkTypeConfig = CONFIG_LIMITS_SCREEN_OFF.normal;
+
     /** Wait for this long after screen off before adjusting the job concurrency. */
     private long mScreenOffAdjustmentDelayMs = DEFAULT_SCREEN_OFF_ADJUSTMENT_DELAY_MS;
 
@@ -353,23 +379,22 @@
         final WorkConfigLimitsPerMemoryTrimLevel workConfigs = mEffectiveInteractiveState
                 ? CONFIG_LIMITS_SCREEN_ON : CONFIG_LIMITS_SCREEN_OFF;
 
-        WorkTypeConfig workTypeConfig;
         switch (mLastMemoryTrimLevel) {
             case ProcessStats.ADJ_MEM_FACTOR_MODERATE:
-                workTypeConfig = workConfigs.moderate;
+                mWorkTypeConfig = workConfigs.moderate;
                 break;
             case ProcessStats.ADJ_MEM_FACTOR_LOW:
-                workTypeConfig = workConfigs.low;
+                mWorkTypeConfig = workConfigs.low;
                 break;
             case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
-                workTypeConfig = workConfigs.critical;
+                mWorkTypeConfig = workConfigs.critical;
                 break;
             default:
-                workTypeConfig = workConfigs.normal;
+                mWorkTypeConfig = workConfigs.normal;
                 break;
         }
 
-        mWorkCountTracker.setConfig(workTypeConfig);
+        mWorkCountTracker.setConfig(mWorkTypeConfig);
     }
 
     /**
@@ -401,13 +426,20 @@
         boolean[] slotChanged = mRecycledSlotChanged;
         int[] preferredUidForContext = mRecycledPreferredUidForContext;
         int[] workTypeForContext = mRecycledWorkTypeForContext;
+        String[] preemptReasonForContext = mRecycledPreemptReasonForContext;
+        String[] shouldStopJobReason = mRecycledShouldStopJobReason;
 
         updateCounterConfigLocked();
         // Reset everything since we'll re-evaluate the current state.
         mWorkCountTracker.resetCounts();
 
+        // Update the priorities of jobs that aren't running, and also count the pending work types.
+        // Do this before the following loop to hopefully reduce the cost of
+        // shouldStopRunningJobLocked().
+        updateNonRunningPriorities(pendingJobs, true);
+
         for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; i++) {
-            final JobServiceContext js = mService.mActiveServices.get(i);
+            final JobServiceContext js = activeServices.get(i);
             final JobStatus status = js.getRunningJobLocked();
 
             if ((contextIdToJobMap[i] = status) != null) {
@@ -417,14 +449,13 @@
 
             slotChanged[i] = false;
             preferredUidForContext[i] = js.getPreferredUid();
+            preemptReasonForContext[i] = null;
+            shouldStopJobReason[i] = shouldStopRunningJobLocked(js);
         }
         if (DEBUG) {
             Slog.d(TAG, printContextIdToJobMap(contextIdToJobMap, "running jobs initial"));
         }
 
-        // Next, update the job priorities, and also count the pending FG / BG jobs.
-        updateNonRunningPriorities(pendingJobs, true);
-
         mWorkCountTracker.onCountDone();
 
         for (int i = 0; i < pendingJobs.size(); i++) {
@@ -434,8 +465,6 @@
                 continue;
             }
 
-            // TODO(171305774): make sure HPJs aren't pre-empted and add dedicated contexts for them
-
             // Find an available slot for nextPending. The context should be available OR
             // it should have lowest priority among all running jobs
             // (sharing the same Uid as nextPending)
@@ -444,6 +473,9 @@
             int allWorkTypes = getJobWorkTypes(nextPending);
             int workType = mWorkCountTracker.canJobStart(allWorkTypes);
             boolean startingJob = false;
+            String preemptReason = null;
+            // TODO(141645789): rewrite this to look at empty contexts first so we don't
+            // unnecessarily preempt
             for (int j = 0; j < MAX_JOB_CONTEXTS_COUNT; j++) {
                 JobStatus job = contextIdToJobMap[j];
                 int preferredUid = preferredUidForContext[j];
@@ -464,6 +496,15 @@
                     continue;
                 }
                 if (job.getUid() != nextPending.getUid()) {
+                    // Maybe stop the job if it has had its day in the sun.
+                    final String reason = shouldStopJobReason[j];
+                    if (reason != null && mWorkCountTracker.canJobStart(allWorkTypes,
+                            activeServices.get(j).getRunningJobWorkType()) != WORK_TYPE_NONE) {
+                        // Right now, the way the code is set up, we don't need to explicitly
+                        // assign the new job to this context since we'll reassign when the
+                        // preempted job finally stops.
+                        preemptReason = reason;
+                    }
                     continue;
                 }
 
@@ -477,6 +518,7 @@
                     // the lowest-priority running job
                     minPriorityForPreemption = jobPriority;
                     selectedContextId = j;
+                    preemptReason = "higher priority job found";
                     // In this case, we're just going to preempt a low priority job, we're not
                     // actually starting a job, so don't set startingJob.
                 }
@@ -484,6 +526,7 @@
             if (selectedContextId != -1) {
                 contextIdToJobMap[selectedContextId] = nextPending;
                 slotChanged[selectedContextId] = true;
+                preemptReasonForContext[selectedContextId] = preemptReason;
             }
             if (startingJob) {
                 // Increase the counters when we're going to start a job.
@@ -509,7 +552,7 @@
                                 + activeServices.get(i).getRunningJobLocked());
                     }
                     // preferredUid will be set to uid of currently running job.
-                    activeServices.get(i).preemptExecutingJobLocked();
+                    activeServices.get(i).preemptExecutingJobLocked(preemptReasonForContext[i]);
                     preservePreferredUid = true;
                 } else {
                     final JobStatus pendingJob = contextIdToJobMap[i];
@@ -692,6 +735,93 @@
         noteConcurrency();
     }
 
+    /**
+     * Returns {@code null} if the job can continue running and a non-null String if the job should
+     * be stopped. The non-null String details the reason for stopping the job. A job will generally
+     * be stopped if there similar job types waiting to be run and stopping this job would allow
+     * another job to run, or if system state suggests the job should stop.
+     */
+    @Nullable
+    String shouldStopRunningJobLocked(@NonNull JobServiceContext context) {
+        final JobStatus js = context.getRunningJobLocked();
+        if (js == null) {
+            // This can happen when we try to assign newly found pending jobs to contexts.
+            return null;
+        }
+
+        if (context.isWithinExecutionGuaranteeTime()) {
+            return null;
+        }
+
+        // We're over the minimum guaranteed runtime. Stop the job if we're over config limits,
+        // there are pending jobs that could replace this one, or the device state is not conducive
+        // to long runs.
+
+        if (mPowerManager.isPowerSaveMode()) {
+            return "battery saver";
+        }
+        if (mPowerManager.isDeviceIdleMode()) {
+            return "deep doze";
+        }
+
+        // Update config in case memory usage has changed significantly.
+        updateCounterConfigLocked();
+
+        @WorkType final int workType = context.getRunningJobWorkType();
+
+        if (mRunningJobs.size() > mWorkTypeConfig.getMaxTotal()
+                || mWorkCountTracker.isOverTypeLimit(workType)) {
+            return "too many jobs running";
+        }
+
+        final List<JobStatus> pendingJobs = mService.mPendingJobs;
+        final int numPending = pendingJobs.size();
+        if (numPending == 0) {
+            // All quiet. We can let this job run to completion.
+            return null;
+        }
+
+        // Only expedited jobs can replace expedited jobs.
+        if (js.shouldTreatAsExpeditedJob()) {
+            // Keep fg/bg user distinction.
+            if (workType == WORK_TYPE_BGUSER) {
+                // For now, let any bg user job replace a bg user expedited job.
+                // TODO: limit to ej once we have dedicated bg user ej slots.
+                if (mWorkCountTracker.getPendingJobCount(WORK_TYPE_BGUSER) > 0) {
+                    return "blocking " + workTypeToString(workType) + " queue";
+                }
+            } else {
+                if (mWorkCountTracker.getPendingJobCount(WORK_TYPE_EJ) > 0) {
+                    return "blocking " + workTypeToString(workType) + " queue";
+                }
+            }
+        }
+
+        // Easy check. If there are pending jobs of the same work type, then we know that
+        // something will replace this.
+        if (mWorkCountTracker.getPendingJobCount(workType) > 0) {
+            return "blocking " + workTypeToString(workType) + " queue";
+        }
+
+        // Harder check. We need to see if a different work type can replace this job.
+        int remainingWorkTypes = ALL_WORK_TYPES;
+        for (int i = 0; i < numPending; ++i) {
+            final JobStatus pending = pendingJobs.get(i);
+            final int workTypes = getJobWorkTypes(pending);
+            if ((workTypes & remainingWorkTypes) > 0
+                    && mWorkCountTracker.canJobStart(workTypes, workType) != WORK_TYPE_NONE) {
+                return "blocking other pending jobs";
+            }
+
+            remainingWorkTypes = remainingWorkTypes & ~workTypes;
+            if (remainingWorkTypes == 0) {
+                break;
+            }
+        }
+
+        return null;
+    }
+
     @GuardedBy("mLock")
     private String printPendingQueueLocked() {
         StringBuilder s = new StringBuilder("Pending queue: ");
@@ -1362,10 +1492,40 @@
             return WORK_TYPE_NONE;
         }
 
+        int canJobStart(int workTypes, @WorkType int replacingWorkType) {
+            final boolean changedNums;
+            int oldNumRunning = mNumRunningJobs.get(replacingWorkType);
+            if (replacingWorkType != WORK_TYPE_NONE && oldNumRunning > 0) {
+                mNumRunningJobs.put(replacingWorkType, oldNumRunning - 1);
+                // Lazy implementation to avoid lots of processing. Best way would be to go
+                // through the whole process of adjusting reservations, but the processing cost
+                // is likely not worth it.
+                mNumUnspecializedRemaining++;
+                changedNums = true;
+            } else {
+                changedNums = false;
+            }
+
+            final int ret = canJobStart(workTypes);
+            if (changedNums) {
+                mNumRunningJobs.put(replacingWorkType, oldNumRunning);
+                mNumUnspecializedRemaining--;
+            }
+            return ret;
+        }
+
+        int getPendingJobCount(@WorkType final int workType) {
+            return mNumPendingJobs.get(workType, 0);
+        }
+
         int getRunningJobCount(@WorkType final int workType) {
             return mNumRunningJobs.get(workType, 0);
         }
 
+        boolean isOverTypeLimit(@WorkType final int workType) {
+            return getRunningJobCount(workType) > mConfigAbsoluteMaxSlots.get(workType);
+        }
+
         public String toString() {
             StringBuilder sb = new StringBuilder();
 
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobPackageTracker.java b/apex/jobscheduler/service/java/com/android/server/job/JobPackageTracker.java
index d050347..6ffac91 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobPackageTracker.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobPackageTracker.java
@@ -25,6 +25,7 @@
 import android.os.UserHandle;
 import android.text.format.DateFormat;
 import android.util.ArrayMap;
+import android.util.IndentingPrintWriter;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.util.TimeUtils;
@@ -33,8 +34,6 @@
 import com.android.internal.util.RingBufferIndices;
 import com.android.server.job.controllers.JobStatus;
 
-import java.io.PrintWriter;
-
 public final class JobPackageTracker {
     // We batch every 30 minutes.
     static final long BATCHING_TIME = 30*60*1000;
@@ -294,53 +293,69 @@
             }
         }
 
-        void printDuration(PrintWriter pw, long period, long duration, int count, String suffix) {
+        /** Return {@code true} if text was printed. */
+        boolean printDuration(IndentingPrintWriter pw, long period, long duration, int count,
+                String suffix) {
             float fraction = duration / (float) period;
             int percent = (int) ((fraction * 100) + .5f);
             if (percent > 0) {
-                pw.print(" ");
                 pw.print(percent);
                 pw.print("% ");
                 pw.print(count);
                 pw.print("x ");
                 pw.print(suffix);
+                return true;
             } else if (count > 0) {
-                pw.print(" ");
                 pw.print(count);
                 pw.print("x ");
                 pw.print(suffix);
+                return true;
             }
+
+            return false;
         }
 
-        void dump(PrintWriter pw, String header, String prefix, long now, long nowElapsed,
-                int filterUid) {
+        void dump(IndentingPrintWriter pw, String header, long now, long nowElapsed,
+                int filterAppId) {
             final long period = getTotalTime(now);
-            pw.print(prefix); pw.print(header); pw.print(" at ");
+            pw.print(header); pw.print(" at ");
             pw.print(DateFormat.format("yyyy-MM-dd-HH-mm-ss", mStartClockTime).toString());
             pw.print(" (");
             TimeUtils.formatDuration(mStartElapsedTime, nowElapsed, pw);
             pw.print(") over ");
             TimeUtils.formatDuration(period, pw);
             pw.println(":");
+            pw.increaseIndent();
+            pw.print("Max concurrency: ");
+            pw.print(mMaxTotalActive); pw.print(" total, ");
+            pw.print(mMaxFgActive); pw.println(" foreground");
+
+            pw.println();
             final int NE = mEntries.size();
             for (int i = 0; i < NE; i++) {
                 int uid = mEntries.keyAt(i);
-                if (filterUid != -1 && filterUid != UserHandle.getAppId(uid)) {
+                if (filterAppId != -1 && filterAppId != UserHandle.getAppId(uid)) {
                     continue;
                 }
                 ArrayMap<String, PackageEntry> uidMap = mEntries.valueAt(i);
                 final int NP = uidMap.size();
                 for (int j = 0; j < NP; j++) {
                     PackageEntry pe = uidMap.valueAt(j);
-                    pw.print(prefix); pw.print("  ");
                     UserHandle.formatUid(pw, uid);
                     pw.print(" / "); pw.print(uidMap.keyAt(j));
                     pw.println(":");
-                    pw.print(prefix); pw.print("   ");
-                    printDuration(pw, period, pe.getPendingTime(now), pe.pendingCount, "pending");
-                    printDuration(pw, period, pe.getActiveTime(now), pe.activeCount, "active");
-                    printDuration(pw, period, pe.getActiveTopTime(now), pe.activeTopCount,
-                            "active-top");
+
+                    pw.increaseIndent();
+                    if (printDuration(pw, period,
+                            pe.getPendingTime(now), pe.pendingCount, "pending")) {
+                        pw.print(" ");
+                    }
+                    if (printDuration(pw, period,
+                            pe.getActiveTime(now), pe.activeCount, "active")) {
+                        pw.print(" ");
+                    }
+                    printDuration(pw, period,
+                            pe.getActiveTopTime(now), pe.activeTopCount, "active-top");
                     if (pe.pendingNesting > 0 || pe.hadPending) {
                         pw.print(" (pending)");
                     }
@@ -352,7 +367,6 @@
                     }
                     pw.println();
                     if (pe.stopReasons.size() > 0) {
-                        pw.print(prefix); pw.print("    ");
                         for (int k = 0; k < pe.stopReasons.size(); k++) {
                             if (k > 0) {
                                 pw.print(", ");
@@ -364,11 +378,10 @@
                         }
                         pw.println();
                     }
+                    pw.decreaseIndent();
                 }
             }
-            pw.print(prefix); pw.print("  Max concurrency: ");
-            pw.print(mMaxTotalActive); pw.print(" total, ");
-            pw.print(mMaxFgActive); pw.println(" foreground");
+            pw.decreaseIndent();
         }
 
         private void printPackageEntryState(ProtoOutputStream proto, long fieldId,
@@ -520,7 +533,7 @@
         return time / (float)period;
     }
 
-    public void dump(PrintWriter pw, String prefix, int filterUid) {
+    void dump(IndentingPrintWriter pw, int filterAppId) {
         final long now = sUptimeMillisClock.millis();
         final long nowElapsed = sElapsedRealtimeClock.millis();
         final DataSet total;
@@ -533,11 +546,11 @@
         mCurDataSet.addTo(total, now);
         for (int i = 1; i < mLastDataSets.length; i++) {
             if (mLastDataSets[i] != null) {
-                mLastDataSets[i].dump(pw, "Historical stats", prefix, now, nowElapsed, filterUid);
+                mLastDataSets[i].dump(pw, "Historical stats", now, nowElapsed, filterAppId);
                 pw.println();
             }
         }
-        total.dump(pw, "Current stats", prefix, now, nowElapsed, filterUid);
+        total.dump(pw, "Current stats", now, nowElapsed, filterAppId);
     }
 
     public void dump(ProtoOutputStream proto, long fieldId, int filterUid) {
@@ -566,17 +579,19 @@
         proto.end(token);
     }
 
-    public boolean dumpHistory(PrintWriter pw, String prefix, int filterUid) {
+    boolean dumpHistory(IndentingPrintWriter pw, int filterAppId) {
         final int size = mEventIndices.size();
         if (size <= 0) {
             return false;
         }
-        pw.println("  Job history:");
+        pw.increaseIndent();
+        pw.println("Job history:");
+        pw.decreaseIndent();
         final long now = sElapsedRealtimeClock.millis();
         for (int i=0; i<size; i++) {
             final int index = mEventIndices.indexOf(i);
             final int uid = mEventUids[index];
-            if (filterUid != -1 && filterUid != UserHandle.getAppId(uid)) {
+            if (filterAppId != -1 && filterAppId != UserHandle.getAppId(uid)) {
                 continue;
             }
             final int cmd = mEventCmds[index] & EVENT_CMD_MASK;
@@ -591,7 +606,6 @@
                 case EVENT_STOP_PERIODIC_JOB:   label = " STOP-P"; break;
                 default:                        label = "     ??"; break;
             }
-            pw.print(prefix);
             TimeUtils.formatDuration(mEventTimes[index]-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
             pw.print(" ");
             pw.print(label);
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 fdbc086..8bb03e9 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -151,6 +151,8 @@
     private static final boolean ENFORCE_MAX_JOBS = true;
     /** The maximum number of jobs that we allow an unprivileged app to schedule */
     private static final int MAX_JOBS_PER_APP = 100;
+    /** The number of the most recently completed jobs to keep track of for debugging purposes. */
+    private static final int NUM_COMPLETED_JOB_HISTORY = 20;
 
     @VisibleForTesting
     public static Clock sSystemClock = Clock.systemUTC();
@@ -297,6 +299,10 @@
      */
     boolean mReportedActive;
 
+    private int mLastCompletedJobIndex = 0;
+    private final JobStatus[] mLastCompletedJobs = new JobStatus[NUM_COMPLETED_JOB_HISTORY];
+    private final long[] mLastCompletedJobTimeElapsed = new long[NUM_COMPLETED_JOB_HISTORY];
+
     /**
      * A mapping of which uids are currently in the foreground to their effective priority.
      */
@@ -339,6 +345,7 @@
         public void onPropertiesChanged(DeviceConfig.Properties properties) {
             boolean apiQuotaScheduleUpdated = false;
             boolean concurrencyUpdated = false;
+            boolean runtimeUpdated = false;
             for (int controller = 0; controller < mControllers.size(); controller++) {
                 final StateController sc = mControllers.get(controller);
                 sc.prepareForUpdatedConstantsLocked();
@@ -377,6 +384,14 @@
                         case Constants.KEY_CONN_PREFETCH_RELAX_FRAC:
                             mConstants.updateConnectivityConstantsLocked();
                             break;
+                        case Constants.KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS:
+                        case Constants.KEY_RUNTIME_MIN_GUARANTEE_MS:
+                        case Constants.KEY_RUNTIME_MIN_EJ_GUARANTEE_MS:
+                            if (!runtimeUpdated) {
+                                mConstants.updateRuntimeConstantsLocked();
+                                runtimeUpdated = true;
+                            }
+                            break;
                         default:
                             if (name.startsWith(JobConcurrencyManager.CONFIG_KEY_PREFIX_CONCURRENCY)
                                     && !concurrencyUpdated) {
@@ -432,6 +447,11 @@
         private static final String KEY_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT =
                 "aq_schedule_return_failure";
 
+        private static final String KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS =
+                "runtime_free_quota_max_limit_ms";
+        private static final String KEY_RUNTIME_MIN_GUARANTEE_MS = "runtime_min_guarantee_ms";
+        private static final String KEY_RUNTIME_MIN_EJ_GUARANTEE_MS = "runtime_min_ej_guarantee_ms";
+
         private static final int DEFAULT_MIN_READY_NON_ACTIVE_JOBS_COUNT = 5;
         private static final long DEFAULT_MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS = 31 * MINUTE_IN_MILLIS;
         private static final float DEFAULT_HEAVY_USE_FACTOR = .9f;
@@ -445,6 +465,12 @@
         private static final long DEFAULT_API_QUOTA_SCHEDULE_WINDOW_MS = MINUTE_IN_MILLIS;
         private static final boolean DEFAULT_API_QUOTA_SCHEDULE_THROW_EXCEPTION = true;
         private static final boolean DEFAULT_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = false;
+        @VisibleForTesting
+        public static final long DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS = 30 * MINUTE_IN_MILLIS;
+        @VisibleForTesting
+        public static final long DEFAULT_RUNTIME_MIN_GUARANTEE_MS = 10 * MINUTE_IN_MILLIS;
+        @VisibleForTesting
+        public static final long DEFAULT_RUNTIME_MIN_EJ_GUARANTEE_MS = 3 * MINUTE_IN_MILLIS;
 
         /**
          * Minimum # of non-ACTIVE jobs for which the JMS will be happy running some work early.
@@ -509,6 +535,19 @@
         public boolean API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT =
                 DEFAULT_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT;
 
+        /** The maximum amount of time we will let a job run for when quota is "free". */
+        public long RUNTIME_FREE_QUOTA_MAX_LIMIT_MS = DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS;
+
+        /**
+         * The minimum amount of time we try to guarantee regular jobs will run for.
+         */
+        public long RUNTIME_MIN_GUARANTEE_MS = DEFAULT_RUNTIME_MIN_GUARANTEE_MS;
+
+        /**
+         * The minimum amount of time we try to guarantee EJs will run for.
+         */
+        public long RUNTIME_MIN_EJ_GUARANTEE_MS = DEFAULT_RUNTIME_MIN_EJ_GUARANTEE_MS;
+
         private void updateBatchingConstantsLocked() {
             MIN_READY_NON_ACTIVE_JOBS_COUNT = DeviceConfig.getInt(
                     DeviceConfig.NAMESPACE_JOB_SCHEDULER,
@@ -568,6 +607,25 @@
                     DEFAULT_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT);
         }
 
+        private void updateRuntimeConstantsLocked() {
+            DeviceConfig.Properties properties = DeviceConfig.getProperties(
+                    DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+                    KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                    KEY_RUNTIME_MIN_GUARANTEE_MS, KEY_RUNTIME_MIN_EJ_GUARANTEE_MS);
+
+            // Make sure min runtime for regular jobs is at least 10 minutes.
+            RUNTIME_MIN_GUARANTEE_MS = Math.max(10 * MINUTE_IN_MILLIS,
+                    properties.getLong(
+                            KEY_RUNTIME_MIN_GUARANTEE_MS, DEFAULT_RUNTIME_MIN_GUARANTEE_MS));
+            // Make sure min runtime for expedited jobs is at least one minute.
+            RUNTIME_MIN_EJ_GUARANTEE_MS = Math.max(MINUTE_IN_MILLIS,
+                    properties.getLong(
+                            KEY_RUNTIME_MIN_EJ_GUARANTEE_MS, DEFAULT_RUNTIME_MIN_EJ_GUARANTEE_MS));
+            RUNTIME_FREE_QUOTA_MAX_LIMIT_MS = Math.max(RUNTIME_MIN_GUARANTEE_MS,
+                    properties.getLong(KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                            DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS));
+        }
+
         void dump(IndentingPrintWriter pw) {
             pw.println("Settings:");
             pw.increaseIndent();
@@ -591,6 +649,11 @@
             pw.print(KEY_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT,
                     API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT).println();
 
+            pw.print(KEY_RUNTIME_MIN_GUARANTEE_MS, RUNTIME_MIN_GUARANTEE_MS).println();
+            pw.print(KEY_RUNTIME_MIN_EJ_GUARANTEE_MS, RUNTIME_MIN_EJ_GUARANTEE_MS).println();
+            pw.print(KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS, RUNTIME_FREE_QUOTA_MAX_LIMIT_MS)
+                    .println();
+
             pw.decreaseIndent();
         }
 
@@ -824,8 +887,10 @@
     }
 
     @Override
-    public void onUserStarting(@NonNull TargetUser user) {
+    public void onUserUnlocked(@NonNull TargetUser user) {
         synchronized (mLock) {
+            // Note that the user has started after its unlocked instead of when the user
+            // actually starts because the storage won't be decrypted until unlock.
             mStartedUsers = ArrayUtils.appendInt(mStartedUsers, user.getUserIdentifier());
         }
         // Let's kick any outstanding jobs for this user.
@@ -833,12 +898,6 @@
     }
 
     @Override
-    public void onUserUnlocking(@NonNull TargetUser user) {
-        // Let's kick any outstanding jobs for this user.
-        mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
-    }
-
-    @Override
     public void onUserStopping(@NonNull TargetUser user) {
         synchronized (mLock) {
             mStartedUsers = ArrayUtils.removeInt(mStartedUsers, user.getUserIdentifier());
@@ -1602,7 +1661,7 @@
      * time of the job to be the time of completion (i.e. the time at which this function is
      * called).
      * <p>This could be inaccurate b/c the job can run for as long as
-     * {@link com.android.server.job.JobServiceContext#DEFAULT_EXECUTING_TIMESLICE_MILLIS}, but
+     * {@link Constants#DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS}, but
      * will lead to underscheduling at least, rather than if we had taken the last execution time
      * to be the start of the execution.
      *
@@ -1695,6 +1754,10 @@
             Slog.d(TAG, "Completed " + jobStatus + ", reschedule=" + needsReschedule);
         }
 
+        mLastCompletedJobs[mLastCompletedJobIndex] = jobStatus;
+        mLastCompletedJobTimeElapsed[mLastCompletedJobIndex] = sElapsedRealtimeClock.millis();
+        mLastCompletedJobIndex = (mLastCompletedJobIndex + 1) % NUM_COMPLETED_JOB_HISTORY;
+
         // Intentionally not checking expedited job quota here. An app can't find out if it's run
         // out of quota when it asks JS to reschedule an expedited job. Instead, the rescheduled
         // EJ will just be demoted to a regular job if the app has no EJ quota left.
@@ -2213,11 +2276,25 @@
         return isComponentUsable(job);
     }
 
+    /** Returns the minimum amount of time we should let this job run before timing out. */
+    public long getMinJobExecutionGuaranteeMs(JobStatus job) {
+        synchronized (mLock) {
+            if (job.shouldTreatAsExpeditedJob()) {
+                // Don't guarantee RESTRICTED jobs more than 5 minutes.
+                return job.getEffectiveStandbyBucket() != RESTRICTED_INDEX
+                        ? mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS
+                        : Math.min(mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS, 5 * MINUTE_IN_MILLIS);
+            } else {
+                return mConstants.RUNTIME_MIN_GUARANTEE_MS;
+            }
+        }
+    }
+
     /** Returns the maximum amount of time this job could run for. */
     public long getMaxJobExecutionTimeMs(JobStatus job) {
         synchronized (mLock) {
-            return Math.min(mQuotaController.getMaxJobExecutionTimeMsLocked(job),
-                    JobServiceContext.DEFAULT_EXECUTING_TIMESLICE_MILLIS);
+            return Math.min(mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                    mQuotaController.getMaxJobExecutionTimeMsLocked(job));
         }
     }
 
@@ -3021,14 +3098,14 @@
     }
 
     void dumpInternal(final IndentingPrintWriter pw, int filterUid) {
-        final int filterUidFinal = UserHandle.getAppId(filterUid);
+        final int filterAppId = UserHandle.getAppId(filterUid);
         final long now = sSystemClock.millis();
         final long nowElapsed = sElapsedRealtimeClock.millis();
         final long nowUptime = sUptimeMillisClock.millis();
 
         final Predicate<JobStatus> predicate = (js) -> {
-            return filterUidFinal == -1 || UserHandle.getAppId(js.getUid()) == filterUidFinal
-                    || UserHandle.getAppId(js.getSourceUid()) == filterUidFinal;
+            return filterAppId == -1 || UserHandle.getAppId(js.getUid()) == filterAppId
+                    || UserHandle.getAppId(js.getSourceUid()) == filterAppId;
         };
         synchronized (mLock) {
             mConstants.dump(pw);
@@ -3041,7 +3118,6 @@
 
             for (int i = mJobRestrictions.size() - 1; i >= 0; i--) {
                 mJobRestrictions.get(i).dumpConstants(pw);
-                pw.println();
             }
             pw.println();
 
@@ -3052,21 +3128,25 @@
             pw.print("Registered ");
             pw.print(mJobs.size());
             pw.println(" jobs:");
+            pw.increaseIndent();
+            boolean jobPrinted = false;
             if (mJobs.size() > 0) {
                 final List<JobStatus> jobs = mJobs.mJobSet.getAllJobs();
                 sortJobs(jobs);
                 for (JobStatus job : jobs) {
-                    pw.print("  JOB #"); job.printUniqueId(pw); pw.print(": ");
-                    pw.println(job.toShortStringExceptUniqueId());
-
                     // Skip printing details if the caller requested a filter
                     if (!predicate.test(job)) {
                         continue;
                     }
+                    jobPrinted = true;
 
-                    job.dump(pw, "    ", true, nowElapsed);
+                    pw.print("JOB #"); job.printUniqueId(pw); pw.print(": ");
+                    pw.println(job.toShortStringExceptUniqueId());
 
-                    pw.print("    Restricted due to:");
+                    pw.increaseIndent();
+                    job.dump(pw, true, nowElapsed);
+
+                    pw.print("Restricted due to:");
                     final boolean isRestricted = checkIfRestricted(job) != null;
                     if (isRestricted) {
                         for (int i = mJobRestrictions.size() - 1; i >= 0; i--) {
@@ -3081,7 +3161,7 @@
                     }
                     pw.println(".");
 
-                    pw.print("    Ready: ");
+                    pw.print("Ready: ");
                     pw.print(isReadyToBeExecutedLocked(job));
                     pw.print(" (job=");
                     pw.print(job.isReady());
@@ -3098,10 +3178,15 @@
                     pw.print(" comp=");
                     pw.print(isComponentUsable(job));
                     pw.println(")");
+
+                    pw.decreaseIndent();
                 }
-            } else {
-                pw.println("  None.");
             }
+            if (!jobPrinted) {
+                pw.println("None.");
+            }
+            pw.decreaseIndent();
+
             for (int i=0; i<mControllers.size(); i++) {
                 pw.println();
                 pw.println(mControllers.get(i).getClass().getSimpleName() + ":");
@@ -3109,66 +3194,105 @@
                 mControllers.get(i).dumpControllerStateLocked(pw, predicate);
                 pw.decreaseIndent();
             }
-            pw.println();
-            pw.println("Uid priority overrides:");
+
+            boolean overridePrinted = false;
             for (int i=0; i< mUidPriorityOverride.size(); i++) {
                 int uid = mUidPriorityOverride.keyAt(i);
-                if (filterUidFinal == -1 || filterUidFinal == UserHandle.getAppId(uid)) {
-                    pw.print("  "); pw.print(UserHandle.formatUid(uid));
+                if (filterAppId == -1 || filterAppId == UserHandle.getAppId(uid)) {
+                    if (!overridePrinted) {
+                        overridePrinted = true;
+                        pw.println();
+                        pw.println("Uid priority overrides:");
+                        pw.increaseIndent();
+                    }
+                    pw.print(UserHandle.formatUid(uid));
                     pw.print(": "); pw.println(mUidPriorityOverride.valueAt(i));
                 }
             }
-            if (mBackingUpUids.size() > 0) {
-                pw.println();
-                pw.println("Backing up uids:");
-                boolean first = true;
-                for (int i = 0; i < mBackingUpUids.size(); i++) {
-                    int uid = mBackingUpUids.keyAt(i);
-                    if (filterUidFinal == -1 || filterUidFinal == UserHandle.getAppId(uid)) {
-                        if (first) {
-                            pw.print("  ");
-                            first = false;
-                        } else {
-                            pw.print(", ");
-                        }
-                        pw.print(UserHandle.formatUid(uid));
+            if (overridePrinted) {
+                pw.decreaseIndent();
+            }
+
+            boolean backingPrinted = false;
+            for (int i = 0; i < mBackingUpUids.size(); i++) {
+                int uid = mBackingUpUids.keyAt(i);
+                if (filterAppId == -1 || filterAppId == UserHandle.getAppId(uid)) {
+                    if (!backingPrinted) {
+                        pw.println();
+                        pw.println("Backing up uids:");
+                        pw.increaseIndent();
+                        backingPrinted = true;
+                    } else {
+                        pw.print(", ");
                     }
+                    pw.print(UserHandle.formatUid(uid));
                 }
+            }
+            if (backingPrinted) {
+                pw.decreaseIndent();
                 pw.println();
             }
+
             pw.println();
-            mJobPackageTracker.dump(pw, "", filterUidFinal);
+            mJobPackageTracker.dump(pw, filterAppId);
             pw.println();
-            if (mJobPackageTracker.dumpHistory(pw, "", filterUidFinal)) {
+            if (mJobPackageTracker.dumpHistory(pw, filterAppId)) {
                 pw.println();
             }
+
+            boolean pendingPrinted = false;
             pw.println("Pending queue:");
+            pw.increaseIndent();
             for (int i=0; i<mPendingJobs.size(); i++) {
                 JobStatus job = mPendingJobs.get(i);
-                pw.print("  Pending #"); pw.print(i); pw.print(": ");
+                if (!predicate.test(job)) {
+                    continue;
+                }
+                if (!pendingPrinted) {
+                    pendingPrinted = true;
+                }
+
+                pw.print("Pending #"); pw.print(i); pw.print(": ");
                 pw.println(job.toShortString());
-                job.dump(pw, "    ", false, nowElapsed);
+
+                pw.increaseIndent();
+                job.dump(pw, false, nowElapsed);
                 int priority = evaluateJobPriorityLocked(job);
-                pw.print("    Evaluated priority: ");
+                pw.print("Evaluated priority: ");
                 pw.println(JobInfo.getPriorityString(priority));
 
-                pw.print("    Tag: "); pw.println(job.getTag());
-                pw.print("    Enq: ");
+                pw.print("Tag: "); pw.println(job.getTag());
+                pw.print("Enq: ");
                 TimeUtils.formatDuration(job.madePending - nowUptime, pw);
+                pw.decreaseIndent();
                 pw.println();
             }
+            if (!pendingPrinted) {
+                pw.println("None");
+            }
+            pw.decreaseIndent();
+
             pw.println();
             pw.println("Active jobs:");
             pw.increaseIndent();
             for (int i=0; i<mActiveServices.size(); i++) {
                 JobServiceContext jsc = mActiveServices.get(i);
+                final JobStatus job = jsc.getRunningJobLocked();
+
+                if (job != null && !predicate.test(job)) {
+                    continue;
+                }
+
                 pw.print("Slot #"); pw.print(i); pw.print(": ");
                 jsc.dumpLocked(pw, nowElapsed);
 
-                final JobStatus job = jsc.getRunningJobLocked();
                 if (job != null) {
                     pw.increaseIndent();
-                    job.dump(pw, "  ", false, nowElapsed);
+
+                    pw.increaseIndent();
+                    job.dump(pw, false, nowElapsed);
+                    pw.decreaseIndent();
+
                     pw.print("Evaluated priority: ");
                     pw.println(JobInfo.getPriorityString(job.lastEvaluatedPriority));
 
@@ -3176,11 +3300,42 @@
                     TimeUtils.formatDuration(job.madeActive - nowUptime, pw);
                     pw.print(", pending for ");
                     TimeUtils.formatDuration(job.madeActive - job.madePending, pw);
-                    pw.println();
                     pw.decreaseIndent();
+                    pw.println();
                 }
             }
             pw.decreaseIndent();
+
+            pw.println();
+            boolean recentPrinted = false;
+            pw.println("Recently completed jobs:");
+            pw.increaseIndent();
+            for (int r = 1; r <= NUM_COMPLETED_JOB_HISTORY; ++r) {
+                // Print most recent first
+                final int idx = (mLastCompletedJobIndex + NUM_COMPLETED_JOB_HISTORY - r)
+                        % NUM_COMPLETED_JOB_HISTORY;
+                final JobStatus job = mLastCompletedJobs[idx];
+                if (job != null) {
+                    if (!predicate.test(job)) {
+                        continue;
+                    }
+                    recentPrinted = true;
+                    TimeUtils.formatDuration(mLastCompletedJobTimeElapsed[idx], nowElapsed, pw);
+                    pw.println();
+                    // Double indent for readability
+                    pw.increaseIndent();
+                    pw.increaseIndent();
+                    job.dump(pw, true, nowElapsed);
+                    pw.decreaseIndent();
+                    pw.decreaseIndent();
+                }
+            }
+            if (!recentPrinted) {
+                pw.println("None");
+            }
+            pw.decreaseIndent();
+            pw.println();
+
             if (filterUid == -1) {
                 pw.println();
                 pw.print("mReadyToRock="); pw.println(mReadyToRock);
@@ -3199,13 +3354,13 @@
 
     void dumpInternalProto(final FileDescriptor fd, int filterUid) {
         ProtoOutputStream proto = new ProtoOutputStream(fd);
-        final int filterUidFinal = UserHandle.getAppId(filterUid);
+        final int filterAppId = UserHandle.getAppId(filterUid);
         final long now = sSystemClock.millis();
         final long nowElapsed = sElapsedRealtimeClock.millis();
         final long nowUptime = sUptimeMillisClock.millis();
         final Predicate<JobStatus> predicate = (js) -> {
-            return filterUidFinal == -1 || UserHandle.getAppId(js.getUid()) == filterUidFinal
-                    || UserHandle.getAppId(js.getSourceUid()) == filterUidFinal;
+            return filterAppId == -1 || UserHandle.getAppId(js.getUid()) == filterAppId
+                    || UserHandle.getAppId(js.getSourceUid()) == filterAppId;
         };
 
         synchronized (mLock) {
@@ -3278,7 +3433,7 @@
             }
             for (int i=0; i< mUidPriorityOverride.size(); i++) {
                 int uid = mUidPriorityOverride.keyAt(i);
-                if (filterUidFinal == -1 || filterUidFinal == UserHandle.getAppId(uid)) {
+                if (filterAppId == -1 || filterAppId == UserHandle.getAppId(uid)) {
                     long pToken = proto.start(JobSchedulerServiceDumpProto.PRIORITY_OVERRIDES);
                     proto.write(JobSchedulerServiceDumpProto.PriorityOverride.UID, uid);
                     proto.write(JobSchedulerServiceDumpProto.PriorityOverride.OVERRIDE_VALUE,
@@ -3288,15 +3443,15 @@
             }
             for (int i = 0; i < mBackingUpUids.size(); i++) {
                 int uid = mBackingUpUids.keyAt(i);
-                if (filterUidFinal == -1 || filterUidFinal == UserHandle.getAppId(uid)) {
+                if (filterAppId == -1 || filterAppId == UserHandle.getAppId(uid)) {
                     proto.write(JobSchedulerServiceDumpProto.BACKING_UP_UIDS, uid);
                 }
             }
 
             mJobPackageTracker.dump(proto, JobSchedulerServiceDumpProto.PACKAGE_TRACKER,
-                    filterUidFinal);
+                    filterAppId);
             mJobPackageTracker.dumpHistory(proto, JobSchedulerServiceDumpProto.HISTORY,
-                    filterUidFinal);
+                    filterAppId);
 
             for (JobStatus job : mPendingJobs) {
                 final long pjToken = proto.start(JobSchedulerServiceDumpProto.PENDING_JOBS);
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 0aca246..2a23d60 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -17,9 +17,9 @@
 package com.android.server.job;
 
 import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_NONE;
-import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
 import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.job.IJobCallback;
 import android.app.job.IJobService;
@@ -76,14 +76,6 @@
     private static final boolean DEBUG_STANDBY = JobSchedulerService.DEBUG_STANDBY;
 
     private static final String TAG = "JobServiceContext";
-    /** Amount of time a job is allowed to execute for before being considered timed-out. */
-    public static final long DEFAULT_EXECUTING_TIMESLICE_MILLIS = 10 * 60 * 1000;  // 10mins.
-    /**
-     * Amount of time a RESTRICTED expedited job is allowed to execute for before being considered
-     * timed-out.
-     */
-    public static final long DEFAULT_RESTRICTED_EXPEDITED_JOB_EXECUTING_TIMESLICE_MILLIS =
-            DEFAULT_EXECUTING_TIMESLICE_MILLIS / 2;
     /** Amount of time the JobScheduler waits for the initial service launch+bind. */
     private static final long OP_BIND_TIMEOUT_MILLIS = 18 * 1000;
     /** Amount of time the JobScheduler will wait for a response from an app for a message. */
@@ -110,6 +102,7 @@
     /** Make callbacks to {@link JobSchedulerService} to inform on job completion status. */
     private final JobCompletedListener mCompletedListener;
     private final JobConcurrencyManager mJobConcurrencyManager;
+    private final JobSchedulerService mService;
     /** Used for service binding, etc. */
     private final Context mContext;
     private final Object mLock;
@@ -149,6 +142,13 @@
     private long mExecutionStartTimeElapsed;
     /** Track when job will timeout. */
     private long mTimeoutElapsed;
+    /**
+     * The minimum amount of time the context will allow the job to run before checking whether to
+     * stop it or not.
+     */
+    private long mMinExecutionGuaranteeMillis;
+    /** The absolute maximum amount of time the job can run */
+    private long mMaxExecutionTimeMillis;
 
     // Debugging: reason this job was last stopped.
     public String mStoppedReason;
@@ -190,6 +190,7 @@
             IBatteryStats batteryStats, JobPackageTracker tracker, Looper looper) {
         mContext = service.getContext();
         mLock = service.getLock();
+        mService = service;
         mBatteryStats = batteryStats;
         mJobPackageTracker = tracker;
         mCallbackHandler = new JobServiceHandler(looper);
@@ -239,6 +240,9 @@
                     isDeadlineExpired, job.shouldTreatAsExpeditedJob(),
                     triggeredUris, triggeredAuthorities, job.network);
             mExecutionStartTimeElapsed = sElapsedRealtimeClock.millis();
+            mMinExecutionGuaranteeMillis = mService.getMinJobExecutionGuaranteeMs(job);
+            mMaxExecutionTimeMillis =
+                    Math.max(mService.getMaxJobExecutionTimeMs(job), mMinExecutionGuaranteeMillis);
 
             final long whenDeferred = job.getWhenStandbyDeferred();
             if (whenDeferred > 0) {
@@ -267,7 +271,9 @@
                 if (job.shouldTreatAsExpeditedJob()) {
                     // TODO(171305774): The job should run on the little cores. We'll probably need
                     // another binding flag for that.
-                    bindFlags = Context.BIND_AUTO_CREATE;
+                    bindFlags = Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
+                            | Context.BIND_ALMOST_PERCEPTIBLE
+                            | Context.BIND_ALLOW_NETWORK_ACCESS;
                 } else {
                     bindFlags = Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
                             | Context.BIND_NOT_PERCEPTIBLE;
@@ -352,8 +358,8 @@
     }
 
     @GuardedBy("mLock")
-    void preemptExecutingJobLocked() {
-        doCancelLocked(JobParameters.REASON_PREEMPT, "cancelled due to preemption");
+    void preemptExecutingJobLocked(@NonNull String reason) {
+        doCancelLocked(JobParameters.REASON_PREEMPT, reason);
     }
 
     int getPreferredUid() {
@@ -372,6 +378,11 @@
         return mTimeoutElapsed;
     }
 
+    boolean isWithinExecutionGuaranteeTime() {
+        return mExecutionStartTimeElapsed + mMinExecutionGuaranteeMillis
+                < sElapsedRealtimeClock.millis();
+    }
+
     @GuardedBy("mLock")
     boolean timeoutIfExecutingLocked(String pkgName, int userId, boolean matchJobId, int jobId,
             String reason) {
@@ -607,7 +618,7 @@
     }
 
     @GuardedBy("mLock")
-    void doCancelLocked(int arg1, String debugReason) {
+    private void doCancelLocked(int stopReasonCode, String debugReason) {
         if (mVerb == VERB_FINISHED) {
             if (DEBUG) {
                 Slog.d(TAG,
@@ -615,8 +626,8 @@
             }
             return;
         }
-        mParams.setStopReason(arg1, debugReason);
-        if (arg1 == JobParameters.REASON_PREEMPT) {
+        mParams.setStopReason(stopReasonCode, debugReason);
+        if (stopReasonCode == JobParameters.REASON_PREEMPT) {
             mPreferredUid = mRunningJob != null ? mRunningJob.getUid() :
                     NO_PREFERRED_UID;
         }
@@ -767,11 +778,30 @@
                 closeAndCleanupJobLocked(true /* needsReschedule */, "timed out while stopping");
                 break;
             case VERB_EXECUTING:
-                // Not an error - client ran out of time.
-                Slog.i(TAG, "Client timed out while executing (no jobFinished received), " +
-                        "sending onStop: " + getRunningJobNameLocked());
-                mParams.setStopReason(JobParameters.REASON_TIMEOUT, "client timed out");
-                sendStopMessageLocked("timeout while executing");
+                final long latestStopTimeElapsed =
+                        mExecutionStartTimeElapsed + mMaxExecutionTimeMillis;
+                final long nowElapsed = sElapsedRealtimeClock.millis();
+                if (nowElapsed >= latestStopTimeElapsed) {
+                    // Not an error - client ran out of time.
+                    Slog.i(TAG, "Client timed out while executing (no jobFinished received)."
+                            + " Sending onStop: " + getRunningJobNameLocked());
+                    mParams.setStopReason(JobParameters.REASON_TIMEOUT, "client timed out");
+                    sendStopMessageLocked("timeout while executing");
+                } else {
+                    // We've given the app the minimum execution time. See if we should stop it or
+                    // let it continue running
+                    final String reason = mJobConcurrencyManager.shouldStopRunningJobLocked(this);
+                    if (reason != null) {
+                        Slog.i(TAG, "Stopping client after min execution time: "
+                                + getRunningJobNameLocked() + " because " + reason);
+                        mParams.setStopReason(JobParameters.REASON_TIMEOUT, reason);
+                        sendStopMessageLocked(reason);
+                    } else {
+                        Slog.i(TAG, "Letting " + getRunningJobNameLocked()
+                                + " continue to run past min execution time");
+                        scheduleOpTimeOutLocked();
+                    }
+                }
                 break;
             default:
                 Slog.e(TAG, "Handling timeout for an invalid job state: "
@@ -878,10 +908,16 @@
         final long timeoutMillis;
         switch (mVerb) {
             case VERB_EXECUTING:
-                timeoutMillis = mRunningJob.shouldTreatAsExpeditedJob()
-                        && mRunningJob.getStandbyBucket() == RESTRICTED_INDEX
-                        ? DEFAULT_RESTRICTED_EXPEDITED_JOB_EXECUTING_TIMESLICE_MILLIS
-                        : DEFAULT_EXECUTING_TIMESLICE_MILLIS;
+                final long earliestStopTimeElapsed =
+                        mExecutionStartTimeElapsed + mMinExecutionGuaranteeMillis;
+                final long latestStopTimeElapsed =
+                        mExecutionStartTimeElapsed + mMaxExecutionTimeMillis;
+                final long nowElapsed = sElapsedRealtimeClock.millis();
+                if (nowElapsed < earliestStopTimeElapsed) {
+                    timeoutMillis = earliestStopTimeElapsed - nowElapsed;
+                } else {
+                    timeoutMillis = latestStopTimeElapsed - nowElapsed;
+                }
                 break;
 
             case VERB_BINDING:
@@ -925,6 +961,13 @@
             pw.print(", timeout at: ");
             TimeUtils.formatDuration(mTimeoutElapsed - nowElapsed, pw);
             pw.println();
+            pw.print("Remaining execution limits: [");
+            TimeUtils.formatDuration(
+                    (mExecutionStartTimeElapsed + mMinExecutionGuaranteeMillis) - nowElapsed, pw);
+            pw.print(", ");
+            TimeUtils.formatDuration(
+                    (mExecutionStartTimeElapsed + mMaxExecutionTimeMillis) - nowElapsed, pw);
+            pw.println("]");
             pw.decreaseIndent();
         }
     }
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
index 58396eb..a230b23 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
@@ -17,6 +17,7 @@
 package com.android.server.job.controllers;
 
 import static com.android.server.job.JobSchedulerService.NEVER_INDEX;
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
 
 import android.os.SystemClock;
 import android.os.UserHandle;
@@ -59,6 +60,8 @@
 
     private final AppStateTrackerImpl mAppStateTracker;
 
+    private final UpdateJobFunctor mUpdateJobFunctor = new UpdateJobFunctor();
+
     public BackgroundJobsController(JobSchedulerService service) {
         super(service);
 
@@ -69,7 +72,7 @@
 
     @Override
     public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
-        updateSingleJobRestrictionLocked(jobStatus, UNKNOWN);
+        updateSingleJobRestrictionLocked(jobStatus, sElapsedRealtimeClock.millis(), UNKNOWN);
     }
 
     @Override
@@ -79,7 +82,7 @@
 
     @Override
     public void evaluateStateLocked(JobStatus jobStatus) {
-        updateSingleJobRestrictionLocked(jobStatus, UNKNOWN);
+        updateSingleJobRestrictionLocked(jobStatus, sElapsedRealtimeClock.millis(), UNKNOWN);
     }
 
     @Override
@@ -163,33 +166,34 @@
     }
 
     private void updateJobRestrictionsLocked(int filterUid, int newActiveState) {
-        final UpdateJobFunctor updateTrackedJobs = new UpdateJobFunctor(newActiveState);
+        mUpdateJobFunctor.prepare(newActiveState);
 
         final long start = DEBUG ? SystemClock.elapsedRealtimeNanos() : 0;
 
         final JobStore store = mService.getJobStore();
         if (filterUid > 0) {
-            store.forEachJobForSourceUid(filterUid, updateTrackedJobs);
+            store.forEachJobForSourceUid(filterUid, mUpdateJobFunctor);
         } else {
-            store.forEachJob(updateTrackedJobs);
+            store.forEachJob(mUpdateJobFunctor);
         }
 
         final long time = DEBUG ? (SystemClock.elapsedRealtimeNanos() - start) : 0;
         if (DEBUG) {
             Slog.d(TAG, String.format(
                     "Job status updated: %d/%d checked/total jobs, %d us",
-                    updateTrackedJobs.mCheckedCount,
-                    updateTrackedJobs.mTotalCount,
+                    mUpdateJobFunctor.mCheckedCount,
+                    mUpdateJobFunctor.mTotalCount,
                     (time / 1000)
-                    ));
+            ));
         }
 
-        if (updateTrackedJobs.mChanged) {
+        if (mUpdateJobFunctor.mChanged) {
             mStateChangedListener.onControllerStateChanged();
         }
     }
 
-    boolean updateSingleJobRestrictionLocked(JobStatus jobStatus, int activeState) {
+    boolean updateSingleJobRestrictionLocked(JobStatus jobStatus, final long nowElapsed,
+            int activeState) {
         final int uid = jobStatus.getSourceUid();
         final String packageName = jobStatus.getSourcePackageName();
 
@@ -205,26 +209,32 @@
         if (isActive && jobStatus.getStandbyBucket() == NEVER_INDEX) {
             jobStatus.maybeLogBucketMismatch();
         }
-        boolean didChange = jobStatus.setBackgroundNotRestrictedConstraintSatisfied(canRun);
+        boolean didChange =
+                jobStatus.setBackgroundNotRestrictedConstraintSatisfied(nowElapsed, canRun);
         didChange |= jobStatus.setUidActive(isActive);
         return didChange;
     }
 
     private final class UpdateJobFunctor implements Consumer<JobStatus> {
-        final int activeState;
+        int mActiveState;
         boolean mChanged = false;
         int mTotalCount = 0;
         int mCheckedCount = 0;
+        long mUpdateTimeElapsed = 0;
 
-        public UpdateJobFunctor(int newActiveState) {
-            activeState = newActiveState;
+        void prepare(int newActiveState) {
+            mActiveState = newActiveState;
+            mUpdateTimeElapsed = sElapsedRealtimeClock.millis();
+            mChanged = false;
+            mTotalCount = 0;
+            mCheckedCount = 0;
         }
 
         @Override
         public void accept(JobStatus jobStatus) {
             mTotalCount++;
             mCheckedCount++;
-            if (updateSingleJobRestrictionLocked(jobStatus, activeState)) {
+            if (updateSingleJobRestrictionLocked(jobStatus, mUpdateTimeElapsed, mActiveState)) {
                 mChanged = true;
             }
         }
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
index 28269c8..6fd0948 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
@@ -65,10 +65,12 @@
     @Override
     public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
         if (taskStatus.hasPowerConstraint()) {
+            final long nowElapsed = sElapsedRealtimeClock.millis();
             mTrackedTasks.add(taskStatus);
             taskStatus.setTrackingController(JobStatus.TRACKING_BATTERY);
-            taskStatus.setChargingConstraintSatisfied(mChargeTracker.isOnStablePower());
-            taskStatus.setBatteryNotLowConstraintSatisfied(mChargeTracker.isBatteryNotLow());
+            taskStatus.setChargingConstraintSatisfied(nowElapsed, mChargeTracker.isOnStablePower());
+            taskStatus.setBatteryNotLowConstraintSatisfied(
+                    nowElapsed, mChargeTracker.isBatteryNotLow());
         }
     }
 
@@ -97,14 +99,15 @@
         if (DEBUG) {
             Slog.d(TAG, "maybeReportNewChargingStateLocked: " + stablePower);
         }
+        final long nowElapsed = sElapsedRealtimeClock.millis();
         boolean reportChange = false;
         for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
             final JobStatus ts = mTrackedTasks.valueAt(i);
-            boolean previous = ts.setChargingConstraintSatisfied(stablePower);
+            boolean previous = ts.setChargingConstraintSatisfied(nowElapsed, stablePower);
             if (previous != stablePower) {
                 reportChange = true;
             }
-            previous = ts.setBatteryNotLowConstraintSatisfied(batteryNotLow);
+            previous = ts.setBatteryNotLowConstraintSatisfied(nowElapsed, batteryNotLow);
             if (previous != batteryNotLow) {
                 reportChange = true;
             }
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 d249f2a..6e542f3 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
@@ -20,6 +20,7 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 
 import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
 
 import android.annotation.Nullable;
 import android.app.job.JobInfo;
@@ -325,6 +326,8 @@
      */
     private boolean isInsane(JobStatus jobStatus, Network network,
             NetworkCapabilities capabilities, Constants constants) {
+        // Use the maximum possible time since it gives us an upper bound, even though the job
+        // could end up stopping earlier.
         final long maxJobExecutionTimeMs = mService.getMaxJobExecutionTimeMs(jobStatus);
 
         final long downloadBytes = jobStatus.getEstimatedNetworkDownloadBytes();
@@ -459,11 +462,12 @@
         final Network network = mConnManager.getActiveNetworkForUid(
                 jobStatus.getSourceUid(), jobStatus.shouldIgnoreNetworkBlocking());
         final NetworkCapabilities capabilities = getNetworkCapabilities(network);
-        return updateConstraintsSatisfied(jobStatus, network, capabilities);
+        return updateConstraintsSatisfied(jobStatus, sElapsedRealtimeClock.millis(),
+                network, capabilities);
     }
 
-    private boolean updateConstraintsSatisfied(JobStatus jobStatus, Network network,
-            NetworkCapabilities capabilities) {
+    private boolean updateConstraintsSatisfied(JobStatus jobStatus, final long nowElapsed,
+            Network network, NetworkCapabilities capabilities) {
         // TODO: consider matching against non-active networks
 
         final boolean ignoreBlocked = jobStatus.shouldIgnoreNetworkBlocking();
@@ -474,7 +478,7 @@
         final boolean satisfied = isSatisfied(jobStatus, network, capabilities, mConstants);
 
         final boolean changed = jobStatus
-                .setConnectivityConstraintSatisfied(connected && satisfied);
+                .setConnectivityConstraintSatisfied(nowElapsed, connected && satisfied);
 
         // Pass along the evaluated network for job to use; prevents race
         // conditions as default routes change over time, and opens the door to
@@ -528,6 +532,7 @@
         NetworkCapabilities exemptedNetworkCapabilities = null;
         boolean exemptedNetworkMatch = false;
 
+        final long nowElapsed = sElapsedRealtimeClock.millis();
         boolean changed = false;
         for (int i = jobs.size() - 1; i >= 0; i--) {
             final JobStatus js = jobs.valueAt(i);
@@ -553,7 +558,7 @@
             // job hasn't yet been evaluated against the currently
             // active network; typically when we just lost a network.
             if (match || !Objects.equals(js.network, net)) {
-                changed |= updateConstraintsSatisfied(js, net, netCap);
+                changed |= updateConstraintsSatisfied(js, nowElapsed, net, netCap);
             }
         }
         return changed;
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ContentObserverController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ContentObserverController.java
index 131a6d4..8b0da34 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ContentObserverController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ContentObserverController.java
@@ -16,6 +16,8 @@
 
 package com.android.server.job.controllers;
 
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+
 import android.annotation.UserIdInt;
 import android.app.job.JobInfo;
 import android.database.ContentObserver;
@@ -74,6 +76,7 @@
     @Override
     public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
         if (taskStatus.hasContentTriggerConstraint()) {
+            final long nowElapsed = sElapsedRealtimeClock.millis();
             if (taskStatus.contentObserverJobInstance == null) {
                 taskStatus.contentObserverJobInstance = new JobInstance(taskStatus);
             }
@@ -110,7 +113,7 @@
             }
             taskStatus.changedAuthorities = null;
             taskStatus.changedUris = null;
-            taskStatus.setContentTriggerConstraintSatisfied(havePendingUris);
+            taskStatus.setContentTriggerConstraintSatisfied(nowElapsed, havePendingUris);
         }
         if (lastJob != null && lastJob.contentObserverJobInstance != null) {
             // And now we can detach the instance state from the last job.
@@ -295,7 +298,8 @@
             boolean reportChange = false;
             synchronized (mLock) {
                 if (mTriggerPending) {
-                    if (mJobStatus.setContentTriggerConstraintSatisfied(true)) {
+                    final long nowElapsed = sElapsedRealtimeClock.millis();
+                    if (mJobStatus.setContentTriggerConstraintSatisfied(nowElapsed, true)) {
                         reportChange = true;
                     }
                     unscheduleLocked();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
index 04b4164..192f5e6 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
@@ -16,6 +16,8 @@
 
 package com.android.server.job.controllers;
 
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+
 import android.app.job.JobInfo;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -104,8 +106,10 @@
                                     + Arrays.toString(mPowerSaveTempWhitelistAppIds));
                         }
                         boolean changed = false;
+                        final long nowElapsed = sElapsedRealtimeClock.millis();
                         for (int i = 0; i < mAllowInIdleJobs.size(); i++) {
-                            changed |= updateTaskStateLocked(mAllowInIdleJobs.valueAt(i));
+                            changed |=
+                                    updateTaskStateLocked(mAllowInIdleJobs.valueAt(i), nowElapsed);
                         }
                         if (changed) {
                             mStateChangedListener.onControllerStateChanged();
@@ -147,6 +151,7 @@
             }
             mDeviceIdleMode = enabled;
             if (DEBUG) Slog.d(TAG, "mDeviceIdleMode=" + mDeviceIdleMode);
+            mDeviceIdleUpdateFunctor.prepare();
             if (enabled) {
                 mHandler.removeMessages(PROCESS_BACKGROUND_JOBS);
                 mService.getJobStore().forEachJob(mDeviceIdleUpdateFunctor);
@@ -180,7 +185,7 @@
             Slog.d(TAG, "uid " + uid + " going " + (active ? "active" : "inactive"));
         }
         mForegroundUids.put(uid, active);
-        mDeviceIdleUpdateFunctor.mChanged = false;
+        mDeviceIdleUpdateFunctor.prepare();
         mService.getJobStore().forEachJobForSourceUid(uid, mDeviceIdleUpdateFunctor);
         if (mDeviceIdleUpdateFunctor.mChanged) {
             mStateChangedListener.onControllerStateChanged();
@@ -203,12 +208,12 @@
                 UserHandle.getAppId(job.getSourceUid()));
     }
 
-    private boolean updateTaskStateLocked(JobStatus task) {
+    private boolean updateTaskStateLocked(JobStatus task, final long nowElapsed) {
         final boolean allowInIdle = ((task.getFlags()&JobInfo.FLAG_IMPORTANT_WHILE_FOREGROUND) != 0)
                 && (mForegroundUids.get(task.getSourceUid()) || isTempWhitelistedLocked(task));
         final boolean whitelisted = isWhitelistedLocked(task);
         final boolean enableTask = !mDeviceIdleMode || whitelisted || allowInIdle;
-        return task.setDeviceNotDozingConstraintSatisfied(enableTask, whitelisted);
+        return task.setDeviceNotDozingConstraintSatisfied(nowElapsed, enableTask, whitelisted);
     }
 
     @Override
@@ -216,7 +221,7 @@
         if ((jobStatus.getFlags()&JobInfo.FLAG_IMPORTANT_WHILE_FOREGROUND) != 0) {
             mAllowInIdleJobs.add(jobStatus);
         }
-        updateTaskStateLocked(jobStatus);
+        updateTaskStateLocked(jobStatus, sElapsedRealtimeClock.millis());
     }
 
     @Override
@@ -282,10 +287,16 @@
 
     final class DeviceIdleUpdateFunctor implements Consumer<JobStatus> {
         boolean mChanged;
+        long mUpdateTimeElapsed = 0;
+
+        void prepare() {
+            mChanged = false;
+            mUpdateTimeElapsed = sElapsedRealtimeClock.millis();
+        }
 
         @Override
         public void accept(JobStatus jobStatus) {
-            mChanged |= updateTaskStateLocked(jobStatus);
+            mChanged |= updateTaskStateLocked(jobStatus, mUpdateTimeElapsed);
         }
     }
 
@@ -300,7 +311,7 @@
                 case PROCESS_BACKGROUND_JOBS:
                     // Just process all the jobs, the ones in foreground should already be running.
                     synchronized (mLock) {
-                        mDeviceIdleUpdateFunctor.mChanged = false;
+                        mDeviceIdleUpdateFunctor.prepare();
                         mService.getJobStore().forEachJob(mDeviceIdleUpdateFunctor);
                         if (mDeviceIdleUpdateFunctor.mChanged) {
                             mStateChangedListener.onControllerStateChanged();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
index 2fe827e..e26a3c6 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
@@ -16,6 +16,8 @@
 
 package com.android.server.job.controllers;
 
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.UserHandle;
@@ -58,9 +60,10 @@
     @Override
     public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
         if (taskStatus.hasIdleConstraint()) {
+            final long nowElapsed = sElapsedRealtimeClock.millis();
             mTrackedTasks.add(taskStatus);
             taskStatus.setTrackingController(JobStatus.TRACKING_IDLE);
-            taskStatus.setIdleConstraintSatisfied(mIdleTracker.isIdle());
+            taskStatus.setIdleConstraintSatisfied(nowElapsed, mIdleTracker.isIdle());
         }
     }
 
@@ -90,8 +93,9 @@
     @Override
     public void reportNewIdleState(boolean isIdle) {
         synchronized (mLock) {
+            final long nowElapsed = sElapsedRealtimeClock.millis();
             for (int i = mTrackedTasks.size()-1; i >= 0; i--) {
-                mTrackedTasks.valueAt(i).setIdleConstraintSatisfied(isIdle);
+                mTrackedTasks.valueAt(i).setIdleConstraintSatisfied(nowElapsed, isIdle);
             }
         }
         mStateChangedListener.onControllerStateChanged();
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 539c3c9..5bdeb38 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
@@ -35,6 +35,7 @@
 import android.provider.MediaStore;
 import android.text.format.DateFormat;
 import android.util.ArraySet;
+import android.util.IndentingPrintWriter;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.TimeUtils;
@@ -72,6 +73,8 @@
     private static final String TAG = "JobScheduler.JobStatus";
     static final boolean DEBUG = JobSchedulerService.DEBUG;
 
+    private static final int NUM_CONSTRAINT_CHANGE_HISTORY = 10;
+
     public static final long NO_LATEST_RUNTIME = Long.MAX_VALUE;
     public static final long NO_EARLIEST_RUNTIME = 0L;
 
@@ -349,6 +352,10 @@
      */
     private Pair<Long, Long> mPersistedUtcTimes;
 
+    private int mConstraintChangeHistoryIndex = 0;
+    private final long[] mConstraintUpdatedTimesElapsed = new long[NUM_CONSTRAINT_CHANGE_HISTORY];
+    private final int[] mConstraintStatusHistory = new int[NUM_CONSTRAINT_CHANGE_HISTORY];
+
     /**
      * For use only by ContentObserverController: state it is maintaining about content URIs
      * being observed.
@@ -1089,28 +1096,28 @@
     }
 
     /** @return true if the constraint was changed, false otherwise. */
-    boolean setChargingConstraintSatisfied(boolean state) {
-        return setConstraintSatisfied(CONSTRAINT_CHARGING, state);
+    boolean setChargingConstraintSatisfied(final long nowElapsed, boolean state) {
+        return setConstraintSatisfied(CONSTRAINT_CHARGING, nowElapsed, state);
     }
 
     /** @return true if the constraint was changed, false otherwise. */
-    boolean setBatteryNotLowConstraintSatisfied(boolean state) {
-        return setConstraintSatisfied(CONSTRAINT_BATTERY_NOT_LOW, state);
+    boolean setBatteryNotLowConstraintSatisfied(final long nowElapsed, boolean state) {
+        return setConstraintSatisfied(CONSTRAINT_BATTERY_NOT_LOW, nowElapsed, state);
     }
 
     /** @return true if the constraint was changed, false otherwise. */
-    boolean setStorageNotLowConstraintSatisfied(boolean state) {
-        return setConstraintSatisfied(CONSTRAINT_STORAGE_NOT_LOW, state);
+    boolean setStorageNotLowConstraintSatisfied(final long nowElapsed, boolean state) {
+        return setConstraintSatisfied(CONSTRAINT_STORAGE_NOT_LOW, nowElapsed, state);
     }
 
     /** @return true if the constraint was changed, false otherwise. */
-    boolean setTimingDelayConstraintSatisfied(boolean state) {
-        return setConstraintSatisfied(CONSTRAINT_TIMING_DELAY, state);
+    boolean setTimingDelayConstraintSatisfied(final long nowElapsed, boolean state) {
+        return setConstraintSatisfied(CONSTRAINT_TIMING_DELAY, nowElapsed, state);
     }
 
     /** @return true if the constraint was changed, false otherwise. */
-    boolean setDeadlineConstraintSatisfied(boolean state) {
-        if (setConstraintSatisfied(CONSTRAINT_DEADLINE, state)) {
+    boolean setDeadlineConstraintSatisfied(final long nowElapsed, boolean state) {
+        if (setConstraintSatisfied(CONSTRAINT_DEADLINE, nowElapsed, state)) {
             // The constraint was changed. Update the ready flag.
             mReadyDeadlineSatisfied = !job.isPeriodic() && hasDeadlineConstraint() && state;
             return true;
@@ -1119,24 +1126,25 @@
     }
 
     /** @return true if the constraint was changed, false otherwise. */
-    boolean setIdleConstraintSatisfied(boolean state) {
-        return setConstraintSatisfied(CONSTRAINT_IDLE, state);
+    boolean setIdleConstraintSatisfied(final long nowElapsed, boolean state) {
+        return setConstraintSatisfied(CONSTRAINT_IDLE, nowElapsed, state);
     }
 
     /** @return true if the constraint was changed, false otherwise. */
-    boolean setConnectivityConstraintSatisfied(boolean state) {
-        return setConstraintSatisfied(CONSTRAINT_CONNECTIVITY, state);
+    boolean setConnectivityConstraintSatisfied(final long nowElapsed, boolean state) {
+        return setConstraintSatisfied(CONSTRAINT_CONNECTIVITY, nowElapsed, state);
     }
 
     /** @return true if the constraint was changed, false otherwise. */
-    boolean setContentTriggerConstraintSatisfied(boolean state) {
-        return setConstraintSatisfied(CONSTRAINT_CONTENT_TRIGGER, state);
+    boolean setContentTriggerConstraintSatisfied(final long nowElapsed, boolean state) {
+        return setConstraintSatisfied(CONSTRAINT_CONTENT_TRIGGER, nowElapsed, state);
     }
 
     /** @return true if the constraint was changed, false otherwise. */
-    boolean setDeviceNotDozingConstraintSatisfied(boolean state, boolean whitelisted) {
+    boolean setDeviceNotDozingConstraintSatisfied(final long nowElapsed,
+            boolean state, boolean whitelisted) {
         dozeWhitelisted = whitelisted;
-        if (setConstraintSatisfied(CONSTRAINT_DEVICE_NOT_DOZING, state)) {
+        if (setConstraintSatisfied(CONSTRAINT_DEVICE_NOT_DOZING, nowElapsed, state)) {
             // The constraint was changed. Update the ready flag.
             mReadyNotDozing = state || canRunInDoze();
             return true;
@@ -1145,8 +1153,8 @@
     }
 
     /** @return true if the constraint was changed, false otherwise. */
-    boolean setBackgroundNotRestrictedConstraintSatisfied(boolean state) {
-        if (setConstraintSatisfied(CONSTRAINT_BACKGROUND_NOT_RESTRICTED, state)) {
+    boolean setBackgroundNotRestrictedConstraintSatisfied(final long nowElapsed, boolean state) {
+        if (setConstraintSatisfied(CONSTRAINT_BACKGROUND_NOT_RESTRICTED, nowElapsed, state)) {
             // The constraint was changed. Update the ready flag.
             mReadyNotRestrictedInBg = state;
             return true;
@@ -1155,8 +1163,8 @@
     }
 
     /** @return true if the constraint was changed, false otherwise. */
-    boolean setQuotaConstraintSatisfied(boolean state) {
-        if (setConstraintSatisfied(CONSTRAINT_WITHIN_QUOTA, state)) {
+    boolean setQuotaConstraintSatisfied(final long nowElapsed, boolean state) {
+        if (setConstraintSatisfied(CONSTRAINT_WITHIN_QUOTA, nowElapsed, state)) {
             // The constraint was changed. Update the ready flag.
             mReadyWithinQuota = state;
             return true;
@@ -1165,8 +1173,8 @@
     }
 
     /** @return true if the constraint was changed, false otherwise. */
-    boolean setExpeditedJobQuotaConstraintSatisfied(boolean state) {
-        if (setConstraintSatisfied(CONSTRAINT_WITHIN_EXPEDITED_QUOTA, state)) {
+    boolean setExpeditedJobQuotaConstraintSatisfied(final long nowElapsed, boolean state) {
+        if (setConstraintSatisfied(CONSTRAINT_WITHIN_EXPEDITED_QUOTA, nowElapsed, state)) {
             // The constraint was changed. Update the ready flag.
             mReadyWithinExpeditedQuota = state;
             // DeviceIdleJobsController currently only tracks jobs with the WILL_BE_FOREGROUND flag.
@@ -1189,7 +1197,7 @@
     }
 
     /** @return true if the constraint was changed, false otherwise. */
-    boolean setConstraintSatisfied(int constraint, boolean state) {
+    boolean setConstraintSatisfied(int constraint, final long nowElapsed, boolean state) {
         boolean old = (satisfiedConstraints&constraint) != 0;
         if (old == state) {
             return false;
@@ -1211,6 +1219,12 @@
                             : FrameworkStatsLog
                                     .SCHEDULED_JOB_CONSTRAINT_CHANGED__STATE__UNSATISFIED);
         }
+
+        mConstraintUpdatedTimesElapsed[mConstraintChangeHistoryIndex] = nowElapsed;
+        mConstraintStatusHistory[mConstraintChangeHistoryIndex] = satisfiedConstraints;
+        mConstraintChangeHistoryIndex =
+                (mConstraintChangeHistoryIndex + 1) % NUM_CONSTRAINT_CHANGE_HISTORY;
+
         return true;
     }
 
@@ -1644,14 +1658,18 @@
         }
     }
 
-    private void dumpJobWorkItem(PrintWriter pw, String prefix, JobWorkItem work, int index) {
-        pw.print(prefix); pw.print("  #"); pw.print(index); pw.print(": #");
+    private void dumpJobWorkItem(IndentingPrintWriter pw, JobWorkItem work, int index) {
+        pw.increaseIndent();
+        pw.print("#"); pw.print(index); pw.print(": #");
         pw.print(work.getWorkId()); pw.print(" "); pw.print(work.getDeliveryCount());
         pw.print("x "); pw.println(work.getIntent());
         if (work.getGrants() != null) {
-            pw.print(prefix); pw.println("  URI grants:");
-            ((GrantedUriPermissions)work.getGrants()).dump(pw, prefix + "    ");
+            pw.println("URI grants:");
+            pw.increaseIndent();
+            ((GrantedUriPermissions) work.getGrants()).dump(pw);
+            pw.decreaseIndent();
         }
+        pw.decreaseIndent();
     }
 
     private void dumpJobWorkItem(ProtoOutputStream proto, long fieldId, JobWorkItem work) {
@@ -1695,36 +1713,38 @@
     }
 
     // Dumpsys infrastructure
-    public void dump(PrintWriter pw, String prefix, boolean full, long elapsedRealtimeMillis) {
-        pw.print(prefix); UserHandle.formatUid(pw, callingUid);
+    public void dump(IndentingPrintWriter pw,  boolean full, long nowElapsed) {
+        UserHandle.formatUid(pw, callingUid);
         pw.print(" tag="); pw.println(tag);
-        pw.print(prefix);
+
         pw.print("Source: uid="); UserHandle.formatUid(pw, getSourceUid());
         pw.print(" user="); pw.print(getSourceUserId());
         pw.print(" pkg="); pw.println(getSourcePackageName());
         if (full) {
-            pw.print(prefix); pw.println("JobInfo:");
-            pw.print(prefix); pw.print("  Service: ");
+            pw.println("JobInfo:");
+            pw.increaseIndent();
+
+            pw.print("Service: ");
             pw.println(job.getService().flattenToShortString());
             if (job.isPeriodic()) {
-                pw.print(prefix); pw.print("  PERIODIC: interval=");
+                pw.print("PERIODIC: interval=");
                 TimeUtils.formatDuration(job.getIntervalMillis(), pw);
                 pw.print(" flex="); TimeUtils.formatDuration(job.getFlexMillis(), pw);
                 pw.println();
             }
             if (job.isPersisted()) {
-                pw.print(prefix); pw.println("  PERSISTED");
+                pw.println("PERSISTED");
             }
             if (job.getPriority() != 0) {
-                pw.print(prefix); pw.print("  Priority: ");
+                pw.print("Priority: ");
                 pw.println(JobInfo.getPriorityString(job.getPriority()));
             }
             if (job.getFlags() != 0) {
-                pw.print(prefix); pw.print("  Flags: ");
+                pw.print("Flags: ");
                 pw.println(Integer.toHexString(job.getFlags()));
             }
             if (getInternalFlags() != 0) {
-                pw.print(prefix); pw.print("  Internal flags: ");
+                pw.print("Internal flags: ");
                 pw.print(Integer.toHexString(getInternalFlags()));
 
                 if ((getInternalFlags()&INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION) != 0) {
@@ -1732,106 +1752,125 @@
                 }
                 pw.println();
             }
-            pw.print(prefix); pw.print("  Requires: charging=");
+            pw.print("Requires: charging=");
             pw.print(job.isRequireCharging()); pw.print(" batteryNotLow=");
             pw.print(job.isRequireBatteryNotLow()); pw.print(" deviceIdle=");
             pw.println(job.isRequireDeviceIdle());
             if (job.getTriggerContentUris() != null) {
-                pw.print(prefix); pw.println("  Trigger content URIs:");
+                pw.println("Trigger content URIs:");
+                pw.increaseIndent();
                 for (int i = 0; i < job.getTriggerContentUris().length; i++) {
                     JobInfo.TriggerContentUri trig = job.getTriggerContentUris()[i];
-                    pw.print(prefix); pw.print("    ");
                     pw.print(Integer.toHexString(trig.getFlags()));
                     pw.print(' '); pw.println(trig.getUri());
                 }
+                pw.decreaseIndent();
                 if (job.getTriggerContentUpdateDelay() >= 0) {
-                    pw.print(prefix); pw.print("  Trigger update delay: ");
+                    pw.print("Trigger update delay: ");
                     TimeUtils.formatDuration(job.getTriggerContentUpdateDelay(), pw);
                     pw.println();
                 }
                 if (job.getTriggerContentMaxDelay() >= 0) {
-                    pw.print(prefix); pw.print("  Trigger max delay: ");
+                    pw.print("Trigger max delay: ");
                     TimeUtils.formatDuration(job.getTriggerContentMaxDelay(), pw);
                     pw.println();
                 }
             }
             if (job.getExtras() != null && !job.getExtras().isDefinitelyEmpty()) {
-                pw.print(prefix); pw.print("  Extras: ");
+                pw.print("Extras: ");
                 pw.println(job.getExtras().toShortString());
             }
             if (job.getTransientExtras() != null && !job.getTransientExtras().isDefinitelyEmpty()) {
-                pw.print(prefix); pw.print("  Transient extras: ");
+                pw.print("Transient extras: ");
                 pw.println(job.getTransientExtras().toShortString());
             }
             if (job.getClipData() != null) {
-                pw.print(prefix); pw.print("  Clip data: ");
+                pw.print("Clip data: ");
                 StringBuilder b = new StringBuilder(128);
                 b.append(job.getClipData());
                 pw.println(b);
             }
             if (uriPerms != null) {
-                pw.print(prefix); pw.println("  Granted URI permissions:");
-                uriPerms.dump(pw, prefix + "  ");
+                pw.println("Granted URI permissions:");
+                uriPerms.dump(pw);
             }
             if (job.getRequiredNetwork() != null) {
-                pw.print(prefix); pw.print("  Network type: ");
+                pw.print("Network type: ");
                 pw.println(job.getRequiredNetwork());
             }
             if (mTotalNetworkDownloadBytes != JobInfo.NETWORK_BYTES_UNKNOWN) {
-                pw.print(prefix); pw.print("  Network download bytes: ");
+                pw.print("Network download bytes: ");
                 pw.println(mTotalNetworkDownloadBytes);
             }
             if (mTotalNetworkUploadBytes != JobInfo.NETWORK_BYTES_UNKNOWN) {
-                pw.print(prefix); pw.print("  Network upload bytes: ");
+                pw.print("Network upload bytes: ");
                 pw.println(mTotalNetworkUploadBytes);
             }
             if (job.getMinLatencyMillis() != 0) {
-                pw.print(prefix); pw.print("  Minimum latency: ");
+                pw.print("Minimum latency: ");
                 TimeUtils.formatDuration(job.getMinLatencyMillis(), pw);
                 pw.println();
             }
             if (job.getMaxExecutionDelayMillis() != 0) {
-                pw.print(prefix); pw.print("  Max execution delay: ");
+                pw.print("Max execution delay: ");
                 TimeUtils.formatDuration(job.getMaxExecutionDelayMillis(), pw);
                 pw.println();
             }
-            pw.print(prefix); pw.print("  Backoff: policy="); pw.print(job.getBackoffPolicy());
+            pw.print("Backoff: policy="); pw.print(job.getBackoffPolicy());
             pw.print(" initial="); TimeUtils.formatDuration(job.getInitialBackoffMillis(), pw);
             pw.println();
             if (job.hasEarlyConstraint()) {
-                pw.print(prefix); pw.println("  Has early constraint");
+                pw.println("Has early constraint");
             }
             if (job.hasLateConstraint()) {
-                pw.print(prefix); pw.println("  Has late constraint");
+                pw.println("Has late constraint");
             }
+
+            pw.decreaseIndent();
         }
-        pw.print(prefix); pw.print("Required constraints:");
+
+        pw.print("Required constraints:");
         dumpConstraints(pw, requiredConstraints);
         pw.println();
-        pw.print(prefix);
         pw.print("Dynamic constraints:");
         dumpConstraints(pw, mDynamicConstraints);
         pw.println();
         if (full) {
-            pw.print(prefix); pw.print("Satisfied constraints:");
+            pw.print("Satisfied constraints:");
             dumpConstraints(pw, satisfiedConstraints);
             pw.println();
-            pw.print(prefix); pw.print("Unsatisfied constraints:");
+            pw.print("Unsatisfied constraints:");
             dumpConstraints(pw,
                     ((requiredConstraints | CONSTRAINT_WITHIN_QUOTA) & ~satisfiedConstraints));
             pw.println();
+
+            pw.println("Constraint history:");
+            pw.increaseIndent();
+            for (int h = 0; h < NUM_CONSTRAINT_CHANGE_HISTORY; ++h) {
+                final int idx = (h + mConstraintChangeHistoryIndex) % NUM_CONSTRAINT_CHANGE_HISTORY;
+                if (mConstraintUpdatedTimesElapsed[idx] == 0) {
+                    continue;
+                }
+                TimeUtils.formatDuration(mConstraintUpdatedTimesElapsed[idx], nowElapsed, pw);
+                // dumpConstraints prepends with a space, so no need to add a space after the =
+                pw.print(" =");
+                dumpConstraints(pw, mConstraintStatusHistory[idx]);
+                pw.println();
+            }
+            pw.decreaseIndent();
+
             if (dozeWhitelisted) {
-                pw.print(prefix); pw.println("Doze whitelisted: true");
+                pw.println("Doze whitelisted: true");
             }
             if (uidActive) {
-                pw.print(prefix); pw.println("Uid: active");
+                pw.println("Uid: active");
             }
             if (job.isExemptedFromAppStandby()) {
-                pw.print(prefix); pw.println("Is exempted from app standby");
+                pw.println("Is exempted from app standby");
             }
         }
         if (trackingControllers != 0) {
-            pw.print(prefix); pw.print("Tracking:");
+            pw.print("Tracking:");
             if ((trackingControllers&TRACKING_BATTERY) != 0) pw.print(" BATTERY");
             if ((trackingControllers&TRACKING_CONNECTIVITY) != 0) pw.print(" CONNECTIVITY");
             if ((trackingControllers&TRACKING_CONTENT) != 0) pw.print(" CONTENT");
@@ -1842,92 +1881,93 @@
             pw.println();
         }
 
-        pw.print(prefix); pw.println("Implicit constraints:");
-        pw.print(prefix); pw.print("  readyNotDozing: ");
+        pw.println("Implicit constraints:");
+        pw.increaseIndent();
+        pw.print("readyNotDozing: ");
         pw.println(mReadyNotDozing);
-        pw.print(prefix); pw.print("  readyNotRestrictedInBg: ");
+        pw.print("readyNotRestrictedInBg: ");
         pw.println(mReadyNotRestrictedInBg);
         if (!job.isPeriodic() && hasDeadlineConstraint()) {
-            pw.print(prefix); pw.print("  readyDeadlineSatisfied: ");
+            pw.print("readyDeadlineSatisfied: ");
             pw.println(mReadyDeadlineSatisfied);
         }
         if (mDynamicConstraints != 0) {
-            pw.print(prefix);
-            pw.print("  readyDynamicSatisfied: ");
+            pw.print("readyDynamicSatisfied: ");
             pw.println(mReadyDynamicSatisfied);
         }
-        pw.print(prefix);
-        pw.print("  readyComponentEnabled: ");
+        pw.print("readyComponentEnabled: ");
         pw.println(serviceInfo != null);
         if ((getFlags() & JobInfo.FLAG_EXPEDITED) != 0) {
-            pw.print(prefix);
-            pw.print("  mReadyWithinExpeditedQuota: ");
+            pw.print("readyWithinExpeditedQuota: ");
             pw.println(mReadyWithinExpeditedQuota);
         }
+        pw.decreaseIndent();
 
         if (changedAuthorities != null) {
-            pw.print(prefix); pw.println("Changed authorities:");
+            pw.println("Changed authorities:");
+            pw.increaseIndent();
             for (int i=0; i<changedAuthorities.size(); i++) {
-                pw.print(prefix); pw.print("  "); pw.println(changedAuthorities.valueAt(i));
+                pw.println(changedAuthorities.valueAt(i));
             }
+            pw.decreaseIndent();
         }
         if (changedUris != null) {
-            pw.print(prefix);
             pw.println("Changed URIs:");
+            pw.increaseIndent();
             for (int i = 0; i < changedUris.size(); i++) {
-                pw.print(prefix);
-                pw.print("  ");
                 pw.println(changedUris.valueAt(i));
             }
+            pw.decreaseIndent();
         }
         if (network != null) {
-            pw.print(prefix); pw.print("Network: "); pw.println(network);
+            pw.print("Network: "); pw.println(network);
         }
         if (pendingWork != null && pendingWork.size() > 0) {
-            pw.print(prefix); pw.println("Pending work:");
+            pw.println("Pending work:");
             for (int i = 0; i < pendingWork.size(); i++) {
-                dumpJobWorkItem(pw, prefix, pendingWork.get(i), i);
+                dumpJobWorkItem(pw, pendingWork.get(i), i);
             }
         }
         if (executingWork != null && executingWork.size() > 0) {
-            pw.print(prefix); pw.println("Executing work:");
+            pw.println("Executing work:");
             for (int i = 0; i < executingWork.size(); i++) {
-                dumpJobWorkItem(pw, prefix, executingWork.get(i), i);
+                dumpJobWorkItem(pw, executingWork.get(i), i);
             }
         }
-        pw.print(prefix); pw.print("Standby bucket: ");
+        pw.print("Standby bucket: ");
         pw.println(getBucketName());
+        pw.increaseIndent();
         if (whenStandbyDeferred != 0) {
-            pw.print(prefix); pw.print("  Deferred since: ");
-            TimeUtils.formatDuration(whenStandbyDeferred, elapsedRealtimeMillis, pw);
+            pw.print("Deferred since: ");
+            TimeUtils.formatDuration(whenStandbyDeferred, nowElapsed, pw);
             pw.println();
         }
         if (mFirstForceBatchedTimeElapsed != 0) {
-            pw.print(prefix);
-            pw.print("  Time since first force batch attempt: ");
-            TimeUtils.formatDuration(mFirstForceBatchedTimeElapsed, elapsedRealtimeMillis, pw);
+            pw.print("Time since first force batch attempt: ");
+            TimeUtils.formatDuration(mFirstForceBatchedTimeElapsed, nowElapsed, pw);
             pw.println();
         }
-        pw.print(prefix); pw.print("Enqueue time: ");
-        TimeUtils.formatDuration(enqueueTime, elapsedRealtimeMillis, pw);
+        pw.decreaseIndent();
+
+        pw.print("Enqueue time: ");
+        TimeUtils.formatDuration(enqueueTime, nowElapsed, pw);
         pw.println();
-        pw.print(prefix); pw.print("Run time: earliest=");
-        formatRunTime(pw, earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME, elapsedRealtimeMillis);
+        pw.print("Run time: earliest=");
+        formatRunTime(pw, earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME, nowElapsed);
         pw.print(", latest=");
-        formatRunTime(pw, latestRunTimeElapsedMillis, NO_LATEST_RUNTIME, elapsedRealtimeMillis);
+        formatRunTime(pw, latestRunTimeElapsedMillis, NO_LATEST_RUNTIME, nowElapsed);
         pw.print(", original latest=");
-        formatRunTime(pw, mOriginalLatestRunTimeElapsedMillis,
-                NO_LATEST_RUNTIME, elapsedRealtimeMillis);
+        formatRunTime(pw, mOriginalLatestRunTimeElapsedMillis, NO_LATEST_RUNTIME, nowElapsed);
         pw.println();
         if (numFailures != 0) {
-            pw.print(prefix); pw.print("Num failures: "); pw.println(numFailures);
+            pw.print("Num failures: "); pw.println(numFailures);
         }
         if (mLastSuccessfulRunTime != 0) {
-            pw.print(prefix); pw.print("Last successful run: ");
+            pw.print("Last successful run: ");
             pw.println(formatTime(mLastSuccessfulRunTime));
         }
         if (mLastFailedRunTime != 0) {
-            pw.print(prefix); pw.print("Last failed run: ");
+            pw.print("Last failed run: ");
             pw.println(formatTime(mLastFailedRunTime));
         }
     }
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index f2d10ac..b70e68b 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -72,7 +72,6 @@
 import com.android.server.PowerAllowlistInternal;
 import com.android.server.job.ConstantsProto;
 import com.android.server.job.JobSchedulerService;
-import com.android.server.job.JobServiceContext;
 import com.android.server.job.StateControllerProto;
 import com.android.server.usage.AppStandbyInternal;
 import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
@@ -627,6 +626,7 @@
 
     @Override
     public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
+        final long nowElapsed = sElapsedRealtimeClock.millis();
         final int userId = jobStatus.getSourceUserId();
         final String pkgName = jobStatus.getSourcePackageName();
         ArraySet<JobStatus> jobs = mTrackedJobs.get(userId, pkgName);
@@ -637,11 +637,11 @@
         jobs.add(jobStatus);
         jobStatus.setTrackingController(JobStatus.TRACKING_QUOTA);
         final boolean isWithinQuota = isWithinQuotaLocked(jobStatus);
-        setConstraintSatisfied(jobStatus, isWithinQuota);
+        setConstraintSatisfied(jobStatus, nowElapsed, isWithinQuota);
         final boolean outOfEJQuota;
         if (jobStatus.isRequestedExpeditedJob()) {
             final boolean isWithinEJQuota = isWithinEJQuotaLocked(jobStatus);
-            setExpeditedConstraintSatisfied(jobStatus, isWithinEJQuota);
+            setExpeditedConstraintSatisfied(jobStatus, nowElapsed, isWithinEJQuota);
             outOfEJQuota = !isWithinEJQuota;
         } else {
             outOfEJQuota = false;
@@ -770,18 +770,38 @@
 
     /** Returns the maximum amount of time this job could run for. */
     public long getMaxJobExecutionTimeMsLocked(@NonNull final JobStatus jobStatus) {
-        // If quota is currently "free", then the job can run for the full amount of time.
-        if (mChargeTracker.isCharging()
-                || isTopStartedJobLocked(jobStatus)
-                || isUidInForeground(jobStatus.getSourceUid())) {
-            return JobServiceContext.DEFAULT_EXECUTING_TIMESLICE_MILLIS;
+        // Need to look at current proc state as well in the case where the job hasn't started yet.
+        final boolean isTop = mActivityManagerInternal
+                .getUidProcessState(jobStatus.getSourceUid()) <= ActivityManager.PROCESS_STATE_TOP;
+
+        if (!jobStatus.shouldTreatAsExpeditedJob()) {
+            // If quota is currently "free", then the job can run for the full amount of time.
+            if (mChargeTracker.isCharging()
+                    || isTop
+                    || isTopStartedJobLocked(jobStatus)
+                    || isUidInForeground(jobStatus.getSourceUid())) {
+                return mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS;
+            }
+            return getTimeUntilQuotaConsumedLocked(
+                    jobStatus.getSourceUserId(), jobStatus.getSourcePackageName());
         }
-        if (jobStatus.shouldTreatAsExpeditedJob()) {
-            return jobStatus.getStandbyBucket() == RESTRICTED_INDEX
-                    ? JobServiceContext.DEFAULT_RESTRICTED_EXPEDITED_JOB_EXECUTING_TIMESLICE_MILLIS
-                    : JobServiceContext.DEFAULT_EXECUTING_TIMESLICE_MILLIS;
+
+        // Expedited job.
+        if (mChargeTracker.isCharging()) {
+            return mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS;
         }
-        return getRemainingExecutionTimeLocked(jobStatus);
+        if (isTop || isTopStartedJobLocked(jobStatus)) {
+            return Math.max(mEJLimitsMs[ACTIVE_INDEX] / 2,
+                    getTimeUntilEJQuotaConsumedLocked(
+                            jobStatus.getSourceUserId(), jobStatus.getSourcePackageName()));
+        }
+        if (isUidInForeground(jobStatus.getSourceUid())) {
+            return Math.max(mEJLimitsMs[WORKING_INDEX] / 2,
+                    getTimeUntilEJQuotaConsumedLocked(
+                            jobStatus.getSourceUserId(), jobStatus.getSourcePackageName()));
+        }
+        return getTimeUntilEJQuotaConsumedLocked(
+                jobStatus.getSourceUserId(), jobStatus.getSourcePackageName());
     }
 
     /** @return true if the job is within expedited job quota. */
@@ -808,8 +828,8 @@
     }
 
     @NonNull
-    private ShrinkableDebits getEJQuotaLocked(final int userId,
-            @NonNull final String packageName) {
+    @VisibleForTesting
+    ShrinkableDebits getEJDebitsLocked(final int userId, @NonNull final String packageName) {
         ShrinkableDebits debits = mEJStats.get(userId, packageName);
         if (debits == null) {
             debits = new ShrinkableDebits(
@@ -911,7 +931,7 @@
 
     @VisibleForTesting
     long getRemainingEJExecutionTimeLocked(final int userId, @NonNull final String packageName) {
-        ShrinkableDebits quota = getEJQuotaLocked(userId, packageName);
+        ShrinkableDebits quota = getEJDebitsLocked(userId, packageName);
         if (quota.getStandbyBucketLocked() == NEVER_INDEX) {
             return 0;
         }
@@ -928,7 +948,7 @@
                 if (ts.endTimeElapsed < windowStartTimeElapsed) {
                     final long duration = ts.endTimeElapsed - ts.startTimeElapsed;
                     remainingMs += duration;
-                    quota.transactOnDebitsLocked(-duration);
+                    quota.transactLocked(-duration);
                     timingSessions.remove(0);
                 } else if (ts.startTimeElapsed < windowStartTimeElapsed) {
                     remainingMs += windowStartTimeElapsed - ts.startTimeElapsed;
@@ -940,15 +960,16 @@
             }
         }
 
+        TopAppTimer topAppTimer = mTopAppTrackers.get(userId, packageName);
+        if (topAppTimer != null && topAppTimer.isActive()) {
+            remainingMs += topAppTimer.getPendingReward(nowElapsed);
+        }
+
         Timer timer = mEJPkgTimers.get(userId, packageName);
         if (timer == null) {
             return remainingMs;
         }
-        // There's a case where the debits tally is 0 but a currently running HPJ still counts
-        // towards quota. If the app gets a reward in this case, the reward is lost and the HPJ
-        // run is still fully counted.
-        // TODO(171305774)/STOPSHIP: make sure getting rewards while HPJ currently executing isn't
-        // treated negatively
+
         return remainingMs - timer.getCurrentDuration(sElapsedRealtimeClock.millis());
     }
 
@@ -974,12 +995,18 @@
         if (standbyBucket == NEVER_INDEX) {
             return 0;
         }
+
         List<TimingSession> sessions = mTimingSessions.get(userId, packageName);
+        final ExecutionStats stats = getExecutionStatsLocked(userId, packageName, standbyBucket);
         if (sessions == null || sessions.size() == 0) {
+            // Regular ACTIVE case. Since the bucket size equals the allowed time, the app jobs can
+            // essentially run until they reach the maximum limit.
+            if (stats.windowSizeMs == mAllowedTimePerPeriodMs) {
+                return mMaxExecutionTimeMs;
+            }
             return mAllowedTimePerPeriodMs;
         }
 
-        final ExecutionStats stats = getExecutionStatsLocked(userId, packageName, standbyBucket);
         final long startWindowElapsed = nowElapsed - stats.windowSizeMs;
         final long startMaxElapsed = nowElapsed - MAX_PERIOD_MS;
         final long allowedTimeRemainingMs = mAllowedTimePerPeriodMs - stats.executionTimeInWindowMs;
@@ -1061,7 +1088,7 @@
         }
 
         final long nowElapsed = sElapsedRealtimeClock.millis();
-        ShrinkableDebits quota = getEJQuotaLocked(userId, packageName);
+        ShrinkableDebits quota = getEJDebitsLocked(userId, packageName);
         final long limitMs = getEJLimitMsLocked(packageName, quota.getStandbyBucketLocked());
         final long startWindowElapsed = Math.max(0, nowElapsed - mEJLimitWindowSizeMs);
         long remainingDeadSpaceMs = remainingExecutionTimeMs;
@@ -1352,6 +1379,11 @@
     @VisibleForTesting
     void saveTimingSession(final int userId, @NonNull final String packageName,
             @NonNull final TimingSession session, boolean isExpedited) {
+        saveTimingSession(userId, packageName, session, isExpedited, 0);
+    }
+
+    private void saveTimingSession(final int userId, @NonNull final String packageName,
+            @NonNull final TimingSession session, boolean isExpedited, long debitAdjustment) {
         synchronized (mLock) {
             final SparseArrayMap<String, List<TimingSession>> sessionMap =
                     isExpedited ? mEJTimingSessions : mTimingSessions;
@@ -1362,8 +1394,9 @@
             }
             sessions.add(session);
             if (isExpedited) {
-                final ShrinkableDebits quota = getEJQuotaLocked(userId, packageName);
-                quota.transactOnDebitsLocked(session.endTimeElapsed - session.startTimeElapsed);
+                final ShrinkableDebits quota = getEJDebitsLocked(userId, packageName);
+                quota.transactLocked(session.endTimeElapsed - session.startTimeElapsed
+                        + debitAdjustment);
             } else {
                 // Adding a new session means that the current stats are now incorrect.
                 invalidateAllExecutionStatsLocked(userId, packageName);
@@ -1376,14 +1409,34 @@
     private void grantRewardForInstantEvent(
             final int userId, @NonNull final String packageName, final long credit) {
         synchronized (mLock) {
-            final ShrinkableDebits quota = getEJQuotaLocked(userId, packageName);
-            quota.transactOnDebitsLocked(-credit);
-            if (maybeUpdateConstraintForPkgLocked(userId, packageName)) {
+            final long nowElapsed = sElapsedRealtimeClock.millis();
+            final ShrinkableDebits quota = getEJDebitsLocked(userId, packageName);
+            if (transactQuotaLocked(userId, packageName, nowElapsed, quota, credit)
+                    && maybeUpdateConstraintForPkgLocked(nowElapsed, userId, packageName)) {
                 mStateChangedListener.onControllerStateChanged();
             }
         }
     }
 
+    private boolean transactQuotaLocked(final int userId, @NonNull final String packageName,
+            final long nowElapsed, @NonNull ShrinkableDebits debits, final long credit) {
+        final long oldTally = debits.getTallyLocked();
+        final long leftover = debits.transactLocked(-credit);
+        if (DEBUG) {
+            Slog.d(TAG, "debits overflowed by " + leftover);
+        }
+        boolean changed = oldTally != debits.getTallyLocked();
+        if (leftover != 0) {
+            // Only adjust timer if its active.
+            final Timer ejTimer = mEJPkgTimers.get(userId, packageName);
+            if (ejTimer != null && ejTimer.isActive()) {
+                ejTimer.updateDebitAdjustment(nowElapsed, leftover);
+                changed = true;
+            }
+        }
+        return changed;
+    }
+
     private final class EarliestEndTimeFunctor implements Consumer<List<TimingSession>> {
         public long earliestEndElapsed = Long.MAX_VALUE;
 
@@ -1480,11 +1533,12 @@
 
     private void maybeUpdateAllConstraintsLocked() {
         boolean changed = false;
+        final long nowElapsed = sElapsedRealtimeClock.millis();
         for (int u = 0; u < mTrackedJobs.numMaps(); ++u) {
             final int userId = mTrackedJobs.keyAt(u);
             for (int p = 0; p < mTrackedJobs.numElementsForKey(userId); ++p) {
                 final String packageName = mTrackedJobs.keyAt(u, p);
-                changed |= maybeUpdateConstraintForPkgLocked(userId, packageName);
+                changed |= maybeUpdateConstraintForPkgLocked(nowElapsed, userId, packageName);
             }
         }
         if (changed) {
@@ -1497,7 +1551,7 @@
      *
      * @return true if at least one job had its bit changed
      */
-    private boolean maybeUpdateConstraintForPkgLocked(final int userId,
+    private boolean maybeUpdateConstraintForPkgLocked(final long nowElapsed, final int userId,
             @NonNull final String packageName) {
         ArraySet<JobStatus> jobs = mTrackedJobs.get(userId, packageName);
         if (jobs == null || jobs.size() == 0) {
@@ -1514,21 +1568,21 @@
             if (isTopStartedJobLocked(js)) {
                 // Job was started while the app was in the TOP state so we should allow it to
                 // finish.
-                changed |= js.setQuotaConstraintSatisfied(true);
+                changed |= js.setQuotaConstraintSatisfied(nowElapsed, true);
             } else if (realStandbyBucket != ACTIVE_INDEX
                     && realStandbyBucket == js.getEffectiveStandbyBucket()) {
                 // An app in the ACTIVE bucket may be out of quota while the job could be in quota
                 // for some reason. Therefore, avoid setting the real value here and check each job
                 // individually.
-                changed |= setConstraintSatisfied(js, realInQuota);
+                changed |= setConstraintSatisfied(js, nowElapsed, realInQuota);
             } else {
                 // This job is somehow exempted. Need to determine its own quota status.
-                changed |= setConstraintSatisfied(js, isWithinQuotaLocked(js));
+                changed |= setConstraintSatisfied(js, nowElapsed, isWithinQuotaLocked(js));
             }
 
             if (js.isRequestedExpeditedJob()) {
                 boolean isWithinEJQuota = isWithinEJQuotaLocked(js);
-                changed |= setExpeditedConstraintSatisfied(js, isWithinEJQuota);
+                changed |= setExpeditedConstraintSatisfied(js, nowElapsed, isWithinEJQuota);
                 outOfEJQuota |= !isWithinEJQuota;
             }
         }
@@ -1547,14 +1601,21 @@
         private final SparseArrayMap<String, Integer> mToScheduleStartAlarms =
                 new SparseArrayMap<>();
         public boolean wasJobChanged;
+        long mUpdateTimeElapsed = 0;
+
+        void prepare() {
+            mUpdateTimeElapsed = sElapsedRealtimeClock.millis();
+        }
 
         @Override
         public void accept(JobStatus jobStatus) {
-            wasJobChanged |= setConstraintSatisfied(jobStatus, isWithinQuotaLocked(jobStatus));
+            wasJobChanged |= setConstraintSatisfied(
+                    jobStatus, mUpdateTimeElapsed, isWithinQuotaLocked(jobStatus));
             final boolean outOfEJQuota;
             if (jobStatus.isRequestedExpeditedJob()) {
                 final boolean isWithinEJQuota = isWithinEJQuotaLocked(jobStatus);
-                wasJobChanged |= setExpeditedConstraintSatisfied(jobStatus, isWithinEJQuota);
+                wasJobChanged |= setExpeditedConstraintSatisfied(
+                        jobStatus, mUpdateTimeElapsed, isWithinEJQuota);
                 outOfEJQuota = !isWithinEJQuota;
             } else {
                 outOfEJQuota = false;
@@ -1592,6 +1653,7 @@
     private final UidConstraintUpdater mUpdateUidConstraints = new UidConstraintUpdater();
 
     private boolean maybeUpdateConstraintForUidLocked(final int uid) {
+        mUpdateUidConstraints.prepare();
         mService.getJobStore().forEachJobForSourceUid(uid, mUpdateUidConstraints);
 
         mUpdateUidConstraints.postProcess();
@@ -1697,21 +1759,22 @@
         mInQuotaAlarmListener.addAlarmLocked(userId, packageName, inQuotaTimeElapsed);
     }
 
-    private boolean setConstraintSatisfied(@NonNull JobStatus jobStatus, boolean isWithinQuota) {
+    private boolean setConstraintSatisfied(@NonNull JobStatus jobStatus, long nowElapsed,
+            boolean isWithinQuota) {
         if (!isWithinQuota && jobStatus.getWhenStandbyDeferred() == 0) {
             // Mark that the job is being deferred due to buckets.
-            jobStatus.setWhenStandbyDeferred(sElapsedRealtimeClock.millis());
+            jobStatus.setWhenStandbyDeferred(nowElapsed);
         }
-        return jobStatus.setQuotaConstraintSatisfied(isWithinQuota);
+        return jobStatus.setQuotaConstraintSatisfied(nowElapsed, isWithinQuota);
     }
 
     /**
      * If the satisfaction changes, this will tell connectivity & background jobs controller to
      * also re-evaluate their state.
      */
-    private boolean setExpeditedConstraintSatisfied(@NonNull JobStatus jobStatus,
+    private boolean setExpeditedConstraintSatisfied(@NonNull JobStatus jobStatus, long nowElapsed,
             boolean isWithinQuota) {
-        if (jobStatus.setExpeditedJobQuotaConstraintSatisfied(isWithinQuota)) {
+        if (jobStatus.setExpeditedJobQuotaConstraintSatisfied(nowElapsed, isWithinQuota)) {
             mBackgroundJobsController.evaluateStateLocked(jobStatus);
             mConnectivityController.evaluateStateLocked(jobStatus);
             if (isWithinQuota && jobStatus.isReady()) {
@@ -1844,7 +1907,8 @@
         }
     }
 
-    private static final class ShrinkableDebits {
+    @VisibleForTesting
+    static final class ShrinkableDebits {
         /** The amount of quota remaining. Can be negative if limit changes. */
         private long mDebitTally;
         private int mStandbyBucket;
@@ -1862,8 +1926,11 @@
          * Negative if the tally should decrease (therefore increasing available quota);
          * or positive if the tally should increase (therefore decreasing available quota).
          */
-        void transactOnDebitsLocked(final long amount) {
+        long transactLocked(final long amount) {
+            final long leftover = amount < 0 && Math.abs(amount) > mDebitTally
+                    ? mDebitTally + amount : 0;
             mDebitTally = Math.max(0, mDebitTally + amount);
+            return leftover;
         }
 
         void setStandbyBucketLocked(int standbyBucket) {
@@ -1896,6 +1963,7 @@
         private final ArraySet<JobStatus> mRunningBgJobs = new ArraySet<>();
         private long mStartTimeElapsed;
         private int mBgJobCount;
+        private long mDebitAdjustment;
 
         Timer(int uid, int userId, String packageName, boolean regularJobTimer) {
             mPkg = new Package(userId, packageName);
@@ -1926,6 +1994,7 @@
                 if (mRunningBgJobs.size() == 1) {
                     // Started tracking the first job.
                     mStartTimeElapsed = sElapsedRealtimeClock.millis();
+                    mDebitAdjustment = 0;
                     if (mRegularJobTimer) {
                         // Starting the timer means that all cached execution stats are now
                         // incorrect.
@@ -1957,6 +2026,11 @@
             }
         }
 
+        void updateDebitAdjustment(long nowElapsed, long debit) {
+            // Make sure we don't have a credit larger than the expected session.
+            mDebitAdjustment = Math.max(mDebitAdjustment + debit, mStartTimeElapsed - nowElapsed);
+        }
+
         /**
          * Stops tracking all jobs and cancels any pending alarms. This should only be called if
          * the Timer is not going to be used anymore.
@@ -1972,7 +2046,8 @@
                 return;
             }
             TimingSession ts = new TimingSession(mStartTimeElapsed, nowElapsed, mBgJobCount);
-            saveTimingSession(mPkg.userId, mPkg.packageName, ts, !mRegularJobTimer);
+            saveTimingSession(mPkg.userId, mPkg.packageName, ts, !mRegularJobTimer,
+                    mDebitAdjustment);
             mBgJobCount = 0;
             // Don't reset the tracked jobs list as we need to keep tracking the current number
             // of jobs.
@@ -1999,7 +2074,7 @@
 
         long getCurrentDuration(long nowElapsed) {
             synchronized (mLock) {
-                return !isActive() ? 0 : nowElapsed - mStartTimeElapsed;
+                return !isActive() ? 0 : nowElapsed - mStartTimeElapsed + mDebitAdjustment;
             }
         }
 
@@ -2028,6 +2103,7 @@
                 // Start timing from unplug.
                 if (mRunningBgJobs.size() > 0) {
                     mStartTimeElapsed = nowElapsed;
+                    mDebitAdjustment = 0;
                     // NOTE: this does have the unfortunate consequence that if the device is
                     // repeatedly plugged in and unplugged, or an app changes foreground state
                     // very frequently, the job count for a package may be artificially high.
@@ -2097,6 +2173,11 @@
             pw.print(", ");
             pw.print(mBgJobCount);
             pw.print(" running bg jobs");
+            if (!mRegularJobTimer) {
+                pw.print(" (debit adj=");
+                pw.print(mDebitAdjustment);
+                pw.print(")");
+            }
             pw.println();
             pw.increaseIndent();
             for (int i = 0; i < mRunningBgJobs.size(); i++) {
@@ -2140,6 +2221,21 @@
             mPkg = new Package(userId, packageName);
         }
 
+        private int calculateTimeChunks(final long nowElapsed) {
+            final long totalTopTimeMs = nowElapsed - mStartTimeElapsed;
+            int numTimeChunks = (int) (totalTopTimeMs / mEJTopAppTimeChunkSizeMs);
+            final long remainderMs = totalTopTimeMs % mEJTopAppTimeChunkSizeMs;
+            if (remainderMs >= SECOND_IN_MILLIS) {
+                // "Round up"
+                numTimeChunks++;
+            }
+            return numTimeChunks;
+        }
+
+        long getPendingReward(final long nowElapsed) {
+            return mEJRewardTopAppMs * calculateTimeChunks(nowElapsed);
+        }
+
         void processEventLocked(@NonNull UsageEvents.Event event) {
             final long nowElapsed = sElapsedRealtimeClock.millis();
             switch (event.getEventType()) {
@@ -2155,21 +2251,17 @@
                     final UsageEvents.Event existingEvent =
                             mActivities.removeReturnOld(event.mInstanceId);
                     if (existingEvent != null && mActivities.size() == 0) {
-                        final long totalTopTimeMs = nowElapsed - mStartTimeElapsed;
-                        int numTimeChunks = (int) (totalTopTimeMs / mEJTopAppTimeChunkSizeMs);
-                        final long remainderMs = totalTopTimeMs % mEJTopAppTimeChunkSizeMs;
-                        if (remainderMs >= SECOND_IN_MILLIS) {
-                            // "Round up"
-                            numTimeChunks++;
-                        }
+                        final long pendingReward = getPendingReward(nowElapsed);
                         if (DEBUG) {
-                            Slog.d(TAG,
-                                    "Crediting " + mPkg + " for " + numTimeChunks + " time chunks");
+                            Slog.d(TAG, "Crediting " + mPkg + " " + pendingReward + "ms"
+                                    + " for " + calculateTimeChunks(nowElapsed) + " time chunks");
                         }
-                        final ShrinkableDebits quota =
-                                getEJQuotaLocked(mPkg.userId, mPkg.packageName);
-                        quota.transactOnDebitsLocked(-mEJRewardTopAppMs * numTimeChunks);
-                        if (maybeUpdateConstraintForPkgLocked(mPkg.userId, mPkg.packageName)) {
+                        final ShrinkableDebits debits =
+                                getEJDebitsLocked(mPkg.userId, mPkg.packageName);
+                        if (transactQuotaLocked(mPkg.userId, mPkg.packageName,
+                                nowElapsed, debits, pendingReward)
+                                && maybeUpdateConstraintForPkgLocked(nowElapsed,
+                                mPkg.userId, mPkg.packageName)) {
                             mStateChangedListener.onControllerStateChanged();
                         }
                     }
@@ -2273,7 +2365,8 @@
             if (timer != null && timer.isActive()) {
                 timer.rescheduleCutoff();
             }
-            if (maybeUpdateConstraintForPkgLocked(userId, packageName)) {
+            if (maybeUpdateConstraintForPkgLocked(sElapsedRealtimeClock.millis(),
+                    userId, packageName)) {
                 mStateChangedListener.onControllerStateChanged();
             }
         }
@@ -2288,7 +2381,7 @@
          */
         @Override
         public void onUsageEvent(int userId, @NonNull UsageEvents.Event event) {
-            mHandler.obtainMessage(MSG_PROCESS_USAGE_EVENT, userId, 0, event);
+            mHandler.obtainMessage(MSG_PROCESS_USAGE_EVENT, userId, 0, event).sendToTarget();
         }
     }
 
@@ -2375,7 +2468,6 @@
     }
 
     private class QcHandler extends Handler {
-        private boolean mIsProcessing;
 
         QcHandler(Looper looper) {
             super(looper);
@@ -2384,8 +2476,6 @@
         @Override
         public void handleMessage(Message msg) {
             synchronized (mLock) {
-                mIsProcessing = true;
-
                 switch (msg.what) {
                     case MSG_REACHED_QUOTA: {
                         Package pkg = (Package) msg.obj;
@@ -2398,7 +2488,8 @@
                         if (timeRemainingMs <= 50) {
                             // Less than 50 milliseconds left. Start process of shutting down jobs.
                             if (DEBUG) Slog.d(TAG, pkg + " has reached its quota.");
-                            if (maybeUpdateConstraintForPkgLocked(pkg.userId, pkg.packageName)) {
+                            if (maybeUpdateConstraintForPkgLocked(sElapsedRealtimeClock.millis(),
+                                    pkg.userId, pkg.packageName)) {
                                 mStateChangedListener.onControllerStateChanged();
                             }
                         } else {
@@ -2425,7 +2516,8 @@
                                 pkg.userId, pkg.packageName);
                         if (timeRemainingMs <= 0) {
                             if (DEBUG) Slog.d(TAG, pkg + " has reached its EJ quota.");
-                            if (maybeUpdateConstraintForPkgLocked(pkg.userId, pkg.packageName)) {
+                            if (maybeUpdateConstraintForPkgLocked(sElapsedRealtimeClock.millis(),
+                                    pkg.userId, pkg.packageName)) {
                                 mStateChangedListener.onControllerStateChanged();
                             }
                         } else {
@@ -2456,7 +2548,8 @@
                         if (DEBUG) {
                             Slog.d(TAG, "Checking pkg " + string(userId, packageName));
                         }
-                        if (maybeUpdateConstraintForPkgLocked(userId, packageName)) {
+                        if (maybeUpdateConstraintForPkgLocked(sElapsedRealtimeClock.millis(),
+                                userId, packageName)) {
                             mStateChangedListener.onControllerStateChanged();
                         }
                         break;
@@ -2503,6 +2596,10 @@
                         final int userId = msg.arg1;
                         final UsageEvents.Event event = (UsageEvents.Event) msg.obj;
                         final String pkgName = event.getPackageName();
+                        if (DEBUG) {
+                            Slog.d(TAG, "Processing event " + event.getEventType()
+                                    + " for " + string(userId, pkgName));
+                        }
                         switch (event.getEventType()) {
                             case UsageEvents.Event.ACTIVITY_RESUMED:
                             case UsageEvents.Event.ACTIVITY_PAUSED:
@@ -2568,8 +2665,6 @@
                     }
                 }
             }
-
-            mIsProcessing = false;
         }
     }
 
@@ -3577,8 +3672,8 @@
                 mEJLimitsMs[RARE_INDEX] = newRareLimitMs;
                 mShouldReevaluateConstraints = true;
             }
-            // The limit must be in the range [0 minutes, rare limit].
-            long newRestrictedLimitMs = Math.max(0,
+            // The limit must be in the range [5 minutes, rare limit].
+            long newRestrictedLimitMs = Math.max(5 * MINUTE_IN_MILLIS,
                     Math.min(newRareLimitMs, EJ_LIMIT_RESTRICTED_MS));
             if (mEJLimitsMs[RESTRICTED_INDEX] != newRestrictedLimitMs) {
                 mEJLimitsMs[RESTRICTED_INDEX] = newRestrictedLimitMs;
@@ -3847,11 +3942,6 @@
         return mQcConstants;
     }
 
-    @VisibleForTesting
-    boolean isActiveBackgroundProcessing() {
-        return mHandler.mIsProcessing;
-    }
-
     //////////////////////////// DATA DUMP //////////////////////////////
 
     @Override
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/StorageController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/StorageController.java
index 0731918..8678913 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/StorageController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/StorageController.java
@@ -61,9 +61,11 @@
     @Override
     public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
         if (taskStatus.hasStorageNotLowConstraint()) {
+            final long nowElapsed = sElapsedRealtimeClock.millis();
             mTrackedTasks.add(taskStatus);
             taskStatus.setTrackingController(JobStatus.TRACKING_STORAGE);
-            taskStatus.setStorageNotLowConstraintSatisfied(mStorageTracker.isStorageNotLow());
+            taskStatus.setStorageNotLowConstraintSatisfied(
+                    nowElapsed, mStorageTracker.isStorageNotLow());
         }
     }
 
@@ -76,12 +78,13 @@
     }
 
     private void maybeReportNewStorageState() {
+        final long nowElapsed = sElapsedRealtimeClock.millis();
         final boolean storageNotLow = mStorageTracker.isStorageNotLow();
         boolean reportChange = false;
         synchronized (mLock) {
             for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
                 final JobStatus ts = mTrackedTasks.valueAt(i);
-                reportChange |= ts.setStorageNotLowConstraintSatisfied(storageNotLow);
+                reportChange |= ts.setStorageNotLowConstraintSatisfied(nowElapsed, storageNotLow);
             }
         }
         if (storageNotLow) {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
index ede14ec..e8ebfb5 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
@@ -258,9 +258,9 @@
 
         if (jobDeadline <= nowElapsedMillis) {
             if (job.hasTimingDelayConstraint()) {
-                job.setTimingDelayConstraintSatisfied(true);
+                job.setTimingDelayConstraintSatisfied(nowElapsedMillis, true);
             }
-            job.setDeadlineConstraintSatisfied(true);
+            job.setDeadlineConstraintSatisfied(nowElapsedMillis, true);
             return true;
         }
         return false;
@@ -332,7 +332,7 @@
     private boolean evaluateTimingDelayConstraint(JobStatus job, long nowElapsedMillis) {
         final long jobDelayTime = job.getEarliestRunTime();
         if (jobDelayTime <= nowElapsedMillis) {
-            job.setTimingDelayConstraintSatisfied(true);
+            job.setTimingDelayConstraintSatisfied(nowElapsedMillis, true);
             return true;
         }
         return false;
diff --git a/apex/jobscheduler/service/java/com/android/server/job/restrictions/ThermalStatusRestriction.java b/apex/jobscheduler/service/java/com/android/server/job/restrictions/ThermalStatusRestriction.java
index 40c8ce0..954a5b8 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/restrictions/ThermalStatusRestriction.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/restrictions/ThermalStatusRestriction.java
@@ -64,7 +64,7 @@
     @Override
     public void dumpConstants(IndentingPrintWriter pw) {
         pw.print("In thermal throttling?: ");
-        pw.print(mIsThermalRestricted);
+        pw.println(mIsThermalRestricted);
     }
 
     @Override
diff --git a/apex/jobscheduler/service/jni/Android.bp b/apex/jobscheduler/service/jni/Android.bp
index 4bcc165..c630217 100644
--- a/apex/jobscheduler/service/jni/Android.bp
+++ b/apex/jobscheduler/service/jni/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_library_shared {
     name: "libalarm_jni",
 
diff --git a/apex/media/Android.bp b/apex/media/Android.bp
index d6666f5..a75f1ae 100644
--- a/apex/media/Android.bp
+++ b/apex/media/Android.bp
@@ -17,6 +17,12 @@
         "//frameworks/av/apex",
         "//frameworks/av/apex/testing",
     ],
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
 }
 
 sdk {
diff --git a/apex/media/aidl/Android.bp b/apex/media/aidl/Android.bp
index c2b00d5..545a0cd 100644
--- a/apex/media/aidl/Android.bp
+++ b/apex/media/aidl/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "stable-media-aidl-srcs",
     srcs: ["stable/**/*.aidl"],
diff --git a/apex/media/aidl/private/android/media/IMediaCommunicationService.aidl b/apex/media/aidl/private/android/media/IMediaCommunicationService.aidl
index 3d50d14..fb3172b 100644
--- a/apex/media/aidl/private/android/media/IMediaCommunicationService.aidl
+++ b/apex/media/aidl/private/android/media/IMediaCommunicationService.aidl
@@ -15,7 +15,17 @@
  */
 package android.media;
 
+import android.media.Session2Token;
+import android.media.IMediaCommunicationServiceCallback;
+import android.media.MediaParceledListSlice;
+
 /** {@hide} */
 interface IMediaCommunicationService {
+    void notifySession2Created(in Session2Token sessionToken);
+    boolean isTrusted(String controllerPackageName, int controllerPid, int controllerUid);
+    MediaParceledListSlice getSession2Tokens(int userId);
+
+    void registerCallback(IMediaCommunicationServiceCallback callback, String packageName);
+    void unregisterCallback(IMediaCommunicationServiceCallback callback);
 }
 
diff --git a/apex/media/aidl/private/android/media/IMediaCommunicationServiceCallback.aidl b/apex/media/aidl/private/android/media/IMediaCommunicationServiceCallback.aidl
new file mode 100644
index 0000000..3d5321c
--- /dev/null
+++ b/apex/media/aidl/private/android/media/IMediaCommunicationServiceCallback.aidl
@@ -0,0 +1,26 @@
+/**
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media;
+
+import android.media.Session2Token;
+import android.media.MediaParceledListSlice;
+
+/** {@hide} */
+interface IMediaCommunicationServiceCallback {
+    void onSession2Created(in Session2Token token);
+    void onSession2Changed(in MediaParceledListSlice tokens);
+}
+
diff --git a/apex/media/framework/Android.bp b/apex/media/framework/Android.bp
index 5773e4d..b18a22b 100644
--- a/apex/media/framework/Android.bp
+++ b/apex/media/framework/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library {
     name: "updatable-media",
 
diff --git a/apex/media/framework/api/current.txt b/apex/media/framework/api/current.txt
index a2366df..1beef40 100644
--- a/apex/media/framework/api/current.txt
+++ b/apex/media/framework/api/current.txt
@@ -26,6 +26,7 @@
   }
 
   public class MediaCommunicationManager {
+    method @NonNull public java.util.List<android.media.Session2Token> getSession2Tokens();
     method @IntRange(from=1) public int getVersion();
   }
 
diff --git a/apex/media/framework/api/module-lib-current.txt b/apex/media/framework/api/module-lib-current.txt
index ad9114f..eb6397a1 100644
--- a/apex/media/framework/api/module-lib-current.txt
+++ b/apex/media/framework/api/module-lib-current.txt
@@ -1,6 +1,16 @@
 // Signature format: 2.0
 package android.media {
 
+  public class MediaCommunicationManager {
+    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void registerSessionCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaCommunicationManager.SessionCallback);
+    method public void unregisterSessionCallback(@NonNull android.media.MediaCommunicationManager.SessionCallback);
+  }
+
+  public static interface MediaCommunicationManager.SessionCallback {
+    method public default void onSession2TokenCreated(@NonNull android.media.Session2Token);
+    method public default void onSession2TokensChanged(@NonNull java.util.List<android.media.Session2Token>);
+  }
+
   public class MediaFrameworkInitializer {
     method public static void registerServiceWrappers();
     method public static void setMediaServiceManager(@NonNull android.media.MediaServiceManager);
diff --git a/apex/media/framework/java/android/media/Controller2Link.java b/apex/media/framework/java/android/media/Controller2Link.java
index 04185e7..8eefec7 100644
--- a/apex/media/framework/java/android/media/Controller2Link.java
+++ b/apex/media/framework/java/android/media/Controller2Link.java
@@ -26,7 +26,7 @@
 import java.util.Objects;
 
 /**
- * Handles incoming commands from {@link MediaSession2} to both {@link MediaController2}.
+ * Handles incoming commands from {@link MediaSession2} to {@link MediaController2}.
  * @hide
  */
 // @SystemApi
diff --git a/apex/media/framework/java/android/media/MediaCommunicationManager.java b/apex/media/framework/java/android/media/MediaCommunicationManager.java
index e686076..9ec25fe 100644
--- a/apex/media/framework/java/android/media/MediaCommunicationManager.java
+++ b/apex/media/framework/java/android/media/MediaCommunicationManager.java
@@ -15,18 +15,36 @@
  */
 package android.media;
 
+import static android.Manifest.permission.MEDIA_CONTENT_CONTROL;
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+
+import android.annotation.CallbackExecutor;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.content.Context;
+import android.media.session.MediaSession;
+import android.media.session.MediaSessionManager;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.service.media.MediaBrowserService;
+import android.util.Log;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.modules.utils.build.SdkLevel;
 
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Executor;
+
 /**
  * Provides support for interacting with {@link android.media.MediaSession2 MediaSession2s}
  * that applications have published to express their ongoing media playback state.
  */
-// TODO: Add notifySession2Created() and sendMessage().
 @SystemService(Context.MEDIA_COMMUNICATION_SERVICE)
 public class MediaCommunicationManager {
     private static final String TAG = "MediaCommunicationManager";
@@ -44,6 +62,13 @@
     private final Context mContext;
     private final IMediaCommunicationService mService;
 
+    private final Object mLock = new Object();
+    private final CopyOnWriteArrayList<SessionCallbackRecord> mTokenCallbackRecords =
+            new CopyOnWriteArrayList<>();
+
+    @GuardedBy("mLock")
+    private MediaCommunicationServiceCallbackStub mCallbackStub;
+
     /**
      * @hide
      */
@@ -64,4 +89,197 @@
     public @IntRange(from = 1) int getVersion() {
         return CURRENT_VERSION;
     }
+
+    /**
+     * Notifies that a new {@link MediaSession2} with type {@link Session2Token#TYPE_SESSION} is
+     * created.
+     * @param token newly created session2 token
+     * @hide
+     */
+    public void notifySession2Created(@NonNull Session2Token token) {
+        Objects.requireNonNull(token, "token shouldn't be null");
+        if (token.getType() != Session2Token.TYPE_SESSION) {
+            throw new IllegalArgumentException("token's type should be TYPE_SESSION");
+        }
+        try {
+            mService.notifySession2Created(token);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Checks whether the remote user is a trusted app.
+     * <p>
+     * An app is trusted if the app holds the
+     * {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission or has an enabled
+     * notification listener.
+     *
+     * @param userInfo The remote user info from either
+     *            {@link MediaSession#getCurrentControllerInfo()} or
+     *            {@link MediaBrowserService#getCurrentBrowserInfo()}.
+     * @return {@code true} if the remote user is trusted or {@code false} otherwise.
+     * @hide
+     */
+    public boolean isTrustedForMediaControl(@NonNull MediaSessionManager.RemoteUserInfo userInfo) {
+        Objects.requireNonNull(userInfo, "userInfo shouldn't be null");
+        if (userInfo.getPackageName() == null) {
+            return false;
+        }
+        try {
+            return mService.isTrusted(
+                    userInfo.getPackageName(), userInfo.getPid(), userInfo.getUid());
+        } catch (RemoteException e) {
+            Log.w(TAG, "Cannot communicate with the service.", e);
+        }
+        return false;
+    }
+
+    /**
+     * This API is not generally intended for third party application developers.
+     * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
+     * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
+     * Library</a> for consistent behavior across all devices.
+     * <p>
+     * Gets a list of {@link Session2Token} with type {@link Session2Token#TYPE_SESSION} for the
+     * current user.
+     * <p>
+     * Although this API can be used without any restriction, each session owners can accept or
+     * reject your uses of {@link MediaSession2}.
+     *
+     * @return A list of {@link Session2Token}.
+     */
+    @NonNull
+    public List<Session2Token> getSession2Tokens() {
+        return getSession2Tokens(UserHandle.myUserId());
+    }
+
+    /**
+     * Adds a callback to be notified when the list of active sessions changes.
+     * <p>
+     * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be
+     * held by the calling app.
+     * </p>
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    @RequiresPermission(MEDIA_CONTENT_CONTROL)
+    public void registerSessionCallback(@CallbackExecutor @NonNull Executor executor,
+            @NonNull SessionCallback callback) {
+        Objects.requireNonNull(executor, "executor must not be null");
+        Objects.requireNonNull(callback, "callback must not be null");
+
+        if (!mTokenCallbackRecords.addIfAbsent(
+                new SessionCallbackRecord(executor, callback))) {
+            Log.w(TAG, "registerSession2TokenCallback: Ignoring the same callback");
+            return;
+        }
+        synchronized (mLock) {
+            if (mCallbackStub == null) {
+                MediaCommunicationServiceCallbackStub callbackStub =
+                        new MediaCommunicationServiceCallbackStub();
+                try {
+                    mService.registerCallback(callbackStub, mContext.getPackageName());
+                    mCallbackStub = callbackStub;
+                } catch (RemoteException ex) {
+                    Log.e(TAG, "Failed to register callback.", ex);
+                }
+            }
+        }
+    }
+
+    /**
+     * Stops receiving active sessions updates on the specified callback.
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    public void unregisterSessionCallback(@NonNull SessionCallback callback) {
+        if (!mTokenCallbackRecords.remove(
+                new SessionCallbackRecord(null, callback))) {
+            Log.w(TAG, "unregisterSession2TokenCallback: Ignoring an unknown callback.");
+            return;
+        }
+        synchronized (mLock) {
+            if (mCallbackStub != null && mTokenCallbackRecords.isEmpty()) {
+                try {
+                    mService.unregisterCallback(mCallbackStub);
+                } catch (RemoteException ex) {
+                    Log.e(TAG, "Failed to unregister callback.", ex);
+                }
+                mCallbackStub = null;
+            }
+        }
+    }
+
+    private List<Session2Token> getSession2Tokens(int userId) {
+        try {
+            MediaParceledListSlice slice = mService.getSession2Tokens(userId);
+            return slice == null ? Collections.emptyList() : slice.getList();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to get session tokens", e);
+        }
+        return Collections.emptyList();
+    }
+
+    /**
+     * Callback for listening to changes to the sessions.
+     * @see #registerSessionCallback(Executor, SessionCallback)
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    public interface SessionCallback {
+        /**
+         * Called when a new {@link MediaSession2 media session2} is created.
+         * @param token the newly created token
+         */
+        default void onSession2TokenCreated(@NonNull Session2Token token) {}
+
+        /**
+         * Called when {@link #getSession2Tokens() session tokens} are changed.
+         */
+        default void onSession2TokensChanged(@NonNull List<Session2Token> tokens) {}
+    }
+
+    private static final class SessionCallbackRecord {
+        public final Executor executor;
+        public final SessionCallback callback;
+
+        SessionCallbackRecord(Executor executor, SessionCallback callback) {
+            this.executor = executor;
+            this.callback = callback;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(callback);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (!(obj instanceof SessionCallbackRecord)) {
+                return false;
+            }
+            return Objects.equals(this.callback, ((SessionCallbackRecord) obj).callback);
+        }
+    }
+
+    class MediaCommunicationServiceCallbackStub extends IMediaCommunicationServiceCallback.Stub {
+        @Override
+        public void onSession2Created(Session2Token token) throws RemoteException {
+            for (SessionCallbackRecord record : mTokenCallbackRecords) {
+                record.executor.execute(() -> record.callback.onSession2TokenCreated(token));
+            }
+        }
+
+        @Override
+        public void onSession2Changed(MediaParceledListSlice tokens) throws RemoteException {
+            List<Session2Token> tokenList = tokens.getList();
+            for (SessionCallbackRecord record : mTokenCallbackRecords) {
+                record.executor.execute(() -> record.callback.onSession2TokensChanged(tokenList));
+            }
+        }
+    }
 }
diff --git a/apex/media/framework/java/android/media/MediaSession2.java b/apex/media/framework/java/android/media/MediaSession2.java
index 6560afe..6397ba3 100644
--- a/apex/media/framework/java/android/media/MediaSession2.java
+++ b/apex/media/framework/java/android/media/MediaSession2.java
@@ -32,7 +32,6 @@
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
-import android.media.session.MediaSessionManager;
 import android.media.session.MediaSessionManager.RemoteUserInfo;
 import android.os.BadParcelableException;
 import android.os.Bundle;
@@ -87,7 +86,7 @@
     private final String mSessionId;
     private final PendingIntent mSessionActivity;
     private final Session2Token mSessionToken;
-    private final MediaSessionManager mSessionManager;
+    private final MediaCommunicationManager mCommunicationManager;
     private final Handler mResultHandler;
 
     //@GuardedBy("mLock")
@@ -115,8 +114,7 @@
         mSessionStub = new Session2Link(this);
         mSessionToken = new Session2Token(Process.myUid(), TYPE_SESSION, context.getPackageName(),
                 mSessionStub, tokenExtras);
-        mSessionManager = (MediaSessionManager) mContext.getSystemService(
-                Context.MEDIA_SESSION_SERVICE);
+        mCommunicationManager = mContext.getSystemService(MediaCommunicationManager.class);
         // NOTE: mResultHandler uses main looper, so this MUST NOT be blocked.
         mResultHandler = new Handler(context.getMainLooper());
         mClosed = false;
@@ -352,7 +350,7 @@
 
         final ControllerInfo controllerInfo = new ControllerInfo(
                 remoteUserInfo,
-                mSessionManager.isTrustedForMediaControl(remoteUserInfo),
+                mCommunicationManager.isTrustedForMediaControl(remoteUserInfo),
                 controller,
                 connectionHints);
         mCallbackExecutor.execute(() -> {
@@ -608,8 +606,8 @@
             // Notify framework about the newly create session after the constructor is finished.
             // Otherwise, framework may access the session before the initialization is finished.
             try {
-                MediaSessionManager manager = (MediaSessionManager) mContext.getSystemService(
-                        Context.MEDIA_SESSION_SERVICE);
+                MediaCommunicationManager manager =
+                        mContext.getSystemService(MediaCommunicationManager.class);
                 manager.notifySession2Created(session2.getToken());
             } catch (Exception e) {
                 session2.close();
diff --git a/apex/media/framework/java/android/media/MediaTranscodeManager.java b/apex/media/framework/java/android/media/MediaTranscodeManager.java
index c924d9a..ca5aeb8 100644
--- a/apex/media/framework/java/android/media/MediaTranscodeManager.java
+++ b/apex/media/framework/java/android/media/MediaTranscodeManager.java
@@ -295,8 +295,8 @@
                 /* ignore */
             }
         }
-
-        throw new UnsupportedOperationException("Failed to connect to MediaTranscoding service");
+        Log.w(TAG, "Failed to get service");
+        return null;
     }
 
     /*
@@ -463,8 +463,7 @@
                 }
             };
 
-    private ITranscodingClient registerClient(IMediaTranscodingService service)
-            throws UnsupportedOperationException {
+    private ITranscodingClient registerClient(IMediaTranscodingService service) {
         synchronized (mLock) {
             try {
                 // Registers the client with MediaTranscoding service.
@@ -476,13 +475,12 @@
                 if (mTranscodingClient != null) {
                     mTranscodingClient.asBinder().linkToDeath(() -> onClientDied(), /* flags */ 0);
                 }
-                return mTranscodingClient;
-            } catch (RemoteException re) {
-                Log.e(TAG, "Failed to register new client due to exception " + re);
+            } catch (Exception ex) {
+                Log.e(TAG, "Failed to register new client due to exception " + ex);
                 mTranscodingClient = null;
             }
         }
-        throw new UnsupportedOperationException("Failed to register new client");
+        return mTranscodingClient;
     }
 
     /**
@@ -495,7 +493,9 @@
         mUid = Os.getuid();
         mPid = Os.getpid();
         IMediaTranscodingService service = getService(false /*retry*/);
-        mTranscodingClient = registerClient(service);
+        if (service != null) {
+            mTranscodingClient = registerClient(service);
+        }
     }
 
     public static final class TranscodingRequest {
@@ -1567,6 +1567,10 @@
                     if (mTranscodingClient == null) {
                         // Try to register with the service again.
                         IMediaTranscodingService service = getService(false /*retry*/);
+                        if (service == null) {
+                            throw new MediaTranscodingException.ServiceNotAvailableException(
+                                    "Service rebooting. Try again later");
+                        }
                         mTranscodingClient = registerClient(service);
                         // If still fails, throws an exception to tell client to try later.
                         if (mTranscodingClient == null) {
diff --git a/apex/media/service/Android.bp b/apex/media/service/Android.bp
index 5b24cfa..9b3399e 100644
--- a/apex/media/service/Android.bp
+++ b/apex/media/service/Android.bp
@@ -11,6 +11,15 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "service-media-s-sources",
     srcs: [
@@ -38,4 +47,3 @@
         "com.android.media",
     ],
 }
-
diff --git a/apex/media/service/java/com/android/server/media/MediaCommunicationService.java b/apex/media/service/java/com/android/server/media/MediaCommunicationService.java
index 0468fdf..06de3f8 100644
--- a/apex/media/service/java/com/android/server/media/MediaCommunicationService.java
+++ b/apex/media/service/java/com/android/server/media/MediaCommunicationService.java
@@ -15,27 +15,538 @@
  */
 package com.android.server.media;
 
-import android.content.Context;
-import android.media.IMediaCommunicationService;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+import static android.os.UserHandle.ALL;
+import static android.os.UserHandle.getUserHandleForUid;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.media.IMediaCommunicationService;
+import android.media.IMediaCommunicationServiceCallback;
+import android.media.MediaController2;
+import android.media.MediaParceledListSlice;
+import android.media.Session2CommandGroup;
+import android.media.Session2Token;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+
+import com.android.internal.annotations.GuardedBy;
 import com.android.server.SystemService;
 
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
+
 /**
- * A system service that managers {@link android.media.MediaSession2} creations
+ * A system service that manages {@link android.media.MediaSession2} creations
  * and their ongoing media playback state.
  * @hide
  */
 public class MediaCommunicationService extends SystemService {
+    private static final String TAG = "MediaCommunicationService";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    final Context mContext;
+
+    private final Object mLock = new Object();
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
+
+    @GuardedBy("mLock")
+    private final SparseIntArray mFullUserIds = new SparseIntArray();
+    @GuardedBy("mLock")
+    private final SparseArray<FullUserRecord> mUserRecords = new SparseArray<>();
+
+    private final Executor mRecordExecutor = Executors.newSingleThreadExecutor();
+    @GuardedBy("mLock")
+    private final List<CallbackRecord> mCallbackRecords = new ArrayList<>();
+    final NotificationManager mNotificationManager;
 
     public MediaCommunicationService(Context context) {
         super(context);
+        mContext = context;
+        mNotificationManager = context.getSystemService(NotificationManager.class);
     }
 
     @Override
     public void onStart() {
         publishBinderService(Context.MEDIA_COMMUNICATION_SERVICE, new Stub());
+        updateUser();
+    }
+
+    @Override
+    public void onUserStarting(@NonNull TargetUser user) {
+        if (DEBUG) Log.d(TAG, "onUserStarting: " + user);
+        updateUser();
+    }
+
+    @Override
+    public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
+        if (DEBUG) Log.d(TAG, "onUserSwitching: " + to);
+        updateUser();
+    }
+
+    @Override
+    public void onUserStopped(@NonNull TargetUser targetUser) {
+        int userId = targetUser.getUserHandle().getIdentifier();
+
+        if (DEBUG) Log.d(TAG, "onUserStopped: " + userId);
+        synchronized (mLock) {
+            FullUserRecord user = getFullUserRecordLocked(userId);
+            if (user != null) {
+                if (user.getFullUserId() == userId) {
+                    user.destroySessionsForUserLocked(UserHandle.ALL.getIdentifier());
+                    mUserRecords.remove(userId);
+                } else {
+                    user.destroySessionsForUserLocked(userId);
+                }
+            }
+            updateUser();
+        }
+    }
+
+    @Nullable
+    CallbackRecord findCallbackRecordLocked(@Nullable IMediaCommunicationServiceCallback callback) {
+        if (callback == null) {
+            return null;
+        }
+        for (CallbackRecord record : mCallbackRecords) {
+            if (Objects.equals(callback.asBinder(), record.mCallback.asBinder())) {
+                return record;
+            }
+        }
+        return null;
+    }
+
+    private FullUserRecord getFullUserRecordLocked(int userId) {
+        int fullUserId = mFullUserIds.get(userId, -1);
+        if (fullUserId < 0) {
+            return null;
+        }
+        return mUserRecords.get(fullUserId);
+    }
+
+    private boolean hasMediaControlPermission(int pid, int uid) {
+        // Check if it's system server or has MEDIA_CONTENT_CONTROL.
+        // Note that system server doesn't have MEDIA_CONTENT_CONTROL, so we need extra
+        // check here.
+        if (uid == Process.SYSTEM_UID || mContext.checkPermission(
+                android.Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid)
+                == PackageManager.PERMISSION_GRANTED) {
+            return true;
+        } else if (DEBUG) {
+            Log.d(TAG, "uid(" + uid + ") hasn't granted MEDIA_CONTENT_CONTROL");
+        }
+        return false;
+    }
+
+    private void updateUser() {
+        UserManager manager = mContext.getSystemService(UserManager.class);
+        List<UserHandle> allUsers = manager.getUserHandles(/*excludeDying=*/false);
+
+        synchronized (mLock) {
+            mFullUserIds.clear();
+            if (allUsers != null) {
+                for (UserHandle user : allUsers) {
+                    UserHandle parent = manager.getProfileParent(user);
+                    if (parent != null) {
+                        mFullUserIds.put(user.getIdentifier(), parent.getIdentifier());
+                    } else {
+                        mFullUserIds.put(user.getIdentifier(), user.getIdentifier());
+                        if (mUserRecords.get(user.getIdentifier()) == null) {
+                            mUserRecords.put(user.getIdentifier(),
+                                    new FullUserRecord(user.getIdentifier()));
+                        }
+                    }
+                }
+            }
+            // Ensure that the current full user exists.
+            int currentFullUserId = ActivityManager.getCurrentUser();
+            FullUserRecord currentFullUserRecord = mUserRecords.get(currentFullUserId);
+            if (currentFullUserRecord == null) {
+                Log.w(TAG, "Cannot find FullUserInfo for the current user " + currentFullUserId);
+                currentFullUserRecord = new FullUserRecord(currentFullUserId);
+                mUserRecords.put(currentFullUserId, currentFullUserRecord);
+            }
+            mFullUserIds.put(currentFullUserId, currentFullUserId);
+        }
+    }
+
+    void dispatchSessionCreated(Session2Token token) {
+        for (CallbackRecord record : mCallbackRecords) {
+            if (record.mUserId != ALL.getIdentifier()
+                    && record.mUserId != getUserHandleForUid(token.getUid()).getIdentifier()) {
+                continue;
+            }
+            try {
+                record.mCallback.onSession2Created(token);
+            } catch (RemoteException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    void onSessionDied(Session2Record record) {
+        synchronized (mLock) {
+            destroySessionLocked(record);
+        }
+    }
+
+    private void destroySessionLocked(Session2Record session) {
+        if (DEBUG) {
+            Log.d(TAG, "Destroying " + session);
+        }
+        if (session.isClosed()) {
+            Log.w(TAG, "Destroying already destroyed session. Ignoring.");
+            return;
+        }
+
+        FullUserRecord user = getFullUserRecordLocked(session.getUserId());
+
+        if (user != null) {
+            user.removeSession(session);
+        }
+
+        session.close();
     }
 
     private class Stub extends IMediaCommunicationService.Stub {
+        @Override
+        public void notifySession2Created(Session2Token sessionToken) {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+
+            try {
+                if (DEBUG) {
+                    Log.d(TAG, "Session2 is created " + sessionToken);
+                }
+                if (uid != sessionToken.getUid()) {
+                    throw new SecurityException("Unexpected Session2Token's UID, expected=" + uid
+                            + " but actually=" + sessionToken.getUid());
+                }
+                synchronized (mLock) {
+                    int userId = getUserHandleForUid(sessionToken.getUid()).getIdentifier();
+                    FullUserRecord user = getFullUserRecordLocked(userId);
+                    if (user == null) {
+                        Log.w(TAG, "notifySession2Created: Ignore session of an unknown user");
+                        return;
+                    }
+                    user.addSession(new Session2Record(MediaCommunicationService.this,
+                            sessionToken, mRecordExecutor));
+                    mHandler.post(() -> dispatchSessionCreated(sessionToken));
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        /**
+         * Returns if the controller's package is trusted (i.e. has either MEDIA_CONTENT_CONTROL
+         * permission or an enabled notification listener)
+         *
+         * @param controllerPackageName package name of the controller app
+         * @param controllerPid pid of the controller app
+         * @param controllerUid uid of the controller app
+         */
+        @Override
+        public boolean isTrusted(String controllerPackageName, int controllerPid,
+                int controllerUid) {
+            final int uid = Binder.getCallingUid();
+            final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
+            final long token = Binder.clearCallingIdentity();
+            try {
+                // Don't perform check between controllerPackageName and controllerUid.
+                // When an (activity|service) runs on the another apps process by specifying
+                // android:process in the AndroidManifest.xml, then PID and UID would have the
+                // running process' information instead of the (activity|service) that has created
+                // MediaController.
+                // Note that we can use Context#getOpPackageName() instead of
+                // Context#getPackageName() for getting package name that matches with the PID/UID,
+                // but it doesn't tell which package has created the MediaController, so useless.
+                return hasMediaControlPermission(controllerPid, controllerUid)
+                        || hasEnabledNotificationListener(
+                        userId, controllerPackageName, controllerUid);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public MediaParceledListSlice getSession2Tokens(int userId) {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+
+            try {
+                // Check that they can make calls on behalf of the user and get the final user id
+                int resolvedUserId = handleIncomingUser(pid, uid, userId, null);
+                List<Session2Token> result;
+                synchronized (mLock) {
+                    FullUserRecord user = getFullUserRecordLocked(userId);
+                    result = user.getSession2Tokens(resolvedUserId);
+                }
+                return new MediaParceledListSlice(result);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void registerCallback(IMediaCommunicationServiceCallback callback,
+                String packageName) throws RemoteException {
+            Objects.requireNonNull(callback, "callback should not be null");
+            Objects.requireNonNull(packageName, "packageName should not be null");
+
+            synchronized (mLock) {
+                if (findCallbackRecordLocked(callback) == null) {
+
+                    CallbackRecord record = new CallbackRecord(callback, packageName,
+                            Binder.getCallingUid(), Binder.getCallingPid());
+                    mCallbackRecords.add(record);
+                    try {
+                        callback.asBinder().linkToDeath(record, 0);
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "Failed to register callback", e);
+                        mCallbackRecords.remove(record);
+                    }
+                } else {
+                    Log.e(TAG, "registerCallback is called with already registered callback. "
+                            + "packageName=" + packageName);
+                }
+            }
+        }
+
+        @Override
+        public void unregisterCallback(IMediaCommunicationServiceCallback callback)
+                throws RemoteException {
+            synchronized (mLock) {
+                CallbackRecord existingRecord = findCallbackRecordLocked(callback);
+                if (existingRecord != null) {
+                    mCallbackRecords.remove(existingRecord);
+                    callback.asBinder().unlinkToDeath(existingRecord, 0);
+                } else {
+                    Log.e(TAG, "unregisterCallback is called with unregistered callback.");
+                }
+            }
+        }
+
+        private boolean hasEnabledNotificationListener(int callingUserId,
+                String controllerPackageName, int controllerUid) {
+            int controllerUserId = UserHandle.getUserHandleForUid(controllerUid).getIdentifier();
+            if (callingUserId != controllerUserId) {
+                // Enabled notification listener only works within the same user.
+                return false;
+            }
+
+            if (mNotificationManager.hasEnabledNotificationListener(controllerPackageName,
+                    UserHandle.getUserHandleForUid(controllerUid))) {
+                return true;
+            }
+            if (DEBUG) {
+                Log.d(TAG, controllerPackageName + " (uid=" + controllerUid
+                        + ") doesn't have an enabled notification listener");
+            }
+            return false;
+        }
+
+        // Handles incoming user by checking whether the caller has permission to access the
+        // given user id's information or not. Permission is not necessary if the given user id is
+        // equal to the caller's user id, but if not, the caller needs to have the
+        // INTERACT_ACROSS_USERS_FULL permission. Otherwise, a security exception will be thrown.
+        // The return value will be the given user id, unless the given user id is
+        // UserHandle.CURRENT, which will return the ActivityManager.getCurrentUser() value instead.
+        private int handleIncomingUser(int pid, int uid, int userId, String packageName) {
+            int callingUserId = UserHandle.getUserHandleForUid(uid).getIdentifier();
+            if (userId == callingUserId) {
+                return userId;
+            }
+
+            boolean canInteractAcrossUsersFull = mContext.checkPermission(
+                    INTERACT_ACROSS_USERS_FULL, pid, uid) == PackageManager.PERMISSION_GRANTED;
+            if (canInteractAcrossUsersFull) {
+                if (userId == UserHandle.CURRENT.getIdentifier()) {
+                    return ActivityManager.getCurrentUser();
+                }
+                return userId;
+            }
+
+            throw new SecurityException("Permission denied while calling from " + packageName
+                    + " with user id: " + userId + "; Need to run as either the calling user id ("
+                    + callingUserId + "), or with " + INTERACT_ACROSS_USERS_FULL + " permission");
+        }
+    }
+
+    final class CallbackRecord implements IBinder.DeathRecipient {
+        private final IMediaCommunicationServiceCallback mCallback;
+        private final String mPackageName;
+        private final int mUid;
+        private int mPid;
+        private final int mUserId;
+
+        CallbackRecord(IMediaCommunicationServiceCallback callback,
+                String packageName, int uid, int pid) {
+            mCallback = callback;
+            mPackageName = packageName;
+            mUid = uid;
+            mPid = pid;
+            mUserId = (mContext.checkPermission(
+                    INTERACT_ACROSS_USERS_FULL, pid, uid) == PackageManager.PERMISSION_GRANTED)
+                    ? ALL.getIdentifier() : UserHandle.getUserHandleForUid(mUid).getIdentifier();
+        }
+
+        @Override
+        public String toString() {
+            return "CallbackRecord[callback=" + mCallback + ", pkg=" + mPackageName
+                    + ", uid=" + mUid + ", pid=" + mPid + "]";
+        }
+
+        @Override
+        public void binderDied() {
+            synchronized (mLock) {
+                mCallbackRecords.remove(this);
+            }
+        }
+    }
+
+    final class FullUserRecord {
+        private final int mFullUserId;
+        /** Sorted list of media sessions */
+        private final List<Session2Record> mSessionRecords = new ArrayList<>();
+
+        FullUserRecord(int fullUserId) {
+            mFullUserId = fullUserId;
+        }
+
+        public void addSession(Session2Record record) {
+            mSessionRecords.add(record);
+        }
+
+        public void removeSession(Session2Record record) {
+            mSessionRecords.remove(record);
+            //TODO: Handle if the removed session was the media button session.
+        }
+
+        public int getFullUserId() {
+            return mFullUserId;
+        }
+
+        public List<Session2Token> getSession2Tokens(int userId) {
+            return mSessionRecords.stream()
+                    .filter(record -> record.isActive()
+                            && (userId == UserHandle.ALL.getIdentifier()
+                                    || record.getUserId() == userId))
+                    .map(Session2Record::getSessionToken)
+                    .collect(Collectors.toList());
+        }
+
+        public void destroySessionsForUserLocked(int userId) {
+            synchronized (mLock) {
+                for (Session2Record record : mSessionRecords) {
+                    if (userId == UserHandle.ALL.getIdentifier()
+                            || record.getUserId() == userId) {
+                        destroySessionLocked(record);
+                    }
+                }
+            }
+        }
+    }
+
+    static final class Session2Record {
+        private final Session2Token mSessionToken;
+        private final Object mLock = new Object();
+        private final WeakReference<MediaCommunicationService> mServiceRef;
+        @GuardedBy("mLock")
+        private final MediaController2 mController;
+
+        @GuardedBy("mLock")
+        private boolean mIsConnected;
+        @GuardedBy("mLock")
+        private boolean mIsClosed;
+
+        Session2Record(MediaCommunicationService service, Session2Token token,
+                Executor controllerExecutor) {
+            mServiceRef = new WeakReference<>(service);
+            mSessionToken = token;
+            mController = new MediaController2.Builder(service.getContext(), token)
+                    .setControllerCallback(controllerExecutor, new Controller2Callback())
+                    .build();
+        }
+
+        public int getUserId() {
+            return UserHandle.getUserHandleForUid(mSessionToken.getUid()).getIdentifier();
+        }
+
+        public boolean isActive() {
+            synchronized (mLock) {
+                return mIsConnected;
+            }
+        }
+
+        public boolean isClosed() {
+            synchronized (mLock) {
+                return mIsClosed;
+            }
+        }
+
+        public void close() {
+            synchronized (mLock) {
+                mIsClosed = true;
+                // Call close regardless of the mIsConnected. This may be called when it's not yet
+                // connected.
+                mController.close();
+            }
+        }
+
+        public Session2Token getSessionToken() {
+            return mSessionToken;
+        }
+
+        private class Controller2Callback extends MediaController2.ControllerCallback {
+            @Override
+            public void onConnected(MediaController2 controller,
+                    Session2CommandGroup allowedCommands) {
+                if (DEBUG) {
+                    Log.d(TAG, "connected to " + mSessionToken + ", allowed=" + allowedCommands);
+                }
+                synchronized (mLock) {
+                    mIsConnected = true;
+                }
+                MediaCommunicationService service = mServiceRef.get();
+                if (service != null) {
+                    //TODO: notify session state changed
+                }
+            }
+
+            @Override
+            public void onDisconnected(MediaController2 controller) {
+                if (DEBUG) {
+                    Log.d(TAG, "disconnected from " + mSessionToken);
+                }
+                synchronized (mLock) {
+                    mIsConnected = false;
+                }
+                MediaCommunicationService service = mServiceRef.get();
+                if (service != null) {
+                    service.onSessionDied(Session2Record.this);
+                }
+            }
+        }
     }
 }
diff --git a/api/Android.bp b/api/Android.bp
index 5466bd2..1d4698e 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -14,6 +14,14 @@
 
 package {
     default_visibility: ["//visibility:private"],
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_base_license"],
 }
 
 genrule {
@@ -32,6 +40,7 @@
         ":art.module.public.api{.public.api.txt}",
         ":conscrypt.module.public.api{.public.api.txt}",
         ":framework-appsearch{.public.api.txt}",
+        ":framework-connectivity{.public.api.txt}",
         ":framework-graphics{.public.api.txt}",
         ":framework-media{.public.api.txt}",
         ":framework-mediaprovider{.public.api.txt}",
@@ -87,6 +96,7 @@
         ":art.module.public.api{.public.stubs.source}",
         ":conscrypt.module.public.api{.public.stubs.source}",
         ":framework-appsearch{.public.stubs.source}",
+        ":framework-connectivity{.public.stubs.source}",
         ":framework-graphics{.public.stubs.source}",
         ":framework-media{.public.stubs.source}",
         ":framework-mediaprovider{.public.stubs.source}",
@@ -112,6 +122,7 @@
         ":art.module.public.api{.public.removed-api.txt}",
         ":conscrypt.module.public.api{.public.removed-api.txt}",
         ":framework-appsearch{.public.removed-api.txt}",
+        ":framework-connectivity{.public.removed-api.txt}",
         ":framework-graphics{.public.removed-api.txt}",
         ":framework-media{.public.removed-api.txt}",
         ":framework-mediaprovider{.public.removed-api.txt}",
@@ -147,6 +158,7 @@
     srcs: [
         ":android.net.ipsec.ike{.system.api.txt}",
         ":framework-appsearch{.system.api.txt}",
+        ":framework-connectivity{.system.api.txt}",
         ":framework-graphics{.system.api.txt}",
         ":framework-media{.system.api.txt}",
         ":framework-mediaprovider{.system.api.txt}",
@@ -200,6 +212,7 @@
     srcs: [
         ":android.net.ipsec.ike{.system.removed-api.txt}",
         ":framework-appsearch{.system.removed-api.txt}",
+        ":framework-connectivity{.system.removed-api.txt}",
         ":framework-graphics{.system.removed-api.txt}",
         ":framework-media{.system.removed-api.txt}",
         ":framework-mediaprovider{.system.removed-api.txt}",
@@ -235,6 +248,7 @@
     srcs: [
         ":android.net.ipsec.ike{.module-lib.api.txt}",
         ":framework-appsearch{.module-lib.api.txt}",
+        ":framework-connectivity{.module-lib.api.txt}",
         ":framework-graphics{.module-lib.api.txt}",
         ":framework-media{.module-lib.api.txt}",
         ":framework-mediaprovider{.module-lib.api.txt}",
@@ -290,6 +304,7 @@
     srcs: [
         ":android.net.ipsec.ike{.module-lib.removed-api.txt}",
         ":framework-appsearch{.module-lib.removed-api.txt}",
+        ":framework-connectivity{.module-lib.removed-api.txt}",
         ":framework-graphics{.module-lib.removed-api.txt}",
         ":framework-media{.module-lib.removed-api.txt}",
         ":framework-mediaprovider{.module-lib.removed-api.txt}",
diff --git a/boot/Android.bp b/boot/Android.bp
index dd4066a..4f7c44e 100644
--- a/boot/Android.bp
+++ b/boot/Android.bp
@@ -12,6 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 boot_image {
     name: "framework-boot-image",
     image_name: "boot",
diff --git a/cmds/abx/Android.bp b/cmds/abx/Android.bp
index 333aced..50a0b75 100644
--- a/cmds/abx/Android.bp
+++ b/cmds/abx/Android.bp
@@ -1,4 +1,21 @@
 
+package {
+    default_applicable_licenses: ["frameworks_base_cmds_abx_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_cmds_abx_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 java_binary {
     name: "abx",
     wrapper: "abx",
diff --git a/cmds/am/Android.bp b/cmds/am/Android.bp
index ed73d55..7bb9675 100644
--- a/cmds/am/Android.bp
+++ b/cmds/am/Android.bp
@@ -1,6 +1,23 @@
 // Copyright 2008 The Android Open Source Project
 //
 
+package {
+    default_applicable_licenses: ["frameworks_base_cmds_am_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_cmds_am_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_library_host_static {
     name: "libinstrumentation",
     srcs: ["**/*.proto"],
diff --git a/cmds/app_process/Android.bp b/cmds/app_process/Android.bp
index 14ebb71..4e5b3ba 100644
--- a/cmds/app_process/Android.bp
+++ b/cmds/app_process/Android.bp
@@ -1,3 +1,20 @@
+package {
+    default_applicable_licenses: ["frameworks_base_cmds_app_process_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_cmds_app_process_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_binary {
     name: "app_process",
 
diff --git a/cmds/appops/Android.bp b/cmds/appops/Android.bp
index 9f330fa..80f8ec6 100644
--- a/cmds/appops/Android.bp
+++ b/cmds/appops/Android.bp
@@ -1,5 +1,22 @@
 // Copyright 2014 The Android Open Source Project
 
+package {
+    default_applicable_licenses: ["frameworks_base_cmds_appops_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_cmds_appops_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 sh_binary {
     name: "appops",
     src: "appops",
diff --git a/cmds/appwidget/Android.bp b/cmds/appwidget/Android.bp
index 487d3e1..8049038 100644
--- a/cmds/appwidget/Android.bp
+++ b/cmds/appwidget/Android.bp
@@ -1,5 +1,22 @@
 // Copyright 2014 The Android Open Source Project
 
+package {
+    default_applicable_licenses: ["frameworks_base_cmds_appwidget_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_cmds_appwidget_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 java_binary {
     name: "appwidget",
     wrapper: "appwidget",
diff --git a/cmds/backup/Android.bp b/cmds/backup/Android.bp
index 287c23b..5e2a56e 100644
--- a/cmds/backup/Android.bp
+++ b/cmds/backup/Android.bp
@@ -1,5 +1,22 @@
 // Copyright 2009 The Android Open Source Project
 
+package {
+    default_applicable_licenses: ["frameworks_base_cmds_backup_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_cmds_backup_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_binary {
     name: "btool",
 
diff --git a/cmds/bmgr/Android.bp b/cmds/bmgr/Android.bp
index b64923b..14beb55 100644
--- a/cmds/bmgr/Android.bp
+++ b/cmds/bmgr/Android.bp
@@ -1,6 +1,23 @@
 // Copyright 2007 The Android Open Source Project
 //
 
+package {
+    default_applicable_licenses: ["frameworks_base_cmds_bmgr_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_cmds_bmgr_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 java_binary {
     name: "bmgr",
     wrapper: "bmgr",
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index 4b7eda0..ed717c4 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -19,7 +19,6 @@
 import android.annotation.IntDef;
 import android.annotation.UserIdInt;
 import android.app.backup.BackupManager;
-import android.app.backup.BackupManager.OperationType;
 import android.app.backup.BackupManagerMonitor;
 import android.app.backup.BackupProgress;
 import android.app.backup.BackupTransport;
@@ -667,7 +666,7 @@
 
         // The rest of the 'list' options work with a restore session on the current transport
         try {
-            mRestore = mBmgr.beginRestoreSessionForUser(userId, null, null, OperationType.BACKUP);
+            mRestore = mBmgr.beginRestoreSessionForUser(userId, null, null);
             if (mRestore == null) {
                 System.err.println(BMGR_ERR_NO_RESTORESESSION_FOR_USER + userId);
                 return;
@@ -822,7 +821,7 @@
 
         try {
             boolean didRestore = false;
-            mRestore = mBmgr.beginRestoreSessionForUser(userId, null, null, OperationType.BACKUP);
+            mRestore = mBmgr.beginRestoreSessionForUser(userId, null, null);
             if (mRestore == null) {
                 System.err.println(BMGR_ERR_NO_RESTORESESSION_FOR_USER + userId);
                 return;
diff --git a/cmds/bootanimation/Android.bp b/cmds/bootanimation/Android.bp
index 0f56997..b2b66c2 100644
--- a/cmds/bootanimation/Android.bp
+++ b/cmds/bootanimation/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_defaults {
     name: "bootanimation_defaults",
 
diff --git a/cmds/bu/Android.bp b/cmds/bu/Android.bp
index 0866ee0..5b4ec31 100644
--- a/cmds/bu/Android.bp
+++ b/cmds/bu/Android.bp
@@ -1,6 +1,23 @@
 // Copyright 2011 The Android Open Source Project
 //
 
+package {
+    default_applicable_licenses: ["frameworks_base_cmds_bu_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_cmds_bu_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 java_binary {
     name: "bu",
     wrapper: "bu",
diff --git a/cmds/content/Android.bp b/cmds/content/Android.bp
index 96d1469..c70d01e 100644
--- a/cmds/content/Android.bp
+++ b/cmds/content/Android.bp
@@ -1,5 +1,22 @@
 // Copyright 2012 The Android Open Source Project
 
+package {
+    default_applicable_licenses: ["frameworks_base_cmds_content_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_cmds_content_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 java_binary {
     name: "content",
     wrapper: "content",
diff --git a/cmds/device_config/Android.bp b/cmds/device_config/Android.bp
index 67e014a..69572d8 100644
--- a/cmds/device_config/Android.bp
+++ b/cmds/device_config/Android.bp
@@ -1,6 +1,17 @@
 // Copyright 2018 The Android Open Source Project
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 sh_binary {
     name: "device_config",
     src: "device_config",
diff --git a/cmds/dpm/Android.bp b/cmds/dpm/Android.bp
index 753121e..665abcd 100644
--- a/cmds/dpm/Android.bp
+++ b/cmds/dpm/Android.bp
@@ -1,6 +1,23 @@
 // Copyright 2014 The Android Open Source Project
 //
 
+package {
+    default_applicable_licenses: ["frameworks_base_cmds_dpm_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_cmds_dpm_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 java_binary {
     name: "dpm",
     wrapper: "dpm",
diff --git a/cmds/hid/Android.bp b/cmds/hid/Android.bp
index 54c8bf3..295c71c 100644
--- a/cmds/hid/Android.bp
+++ b/cmds/hid/Android.bp
@@ -1,6 +1,23 @@
 // Copyright 2015 The Android Open Source Project
 //
 
+package {
+    default_applicable_licenses: ["frameworks_base_cmds_hid_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_cmds_hid_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 java_binary {
     name: "hid",
     wrapper: "hid",
diff --git a/cmds/hid/OWNERS b/cmds/hid/OWNERS
new file mode 100644
index 0000000..d701f23
--- /dev/null
+++ b/cmds/hid/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/hardware/input/OWNERS
diff --git a/cmds/hid/jni/Android.bp b/cmds/hid/jni/Android.bp
index 2c07de0..11d9290 100644
--- a/cmds/hid/jni/Android.bp
+++ b/cmds/hid/jni/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_cmds_hid_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_cmds_hid_license"],
+}
+
 cc_library_shared {
     name: "libhidcommand_jni",
 
diff --git a/cmds/hid/jni/com_android_commands_hid_Device.cpp b/cmds/hid/jni/com_android_commands_hid_Device.cpp
index 437a87e..2cda57d 100644
--- a/cmds/hid/jni/com_android_commands_hid_Device.cpp
+++ b/cmds/hid/jni/com_android_commands_hid_Device.cpp
@@ -48,6 +48,7 @@
 static struct {
     jmethodID onDeviceOpen;
     jmethodID onDeviceGetReport;
+    jmethodID onDeviceSetReport;
     jmethodID onDeviceOutput;
     jmethodID onDeviceError;
 } gDeviceCallbackClassInfo;
@@ -113,7 +114,16 @@
     checkAndClearException(env, "onDeviceGetReport");
 }
 
-void DeviceCallback::onDeviceOutput(uint8_t rType, const std::vector<uint8_t>& data) {
+void DeviceCallback::onDeviceSetReport(uint8_t rType,
+                                    const std::vector<uint8_t>& data) {
+    JNIEnv* env = getJNIEnv();
+    env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceSetReport, rType,
+                        toJbyteArray(env, data).get());
+    checkAndClearException(env, "onDeviceSetReport");
+}
+
+void DeviceCallback::onDeviceOutput(uint8_t rType,
+                                    const std::vector<uint8_t>& data) {
     JNIEnv* env = getJNIEnv();
     env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceOutput, rType,
                         toJbyteArray(env, data).get());
@@ -261,6 +271,7 @@
                 ALOGD("Received SET_REPORT: id=%" PRIu32 " rnum=%" PRIu8 " data=%s", set_report.id,
                       set_report.rnum, toString(data).c_str());
             }
+            mDeviceCallback->onDeviceSetReport(set_report.rtype, data);
             break;
         }
         case UHID_OUTPUT: {
@@ -364,6 +375,8 @@
             env->GetMethodID(clazz, "onDeviceOpen", "()V");
     uhid::gDeviceCallbackClassInfo.onDeviceGetReport =
             env->GetMethodID(clazz, "onDeviceGetReport", "(II)V");
+    uhid::gDeviceCallbackClassInfo.onDeviceSetReport =
+            env->GetMethodID(clazz, "onDeviceSetReport", "(B[B)V");
     uhid::gDeviceCallbackClassInfo.onDeviceOutput =
             env->GetMethodID(clazz, "onDeviceOutput", "(B[B)V");
     uhid::gDeviceCallbackClassInfo.onDeviceError =
diff --git a/cmds/hid/jni/com_android_commands_hid_Device.h b/cmds/hid/jni/com_android_commands_hid_Device.h
index 5483b40..d10a9aa 100644
--- a/cmds/hid/jni/com_android_commands_hid_Device.h
+++ b/cmds/hid/jni/com_android_commands_hid_Device.h
@@ -31,6 +31,7 @@
 
     void onDeviceOpen();
     void onDeviceGetReport(uint32_t requestId, uint8_t reportId);
+    void onDeviceSetReport(uint8_t rType, const std::vector<uint8_t>& data);
     void onDeviceOutput(uint8_t rType, const std::vector<uint8_t>& data);
     void onDeviceError();
 
diff --git a/cmds/hid/src/com/android/commands/hid/Device.java b/cmds/hid/src/com/android/commands/hid/Device.java
index 20b4bd8..95b1e9a 100644
--- a/cmds/hid/src/com/android/commands/hid/Device.java
+++ b/cmds/hid/src/com/android/commands/hid/Device.java
@@ -46,7 +46,8 @@
 
     // Sync with linux uhid_event_type::UHID_OUTPUT
     private static final byte UHID_EVENT_TYPE_UHID_OUTPUT = 6;
-
+    // Sync with linux uhid_event_type::UHID_SET_REPORT
+    private static final byte UHID_EVENT_TYPE_SET_REPORT = 13;
     private final int mId;
     private final HandlerThread mThread;
     private final DeviceHandler mHandler;
@@ -198,11 +199,11 @@
             mHandler.sendMessageAtTime(msg, mTimeToSend);
         }
 
-        // native callback
-        public void onDeviceOutput(byte rtype, byte[] data) {
+        // Send out the report to HID command output
+        private void sendReportOutput(byte eventId, byte rtype, byte[] data) {
             JSONObject json = new JSONObject();
             try {
-                json.put("eventId", UHID_EVENT_TYPE_UHID_OUTPUT);
+                json.put("eventId", eventId);
                 json.put("deviceId", mId);
                 json.put("reportType", rtype);
                 JSONArray dataArray = new JSONArray();
@@ -220,6 +221,18 @@
                 throw new RuntimeException(e);
             }
 
+        }
+
+        // native callback
+        public void onDeviceSetReport(byte rtype, byte[] data) {
+            // We don't need to reply for the SET_REPORT but just send it to HID output for test
+            // verification.
+            sendReportOutput(UHID_EVENT_TYPE_SET_REPORT, rtype, data);
+        }
+
+        // native callback
+        public void onDeviceOutput(byte rtype, byte[] data) {
+            sendReportOutput(UHID_EVENT_TYPE_UHID_OUTPUT, rtype, data);
             if (mOutputs == null) {
                 Log.e(TAG, "Received OUTPUT request, but 'outputs' section is not found");
                 return;
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index 5d64579..de1bcae 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_defaults {
     name: "idmap2_defaults",
     tidy: true,
diff --git a/cmds/ime/Android.bp b/cmds/ime/Android.bp
index 76a16c8..6dd3ba1 100644
--- a/cmds/ime/Android.bp
+++ b/cmds/ime/Android.bp
@@ -1,6 +1,23 @@
 // Copyright 2007 The Android Open Source Project
 //
 
+package {
+    default_applicable_licenses: ["frameworks_base_cmds_ime_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_cmds_ime_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 sh_binary {
     name: "ime",
     src: "ime",
diff --git a/cmds/incident/Android.bp b/cmds/incident/Android.bp
index 94855aa..147885f 100644
--- a/cmds/incident/Android.bp
+++ b/cmds/incident/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_binary {
     name: "incident",
 
diff --git a/cmds/incident_helper/Android.bp b/cmds/incident_helper/Android.bp
index f07743e..5b819eb 100644
--- a/cmds/incident_helper/Android.bp
+++ b/cmds/incident_helper/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_binary {
     name: "incident-helper-cmd",
     wrapper: "incident_helper_cmd",
diff --git a/cmds/incidentd/Android.bp b/cmds/incidentd/Android.bp
index c47526a..b0b23f5 100644
--- a/cmds/incidentd/Android.bp
+++ b/cmds/incidentd/Android.bp
@@ -16,6 +16,15 @@
 // incidentd
 // =========
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_binary {
     name: "incidentd",
 
diff --git a/cmds/input/Android.bp b/cmds/input/Android.bp
index 1ee9dd3..2e30176 100644
--- a/cmds/input/Android.bp
+++ b/cmds/input/Android.bp
@@ -1,6 +1,23 @@
 // Copyright 2008 The Android Open Source Project
 //
 
+package {
+    default_applicable_licenses: ["frameworks_base_cmds_input_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_cmds_input_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 sh_binary {
     name: "input",
     src: "input",
diff --git a/cmds/interrupter/Android.bp b/cmds/interrupter/Android.bp
index d68e7fe..d7f744d 100644
--- a/cmds/interrupter/Android.bp
+++ b/cmds/interrupter/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_library_shared {
     name: "interrupter",
     host_supported: true,
diff --git a/cmds/locksettings/Android.bp b/cmds/locksettings/Android.bp
index 59ccc5c..3869c8f 100644
--- a/cmds/locksettings/Android.bp
+++ b/cmds/locksettings/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_binary {
     name: "locksettings",
     wrapper: "locksettings",
diff --git a/cmds/pm/Android.bp b/cmds/pm/Android.bp
index 0644f6e..847dbab 100644
--- a/cmds/pm/Android.bp
+++ b/cmds/pm/Android.bp
@@ -1,6 +1,23 @@
 // Copyright 2007 The Android Open Source Project
 //
 
+package {
+    default_applicable_licenses: ["frameworks_base_cmds_pm_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_cmds_pm_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 sh_binary {
     name: "pm",
     src: "pm",
diff --git a/cmds/requestsync/Android.bp b/cmds/requestsync/Android.bp
index ef2a8a6..57e8dd3 100644
--- a/cmds/requestsync/Android.bp
+++ b/cmds/requestsync/Android.bp
@@ -1,6 +1,23 @@
 // Copyright 2012 The Android Open Source Project
 //
 
+package {
+    default_applicable_licenses: ["frameworks_base_cmds_requestsync_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_cmds_requestsync_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 java_binary {
     name: "requestsync",
     wrapper: "requestsync",
diff --git a/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java b/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java
index a0361d0..ca9df39 100644
--- a/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java
+++ b/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java
@@ -182,6 +182,8 @@
                 mExtras.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, true);
             } else if (opt.equals("--rc") || opt.equals("--require-charging")) {
                 mExtras.putBoolean(ContentResolver.SYNC_EXTRAS_REQUIRE_CHARGING, true);
+            } else if (opt.equals("--ej") || opt.equals("--schedule-as-ej")) {
+                mExtras.putBoolean(ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB, true);
             } else if (opt.equals("-e") || opt.equals("--es") || opt.equals("--extra-string")) {
                 final String key = nextArgRequired();
                 final String value = nextArgRequired();
diff --git a/cmds/screencap/Android.bp b/cmds/screencap/Android.bp
index fc628a6..c009c1f 100644
--- a/cmds/screencap/Android.bp
+++ b/cmds/screencap/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_binary {
     name: "screencap",
 
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 5c08704..d4da5e5 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -34,7 +34,6 @@
 #include <gui/SurfaceComposerClient.h>
 #include <gui/SyncScreenCaptureListener.h>
 
-#include <ui/DisplayInfo.h>
 #include <ui/GraphicTypes.h>
 #include <ui/PixelFormat.h>
 
diff --git a/cmds/settings/Android.bp b/cmds/settings/Android.bp
index 8a78e54..cc73006 100644
--- a/cmds/settings/Android.bp
+++ b/cmds/settings/Android.bp
@@ -1,6 +1,17 @@
 // Copyright 2011 The Android Open Source Project
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 sh_binary {
     name: "settings",
     src: "settings",
diff --git a/cmds/sm/Android.bp b/cmds/sm/Android.bp
index 11e4e72..ecfacae 100644
--- a/cmds/sm/Android.bp
+++ b/cmds/sm/Android.bp
@@ -1,6 +1,23 @@
 // Copyright 2015 The Android Open Source Project
 //
 
+package {
+    default_applicable_licenses: ["frameworks_base_cmds_sm_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_cmds_sm_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 java_binary {
     name: "sm",
     wrapper: "sm",
diff --git a/cmds/svc/Android.bp b/cmds/svc/Android.bp
index 68b48f1..41a3ebd 100644
--- a/cmds/svc/Android.bp
+++ b/cmds/svc/Android.bp
@@ -1,6 +1,23 @@
 // Copyright 2007 The Android Open Source Project
 //
 
+package {
+    default_applicable_licenses: ["frameworks_base_cmds_svc_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_cmds_svc_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 java_binary {
     name: "svc",
     wrapper: "svc",
diff --git a/cmds/telecom/Android.bp b/cmds/telecom/Android.bp
index 56e147c..4da79c5 100644
--- a/cmds/telecom/Android.bp
+++ b/cmds/telecom/Android.bp
@@ -1,6 +1,23 @@
 // Copyright 2015 The Android Open Source Project
 //
 
+package {
+    default_applicable_licenses: ["frameworks_base_cmds_telecom_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_cmds_telecom_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 java_binary {
     name: "telecom",
     wrapper: "telecom",
diff --git a/cmds/uiautomator/Android.bp b/cmds/uiautomator/Android.bp
index f9cb3dd..a0bf624 100644
--- a/cmds/uiautomator/Android.bp
+++ b/cmds/uiautomator/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 genrule {
     name: "uiautomator-last-released-api",
     srcs: ["api/*.txt"],
diff --git a/cmds/uiautomator/cmds/uiautomator/Android.bp b/cmds/uiautomator/cmds/uiautomator/Android.bp
index 68cc5a3..56e2e70 100644
--- a/cmds/uiautomator/cmds/uiautomator/Android.bp
+++ b/cmds/uiautomator/cmds/uiautomator/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_binary {
     name: "uiautomator",
     wrapper: "uiautomator",
diff --git a/cmds/uiautomator/instrumentation/Android.bp b/cmds/uiautomator/instrumentation/Android.bp
index 477f0d1..50e2234 100644
--- a/cmds/uiautomator/instrumentation/Android.bp
+++ b/cmds/uiautomator/instrumentation/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_test {
     name: "uiautomator-instrumentation",
 
diff --git a/cmds/uiautomator/library/Android.bp b/cmds/uiautomator/library/Android.bp
index 14b74da..469b452 100644
--- a/cmds/uiautomator/library/Android.bp
+++ b/cmds/uiautomator/library/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 droidstubs {
     name: "uiautomator-stubs",
     srcs: [
diff --git a/cmds/uinput/Android.bp b/cmds/uinput/Android.bp
index 0d7fed2..260cfc7 100644
--- a/cmds/uinput/Android.bp
+++ b/cmds/uinput/Android.bp
@@ -1,6 +1,23 @@
 // Copyright 2020 The Android Open Source Project
 //
 
+package {
+    default_applicable_licenses: ["frameworks_base_cmds_uinput_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_cmds_uinput_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 java_binary {
     name: "uinput",
     wrapper: "uinput",
@@ -15,4 +32,4 @@
     srcs: [
         "src/com/android/commands/uinput/InputAbsInfo.aidl",
     ],
-}
\ No newline at end of file
+}
diff --git a/cmds/uinput/jni/Android.bp b/cmds/uinput/jni/Android.bp
index 199bbbd..c56adc3 100644
--- a/cmds/uinput/jni/Android.bp
+++ b/cmds/uinput/jni/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_cmds_uinput_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_cmds_uinput_license"],
+}
+
 cc_library_shared {
     name: "libuinputcommand_jni",
 
diff --git a/cmds/vr/Android.bp b/cmds/vr/Android.bp
index cb129bd..8936491 100644
--- a/cmds/vr/Android.bp
+++ b/cmds/vr/Android.bp
@@ -1,6 +1,23 @@
 // Copyright 2017 The Android Open Source Project
 //
 
+package {
+    default_applicable_licenses: ["frameworks_base_cmds_vr_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_cmds_vr_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 java_binary {
     name: "vr",
     wrapper: "vr",
diff --git a/cmds/wm/Android.bp b/cmds/wm/Android.bp
index 609f84b..cf6b019 100644
--- a/cmds/wm/Android.bp
+++ b/cmds/wm/Android.bp
@@ -1,6 +1,23 @@
 // Copyright 2013 The Android Open Source Project
 //
 
+package {
+    default_applicable_licenses: ["frameworks_base_cmds_wm_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_cmds_wm_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 sh_binary {
     name: "wm",
     src: "wm",
diff --git a/config/Android.bp b/config/Android.bp
index 8dd409b..6a6f848 100644
--- a/config/Android.bp
+++ b/config/Android.bp
@@ -12,6 +12,23 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: ["frameworks_base_config_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_config_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "copyright-header",
+    ],
+}
+
 filegroup {
     name: "preloaded-classes-denylist",
     srcs: ["preloaded-classes-denylist"],
diff --git a/config/dirty-image-objects b/config/dirty-image-objects
index 2dfe019..dfd091c 100644
--- a/config/dirty-image-objects
+++ b/config/dirty-image-objects
@@ -28,359 +28,359 @@
 # Then, grep for lines containing "Private dirty object" from the output.
 # This particular file was generated by dumping systemserver and systemui.
 #
-android.accounts.Account
-android.accounts.OnAccountsUpdateListener
-android.animation.LayoutTransition
-android.app.ActivityManager
-android.app.ActivityManager$OnUidImportanceListener
-android.app.ActivityTaskManager
-android.app.ActivityThread
-android.app.admin.DevicePolicyManager
-android.app.AlarmManager
-android.app.Application
-android.app.AppOpsManager
-android.app.backup.BackupManager
-android.app.ContextImpl
-android.app.INotificationManager
-android.app.Notification$BigPictureStyle
-android.app.Notification$BigTextStyle
-android.app.Notification$InboxStyle
-android.app.NotificationChannel
-android.app.NotificationChannelGroup
-android.app.NotificationManager
-android.app.PendingIntent
-android.app.PendingIntent$OnFinished
-android.app.QueuedWork
-android.app.ResourcesManager
-android.app.WallpaperManager
-android.app.WindowConfiguration
-android.bluetooth.BluetoothAdapter
-android.bluetooth.BluetoothDevice
-android.bluetooth.BluetoothProfile
-android.bluetooth.IBluetoothA2dp
-android.bluetooth.IBluetoothHeadsetPhone
-android.bluetooth.IBluetoothHidDevice
-android.bluetooth.IBluetoothHidHost
-android.bluetooth.IBluetoothMap
-android.bluetooth.IBluetoothPan
-android.bluetooth.IBluetoothPbap
-android.bluetooth.IBluetoothSap
-android.content.ClipboardManager$OnPrimaryClipChangedListener
-android.content.ComponentName
-android.content.ContentProvider$PipeDataWriter
-android.content.ContentResolver
-android.content.Context
-android.content.Intent
-android.content.pm.PackageManager$OnPermissionsChangedListener
-android.content.pm.VersionedPackage
-android.content.res.Configuration
-android.content.SharedPreferences$OnSharedPreferenceChangeListener
-android.database.CursorWindow
-android.database.sqlite.SQLiteCompatibilityWalFlags
-android.database.sqlite.SQLiteDatabase$CursorFactory
-android.database.sqlite.SQLiteGlobal
-android.database.sqlite.SQLiteTransactionListener
-android.ddm.DdmHandleAppName
-android.graphics.Bitmap
-android.graphics.Canvas
-android.graphics.drawable.AdaptiveIconDrawable
-android.graphics.drawable.ColorDrawable
-android.graphics.drawable.GradientDrawable
-android.graphics.drawable.Icon
-android.graphics.drawable.InsetDrawable
-android.graphics.drawable.RippleDrawable
-android.graphics.drawable.VectorDrawable$VGroup
-android.graphics.ImageDecoder
-android.graphics.Rect
-android.graphics.TemporaryBuffer
-android.hardware.biometrics.BiometricSourceType
-android.hardware.display.ColorDisplayManager$ColorDisplayManagerInternal
-android.hardware.display.DisplayManagerGlobal
-android.hardware.display.NightDisplayListener$Callback
-android.hardware.input.InputManager
-android.hardware.input.InputManager$InputDeviceListener
-android.hardware.SensorPrivacyManager
-android.hardware.SystemSensorManager
-android.icu.impl.OlsonTimeZone
-android.icu.text.BreakIterator
-android.icu.text.Collator
-android.icu.text.DateFormat$BooleanAttribute
-android.icu.text.DateTimePatternGenerator$DTPGflags
-android.icu.text.PluralRules$Operand
-android.icu.util.TimeZone
-android.location.GpsStatus$Listener
-android.location.LocationListener
-android.media.AudioManager
-android.media.MediaRouter
-android.media.PlayerBase
-android.media.session.MediaSessionManager
-android.net.apf.ApfCapabilities
-android.net.ConnectivityManager
-android.net.ConnectivityManager$OnNetworkActiveListener
-android.net.ConnectivityThread$Singleton
-android.net.IpConfiguration$IpAssignment
-android.net.IpConfiguration$ProxySettings
-android.net.IpPrefix
-android.net.LinkAddress
-android.net.LinkProperties
-android.net.Network
-android.net.NetworkCapabilities
-android.net.NetworkInfo
-android.net.NetworkInfo$State
-android.net.NetworkRequest
-android.net.NetworkRequest$Type
-android.net.RouteInfo
-android.net.StringNetworkSpecifier
-android.net.TrafficStats
-android.net.UidRange
-android.net.Uri$HierarchicalUri
-android.net.Uri$StringUri
-android.net.wifi.WifiManager
-android.net.wifi.WifiManager$SoftApCallback
-android.os.AsyncResult
-android.os.AsyncTask
-android.os.BinderProxy
-android.os.Bundle
-android.os.DeadObjectException
-android.os.Environment
-android.os.FileObserver
-android.os.Handler
-android.os.IDeviceIdleController
-android.os.LocaleList
-android.os.Looper
-android.os.Message
-android.os.ParcelUuid
-android.os.Process
-android.os.RecoverySystem
-android.os.ServiceManager
-android.os.storage.StorageManager
-android.os.StrictMode
-android.os.Trace
-android.os.WorkSource
-android.os.WorkSource$WorkChain
-android.permission.PermissionManager
-android.provider.FontsContract
-android.provider.Settings$SettingNotFoundException
-android.renderscript.RenderScriptCacheDir
-android.security.IKeyChainService
-android.security.keystore.AndroidKeyStoreProvider
-android.security.net.config.ApplicationConfig
-android.security.net.config.SystemCertificateSource$NoPreloadHolder
-android.telecom.PhoneAccountHandle
-android.telephony.AnomalyReporter
-android.telephony.CellSignalStrengthCdma
-android.telephony.CellSignalStrengthGsm
-android.telephony.CellSignalStrengthLte
-android.telephony.CellSignalStrengthNr
-android.telephony.CellSignalStrengthTdscdma
-android.telephony.CellSignalStrengthWcdma
-android.telephony.DataSpecificRegistrationInfo
-android.telephony.emergency.EmergencyNumber
-android.telephony.ims.ImsMmTelManager$CapabilityCallback$CapabilityBinder
-android.telephony.ims.ImsMmTelManager$RegistrationCallback$RegistrationBinder
-android.telephony.ims.ImsReasonInfo
-android.telephony.ims.ProvisioningManager$Callback$CallbackBinder
-android.telephony.ModemActivityInfo
-android.telephony.ModemInfo
-android.telephony.NetworkRegistrationInfo
-android.telephony.NetworkService
-android.telephony.TelephonyManager
-android.telephony.VoiceSpecificRegistrationInfo
-android.text.format.DateFormat
-android.text.method.SingleLineTransformationMethod
-android.text.Selection$MemoryTextWatcher
-android.text.SpanWatcher
-android.text.style.AlignmentSpan
-android.text.style.CharacterStyle
-android.text.style.LeadingMarginSpan
-android.text.style.LineBackgroundSpan
-android.text.style.LineHeightSpan
-android.text.style.MetricAffectingSpan
-android.text.style.ReplacementSpan
-android.text.style.SuggestionSpan
-android.text.style.TabStopSpan
-android.text.TextUtils
-android.text.TextWatcher
-android.transition.ChangeClipBounds
-android.transition.ChangeImageTransform
-android.transition.ChangeTransform
-android.util.ArrayMap
-android.util.ArraySet
-android.util.DisplayMetrics
-android.util.EventLog
-android.util.Log
-android.util.Patterns
-android.view.AbsSavedState$1
-android.view.accessibility.AccessibilityManager
-android.view.accessibility.AccessibilityManager$AccessibilityServicesStateChangeListener
-android.view.accessibility.AccessibilityManager$TouchExplorationStateChangeListener
-android.view.accessibility.AccessibilityNodeIdManager
-android.view.autofill.AutofillManager
-android.view.autofill.Helper
-android.view.Choreographer
-android.view.inputmethod.InputMethodManager
-android.view.IWindowManager
-android.view.PointerIcon
-android.view.RemoteAnimationAdapter
-android.view.ThreadedRenderer
-android.view.View
-android.view.View$OnHoverListener
-android.view.ViewRootImpl
-android.view.ViewStub
-android.view.ViewStub$OnInflateListener
-android.view.ViewTreeObserver
-android.view.WindowManager$LayoutParams
-android.view.WindowManagerGlobal
-android.widget.ActionMenuPresenter$OverflowMenuButton
-android.widget.ActionMenuView
-android.widget.Button
-android.widget.CheckBox
-android.widget.FrameLayout
-android.widget.ImageButton
-android.widget.ImageView
-android.widget.LinearLayout
-android.widget.RelativeLayout
-android.widget.SeekBar
-android.widget.Space
-android.widget.TextView
-android.widget.Toolbar
-byte[]
-com.android.ims.ImsManager
-com.android.internal.logging.MetricsLogger
-com.android.internal.os.BackgroundThread
-com.android.internal.os.BinderInternal
-com.android.internal.os.BinderInternal$BinderProxyLimitListener
-com.android.internal.os.RuntimeInit
-com.android.internal.os.SomeArgs
-com.android.internal.policy.DecorView
-com.android.internal.statusbar.IStatusBarService
-com.android.internal.telephony.AppSmsManager
-android.telephony.CallerInfoAsyncQuery$OnQueryCompleteListener
-com.android.internal.telephony.CarrierActionAgent
-com.android.internal.telephony.cat.CatService
-com.android.internal.telephony.cat.IconLoader
-com.android.internal.telephony.cat.RilMessageDecoder
-com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager
-com.android.internal.telephony.cdma.EriManager
-com.android.internal.telephony.CellularNetworkValidator
-com.android.internal.telephony.CommandException
-com.android.internal.telephony.dataconnection.DataConnection$DcActivatingState
-com.android.internal.telephony.dataconnection.DataConnection$DcActiveState
-com.android.internal.telephony.dataconnection.DataConnection$DcInactiveState
-com.android.internal.telephony.dataconnection.DataEnabledSettings
-com.android.internal.telephony.dataconnection.DcTracker
-com.android.internal.telephony.euicc.EuiccCardController
-com.android.internal.telephony.euicc.EuiccController
-com.android.internal.telephony.GsmAlphabet
-com.android.internal.telephony.GsmCdmaCallTracker
-com.android.internal.telephony.GsmCdmaPhone
-com.android.internal.telephony.IccPhoneBookInterfaceManager
-com.android.internal.telephony.IccSmsInterfaceManager
-com.android.internal.telephony.ims.ImsResolver
-com.android.internal.telephony.imsphone.ImsExternalCallTracker
-com.android.internal.telephony.imsphone.ImsPhone
-com.android.internal.telephony.imsphone.ImsPhoneCallTracker
-com.android.internal.telephony.ims.RcsMessageStoreController
-com.android.internal.telephony.IntentBroadcaster
-com.android.internal.telephony.ITelephonyRegistry$Stub$Proxy
-com.android.internal.telephony.metrics.TelephonyMetrics
-com.android.internal.telephony.MultiSimSettingController
-com.android.internal.telephony.nano.CarrierIdProto$CarrierAttribute
-com.android.internal.telephony.nano.CarrierIdProto$CarrierId
-com.android.internal.telephony.nano.TelephonyProto$RilDataCall
-com.android.internal.telephony.nano.TelephonyProto$SmsSession$Event
-com.android.internal.telephony.nano.TelephonyProto$TelephonyCallSession$Event$RilCall
-com.android.internal.telephony.NitzStateMachine
-com.android.internal.telephony.PhoneConfigurationManager
-com.android.internal.telephony.PhoneFactory
-com.android.internal.telephony.PhoneSwitcher
-com.android.internal.telephony.ProxyController
-com.android.internal.telephony.RadioConfig
-com.android.internal.telephony.RIL
-com.android.internal.telephony.RILRequest
-com.android.internal.telephony.RilWakelockInfo
-com.android.internal.telephony.ServiceStateTracker
-com.android.internal.telephony.SimActivationTracker
-com.android.internal.telephony.SmsApplication
-com.android.internal.telephony.SmsBroadcastUndelivered
-com.android.internal.telephony.SmsStorageMonitor
-com.android.internal.telephony.SmsUsageMonitor
-com.android.internal.telephony.SubscriptionController
-com.android.internal.telephony.SubscriptionInfoUpdater
-com.android.internal.telephony.TelephonyComponentFactory
-com.android.internal.telephony.TelephonyDevController
-com.android.internal.telephony.TelephonyTester
-com.android.internal.telephony.uicc.AdnRecordCache
-com.android.internal.telephony.uicc.UiccCardApplication
-com.android.internal.telephony.uicc.UiccController
-com.android.internal.telephony.uicc.UiccProfile
-com.android.internal.telephony.uicc.UiccStateChangedLauncher
-com.android.internal.telephony.uicc.UsimFileHandler
-com.android.internal.telephony.uicc.VoiceMailConstants
-com.android.internal.util.LatencyTracker
-com.android.internal.util.StateMachine$SmHandler
-com.android.okhttp.OkHttpClient
-com.android.okhttp.okio.AsyncTimeout
-com.android.okhttp.okio.SegmentPool
-com.android.phone.ecc.nano.ProtobufEccData$CountryInfo
-com.android.phone.ecc.nano.ProtobufEccData$EccInfo
-com.android.server.sip.SipWakeupTimer
-com.android.server.SystemConfig
-dalvik.system.BaseDexClassLoader
-dalvik.system.BlockGuard
-dalvik.system.CloseGuard
-dalvik.system.RuntimeHooks
-dalvik.system.SocketTagger
-java.io.BufferedReader
-java.lang.AssertionError
-java.lang.Boolean
-java.lang.Byte
-java.lang.Character
-java.lang.CharSequence
-java.lang.Class
-java.lang.IllegalAccessException
-java.lang.IllegalStateException
-java.lang.NoSuchMethodException
-java.lang.NullPointerException
-java.lang.Object
-java.lang.Object[]
-java.lang.ref.FinalizerReference
-java.lang.Runnable
-java.lang.SecurityException
-java.lang.Short
-java.lang.String[]
-java.lang.System
-java.lang.Thread
-java.lang.Throwable
-java.lang.UnsatisfiedLinkError
-java.net.Inet6Address
-java.net.Socket
-java.net.SocketException
-java.nio.Bits
-java.nio.charset.Charset
-java.security.interfaces.RSAPrivateKey
-java.security.Provider
-java.util.Collections
-java.util.concurrent.Executor
-java.util.GregorianCalendar
-java.util.Locale
-java.util.Locale$NoImagePreloadHolder
-java.util.Scanner
-java.util.Set
-java.util.TimeZone
-javax.net.SocketFactory
-javax.net.ssl.HttpsURLConnection
-javax.net.ssl.HttpsURLConnection$NoPreloadHolder
-javax.net.ssl.SSLContext
-javax.net.ssl.SSLSessionContext
-javax.net.ssl.SSLSocketFactory
-libcore.io.Libcore
-libcore.io.Memory
-libcore.net.NetworkSecurityPolicy
-libcore.timezone.TimeZoneFinder
-org.apache.http.params.HttpParams
-sun.misc.Cleaner
-sun.nio.ch.FileChannelImpl
-sun.nio.ch.FileChannelImpl$Unmapper
-sun.nio.fs.UnixChannelFactory
-sun.security.jca.Providers
+Landroid/accounts/Account;
+Landroid/accounts/OnAccountsUpdateListener;
+Landroid/animation/LayoutTransition;
+Landroid/app/ActivityManager;
+Landroid/app/ActivityManager$OnUidImportanceListener;
+Landroid/app/ActivityTaskManager;
+Landroid/app/ActivityThread;
+Landroid/app/admin/DevicePolicyManager;
+Landroid/app/AlarmManager;
+Landroid/app/Application;
+Landroid/app/AppOpsManager;
+Landroid/app/backup/BackupManager;
+Landroid/app/ContextImpl;
+Landroid/app/INotificationManager;
+Landroid/app/Notification$BigPictureStyle;
+Landroid/app/Notification$BigTextStyle;
+Landroid/app/Notification$InboxStyle;
+Landroid/app/NotificationChannel;
+Landroid/app/NotificationChannelGroup;
+Landroid/app/NotificationManager;
+Landroid/app/PendingIntent;
+Landroid/app/PendingIntent$OnFinished;
+Landroid/app/QueuedWork;
+Landroid/app/ResourcesManager;
+Landroid/app/WallpaperManager;
+Landroid/app/WindowConfiguration;
+Landroid/bluetooth/BluetoothAdapter;
+Landroid/bluetooth/BluetoothDevice;
+Landroid/bluetooth/BluetoothProfile;
+Landroid/bluetooth/IBluetoothA2dp;
+Landroid/bluetooth/IBluetoothHeadsetPhone;
+Landroid/bluetooth/IBluetoothHidDevice;
+Landroid/bluetooth/IBluetoothHidHost;
+Landroid/bluetooth/IBluetoothMap;
+Landroid/bluetooth/IBluetoothPan;
+Landroid/bluetooth/IBluetoothPbap;
+Landroid/bluetooth/IBluetoothSap;
+Landroid/content/ClipboardManager$OnPrimaryClipChangedListener;
+Landroid/content/ComponentName;
+Landroid/content/ContentProvider$PipeDataWriter;
+Landroid/content/ContentResolver;
+Landroid/content/Context;
+Landroid/content/Intent;
+Landroid/content/pm/PackageManager$OnPermissionsChangedListener;
+Landroid/content/pm/VersionedPackage;
+Landroid/content/res/Configuration;
+Landroid/content/SharedPreferences$OnSharedPreferenceChangeListener;
+Landroid/database/CursorWindow;
+Landroid/database/sqlite/SQLiteCompatibilityWalFlags;
+Landroid/database/sqlite/SQLiteDatabase$CursorFactory;
+Landroid/database/sqlite/SQLiteGlobal;
+Landroid/database/sqlite/SQLiteTransactionListener;
+Landroid/ddm/DdmHandleAppName;
+Landroid/graphics/Bitmap;
+Landroid/graphics/Canvas;
+Landroid/graphics/drawable/AdaptiveIconDrawable;
+Landroid/graphics/drawable/ColorDrawable;
+Landroid/graphics/drawable/GradientDrawable;
+Landroid/graphics/drawable/Icon;
+Landroid/graphics/drawable/InsetDrawable;
+Landroid/graphics/drawable/RippleDrawable;
+Landroid/graphics/drawable/VectorDrawable$VGroup;
+Landroid/graphics/ImageDecoder;
+Landroid/graphics/Rect;
+Landroid/graphics/TemporaryBuffer;
+Landroid/hardware/biometrics/BiometricSourceType;
+Landroid/hardware/display/ColorDisplayManager$ColorDisplayManagerInternal;
+Landroid/hardware/display/DisplayManagerGlobal;
+Landroid/hardware/display/NightDisplayListener$Callback;
+Landroid/hardware/input/InputManager;
+Landroid/hardware/input/InputManager$InputDeviceListener;
+Landroid/hardware/SensorPrivacyManager;
+Landroid/hardware/SystemSensorManager;
+Landroid/icu/impl/OlsonTimeZone;
+Landroid/icu/text/BreakIterator;
+Landroid/icu/text/Collator;
+Landroid/icu/text/DateFormat$BooleanAttribute;
+Landroid/icu/text/DateTimePatternGenerator$DTPGflags;
+Landroid/icu/text/PluralRules$Operand;
+Landroid/icu/util/TimeZone;
+Landroid/location/GpsStatus$Listener;
+Landroid/location/LocationListener;
+Landroid/media/AudioManager;
+Landroid/media/MediaRouter;
+Landroid/media/PlayerBase;
+Landroid/media/session/MediaSessionManager;
+Landroid/net/apf/ApfCapabilities;
+Landroid/net/ConnectivityManager;
+Landroid/net/ConnectivityManager$OnNetworkActiveListener;
+Landroid/net/ConnectivityThread$Singleton;
+Landroid/net/IpConfiguration$IpAssignment;
+Landroid/net/IpConfiguration$ProxySettings;
+Landroid/net/IpPrefix;
+Landroid/net/LinkAddress;
+Landroid/net/LinkProperties;
+Landroid/net/Network;
+Landroid/net/NetworkCapabilities;
+Landroid/net/NetworkInfo;
+Landroid/net/NetworkInfo$State;
+Landroid/net/NetworkRequest;
+Landroid/net/NetworkRequest$Type;
+Landroid/net/RouteInfo;
+Landroid/net/StringNetworkSpecifier;
+Landroid/net/TrafficStats;
+Landroid/net/UidRange;
+Landroid/net/Uri$HierarchicalUri;
+Landroid/net/Uri$StringUri;
+Landroid/net/wifi/WifiManager;
+Landroid/net/wifi/WifiManager$SoftApCallback;
+Landroid/os/AsyncResult;
+Landroid/os/AsyncTask;
+Landroid/os/BinderProxy;
+Landroid/os/Bundle;
+Landroid/os/DeadObjectException;
+Landroid/os/Environment;
+Landroid/os/FileObserver;
+Landroid/os/Handler;
+Landroid/os/IDeviceIdleController;
+Landroid/os/LocaleList;
+Landroid/os/Looper;
+Landroid/os/Message;
+Landroid/os/ParcelUuid;
+Landroid/os/Process;
+Landroid/os/RecoverySystem;
+Landroid/os/ServiceManager;
+Landroid/os/storage/StorageManager;
+Landroid/os/StrictMode;
+Landroid/os/Trace;
+Landroid/os/WorkSource;
+Landroid/os/WorkSource$WorkChain;
+Landroid/permission/PermissionManager;
+Landroid/provider/FontsContract;
+Landroid/provider/Settings$SettingNotFoundException;
+Landroid/renderscript/RenderScriptCacheDir;
+Landroid/security/IKeyChainService;
+Landroid/security/keystore/AndroidKeyStoreProvider;
+Landroid/security/net/config/ApplicationConfig;
+Landroid/security/net/config/SystemCertificateSource$NoPreloadHolder;
+Landroid/telecom/PhoneAccountHandle;
+Landroid/telephony/AnomalyReporter;
+Landroid/telephony/CellSignalStrengthCdma;
+Landroid/telephony/CellSignalStrengthGsm;
+Landroid/telephony/CellSignalStrengthLte;
+Landroid/telephony/CellSignalStrengthNr;
+Landroid/telephony/CellSignalStrengthTdscdma;
+Landroid/telephony/CellSignalStrengthWcdma;
+Landroid/telephony/DataSpecificRegistrationInfo;
+Landroid/telephony/emergency/EmergencyNumber;
+Landroid/telephony/ims/ImsMmTelManager$CapabilityCallback$CapabilityBinder;
+Landroid/telephony/ims/ImsMmTelManager$RegistrationCallback$RegistrationBinder;
+Landroid/telephony/ims/ImsReasonInfo;
+Landroid/telephony/ims/ProvisioningManager$Callback$CallbackBinder;
+Landroid/telephony/ModemActivityInfo;
+Landroid/telephony/ModemInfo;
+Landroid/telephony/NetworkRegistrationInfo;
+Landroid/telephony/NetworkService;
+Landroid/telephony/TelephonyManager;
+Landroid/telephony/VoiceSpecificRegistrationInfo;
+Landroid/text/format/DateFormat;
+Landroid/text/method/SingleLineTransformationMethod;
+Landroid/text/Selection$MemoryTextWatcher;
+Landroid/text/SpanWatcher;
+Landroid/text/style/AlignmentSpan;
+Landroid/text/style/CharacterStyle;
+Landroid/text/style/LeadingMarginSpan;
+Landroid/text/style/LineBackgroundSpan;
+Landroid/text/style/LineHeightSpan;
+Landroid/text/style/MetricAffectingSpan;
+Landroid/text/style/ReplacementSpan;
+Landroid/text/style/SuggestionSpan;
+Landroid/text/style/TabStopSpan;
+Landroid/text/TextUtils;
+Landroid/text/TextWatcher;
+Landroid/transition/ChangeClipBounds;
+Landroid/transition/ChangeImageTransform;
+Landroid/transition/ChangeTransform;
+Landroid/util/ArrayMap;
+Landroid/util/ArraySet;
+Landroid/util/DisplayMetrics;
+Landroid/util/EventLog;
+Landroid/util/Log;
+Landroid/util/Patterns;
+Landroid/view/AbsSavedState$1;
+Landroid/view/accessibility/AccessibilityManager;
+Landroid/view/accessibility/AccessibilityManager$AccessibilityServicesStateChangeListener;
+Landroid/view/accessibility/AccessibilityManager$TouchExplorationStateChangeListener;
+Landroid/view/accessibility/AccessibilityNodeIdManager;
+Landroid/view/autofill/AutofillManager;
+Landroid/view/autofill/Helper;
+Landroid/view/Choreographer;
+Landroid/view/inputmethod/InputMethodManager;
+Landroid/view/IWindowManager;
+Landroid/view/PointerIcon;
+Landroid/view/RemoteAnimationAdapter;
+Landroid/view/ThreadedRenderer;
+Landroid/view/View;
+Landroid/view/View$OnHoverListener;
+Landroid/view/ViewRootImpl;
+Landroid/view/ViewStub;
+Landroid/view/ViewStub$OnInflateListener;
+Landroid/view/ViewTreeObserver;
+Landroid/view/WindowManager$LayoutParams;
+Landroid/view/WindowManagerGlobal;
+Landroid/widget/ActionMenuPresenter$OverflowMenuButton;
+Landroid/widget/ActionMenuView;
+Landroid/widget/Button;
+Landroid/widget/CheckBox;
+Landroid/widget/FrameLayout;
+Landroid/widget/ImageButton;
+Landroid/widget/ImageView;
+Landroid/widget/LinearLayout;
+Landroid/widget/RelativeLayout;
+Landroid/widget/SeekBar;
+Landroid/widget/Space;
+Landroid/widget/TextView;
+Landroid/widget/Toolbar;
+[B
+Lcom/android/ims/ImsManager;
+Lcom/android/internal/logging/MetricsLogger;
+Lcom/android/internal/os/BackgroundThread;
+Lcom/android/internal/os/BinderInternal;
+Lcom/android/internal/os/BinderInternal$BinderProxyLimitListener;
+Lcom/android/internal/os/RuntimeInit;
+Lcom/android/internal/os/SomeArgs;
+Lcom/android/internal/policy/DecorView;
+Lcom/android/internal/statusbar/IStatusBarService;
+Lcom/android/internal/telephony/AppSmsManager;
+Landroid/telephony/CallerInfoAsyncQuery$OnQueryCompleteListener;
+Lcom/android/internal/telephony/CarrierActionAgent;
+Lcom/android/internal/telephony/cat/CatService;
+Lcom/android/internal/telephony/cat/IconLoader;
+Lcom/android/internal/telephony/cat/RilMessageDecoder;
+Lcom/android/internal/telephony/cdma/CdmaSubscriptionSourceManager;
+Lcom/android/internal/telephony/cdma/EriManager;
+Lcom/android/internal/telephony/CellularNetworkValidator;
+Lcom/android/internal/telephony/CommandException;
+Lcom/android/internal/telephony/dataconnection/DataConnection$DcActivatingState;
+Lcom/android/internal/telephony/dataconnection/DataConnection$DcActiveState;
+Lcom/android/internal/telephony/dataconnection/DataConnection$DcInactiveState;
+Lcom/android/internal/telephony/dataconnection/DataEnabledSettings;
+Lcom/android/internal/telephony/dataconnection/DcTracker;
+Lcom/android/internal/telephony/euicc/EuiccCardController;
+Lcom/android/internal/telephony/euicc/EuiccController;
+Lcom/android/internal/telephony/GsmAlphabet;
+Lcom/android/internal/telephony/GsmCdmaCallTracker;
+Lcom/android/internal/telephony/GsmCdmaPhone;
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;
+Lcom/android/internal/telephony/IccSmsInterfaceManager;
+Lcom/android/internal/telephony/ims/ImsResolver;
+Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker;
+Lcom/android/internal/telephony/imsphone/ImsPhone;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;
+Lcom/android/internal/telephony/ims/RcsMessageStoreController;
+Lcom/android/internal/telephony/IntentBroadcaster;
+Lcom/android/internal/telephony/ITelephonyRegistry$Stub$Proxy;
+Lcom/android/internal/telephony/metrics/TelephonyMetrics;
+Lcom/android/internal/telephony/MultiSimSettingController;
+Lcom/android/internal/telephony/nano/CarrierIdProto$CarrierAttribute;
+Lcom/android/internal/telephony/nano/CarrierIdProto$CarrierId;
+Lcom/android/internal/telephony/nano/TelephonyProto$RilDataCall;
+Lcom/android/internal/telephony/nano/TelephonyProto$SmsSession$Event;
+Lcom/android/internal/telephony/nano/TelephonyProto$TelephonyCallSession$Event$RilCall;
+Lcom/android/internal/telephony/NitzStateMachine;
+Lcom/android/internal/telephony/PhoneConfigurationManager;
+Lcom/android/internal/telephony/PhoneFactory;
+Lcom/android/internal/telephony/PhoneSwitcher;
+Lcom/android/internal/telephony/ProxyController;
+Lcom/android/internal/telephony/RadioConfig;
+Lcom/android/internal/telephony/RIL;
+Lcom/android/internal/telephony/RILRequest;
+Lcom/android/internal/telephony/RilWakelockInfo;
+Lcom/android/internal/telephony/ServiceStateTracker;
+Lcom/android/internal/telephony/SimActivationTracker;
+Lcom/android/internal/telephony/SmsApplication;
+Lcom/android/internal/telephony/SmsBroadcastUndelivered;
+Lcom/android/internal/telephony/SmsStorageMonitor;
+Lcom/android/internal/telephony/SmsUsageMonitor;
+Lcom/android/internal/telephony/SubscriptionController;
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;
+Lcom/android/internal/telephony/TelephonyComponentFactory;
+Lcom/android/internal/telephony/TelephonyDevController;
+Lcom/android/internal/telephony/TelephonyTester;
+Lcom/android/internal/telephony/uicc/AdnRecordCache;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;
+Lcom/android/internal/telephony/uicc/UiccController;
+Lcom/android/internal/telephony/uicc/UiccProfile;
+Lcom/android/internal/telephony/uicc/UiccStateChangedLauncher;
+Lcom/android/internal/telephony/uicc/UsimFileHandler;
+Lcom/android/internal/telephony/uicc/VoiceMailConstants;
+Lcom/android/internal/util/LatencyTracker;
+Lcom/android/internal/util/StateMachine$SmHandler;
+Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/okio/AsyncTimeout;
+Lcom/android/okhttp/okio/SegmentPool;
+Lcom/android/phone/ecc/nano/ProtobufEccData$CountryInfo;
+Lcom/android/phone/ecc/nano/ProtobufEccData$EccInfo;
+Lcom/android/server/sip/SipWakeupTimer;
+Lcom/android/server/SystemConfig;
+Ldalvik/system/BaseDexClassLoader;
+Ldalvik/system/BlockGuard;
+Ldalvik/system/CloseGuard;
+Ldalvik/system/RuntimeHooks;
+Ldalvik/system/SocketTagger;
+Ljava/io/BufferedReader;
+Ljava/lang/AssertionError;
+Ljava/lang/Boolean;
+Ljava/lang/Byte;
+Ljava/lang/Character;
+Ljava/lang/CharSequence;
+Ljava/lang/Class;
+Ljava/lang/IllegalAccessException;
+Ljava/lang/IllegalStateException;
+Ljava/lang/NoSuchMethodException;
+Ljava/lang/NullPointerException;
+Ljava/lang/Object;
+[Ljava/lang/Object;
+Ljava/lang/ref/FinalizerReference;
+Ljava/lang/Runnable;
+Ljava/lang/SecurityException;
+Ljava/lang/Short;
+[Ljava/lang/String;
+Ljava/lang/System;
+Ljava/lang/Thread;
+Ljava/lang/Throwable;
+Ljava/lang/UnsatisfiedLinkError;
+Ljava/net/Inet6Address;
+Ljava/net/Socket;
+Ljava/net/SocketException;
+Ljava/nio/Bits;
+Ljava/nio/charset/Charset;
+Ljava/security/interfaces/RSAPrivateKey;
+Ljava/security/Provider;
+Ljava/util/Collections;
+Ljava/util/concurrent/Executor;
+Ljava/util/GregorianCalendar;
+Ljava/util/Locale;
+Ljava/util/Locale$NoImagePreloadHolder;
+Ljava/util/Scanner;
+Ljava/util/Set;
+Ljava/util/TimeZone;
+Ljavax/net/SocketFactory;
+Ljavax/net/ssl/HttpsURLConnection;
+Ljavax/net/ssl/HttpsURLConnection$NoPreloadHolder;
+Ljavax/net/ssl/SSLContext;
+Ljavax/net/ssl/SSLSessionContext;
+Ljavax/net/ssl/SSLSocketFactory;
+Llibcore/io/Libcore;
+Llibcore/io/Memory;
+Llibcore/net/NetworkSecurityPolicy;
+Llibcore/timezone/TimeZoneFinder;
+Lorg/apache/http/params/HttpParams;
+Lsun/misc/Cleaner;
+Lsun/nio/ch/FileChannelImpl;
+Lsun/nio/ch/FileChannelImpl$Unmapper;
+Lsun/nio/fs/UnixChannelFactory;
+Lsun/security/jca/Providers;
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 0c440e8..c6ec376 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -400,6 +400,9 @@
 android.app.IProcessObserver$Stub$Proxy
 android.app.IProcessObserver$Stub
 android.app.IProcessObserver
+android.app.IRequestFinishCallback$Stub$Proxy
+android.app.IRequestFinishCallback$Stub
+android.app.IRequestFinishCallback
 android.app.ISearchManager$Stub$Proxy
 android.app.ISearchManager$Stub
 android.app.ISearchManager
diff --git a/core/api/Android.bp b/core/api/Android.bp
index 00b9019..170febb 100644
--- a/core/api/Android.bp
+++ b/core/api/Android.bp
@@ -14,6 +14,14 @@
 
 package {
     default_visibility: ["//visibility:private"],
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_base_license"],
 }
 
 filegroup {
diff --git a/core/api/current.txt b/core/api/current.txt
index e72f943..709032b 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -21,7 +21,6 @@
     field public static final String ACTIVITY_RECOGNITION = "android.permission.ACTIVITY_RECOGNITION";
     field public static final String ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL";
     field public static final String ANSWER_PHONE_CALLS = "android.permission.ANSWER_PHONE_CALLS";
-    field public static final String BACKGROUND_CAMERA = "android.permission.BACKGROUND_CAMERA";
     field public static final String BATTERY_STATS = "android.permission.BATTERY_STATS";
     field public static final String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE";
     field public static final String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
@@ -134,7 +133,6 @@
     field public static final String RECEIVE_SMS = "android.permission.RECEIVE_SMS";
     field public static final String RECEIVE_WAP_PUSH = "android.permission.RECEIVE_WAP_PUSH";
     field public static final String RECORD_AUDIO = "android.permission.RECORD_AUDIO";
-    field public static final String RECORD_BACKGROUND_AUDIO = "android.permission.RECORD_BACKGROUND_AUDIO";
     field public static final String REORDER_TASKS = "android.permission.REORDER_TASKS";
     field public static final String REQUEST_COMPANION_PROFILE_WATCH = "android.permission.REQUEST_COMPANION_PROFILE_WATCH";
     field public static final String REQUEST_COMPANION_RUN_IN_BACKGROUND = "android.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND";
@@ -145,6 +143,7 @@
     field public static final String REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE = "android.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE";
     field public static final String REQUEST_PASSWORD_COMPLEXITY = "android.permission.REQUEST_PASSWORD_COMPLEXITY";
     field @Deprecated public static final String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
+    field public static final String SCHEDULE_EXACT_ALARM = "android.permission.SCHEDULE_EXACT_ALARM";
     field public static final String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
     field public static final String SEND_SMS = "android.permission.SEND_SMS";
     field public static final String SET_ALARM = "com.android.alarm.permission.SET_ALARM";
@@ -506,6 +505,7 @@
     field public static final int dashGap = 16843175; // 0x10101a7
     field public static final int dashWidth = 16843174; // 0x10101a6
     field public static final int data = 16842798; // 0x101002e
+    field public static final int dataExtractionRules = 16844350; // 0x101063e
     field public static final int datePickerDialogTheme = 16843948; // 0x10104ac
     field public static final int datePickerMode = 16843955; // 0x10104b3
     field public static final int datePickerStyle = 16843612; // 0x101035c
@@ -527,6 +527,8 @@
     field public static final int detailSocialSummary = 16843428; // 0x10102a4
     field public static final int detailsElementBackground = 16843598; // 0x101034e
     field public static final int dial = 16843010; // 0x1010102
+    field public static final int dialTint = 16844342; // 0x1010636
+    field public static final int dialTintMode = 16844343; // 0x1010637
     field public static final int dialogCornerRadius = 16844145; // 0x1010571
     field public static final int dialogIcon = 16843252; // 0x10101f4
     field public static final int dialogLayout = 16843255; // 0x10101f7
@@ -724,8 +726,14 @@
     field public static final int groupIndicator = 16843019; // 0x101010b
     field public static final int gwpAsanMode = 16844310; // 0x1010616
     field public static final int hand_hour = 16843011; // 0x1010103
+    field public static final int hand_hourTint = 16844344; // 0x1010638
+    field public static final int hand_hourTintMode = 16844345; // 0x1010639
     field public static final int hand_minute = 16843012; // 0x1010104
+    field public static final int hand_minuteTint = 16844346; // 0x101063a
+    field public static final int hand_minuteTintMode = 16844347; // 0x101063b
     field public static final int hand_second = 16844323; // 0x1010623
+    field public static final int hand_secondTint = 16844348; // 0x101063c
+    field public static final int hand_secondTintMode = 16844349; // 0x101063d
     field public static final int handle = 16843354; // 0x101025a
     field public static final int handleProfiling = 16842786; // 0x1010022
     field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e
@@ -4328,16 +4336,17 @@
   }
 
   public class AlarmManager {
+    method public boolean canScheduleExactAlarms();
     method public void cancel(android.app.PendingIntent);
     method public void cancel(android.app.AlarmManager.OnAlarmListener);
     method public android.app.AlarmManager.AlarmClockInfo getNextAlarmClock();
     method public void set(int, long, android.app.PendingIntent);
     method public void set(int, long, String, android.app.AlarmManager.OnAlarmListener, android.os.Handler);
-    method public void setAlarmClock(android.app.AlarmManager.AlarmClockInfo, android.app.PendingIntent);
+    method @RequiresPermission(android.Manifest.permission.SCHEDULE_EXACT_ALARM) public void setAlarmClock(android.app.AlarmManager.AlarmClockInfo, android.app.PendingIntent);
     method public void setAndAllowWhileIdle(int, long, android.app.PendingIntent);
     method public void setExact(int, long, android.app.PendingIntent);
     method public void setExact(int, long, String, android.app.AlarmManager.OnAlarmListener, android.os.Handler);
-    method public void setExactAndAllowWhileIdle(int, long, android.app.PendingIntent);
+    method @RequiresPermission(value=android.Manifest.permission.SCHEDULE_EXACT_ALARM, conditional=true) public void setExactAndAllowWhileIdle(int, long, android.app.PendingIntent);
     method public void setInexactRepeating(int, long, long, android.app.PendingIntent);
     method public void setRepeating(int, long, long, android.app.PendingIntent);
     method @RequiresPermission(android.Manifest.permission.SET_TIME) public void setTime(long);
@@ -4733,6 +4742,13 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.app.AutomaticZenRule> CREATOR;
   }
 
+  public final class BackgroundServiceStartNotAllowedException extends android.app.ServiceStartNotAllowedException implements android.os.Parcelable {
+    ctor public BackgroundServiceStartNotAllowedException(@NonNull String);
+    method public int describeContents();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.BackgroundServiceStartNotAllowedException> CREATOR;
+  }
+
   public class DatePickerDialog extends android.app.AlertDialog implements android.widget.DatePicker.OnDateChangedListener android.content.DialogInterface.OnClickListener {
     ctor public DatePickerDialog(@NonNull android.content.Context);
     ctor public DatePickerDialog(@NonNull android.content.Context, @StyleRes int);
@@ -4978,6 +4994,13 @@
     method @Deprecated public void setSelectedGroup(int);
   }
 
+  public final class ForegroundServiceStartNotAllowedException extends android.app.ServiceStartNotAllowedException implements android.os.Parcelable {
+    ctor public ForegroundServiceStartNotAllowedException(@NonNull String);
+    method public int describeContents();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.ForegroundServiceStartNotAllowedException> CREATOR;
+  }
+
   @Deprecated public class Fragment implements android.content.ComponentCallbacks2 android.view.View.OnCreateContextMenuListener {
     ctor @Deprecated public Fragment();
     method @Deprecated public void dump(String, java.io.FileDescriptor, java.io.PrintWriter, String[]);
@@ -5554,6 +5577,7 @@
     method public android.graphics.drawable.Icon getSmallIcon();
     method public String getSortKey();
     method public long getTimeoutAfter();
+    method public boolean hasImage();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT;
     field public static final int BADGE_ICON_LARGE = 2; // 0x2
@@ -5585,6 +5609,7 @@
     field public static final int DEFAULT_LIGHTS = 4; // 0x4
     field public static final int DEFAULT_SOUND = 1; // 0x1
     field public static final int DEFAULT_VIBRATE = 2; // 0x2
+    field public static final String EXTRA_ANSWER_COLOR = "android.answerColor";
     field public static final String EXTRA_ANSWER_INTENT = "android.answerIntent";
     field public static final String EXTRA_AUDIO_CONTENTS_URI = "android.audioContents";
     field public static final String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri";
@@ -5596,6 +5621,7 @@
     field public static final String EXTRA_COLORIZED = "android.colorized";
     field public static final String EXTRA_COMPACT_ACTIONS = "android.compactActions";
     field public static final String EXTRA_CONVERSATION_TITLE = "android.conversationTitle";
+    field public static final String EXTRA_DECLINE_COLOR = "android.declineColor";
     field public static final String EXTRA_DECLINE_INTENT = "android.declineIntent";
     field public static final String EXTRA_HANG_UP_INTENT = "android.hangUpIntent";
     field public static final String EXTRA_HISTORIC_MESSAGES = "android.messages.historic";
@@ -5883,6 +5909,8 @@
     method @NonNull public static android.app.Notification.CallStyle forIncomingCall(@NonNull android.app.Person, @NonNull android.app.PendingIntent, @NonNull android.app.PendingIntent);
     method @NonNull public static android.app.Notification.CallStyle forOngoingCall(@NonNull android.app.Person, @NonNull android.app.PendingIntent);
     method @NonNull public static android.app.Notification.CallStyle forScreeningCall(@NonNull android.app.Person, @NonNull android.app.PendingIntent, @NonNull android.app.PendingIntent);
+    method @NonNull public android.app.Notification.CallStyle setAnswerButtonColorHint(@ColorInt int);
+    method @NonNull public android.app.Notification.CallStyle setDeclineButtonColorHint(@ColorInt int);
     method @NonNull public android.app.Notification.CallStyle setVerificationIcon(@Nullable android.graphics.drawable.Icon);
     method @NonNull public android.app.Notification.CallStyle setVerificationText(@Nullable CharSequence);
   }
@@ -6240,14 +6268,14 @@
     method public static android.app.PendingIntent getActivities(android.content.Context, int, @NonNull android.content.Intent[], int, @Nullable android.os.Bundle);
     method public static android.app.PendingIntent getActivity(android.content.Context, int, android.content.Intent, int);
     method public static android.app.PendingIntent getActivity(android.content.Context, int, @NonNull android.content.Intent, int, @Nullable android.os.Bundle);
-    method public static android.app.PendingIntent getBroadcast(android.content.Context, int, android.content.Intent, int);
-    method @Nullable public String getCreatorPackage();
+    method public static android.app.PendingIntent getBroadcast(android.content.Context, int, @NonNull android.content.Intent, int);
+    method @NonNull public String getCreatorPackage();
     method public int getCreatorUid();
-    method @Nullable public android.os.UserHandle getCreatorUserHandle();
+    method @NonNull public android.os.UserHandle getCreatorUserHandle();
     method public static android.app.PendingIntent getForegroundService(android.content.Context, int, @NonNull android.content.Intent, int);
-    method public android.content.IntentSender getIntentSender();
+    method @NonNull public android.content.IntentSender getIntentSender();
     method public static android.app.PendingIntent getService(android.content.Context, int, @NonNull android.content.Intent, int);
-    method @Deprecated public String getTargetPackage();
+    method @Deprecated @NonNull public String getTargetPackage();
     method public boolean isActivity();
     method public boolean isBroadcast();
     method public boolean isForegroundService();
@@ -6560,6 +6588,9 @@
     field public static final int STOP_FOREGROUND_REMOVE = 1; // 0x1
   }
 
+  public abstract class ServiceStartNotAllowedException extends java.lang.IllegalStateException {
+  }
+
   public abstract class SharedElementCallback {
     ctor public SharedElementCallback();
     method public android.os.Parcelable onCaptureSharedElementSnapshot(android.view.View, android.graphics.Matrix, android.graphics.RectF);
@@ -6779,14 +6810,18 @@
   public final class WallpaperColors implements android.os.Parcelable {
     ctor public WallpaperColors(android.os.Parcel);
     ctor public WallpaperColors(@NonNull android.graphics.Color, @Nullable android.graphics.Color, @Nullable android.graphics.Color);
+    ctor public WallpaperColors(@NonNull android.graphics.Color, @Nullable android.graphics.Color, @Nullable android.graphics.Color, int);
     method public int describeContents();
     method public static android.app.WallpaperColors fromBitmap(@NonNull android.graphics.Bitmap);
     method public static android.app.WallpaperColors fromDrawable(android.graphics.drawable.Drawable);
+    method public int getColorHints();
     method @NonNull public android.graphics.Color getPrimaryColor();
     method @Nullable public android.graphics.Color getSecondaryColor();
     method @Nullable public android.graphics.Color getTertiaryColor();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR;
+    field public static final int HINT_SUPPORTS_DARK_TEXT = 1; // 0x1
+    field public static final int HINT_SUPPORTS_DARK_THEME = 2; // 0x2
   }
 
   public final class WallpaperInfo implements android.os.Parcelable {
@@ -8343,7 +8378,9 @@
     method protected android.view.View getDefaultView();
     method protected android.view.View getErrorView();
     method protected void prepareView(android.view.View);
+    method public void resetColorResources();
     method public void setAppWidget(int, android.appwidget.AppWidgetProviderInfo);
+    method public void setColorResources(@NonNull android.util.SparseIntArray);
     method public void setCurrentSize(@NonNull android.graphics.PointF);
     method public void setExecutor(java.util.concurrent.Executor);
     method public void setOnLightBackground(boolean);
@@ -8424,7 +8461,7 @@
     method public int describeContents();
     method public final android.os.UserHandle getProfile();
     method @NonNull public android.content.pm.ActivityInfo getProviderInfo();
-    method @Nullable public final String loadDescription(@NonNull android.content.Context);
+    method @Nullable public final CharSequence loadDescription(@NonNull android.content.Context);
     method public final android.graphics.drawable.Drawable loadIcon(@NonNull android.content.Context, int);
     method public final String loadLabel(android.content.pm.PackageManager);
     method public final android.graphics.drawable.Drawable loadPreviewImage(@NonNull android.content.Context, int);
@@ -8442,7 +8479,7 @@
     field public static final int WIDGET_FEATURE_RECONFIGURABLE = 1; // 0x1
     field public int autoAdvanceViewId;
     field public android.content.ComponentName configure;
-    field @IdRes public int descriptionResource;
+    field @IdRes public int descriptionRes;
     field public int icon;
     field public int initialKeyguardLayout;
     field public int initialLayout;
@@ -9706,7 +9743,7 @@
   public interface DeviceFilter<D extends android.os.Parcelable> extends android.os.Parcelable {
   }
 
-  public class DeviceNotAssociatedException extends java.lang.Exception {
+  public class DeviceNotAssociatedException extends java.lang.RuntimeException {
   }
 
   public final class WifiDeviceFilter implements android.companion.DeviceFilter<android.net.wifi.ScanResult> {
@@ -10210,6 +10247,7 @@
     field public static final String SYNC_EXTRAS_MANUAL = "force";
     field public static final String SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS = "deletions_override";
     field public static final String SYNC_EXTRAS_REQUIRE_CHARGING = "require_charging";
+    field public static final String SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB = "schedule_as_expedited_job";
     field public static final String SYNC_EXTRAS_UPLOAD = "upload";
     field public static final int SYNC_OBSERVER_TYPE_ACTIVE = 4; // 0x4
     field public static final int SYNC_OBSERVER_TYPE_PENDING = 2; // 0x2
@@ -10353,7 +10391,7 @@
     method public abstract void grantUriPermission(String, android.net.Uri, int);
     method public abstract boolean isDeviceProtectedStorage();
     method public boolean isRestricted();
-    method public static boolean isUiContext(@NonNull android.content.Context);
+    method public boolean isUiContext();
     method public abstract boolean moveDatabaseFrom(android.content.Context, String);
     method public abstract boolean moveSharedPreferencesFrom(android.content.Context, String);
     method @NonNull public final android.content.res.TypedArray obtainStyledAttributes(@NonNull @StyleableRes int[]);
@@ -10442,6 +10480,7 @@
     field public static final int CONTEXT_RESTRICTED = 4; // 0x4
     field public static final String CROSS_PROFILE_APPS_SERVICE = "crossprofileapps";
     field public static final String DEVICE_POLICY_SERVICE = "device_policy";
+    field public static final String DISPLAY_HASH_SERVICE = "display_hash";
     field public static final String DISPLAY_SERVICE = "display";
     field public static final String DOWNLOAD_SERVICE = "download";
     field public static final String DROPBOX_SERVICE = "dropbox";
@@ -11531,6 +11570,7 @@
     method public android.content.SyncRequest.Builder setManual(boolean);
     method public android.content.SyncRequest.Builder setNoRetry(boolean);
     method public android.content.SyncRequest.Builder setRequiresCharging(boolean);
+    method @NonNull public android.content.SyncRequest.Builder setScheduleAsExpeditedJob(boolean);
     method public android.content.SyncRequest.Builder setSyncAdapter(android.accounts.Account, String);
     method public android.content.SyncRequest.Builder syncOnce();
     method public android.content.SyncRequest.Builder syncPeriodic(long, long);
@@ -11782,6 +11822,8 @@
     field public int category;
     field public String className;
     field public int compatibleWidthLimitDp;
+    field public int compileSdkVersion;
+    field @Nullable public String compileSdkVersionCodename;
     field public String dataDir;
     field public int descriptionRes;
     field public String deviceProtectedDataDir;
@@ -12523,7 +12565,6 @@
     field public static final String FEATURE_WIFI_DIRECT = "android.hardware.wifi.direct";
     field public static final String FEATURE_WIFI_PASSPOINT = "android.hardware.wifi.passpoint";
     field public static final String FEATURE_WIFI_RTT = "android.hardware.wifi.rtt";
-    field public static final int FLAG_PERMISSION_ALLOWLIST_ROLE = 8; // 0x8
     field public static final int FLAG_PERMISSION_WHITELIST_INSTALLER = 2; // 0x2
     field public static final int FLAG_PERMISSION_WHITELIST_SYSTEM = 1; // 0x1
     field public static final int FLAG_PERMISSION_WHITELIST_UPGRADE = 4; // 0x4
@@ -12662,7 +12703,6 @@
     field public static final int FLAG_HARD_RESTRICTED = 4; // 0x4
     field public static final int FLAG_IMMUTABLY_RESTRICTED = 16; // 0x10
     field public static final int FLAG_INSTALLED = 1073741824; // 0x40000000
-    field public static final int FLAG_INSTALLER_EXEMPT_IGNORED = 32; // 0x20
     field public static final int FLAG_SOFT_RESTRICTED = 8; // 0x8
     field public static final int PROTECTION_DANGEROUS = 1; // 0x1
     field public static final int PROTECTION_FLAG_APPOP = 64; // 0x40
@@ -12862,6 +12902,7 @@
     method public void reportShortcutUsed(String);
     method public boolean requestPinShortcut(@NonNull android.content.pm.ShortcutInfo, @Nullable android.content.IntentSender);
     method public boolean setDynamicShortcuts(@NonNull java.util.List<android.content.pm.ShortcutInfo>);
+    method public void updateShortcutVisibility(@NonNull String, @Nullable byte[], boolean);
     method public boolean updateShortcuts(@NonNull java.util.List<android.content.pm.ShortcutInfo>);
     field public static final int FLAG_MATCH_CACHED = 8; // 0x8
     field public static final int FLAG_MATCH_DYNAMIC = 2; // 0x2
@@ -14611,11 +14652,6 @@
     enum_constant public static final android.graphics.BlurMaskFilter.Blur SOLID;
   }
 
-  public final class BlurShader extends android.graphics.Shader {
-    ctor public BlurShader(float, float, @Nullable android.graphics.Shader);
-    ctor public BlurShader(float, float, @Nullable android.graphics.Shader, @NonNull android.graphics.Shader.TileMode);
-  }
-
   public class Camera {
     ctor public Camera();
     method public void applyToCanvas(android.graphics.Canvas);
@@ -18533,6 +18569,23 @@
 
 package android.hardware.display {
 
+  public final class DeviceProductInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getConnectionToSinkType();
+    method public int getManufactureWeek();
+    method public int getManufactureYear();
+    method @NonNull public String getManufacturerPnpId();
+    method public int getModelYear();
+    method @Nullable public String getName();
+    method @NonNull public String getProductId();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field public static final int CONNECTION_TO_SINK_BUILT_IN = 1; // 0x1
+    field public static final int CONNECTION_TO_SINK_DIRECT = 2; // 0x2
+    field public static final int CONNECTION_TO_SINK_TRANSITIVE = 3; // 0x3
+    field public static final int CONNECTION_TO_SINK_UNKNOWN = 0; // 0x0
+    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.DeviceProductInfo> CREATOR;
+  }
+
   public final class DisplayManager {
     method public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, int, int, int, @Nullable android.view.Surface, int);
     method public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, int, int, int, @Nullable android.view.Surface, int, @Nullable android.hardware.display.VirtualDisplay.Callback, @Nullable android.os.Handler);
@@ -18641,6 +18694,58 @@
 
 }
 
+package android.hardware.lights {
+
+  public final class Light implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getId();
+    method @NonNull public String getName();
+    method public int getOrdinal();
+    method public int getType();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.lights.Light> CREATOR;
+    field public static final int LIGHT_TYPE_INPUT_PLAYER_ID = 10; // 0xa
+    field public static final int LIGHT_TYPE_INPUT_RGB = 11; // 0xb
+    field public static final int LIGHT_TYPE_INPUT_SINGLE = 9; // 0x9
+    field public static final int LIGHT_TYPE_MICROPHONE = 8; // 0x8
+  }
+
+  public final class LightState implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public static android.hardware.lights.LightState forColor(@ColorInt int);
+    method @NonNull public static android.hardware.lights.LightState forPlayerId(int);
+    method @ColorInt public int getColor();
+    method public int getPlayerId();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.lights.LightState> CREATOR;
+  }
+
+  public abstract class LightsManager {
+    method @NonNull public abstract android.hardware.lights.LightState getLightState(@NonNull android.hardware.lights.Light);
+    method @NonNull public abstract java.util.List<android.hardware.lights.Light> getLights();
+    method @NonNull public abstract android.hardware.lights.LightsManager.LightsSession openSession();
+  }
+
+  public abstract static class LightsManager.LightsSession implements java.lang.AutoCloseable {
+    ctor public LightsManager.LightsSession();
+    method public abstract void close();
+    method public abstract void requestLights(@NonNull android.hardware.lights.LightsRequest);
+  }
+
+  public final class LightsRequest {
+    method @NonNull public java.util.List<android.hardware.lights.LightState> getLightStates();
+    method @NonNull public java.util.List<java.lang.Integer> getLights();
+  }
+
+  public static final class LightsRequest.Builder {
+    ctor public LightsRequest.Builder();
+    method @NonNull public android.hardware.lights.LightsRequest.Builder addLight(@NonNull android.hardware.lights.Light, @NonNull android.hardware.lights.LightState);
+    method @NonNull public android.hardware.lights.LightsRequest build();
+    method @NonNull public android.hardware.lights.LightsRequest.Builder clearLight(@NonNull android.hardware.lights.Light);
+  }
+
+}
+
 package android.hardware.usb {
 
   public class UsbAccessory implements android.os.Parcelable {
@@ -18809,6 +18914,7 @@
   public abstract class AbstractInputMethodService extends android.app.Service implements android.view.KeyEvent.Callback {
     ctor public AbstractInputMethodService();
     method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
+    method public final boolean isUiContext();
     method public final android.os.IBinder onBind(android.content.Intent);
     method public abstract android.inputmethodservice.AbstractInputMethodService.AbstractInputMethodImpl onCreateInputMethodInterface();
     method public abstract android.inputmethodservice.AbstractInputMethodService.AbstractInputMethodSessionImpl onCreateInputMethodSessionInterface();
@@ -19205,8 +19311,8 @@
     method @NonNull public android.location.GnssAntennaInfo.Builder setSignalGainCorrections(@Nullable android.location.GnssAntennaInfo.SphericalCorrections);
   }
 
-  @Deprecated public static interface GnssAntennaInfo.Listener {
-    method @Deprecated public void onGnssAntennaInfoReceived(@NonNull java.util.List<android.location.GnssAntennaInfo>);
+  public static interface GnssAntennaInfo.Listener {
+    method public void onGnssAntennaInfoReceived(@NonNull java.util.List<android.location.GnssAntennaInfo>);
   }
 
   public static final class GnssAntennaInfo.PhaseCenterOffset implements android.os.Parcelable {
@@ -19574,6 +19680,7 @@
     method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void addProximityAlert(double, double, float, long, @NonNull android.app.PendingIntent);
     method public void addTestProvider(@NonNull String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
     method public void addTestProvider(@NonNull String, @NonNull android.location.provider.ProviderProperties);
+    method public void addTestProvider(@NonNull String, @NonNull android.location.provider.ProviderProperties, @NonNull java.util.Set<java.lang.String>);
     method @Deprecated public void clearTestProviderEnabled(@NonNull String);
     method @Deprecated public void clearTestProviderLocation(@NonNull String);
     method @Deprecated public void clearTestProviderStatus(@NonNull String);
@@ -19594,7 +19701,7 @@
     method public boolean hasProvider(@NonNull String);
     method public boolean isLocationEnabled();
     method public boolean isProviderEnabled(@NonNull String);
-    method @Deprecated public boolean registerAntennaInfoListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssAntennaInfo.Listener);
+    method public boolean registerAntennaInfoListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssAntennaInfo.Listener);
     method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback, @Nullable android.os.Handler);
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
@@ -19631,13 +19738,11 @@
     method public void setTestProviderEnabled(@NonNull String, boolean);
     method public void setTestProviderLocation(@NonNull String, @NonNull android.location.Location);
     method @Deprecated public void setTestProviderStatus(@NonNull String, int, @Nullable android.os.Bundle, long);
-    method @Deprecated public void unregisterAntennaInfoListener(@NonNull android.location.GnssAntennaInfo.Listener);
+    method public void unregisterAntennaInfoListener(@NonNull android.location.GnssAntennaInfo.Listener);
     method public void unregisterGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
     method public void unregisterGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
     method public void unregisterGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
-    field public static final String ACTION_GNSS_ANTENNA_INFOS_CHANGED = "android.location.action.GNSS_ANTENNA_INFOS_CHANGED";
     field public static final String ACTION_GNSS_CAPABILITIES_CHANGED = "android.location.action.GNSS_CAPABILITIES_CHANGED";
-    field public static final String EXTRA_GNSS_ANTENNA_INFOS = "android.location.extra.GNSS_ANTENNA_INFOS";
     field public static final String EXTRA_GNSS_CAPABILITIES = "android.location.extra.GNSS_CAPABILITIES";
     field public static final String EXTRA_LOCATION_ENABLED = "android.location.extra.LOCATION_ENABLED";
     field public static final String EXTRA_PROVIDER_ENABLED = "android.location.extra.PROVIDER_ENABLED";
@@ -19780,7 +19885,6 @@
     method public int getFlags();
     method public int getUsage();
     method public int getVolumeControlStream();
-    method @NonNull public static String usageToString(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ALLOW_CAPTURE_BY_ALL = 1; // 0x1
     field public static final int ALLOW_CAPTURE_BY_NONE = 3; // 0x3
@@ -21115,15 +21219,15 @@
   public static final class MediaCodec.CryptoException extends java.lang.RuntimeException {
     ctor public MediaCodec.CryptoException(int, @Nullable String);
     method public int getErrorCode();
-    field public static final int ERROR_FRAME_TOO_LARGE = 8; // 0x8
-    field public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4; // 0x4
-    field public static final int ERROR_INSUFFICIENT_SECURITY = 7; // 0x7
-    field public static final int ERROR_KEY_EXPIRED = 2; // 0x2
-    field public static final int ERROR_LOST_STATE = 9; // 0x9
-    field public static final int ERROR_NO_KEY = 1; // 0x1
-    field public static final int ERROR_RESOURCE_BUSY = 3; // 0x3
-    field public static final int ERROR_SESSION_NOT_OPENED = 5; // 0x5
-    field public static final int ERROR_UNSUPPORTED_OPERATION = 6; // 0x6
+    field @Deprecated public static final int ERROR_FRAME_TOO_LARGE = 8; // 0x8
+    field @Deprecated public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4; // 0x4
+    field @Deprecated public static final int ERROR_INSUFFICIENT_SECURITY = 7; // 0x7
+    field @Deprecated public static final int ERROR_KEY_EXPIRED = 2; // 0x2
+    field @Deprecated public static final int ERROR_LOST_STATE = 9; // 0x9
+    field @Deprecated public static final int ERROR_NO_KEY = 1; // 0x1
+    field @Deprecated public static final int ERROR_RESOURCE_BUSY = 3; // 0x3
+    field @Deprecated public static final int ERROR_SESSION_NOT_OPENED = 5; // 0x5
+    field @Deprecated public static final int ERROR_UNSUPPORTED_OPERATION = 6; // 0x6
   }
 
   public static final class MediaCodec.CryptoInfo {
@@ -21213,8 +21317,8 @@
   public static final class MediaCodecInfo.AudioCapabilities {
     method public android.util.Range<java.lang.Integer> getBitrateRange();
     method @NonNull public android.util.Range<java.lang.Integer>[] getInputChannelCountRanges();
-    method public int getMaxInputChannelCount();
-    method public int getMinInputChannelCount();
+    method @IntRange(from=1, to=255) public int getMaxInputChannelCount();
+    method @IntRange(from=1, to=255) public int getMinInputChannelCount();
     method public android.util.Range<java.lang.Integer>[] getSupportedSampleRateRanges();
     method public int[] getSupportedSampleRates();
     method public boolean isSampleRateSupported(int);
@@ -21742,6 +21846,42 @@
     method public boolean verify(@NonNull byte[], @NonNull byte[], @NonNull byte[]);
   }
 
+  public static final class MediaDrm.ErrorCodes {
+    field public static final int ERROR_CERTIFICATE_MALFORMED = 10; // 0xa
+    field public static final int ERROR_CERTIFICATE_MISSING = 11; // 0xb
+    field public static final int ERROR_CRYPTO_LIBRARY = 12; // 0xc
+    field public static final int ERROR_FRAME_TOO_LARGE = 8; // 0x8
+    field public static final int ERROR_GENERIC_OEM = 13; // 0xd
+    field public static final int ERROR_GENERIC_PLUGIN = 14; // 0xe
+    field public static final int ERROR_INIT_DATA = 15; // 0xf
+    field public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4; // 0x4
+    field public static final int ERROR_INSUFFICIENT_SECURITY = 7; // 0x7
+    field public static final int ERROR_KEY_EXPIRED = 2; // 0x2
+    field public static final int ERROR_KEY_NOT_LOADED = 16; // 0x10
+    field public static final int ERROR_LICENSE_PARSE = 17; // 0x11
+    field public static final int ERROR_LICENSE_POLICY = 18; // 0x12
+    field public static final int ERROR_LICENSE_RELEASE = 19; // 0x13
+    field public static final int ERROR_LICENSE_REQUEST_REJECTED = 20; // 0x14
+    field public static final int ERROR_LICENSE_RESTORE = 21; // 0x15
+    field public static final int ERROR_LICENSE_STATE = 22; // 0x16
+    field public static final int ERROR_LOST_STATE = 9; // 0x9
+    field public static final int ERROR_MEDIA_FRAMEWORK = 23; // 0x17
+    field public static final int ERROR_NO_KEY = 1; // 0x1
+    field public static final int ERROR_PROVISIONING_CERTIFICATE = 24; // 0x18
+    field public static final int ERROR_PROVISIONING_CONFIG = 25; // 0x19
+    field public static final int ERROR_PROVISIONING_PARSE = 26; // 0x1a
+    field public static final int ERROR_PROVISIONING_RETRY = 27; // 0x1b
+    field public static final int ERROR_RESOURCE_BUSY = 3; // 0x3
+    field public static final int ERROR_RESOURCE_CONTENTION = 28; // 0x1c
+    field public static final int ERROR_SECURE_STOP_RELEASE = 29; // 0x1d
+    field public static final int ERROR_SESSION_NOT_OPENED = 5; // 0x5
+    field public static final int ERROR_STORAGE_READ = 30; // 0x1e
+    field public static final int ERROR_STORAGE_WRITE = 31; // 0x1f
+    field public static final int ERROR_UNKNOWN = 0; // 0x0
+    field public static final int ERROR_UNSUPPORTED_OPERATION = 6; // 0x6
+    field public static final int ERROR_ZERO_SUBSAMPLES = 32; // 0x20
+  }
+
   @Deprecated @IntDef({android.media.MediaDrm.HDCP_LEVEL_UNKNOWN, android.media.MediaDrm.HDCP_NONE, android.media.MediaDrm.HDCP_V1, android.media.MediaDrm.HDCP_V2, android.media.MediaDrm.HDCP_V2_1, android.media.MediaDrm.HDCP_V2_2, android.media.MediaDrm.HDCP_V2_3, android.media.MediaDrm.HDCP_NO_DIGITAL_OUTPUT}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface MediaDrm.HdcpLevel {
   }
 
@@ -21775,6 +21915,8 @@
 
   public static final class MediaDrm.MediaDrmStateException extends java.lang.IllegalStateException {
     method @NonNull public String getDiagnosticInfo();
+    method public int getErrorCode();
+    method public boolean isTransient();
   }
 
   public static final class MediaDrm.MetricsConstants {
@@ -21841,9 +21983,10 @@
 
   public static final class MediaDrm.SessionException extends java.lang.RuntimeException {
     ctor public MediaDrm.SessionException(int, @Nullable String);
-    method public int getErrorCode();
-    field public static final int ERROR_RESOURCE_CONTENTION = 1; // 0x1
-    field public static final int ERROR_UNKNOWN = 0; // 0x0
+    method @Deprecated public int getErrorCode();
+    method public boolean isTransient();
+    field @Deprecated public static final int ERROR_RESOURCE_CONTENTION = 1; // 0x1
+    field @Deprecated public static final int ERROR_UNKNOWN = 0; // 0x0
   }
 
   public class MediaDrmException extends java.lang.Exception {
@@ -22023,6 +22166,14 @@
     field public static final String KEY_TILE_HEIGHT = "tile-height";
     field public static final String KEY_TILE_WIDTH = "tile-width";
     field public static final String KEY_TRACK_ID = "track-id";
+    field public static final String KEY_VIDEO_QP_B_MAX = "video-qp-b-max";
+    field public static final String KEY_VIDEO_QP_B_MIN = "video-qp-b-min";
+    field public static final String KEY_VIDEO_QP_I_MAX = "video-qp-i-max";
+    field public static final String KEY_VIDEO_QP_I_MIN = "video-qp-i-min";
+    field public static final String KEY_VIDEO_QP_MAX = "video-qp-max";
+    field public static final String KEY_VIDEO_QP_MIN = "video-qp-min";
+    field public static final String KEY_VIDEO_QP_P_MAX = "video-qp-p-max";
+    field public static final String KEY_VIDEO_QP_P_MIN = "video-qp-p-min";
     field public static final String KEY_WIDTH = "width";
     field public static final String MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
     field public static final String MIMETYPE_AUDIO_AC3 = "audio/ac3";
@@ -24624,7 +24775,7 @@
     method @NonNull public java.util.List<android.media.session.MediaController> getActiveSessions(@Nullable android.content.ComponentName);
     method @NonNull public java.util.List<android.media.Session2Token> getSession2Tokens();
     method public boolean isTrustedForMediaControl(@NonNull android.media.session.MediaSessionManager.RemoteUserInfo);
-    method public void notifySession2Created(@NonNull android.media.Session2Token);
+    method @Deprecated public void notifySession2Created(@NonNull android.media.Session2Token);
     method public void removeOnActiveSessionsChangedListener(@NonNull android.media.session.MediaSessionManager.OnActiveSessionsChangedListener);
     method public void removeOnSession2TokensChangedListener(@NonNull android.media.session.MediaSessionManager.OnSession2TokensChangedListener);
   }
@@ -25691,161 +25842,6 @@
 
 package android.net {
 
-  public class CaptivePortal implements android.os.Parcelable {
-    method public int describeContents();
-    method public void ignoreNetwork();
-    method public void reportCaptivePortalDismissed();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.CaptivePortal> CREATOR;
-  }
-
-  public class ConnectivityDiagnosticsManager {
-    method public void registerConnectivityDiagnosticsCallback(@NonNull android.net.NetworkRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback);
-    method public void unregisterConnectivityDiagnosticsCallback(@NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback);
-  }
-
-  public abstract static class ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback {
-    ctor public ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback();
-    method public void onConnectivityReportAvailable(@NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityReport);
-    method public void onDataStallSuspected(@NonNull android.net.ConnectivityDiagnosticsManager.DataStallReport);
-    method public void onNetworkConnectivityReported(@NonNull android.net.Network, boolean);
-  }
-
-  public static final class ConnectivityDiagnosticsManager.ConnectivityReport implements android.os.Parcelable {
-    ctor public ConnectivityDiagnosticsManager.ConnectivityReport(@NonNull android.net.Network, long, @NonNull android.net.LinkProperties, @NonNull android.net.NetworkCapabilities, @NonNull android.os.PersistableBundle);
-    method public int describeContents();
-    method @NonNull public android.os.PersistableBundle getAdditionalInfo();
-    method @NonNull public android.net.LinkProperties getLinkProperties();
-    method @NonNull public android.net.Network getNetwork();
-    method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities();
-    method public long getReportTimestamp();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.ConnectivityDiagnosticsManager.ConnectivityReport> CREATOR;
-    field public static final String KEY_NETWORK_PROBES_ATTEMPTED_BITMASK = "networkProbesAttempted";
-    field public static final String KEY_NETWORK_PROBES_SUCCEEDED_BITMASK = "networkProbesSucceeded";
-    field public static final String KEY_NETWORK_VALIDATION_RESULT = "networkValidationResult";
-    field public static final int NETWORK_PROBE_DNS = 4; // 0x4
-    field public static final int NETWORK_PROBE_FALLBACK = 32; // 0x20
-    field public static final int NETWORK_PROBE_HTTP = 8; // 0x8
-    field public static final int NETWORK_PROBE_HTTPS = 16; // 0x10
-    field public static final int NETWORK_PROBE_PRIVATE_DNS = 64; // 0x40
-    field public static final int NETWORK_VALIDATION_RESULT_INVALID = 0; // 0x0
-    field public static final int NETWORK_VALIDATION_RESULT_PARTIALLY_VALID = 2; // 0x2
-    field public static final int NETWORK_VALIDATION_RESULT_SKIPPED = 3; // 0x3
-    field public static final int NETWORK_VALIDATION_RESULT_VALID = 1; // 0x1
-  }
-
-  public static final class ConnectivityDiagnosticsManager.DataStallReport implements android.os.Parcelable {
-    ctor public ConnectivityDiagnosticsManager.DataStallReport(@NonNull android.net.Network, long, int, @NonNull android.net.LinkProperties, @NonNull android.net.NetworkCapabilities, @NonNull android.os.PersistableBundle);
-    method public int describeContents();
-    method public int getDetectionMethod();
-    method @NonNull public android.net.LinkProperties getLinkProperties();
-    method @NonNull public android.net.Network getNetwork();
-    method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities();
-    method public long getReportTimestamp();
-    method @NonNull public android.os.PersistableBundle getStallDetails();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.ConnectivityDiagnosticsManager.DataStallReport> CREATOR;
-    field public static final int DETECTION_METHOD_DNS_EVENTS = 1; // 0x1
-    field public static final int DETECTION_METHOD_TCP_METRICS = 2; // 0x2
-    field public static final String KEY_DNS_CONSECUTIVE_TIMEOUTS = "dnsConsecutiveTimeouts";
-    field public static final String KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS = "tcpMetricsCollectionPeriodMillis";
-    field public static final String KEY_TCP_PACKET_FAIL_RATE = "tcpPacketFailRate";
-  }
-
-  public class ConnectivityManager {
-    method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
-    method public boolean bindProcessToNetwork(@Nullable android.net.Network);
-    method @NonNull public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull android.net.IpSecManager.UdpEncapsulationSocket, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
-    method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network getActiveNetwork();
-    method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getActiveNetworkInfo();
-    method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo[] getAllNetworkInfo();
-    method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network[] getAllNetworks();
-    method @Deprecated public boolean getBackgroundDataSetting();
-    method @Nullable public android.net.Network getBoundNetworkForProcess();
-    method public int getConnectionOwnerUid(int, @NonNull java.net.InetSocketAddress, @NonNull java.net.InetSocketAddress);
-    method @Nullable public android.net.ProxyInfo getDefaultProxy();
-    method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.LinkProperties getLinkProperties(@Nullable android.net.Network);
-    method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public int getMultipathPreference(@Nullable android.net.Network);
-    method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkCapabilities getNetworkCapabilities(@Nullable android.net.Network);
-    method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getNetworkInfo(int);
-    method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getNetworkInfo(@Nullable android.net.Network);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public int getNetworkPreference();
-    method @Nullable public byte[] getNetworkWatchlistConfigHash();
-    method @Deprecated @Nullable public static android.net.Network getProcessDefaultNetwork();
-    method public int getRestrictBackgroundStatus();
-    method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public boolean isActiveNetworkMetered();
-    method public boolean isDefaultNetworkActive();
-    method @Deprecated public static boolean isNetworkTypeValid(int);
-    method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback);
-    method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
-    method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback);
-    method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
-    method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.app.PendingIntent);
-    method public void releaseNetworkRequest(@NonNull android.app.PendingIntent);
-    method public void removeDefaultNetworkActiveListener(@NonNull android.net.ConnectivityManager.OnNetworkActiveListener);
-    method @Deprecated public void reportBadNetwork(@Nullable android.net.Network);
-    method public void reportNetworkConnectivity(@Nullable android.net.Network, boolean);
-    method public boolean requestBandwidthUpdate(@NonNull android.net.Network);
-    method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback);
-    method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
-    method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, int);
-    method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler, int);
-    method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.app.PendingIntent);
-    method @Deprecated public void setNetworkPreference(int);
-    method @Deprecated public static boolean setProcessDefaultNetwork(@Nullable android.net.Network);
-    method public void unregisterNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback);
-    method public void unregisterNetworkCallback(@NonNull android.app.PendingIntent);
-    field @Deprecated public static final String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
-    field public static final String ACTION_CAPTIVE_PORTAL_SIGN_IN = "android.net.conn.CAPTIVE_PORTAL";
-    field public static final String ACTION_RESTRICT_BACKGROUND_CHANGED = "android.net.conn.RESTRICT_BACKGROUND_CHANGED";
-    field @Deprecated public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
-    field @Deprecated public static final int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1
-    field public static final String EXTRA_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL";
-    field public static final String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL";
-    field @Deprecated public static final String EXTRA_EXTRA_INFO = "extraInfo";
-    field @Deprecated public static final String EXTRA_IS_FAILOVER = "isFailover";
-    field public static final String EXTRA_NETWORK = "android.net.extra.NETWORK";
-    field @Deprecated public static final String EXTRA_NETWORK_INFO = "networkInfo";
-    field public static final String EXTRA_NETWORK_REQUEST = "android.net.extra.NETWORK_REQUEST";
-    field @Deprecated public static final String EXTRA_NETWORK_TYPE = "networkType";
-    field public static final String EXTRA_NO_CONNECTIVITY = "noConnectivity";
-    field @Deprecated public static final String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
-    field public static final String EXTRA_REASON = "reason";
-    field public static final int MULTIPATH_PREFERENCE_HANDOVER = 1; // 0x1
-    field public static final int MULTIPATH_PREFERENCE_PERFORMANCE = 4; // 0x4
-    field public static final int MULTIPATH_PREFERENCE_RELIABILITY = 2; // 0x2
-    field public static final int RESTRICT_BACKGROUND_STATUS_DISABLED = 1; // 0x1
-    field public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3; // 0x3
-    field public static final int RESTRICT_BACKGROUND_STATUS_WHITELISTED = 2; // 0x2
-    field @Deprecated public static final int TYPE_BLUETOOTH = 7; // 0x7
-    field @Deprecated public static final int TYPE_DUMMY = 8; // 0x8
-    field @Deprecated public static final int TYPE_ETHERNET = 9; // 0x9
-    field @Deprecated public static final int TYPE_MOBILE = 0; // 0x0
-    field @Deprecated public static final int TYPE_MOBILE_DUN = 4; // 0x4
-    field @Deprecated public static final int TYPE_MOBILE_HIPRI = 5; // 0x5
-    field @Deprecated public static final int TYPE_MOBILE_MMS = 2; // 0x2
-    field @Deprecated public static final int TYPE_MOBILE_SUPL = 3; // 0x3
-    field @Deprecated public static final int TYPE_VPN = 17; // 0x11
-    field @Deprecated public static final int TYPE_WIFI = 1; // 0x1
-    field @Deprecated public static final int TYPE_WIMAX = 6; // 0x6
-  }
-
-  public static class ConnectivityManager.NetworkCallback {
-    ctor public ConnectivityManager.NetworkCallback();
-    method public void onAvailable(@NonNull android.net.Network);
-    method public void onBlockedStatusChanged(@NonNull android.net.Network, boolean);
-    method public void onCapabilitiesChanged(@NonNull android.net.Network, @NonNull android.net.NetworkCapabilities);
-    method public void onLinkPropertiesChanged(@NonNull android.net.Network, @NonNull android.net.LinkProperties);
-    method public void onLosing(@NonNull android.net.Network, int);
-    method public void onLost(@NonNull android.net.Network);
-    method public void onUnavailable();
-  }
-
-  public static interface ConnectivityManager.OnNetworkActiveListener {
-    method public void onNetworkActive();
-  }
-
   public class Credentials {
     ctor public Credentials(int, int, int);
     method public int getGid();
@@ -25853,46 +25849,6 @@
     method public int getUid();
   }
 
-  public class DhcpInfo implements android.os.Parcelable {
-    ctor public DhcpInfo();
-    method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.DhcpInfo> CREATOR;
-    field public int dns1;
-    field public int dns2;
-    field public int gateway;
-    field public int ipAddress;
-    field public int leaseDuration;
-    field public int netmask;
-    field public int serverAddress;
-  }
-
-  public final class DnsResolver {
-    method @NonNull public static android.net.DnsResolver getInstance();
-    method public void query(@Nullable android.net.Network, @NonNull String, int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback<? super java.util.List<java.net.InetAddress>>);
-    method public void query(@Nullable android.net.Network, @NonNull String, int, int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback<? super java.util.List<java.net.InetAddress>>);
-    method public void rawQuery(@Nullable android.net.Network, @NonNull byte[], int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback<? super byte[]>);
-    method public void rawQuery(@Nullable android.net.Network, @NonNull String, int, int, int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback<? super byte[]>);
-    field public static final int CLASS_IN = 1; // 0x1
-    field public static final int ERROR_PARSE = 0; // 0x0
-    field public static final int ERROR_SYSTEM = 1; // 0x1
-    field public static final int FLAG_EMPTY = 0; // 0x0
-    field public static final int FLAG_NO_CACHE_LOOKUP = 4; // 0x4
-    field public static final int FLAG_NO_CACHE_STORE = 2; // 0x2
-    field public static final int FLAG_NO_RETRY = 1; // 0x1
-    field public static final int TYPE_A = 1; // 0x1
-    field public static final int TYPE_AAAA = 28; // 0x1c
-  }
-
-  public static interface DnsResolver.Callback<T> {
-    method public void onAnswer(@NonNull T, int);
-    method public void onError(@NonNull android.net.DnsResolver.DnsException);
-  }
-
-  public static class DnsResolver.DnsException extends java.lang.Exception {
-    field public final int code;
-  }
-
   public final class Ikev2VpnProfile extends android.net.PlatformVpnProfile {
     method @NonNull public java.util.List<java.lang.String> getAllowedAlgorithms();
     method public int getMaxMtu();
@@ -25922,21 +25878,6 @@
     method @NonNull public android.net.Ikev2VpnProfile.Builder setProxy(@Nullable android.net.ProxyInfo);
   }
 
-  public class InetAddresses {
-    method public static boolean isNumericAddress(@NonNull String);
-    method @NonNull public static java.net.InetAddress parseNumericAddress(@NonNull String);
-  }
-
-  public final class IpPrefix implements android.os.Parcelable {
-    method public boolean contains(@NonNull java.net.InetAddress);
-    method public int describeContents();
-    method @NonNull public java.net.InetAddress getAddress();
-    method @IntRange(from=0, to=128) public int getPrefixLength();
-    method @NonNull public byte[] getRawAddress();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.IpPrefix> CREATOR;
-  }
-
   public final class IpSecAlgorithm implements android.os.Parcelable {
     ctor public IpSecAlgorithm(@NonNull String, @NonNull byte[]);
     ctor public IpSecAlgorithm(@NonNull String, @NonNull byte[], int);
@@ -26005,45 +25946,6 @@
     method @NonNull public android.net.IpSecTransform.Builder setIpv4Encapsulation(@NonNull android.net.IpSecManager.UdpEncapsulationSocket, int);
   }
 
-  public class LinkAddress implements android.os.Parcelable {
-    method public int describeContents();
-    method public java.net.InetAddress getAddress();
-    method public int getFlags();
-    method @IntRange(from=0, to=128) public int getPrefixLength();
-    method public int getScope();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.LinkAddress> CREATOR;
-  }
-
-  public final class LinkProperties implements android.os.Parcelable {
-    ctor public LinkProperties();
-    method public boolean addRoute(@NonNull android.net.RouteInfo);
-    method public void clear();
-    method public int describeContents();
-    method @Nullable public java.net.Inet4Address getDhcpServerAddress();
-    method @NonNull public java.util.List<java.net.InetAddress> getDnsServers();
-    method @Nullable public String getDomains();
-    method @Nullable public android.net.ProxyInfo getHttpProxy();
-    method @Nullable public String getInterfaceName();
-    method @NonNull public java.util.List<android.net.LinkAddress> getLinkAddresses();
-    method public int getMtu();
-    method @Nullable public android.net.IpPrefix getNat64Prefix();
-    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 setDhcpServerAddress(@Nullable java.net.Inet4Address);
-    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);
-    method public void setInterfaceName(@Nullable String);
-    method public void setLinkAddresses(@NonNull java.util.Collection<android.net.LinkAddress>);
-    method public void setMtu(int);
-    method public void setNat64Prefix(@Nullable android.net.IpPrefix);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.LinkProperties> CREATOR;
-  }
-
   public class LocalServerSocket implements java.io.Closeable {
     ctor public LocalServerSocket(String) throws java.io.IOException;
     ctor public LocalServerSocket(java.io.FileDescriptor) throws java.io.IOException;
@@ -26099,24 +26001,6 @@
     enum_constant public static final android.net.LocalSocketAddress.Namespace RESERVED;
   }
 
-  public final class MacAddress implements android.os.Parcelable {
-    method public int describeContents();
-    method @NonNull public static android.net.MacAddress fromBytes(@NonNull byte[]);
-    method @NonNull public static android.net.MacAddress fromString(@NonNull String);
-    method public int getAddressType();
-    method @Nullable public java.net.Inet6Address getLinkLocalIpv6FromEui48Mac();
-    method public boolean isLocallyAssigned();
-    method public boolean matches(@NonNull android.net.MacAddress, @NonNull android.net.MacAddress);
-    method @NonNull public byte[] toByteArray();
-    method @NonNull public String toOuiString();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.net.MacAddress BROADCAST_ADDRESS;
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.MacAddress> CREATOR;
-    field public static final int TYPE_BROADCAST = 3; // 0x3
-    field public static final int TYPE_MULTICAST = 2; // 0x2
-    field public static final int TYPE_UNICAST = 1; // 0x1
-  }
-
   public class MailTo {
     method public String getBody();
     method public String getCc();
@@ -26128,138 +26012,6 @@
     field public static final String MAILTO_SCHEME = "mailto:";
   }
 
-  public class Network implements android.os.Parcelable {
-    method public void bindSocket(java.net.DatagramSocket) throws java.io.IOException;
-    method public void bindSocket(java.net.Socket) throws java.io.IOException;
-    method public void bindSocket(java.io.FileDescriptor) throws java.io.IOException;
-    method public int describeContents();
-    method public static android.net.Network fromNetworkHandle(long);
-    method public java.net.InetAddress[] getAllByName(String) throws java.net.UnknownHostException;
-    method public java.net.InetAddress getByName(String) throws java.net.UnknownHostException;
-    method public long getNetworkHandle();
-    method public javax.net.SocketFactory getSocketFactory();
-    method public java.net.URLConnection openConnection(java.net.URL) throws java.io.IOException;
-    method public java.net.URLConnection openConnection(java.net.URL, java.net.Proxy) throws java.io.IOException;
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.Network> CREATOR;
-  }
-
-  public final class NetworkCapabilities implements android.os.Parcelable {
-    ctor public NetworkCapabilities();
-    ctor public NetworkCapabilities(android.net.NetworkCapabilities);
-    method public int describeContents();
-    method public int getLinkDownstreamBandwidthKbps();
-    method public int getLinkUpstreamBandwidthKbps();
-    method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier();
-    method public int getOwnerUid();
-    method public int getSignalStrength();
-    method @Nullable public android.net.TransportInfo getTransportInfo();
-    method public boolean hasCapability(int);
-    method public boolean hasTransport(int);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkCapabilities> CREATOR;
-    field public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17; // 0x11
-    field public static final int NET_CAPABILITY_CBS = 5; // 0x5
-    field public static final int NET_CAPABILITY_DUN = 2; // 0x2
-    field public static final int NET_CAPABILITY_EIMS = 10; // 0xa
-    field public static final int NET_CAPABILITY_FOREGROUND = 19; // 0x13
-    field public static final int NET_CAPABILITY_FOTA = 3; // 0x3
-    field public static final int NET_CAPABILITY_IA = 7; // 0x7
-    field public static final int NET_CAPABILITY_IMS = 4; // 0x4
-    field public static final int NET_CAPABILITY_INTERNET = 12; // 0xc
-    field public static final int NET_CAPABILITY_MCX = 23; // 0x17
-    field public static final int NET_CAPABILITY_MMS = 0; // 0x0
-    field public static final int NET_CAPABILITY_NOT_CONGESTED = 20; // 0x14
-    field public static final int NET_CAPABILITY_NOT_METERED = 11; // 0xb
-    field public static final int NET_CAPABILITY_NOT_RESTRICTED = 13; // 0xd
-    field public static final int NET_CAPABILITY_NOT_ROAMING = 18; // 0x12
-    field public static final int NET_CAPABILITY_NOT_SUSPENDED = 21; // 0x15
-    field public static final int NET_CAPABILITY_NOT_VPN = 15; // 0xf
-    field public static final int NET_CAPABILITY_RCS = 8; // 0x8
-    field public static final int NET_CAPABILITY_SUPL = 1; // 0x1
-    field public static final int NET_CAPABILITY_TEMPORARILY_NOT_METERED = 25; // 0x19
-    field public static final int NET_CAPABILITY_TRUSTED = 14; // 0xe
-    field public static final int NET_CAPABILITY_VALIDATED = 16; // 0x10
-    field public static final int NET_CAPABILITY_WIFI_P2P = 6; // 0x6
-    field public static final int NET_CAPABILITY_XCAP = 9; // 0x9
-    field public static final int SIGNAL_STRENGTH_UNSPECIFIED = -2147483648; // 0x80000000
-    field public static final int TRANSPORT_BLUETOOTH = 2; // 0x2
-    field public static final int TRANSPORT_CELLULAR = 0; // 0x0
-    field public static final int TRANSPORT_ETHERNET = 3; // 0x3
-    field public static final int TRANSPORT_LOWPAN = 6; // 0x6
-    field public static final int TRANSPORT_VPN = 4; // 0x4
-    field public static final int TRANSPORT_WIFI = 1; // 0x1
-    field public static final int TRANSPORT_WIFI_AWARE = 5; // 0x5
-  }
-
-  @Deprecated public class NetworkInfo implements android.os.Parcelable {
-    ctor @Deprecated public NetworkInfo(int, int, @Nullable String, @Nullable String);
-    method @Deprecated public int describeContents();
-    method @Deprecated @NonNull public android.net.NetworkInfo.DetailedState getDetailedState();
-    method @Deprecated public String getExtraInfo();
-    method @Deprecated public String getReason();
-    method @Deprecated public android.net.NetworkInfo.State getState();
-    method @Deprecated public int getSubtype();
-    method @Deprecated public String getSubtypeName();
-    method @Deprecated public int getType();
-    method @Deprecated public String getTypeName();
-    method @Deprecated public boolean isAvailable();
-    method @Deprecated public boolean isConnected();
-    method @Deprecated public boolean isConnectedOrConnecting();
-    method @Deprecated public boolean isFailover();
-    method @Deprecated public boolean isRoaming();
-    method @Deprecated public void setDetailedState(@NonNull android.net.NetworkInfo.DetailedState, @Nullable String, @Nullable String);
-    method @Deprecated public void writeToParcel(android.os.Parcel, int);
-    field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkInfo> CREATOR;
-  }
-
-  @Deprecated public enum NetworkInfo.DetailedState {
-    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState AUTHENTICATING;
-    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState BLOCKED;
-    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState CAPTIVE_PORTAL_CHECK;
-    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState CONNECTED;
-    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState CONNECTING;
-    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState DISCONNECTED;
-    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState DISCONNECTING;
-    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState FAILED;
-    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState IDLE;
-    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState OBTAINING_IPADDR;
-    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState SCANNING;
-    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState SUSPENDED;
-    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState VERIFYING_POOR_LINK;
-  }
-
-  @Deprecated public enum NetworkInfo.State {
-    enum_constant @Deprecated public static final android.net.NetworkInfo.State CONNECTED;
-    enum_constant @Deprecated public static final android.net.NetworkInfo.State CONNECTING;
-    enum_constant @Deprecated public static final android.net.NetworkInfo.State DISCONNECTED;
-    enum_constant @Deprecated public static final android.net.NetworkInfo.State DISCONNECTING;
-    enum_constant @Deprecated public static final android.net.NetworkInfo.State SUSPENDED;
-    enum_constant @Deprecated public static final android.net.NetworkInfo.State UNKNOWN;
-  }
-
-  public class NetworkRequest implements android.os.Parcelable {
-    method public boolean canBeSatisfiedBy(@Nullable android.net.NetworkCapabilities);
-    method public int describeContents();
-    method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier();
-    method public boolean hasCapability(int);
-    method public boolean hasTransport(int);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkRequest> CREATOR;
-  }
-
-  public static class NetworkRequest.Builder {
-    ctor public NetworkRequest.Builder();
-    method public android.net.NetworkRequest.Builder addCapability(int);
-    method public android.net.NetworkRequest.Builder addTransportType(int);
-    method public android.net.NetworkRequest build();
-    method @NonNull public android.net.NetworkRequest.Builder clearCapabilities();
-    method public android.net.NetworkRequest.Builder removeCapability(int);
-    method public android.net.NetworkRequest.Builder removeTransportType(int);
-    method @Deprecated public android.net.NetworkRequest.Builder setNetworkSpecifier(String);
-    method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier);
-  }
-
   public abstract class NetworkSpecifier {
     ctor public NetworkSpecifier();
   }
@@ -26276,44 +26028,6 @@
     field public static final int TYPE_IKEV2_IPSEC_USER_PASS = 6; // 0x6
   }
 
-  public final class Proxy {
-    ctor public Proxy();
-    method @Deprecated public static String getDefaultHost();
-    method @Deprecated public static int getDefaultPort();
-    method @Deprecated public static String getHost(android.content.Context);
-    method @Deprecated public static int getPort(android.content.Context);
-    field @Deprecated public static final String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO";
-    field public static final String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE";
-  }
-
-  public class ProxyInfo implements android.os.Parcelable {
-    ctor public ProxyInfo(@Nullable android.net.ProxyInfo);
-    method public static android.net.ProxyInfo buildDirectProxy(String, int);
-    method public static android.net.ProxyInfo buildDirectProxy(String, int, java.util.List<java.lang.String>);
-    method public static android.net.ProxyInfo buildPacProxy(android.net.Uri);
-    method @NonNull public static android.net.ProxyInfo buildPacProxy(@NonNull android.net.Uri, int);
-    method public int describeContents();
-    method public String[] getExclusionList();
-    method public String getHost();
-    method public android.net.Uri getPacFileUrl();
-    method public int getPort();
-    method public boolean isValid();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.ProxyInfo> CREATOR;
-  }
-
-  public final class RouteInfo implements android.os.Parcelable {
-    method public int describeContents();
-    method @NonNull public android.net.IpPrefix getDestination();
-    method @Nullable public java.net.InetAddress getGateway();
-    method @Nullable public String getInterface();
-    method public boolean hasGateway();
-    method public boolean isDefaultRoute();
-    method public boolean matches(java.net.InetAddress);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.RouteInfo> CREATOR;
-  }
-
   @Deprecated public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
     ctor @Deprecated public SSLCertificateSocketFactory(int);
     method @Deprecated public java.net.Socket createSocket(java.net.Socket, String, int, boolean) throws java.io.IOException;
@@ -26339,30 +26053,6 @@
     ctor public SSLSessionCache(android.content.Context);
   }
 
-  public abstract class SocketKeepalive implements java.lang.AutoCloseable {
-    method public final void close();
-    method public final void start(@IntRange(from=0xa, to=0xe10) int);
-    method public final void stop();
-    field public static final int ERROR_HARDWARE_ERROR = -31; // 0xffffffe1
-    field public static final int ERROR_INSUFFICIENT_RESOURCES = -32; // 0xffffffe0
-    field public static final int ERROR_INVALID_INTERVAL = -24; // 0xffffffe8
-    field public static final int ERROR_INVALID_IP_ADDRESS = -21; // 0xffffffeb
-    field public static final int ERROR_INVALID_LENGTH = -23; // 0xffffffe9
-    field public static final int ERROR_INVALID_NETWORK = -20; // 0xffffffec
-    field public static final int ERROR_INVALID_PORT = -22; // 0xffffffea
-    field public static final int ERROR_INVALID_SOCKET = -25; // 0xffffffe7
-    field public static final int ERROR_SOCKET_NOT_IDLE = -26; // 0xffffffe6
-    field public static final int ERROR_UNSUPPORTED = -30; // 0xffffffe2
-  }
-
-  public static class SocketKeepalive.Callback {
-    ctor public SocketKeepalive.Callback();
-    method public void onDataReceived();
-    method public void onError(int);
-    method public void onStarted();
-    method public void onStopped();
-  }
-
   public final class TelephonyNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
     method public int describeContents();
     method public int getSubscriptionId();
@@ -26420,9 +26110,6 @@
     field public static final int UNSUPPORTED = -1; // 0xffffffff
   }
 
-  public interface TransportInfo {
-  }
-
   public abstract class Uri implements java.lang.Comparable<android.net.Uri> android.os.Parcelable {
     method public abstract android.net.Uri.Builder buildUpon();
     method public int compareTo(android.net.Uri);
@@ -26983,6 +26670,15 @@
     method @NonNull public android.net.vcn.VcnConfig build();
   }
 
+  public abstract class VcnControlPlaneConfig {
+  }
+
+  public final class VcnControlPlaneIkeConfig extends android.net.vcn.VcnControlPlaneConfig {
+    ctor public VcnControlPlaneIkeConfig(@NonNull android.net.ipsec.ike.IkeSessionParams, @NonNull android.net.ipsec.ike.TunnelModeChildSessionParams);
+    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams getChildSessionParams();
+    method @NonNull public android.net.ipsec.ike.IkeSessionParams getIkeSessionParams();
+  }
+
   public final class VcnGatewayConnectionConfig {
     method @NonNull public int[] getExposedCapabilities();
     method @IntRange(from=android.net.vcn.VcnGatewayConnectionConfig.MIN_MTU_V6) public int getMaxMtu();
@@ -26991,7 +26687,7 @@
   }
 
   public static final class VcnGatewayConnectionConfig.Builder {
-    ctor public VcnGatewayConnectionConfig.Builder();
+    ctor public VcnGatewayConnectionConfig.Builder(@NonNull android.net.vcn.VcnControlPlaneConfig);
     method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder addExposedCapability(int);
     method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder addRequiredUnderlyingCapability(int);
     method @NonNull public android.net.vcn.VcnGatewayConnectionConfig build();
@@ -30520,8 +30216,8 @@
   }
 
   public final class BugreportManager {
-    method public void cancelBugreport();
-    method public void startConnectivityBugreport(@NonNull android.os.ParcelFileDescriptor, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback);
+    method @WorkerThread public void cancelBugreport();
+    method @WorkerThread public void startConnectivityBugreport(@NonNull android.os.ParcelFileDescriptor, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback);
   }
 
   public abstract static class BugreportManager.BugreportCallback {
@@ -31786,10 +31482,10 @@
     method public static android.content.Intent createUserCreationIntent(@Nullable String, @Nullable String, @Nullable String, @Nullable android.os.PersistableBundle);
     method @WorkerThread public android.os.Bundle getApplicationRestrictions(String);
     method public long getSerialNumberForUser(android.os.UserHandle);
-    method @RequiresPermission("android.permission.MANAGE_USERS") public int getUserCount();
+    method @RequiresPermission(anyOf={"android.permission.MANAGE_USERS", "android.permission.CREATE_USERS"}) public int getUserCount();
     method public long getUserCreationTime(android.os.UserHandle);
     method public android.os.UserHandle getUserForSerialNumber(long);
-    method @NonNull @RequiresPermission(anyOf={"android.permission.MANAGE_USERS", android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED}, conditional=true) public String getUserName();
+    method @NonNull @RequiresPermission(anyOf={"android.permission.MANAGE_USERS", android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED, "android.permission.CREATE_USERS"}, conditional=true) public String getUserName();
     method public java.util.List<android.os.UserHandle> getUserProfiles();
     method public android.os.Bundle getUserRestrictions();
     method @RequiresPermission(anyOf={"android.permission.MANAGE_USERS", "android.permission.INTERACT_ACROSS_USERS"}, conditional=true) public android.os.Bundle getUserRestrictions(android.os.UserHandle);
@@ -34983,6 +34679,7 @@
     field public static final String ACTION_QUICK_ACCESS_WALLET_SETTINGS = "android.settings.QUICK_ACCESS_WALLET_SETTINGS";
     field public static final String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS";
     field public static final String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
+    field public static final String ACTION_REQUEST_SCHEDULE_EXACT_ALARM = "android.settings.REQUEST_SCHEDULE_EXACT_ALARM";
     field public static final String ACTION_REQUEST_SET_AUTOFILL_SERVICE = "android.settings.REQUEST_SET_AUTOFILL_SERVICE";
     field public static final String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS";
     field public static final String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS";
@@ -37027,8 +36724,10 @@
     method @NonNull public static android.content.Intent createInstallIntent();
     method @NonNull public static android.content.Intent createManageCredentialsIntent(@NonNull android.security.AppUriAuthenticationPolicy);
     method @Nullable @WorkerThread public static java.security.cert.X509Certificate[] getCertificateChain(@NonNull android.content.Context, @NonNull String) throws java.lang.InterruptedException, android.security.KeyChainException;
+    method @NonNull public static android.security.AppUriAuthenticationPolicy getCredentialManagementAppPolicy(@NonNull android.content.Context) throws java.lang.SecurityException;
     method @Nullable @WorkerThread public static java.security.PrivateKey getPrivateKey(@NonNull android.content.Context, @NonNull String) throws java.lang.InterruptedException, android.security.KeyChainException;
     method @Deprecated public static boolean isBoundKeyAlgorithm(@NonNull String);
+    method public static boolean isCredentialManagementApp(@NonNull android.content.Context);
     method public static boolean isKeyAlgorithmSupported(@NonNull String);
     field public static final String ACTION_KEYCHAIN_CHANGED = "android.security.action.KEYCHAIN_CHANGED";
     field public static final String ACTION_KEY_ACCESS_CHANGED = "android.security.action.KEY_ACCESS_CHANGED";
@@ -38398,6 +38097,7 @@
     field public static final int INTERRUPTION_FILTER_PRIORITY = 2; // 0x2
     field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
     field public static final String META_DATA_DEFAULT_FILTER_TYPES = "android.service.notification.default_filter_types";
+    field public static final String META_DATA_DISABLED_FILTER_TYPES = "android.service.notification.disabled_filter_types";
     field public static final int NOTIFICATION_CHANNEL_OR_GROUP_ADDED = 1; // 0x1
     field public static final int NOTIFICATION_CHANNEL_OR_GROUP_DELETED = 3; // 0x3
     field public static final int NOTIFICATION_CHANNEL_OR_GROUP_UPDATED = 2; // 0x2
@@ -39024,7 +38724,9 @@
     field public static final int ERROR_NO_MATCH = 7; // 0x7
     field public static final int ERROR_RECOGNIZER_BUSY = 8; // 0x8
     field public static final int ERROR_SERVER = 4; // 0x4
+    field public static final int ERROR_SERVER_DISCONNECTED = 11; // 0xb
     field public static final int ERROR_SPEECH_TIMEOUT = 6; // 0x6
+    field public static final int ERROR_TOO_MANY_REQUESTS = 10; // 0xa
     field public static final String RESULTS_RECOGNITION = "results_recognition";
   }
 
@@ -40106,7 +39808,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailNumber(android.telecom.PhoneAccountHandle);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handleMmi(String);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handleMmi(String, android.telecom.PhoneAccountHandle);
-    method public boolean hasCompanionInCallServiceAccess();
+    method public boolean hasManageOngoingCallsPermission();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isInCall();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isInManagedCall();
     method public boolean isIncomingCallPermitted(android.telecom.PhoneAccountHandle);
@@ -40686,7 +40388,6 @@
     field public static final String KEY_SIMPLIFIED_NETWORK_SETTINGS_BOOL = "simplified_network_settings_bool";
     field public static final String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
     field public static final String KEY_SMS_REQUIRES_DESTINATION_NUMBER_CONVERSION_BOOL = "sms_requires_destination_number_conversion_bool";
-    field public static final String KEY_STORE_SIM_PIN_FOR_UNATTENDED_REBOOT_BOOL = "store_sim_pin_for_unattended_reboot_bool";
     field public static final String KEY_SUPPORTS_CALL_COMPOSER_BOOL = "supports_call_composer_bool";
     field public static final String KEY_SUPPORT_3GPP_CALL_FORWARDING_WHILE_ROAMING_BOOL = "support_3gpp_call_forwarding_while_roaming_bool";
     field public static final String KEY_SUPPORT_ADD_CONFERENCE_PARTICIPANTS_BOOL = "support_add_conference_participants_bool";
@@ -40734,6 +40435,7 @@
   }
 
   public static final class CarrierConfigManager.Apn {
+    field @Deprecated public static final String KEY_PREFIX = "apn.";
     field public static final String KEY_SETTINGS_DEFAULT_PROTOCOL_STRING = "apn.settings_default_protocol_string";
     field public static final String KEY_SETTINGS_DEFAULT_ROAMING_PROTOCOL_STRING = "apn.settings_default_roaming_protocol_string";
     field public static final String PROTOCOL_IPV4 = "IP";
@@ -40758,7 +40460,7 @@
   }
 
   public static final class CarrierConfigManager.ImsServiceEntitlement {
-    field public static final String KEY_AES_URL_STRING = "imsserviceentitlement.aes_url_string";
+    field public static final String KEY_ENTITLEMENT_SERVER_URL_STRING = "imsserviceentitlement.entitlement_server_url_string";
     field public static final String KEY_PREFIX = "imsserviceentitlement.";
   }
 
@@ -40787,7 +40489,6 @@
     field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_512_256 = 14; // 0xe
     field public static final int INTEGRITY_ALGORITHM_NONE = 0; // 0x0
     field public static final String KEY_ADD_KE_TO_CHILD_SESSION_REKEY_BOOL = "iwlan.add_ke_to_child_session_rekey_bool";
-    field public static final String KEY_ADD_WIFI_MAC_ADDR_TO_NAI_BOOL = "iwlan.add_wifi_mac_addr_to_nai_bool";
     field public static final String KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT = "iwlan.child_sa_rekey_hard_timer_sec_int";
     field public static final String KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT = "iwlan.child_sa_rekey_soft_timer_sec_int";
     field public static final String KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY = "iwlan.child_session_aes_cbc_key_size_int_array";
@@ -41099,6 +40800,7 @@
     field public static final int ACTIVATION_REJECT_GGSN = 30; // 0x1e
     field public static final int ACTIVATION_REJECT_UNSPECIFIED = 31; // 0x1f
     field public static final int ACTIVE_PDP_CONTEXT_MAX_NUMBER_REACHED = 65; // 0x41
+    field public static final int ALL_MATCHING_RULES_FAILED = 2254; // 0x8ce
     field public static final int APN_DISABLED = 2045; // 0x7fd
     field public static final int APN_DISALLOWED_ON_ROAMING = 2059; // 0x80b
     field public static final int APN_MISMATCH = 2054; // 0x806
@@ -41248,6 +40950,7 @@
     field public static final int LTE_NAS_SERVICE_REQUEST_FAILED = 2117; // 0x845
     field public static final int LTE_THROTTLING_NOT_REQUIRED = 2127; // 0x84f
     field public static final int MAC_FAILURE = 2183; // 0x887
+    field public static final int MATCH_ALL_RULE_NOT_ALLOWED = 2253; // 0x8cd
     field public static final int MAXIMIUM_NSAPIS_EXCEEDED = 2157; // 0x86d
     field public static final int MAXINUM_SIZE_OF_L2_MESSAGE_EXCEEDED = 2166; // 0x876
     field public static final int MAX_ACCESS_PROBE = 2079; // 0x81f
@@ -41985,7 +41688,6 @@
 
   public final class SignalStrengthUpdateRequest implements android.os.Parcelable {
     method public int describeContents();
-    method @NonNull public android.os.IBinder getLiveToken();
     method @NonNull public java.util.Collection<android.telephony.SignalThresholdInfo> getSignalThresholdInfos();
     method public boolean isReportingRequestedWhileIdle();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -42033,6 +41735,7 @@
     method @NonNull public android.telephony.SmsManager createForSubscriptionId(int);
     method public java.util.ArrayList<java.lang.String> divideMessage(String);
     method public void downloadMultimediaMessage(android.content.Context, String, android.net.Uri, android.os.Bundle, android.app.PendingIntent);
+    method public void downloadMultimediaMessage(@NonNull android.content.Context, @NonNull String, @NonNull android.net.Uri, @Nullable android.os.Bundle, @Nullable android.app.PendingIntent, long);
     method @NonNull public android.os.Bundle getCarrierConfigValues();
     method @Deprecated public static android.telephony.SmsManager getDefault();
     method public static int getDefaultSmsSubscriptionId();
@@ -42044,6 +41747,7 @@
     method public void injectSmsPdu(byte[], String, android.app.PendingIntent);
     method public void sendDataMessage(String, String, short, byte[], android.app.PendingIntent, android.app.PendingIntent);
     method public void sendMultimediaMessage(android.content.Context, android.net.Uri, String, android.os.Bundle, android.app.PendingIntent);
+    method public void sendMultimediaMessage(@NonNull android.content.Context, @NonNull android.net.Uri, @Nullable String, @Nullable android.os.Bundle, @Nullable android.app.PendingIntent, long);
     method public void sendMultipartTextMessage(String, String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>);
     method public void sendMultipartTextMessage(@NonNull String, @Nullable String, @NonNull java.util.List<java.lang.String>, @Nullable java.util.List<android.app.PendingIntent>, @Nullable java.util.List<android.app.PendingIntent>, long);
     method public void sendMultipartTextMessage(@NonNull String, @Nullable String, @NonNull java.util.List<java.lang.String>, @Nullable java.util.List<android.app.PendingIntent>, @Nullable java.util.List<android.app.PendingIntent>, @NonNull String, @Nullable String);
@@ -42413,7 +42117,7 @@
     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 @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telephony.ServiceState getServiceState();
+    method @Nullable @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public android.telephony.ServiceState getServiceState();
     method @Nullable public android.telephony.SignalStrength getSignalStrength();
     method public int getSimCarrierId();
     method @Nullable public CharSequence getSimCarrierIdName();
@@ -46561,6 +46265,7 @@
     method public long getAppVsyncOffsetNanos();
     method public void getCurrentSizeRange(android.graphics.Point, android.graphics.Point);
     method @Nullable public android.view.DisplayCutout getCutout();
+    method @Nullable public android.hardware.display.DeviceProductInfo getDeviceProductInfo();
     method public int getDisplayId();
     method public int getFlags();
     method public android.view.Display.HdrCapabilities getHdrCapabilities();
@@ -46831,6 +46536,7 @@
     method public int getId();
     method public android.view.KeyCharacterMap getKeyCharacterMap();
     method public int getKeyboardType();
+    method @NonNull public android.hardware.lights.LightsManager getLightsManager();
     method public android.view.InputDevice.MotionRange getMotionRange(int);
     method public android.view.InputDevice.MotionRange getMotionRange(int, int);
     method public java.util.List<android.view.InputDevice.MotionRange> getMotionRanges();
@@ -47883,16 +47589,47 @@
     method public void onScaleEnd(android.view.ScaleGestureDetector);
   }
 
+  @UiThread public interface ScrollCaptureCallback {
+    method public void onScrollCaptureEnd(@NonNull Runnable);
+    method public void onScrollCaptureImageRequest(@NonNull android.view.ScrollCaptureSession, @NonNull android.os.CancellationSignal, @NonNull android.graphics.Rect, @NonNull java.util.function.Consumer<android.graphics.Rect>);
+    method public void onScrollCaptureSearch(@NonNull android.os.CancellationSignal, @NonNull java.util.function.Consumer<android.graphics.Rect>);
+    method public void onScrollCaptureStart(@NonNull android.view.ScrollCaptureSession, @NonNull android.os.CancellationSignal, @NonNull Runnable);
+  }
+
+  public class ScrollCaptureSession {
+    ctor public ScrollCaptureSession(@NonNull android.view.Surface, @NonNull android.graphics.Rect, @NonNull android.graphics.Point);
+    method @NonNull public android.graphics.Point getPositionInWindow();
+    method @NonNull public android.graphics.Rect getScrollBounds();
+    method @NonNull public android.view.Surface getSurface();
+  }
+
+  public final class ScrollCaptureTarget {
+    ctor public ScrollCaptureTarget(@NonNull android.view.View, @NonNull android.graphics.Rect, @NonNull android.graphics.Point, @NonNull android.view.ScrollCaptureCallback);
+    method @NonNull public android.view.ScrollCaptureCallback getCallback();
+    method @NonNull public android.view.View getContainingView();
+    method public int getHint();
+    method @NonNull public android.graphics.Rect getLocalVisibleRect();
+    method @NonNull public android.graphics.Point getPositionInWindow();
+    method @Nullable public android.graphics.Rect getScrollBounds();
+    method public void setScrollBounds(@Nullable android.graphics.Rect);
+    method @UiThread public void updatePositionInWindow();
+  }
+
   public class SearchEvent {
     ctor public SearchEvent(android.view.InputDevice);
     method public android.view.InputDevice getInputDevice();
   }
 
   public class SoundEffectConstants {
+    method public static int getConstantForFocusDirection(int, boolean);
     method public static int getContantForFocusDirection(int);
     field public static final int CLICK = 0; // 0x0
     field public static final int NAVIGATION_DOWN = 4; // 0x4
     field public static final int NAVIGATION_LEFT = 1; // 0x1
+    field public static final int NAVIGATION_REPEAT_DOWN = 8; // 0x8
+    field public static final int NAVIGATION_REPEAT_LEFT = 5; // 0x5
+    field public static final int NAVIGATION_REPEAT_RIGHT = 7; // 0x7
+    field public static final int NAVIGATION_REPEAT_UP = 6; // 0x6
     field public static final int NAVIGATION_RIGHT = 3; // 0x3
     field public static final int NAVIGATION_UP = 2; // 0x2
   }
@@ -48204,6 +47941,7 @@
     method public void dispatchProvideStructure(android.view.ViewStructure);
     method protected void dispatchRestoreInstanceState(android.util.SparseArray<android.os.Parcelable>);
     method protected void dispatchSaveInstanceState(android.util.SparseArray<android.os.Parcelable>);
+    method public void dispatchScrollCaptureSearch(@NonNull android.graphics.Rect, @NonNull android.graphics.Point, @NonNull java.util.function.Consumer<android.view.ScrollCaptureTarget>);
     method protected void dispatchSetActivated(boolean);
     method protected void dispatchSetPressed(boolean);
     method protected void dispatchSetSelected(boolean);
@@ -48231,6 +47969,7 @@
     method public android.view.View focusSearch(int);
     method public void forceHasOverlappingRendering(boolean);
     method public void forceLayout();
+    method @Nullable public void generateDisplayHash(@NonNull String, @Nullable android.graphics.Rect, @NonNull java.util.concurrent.Executor, @NonNull android.view.displayhash.DisplayHashResultCallback);
     method public static int generateViewId();
     method public CharSequence getAccessibilityClassName();
     method public android.view.View.AccessibilityDelegate getAccessibilityDelegate();
@@ -48362,6 +48101,7 @@
     method public int getScrollBarFadeDuration();
     method public int getScrollBarSize();
     method public int getScrollBarStyle();
+    method public int getScrollCaptureHint();
     method public int getScrollIndicators();
     method public final int getScrollX();
     method public final int getScrollY();
@@ -48530,6 +48270,7 @@
     method public void onRtlPropertiesChanged(int);
     method @CallSuper @Nullable protected android.os.Parcelable onSaveInstanceState();
     method public void onScreenStateChanged(int);
+    method public void onScrollCaptureSearch(@NonNull android.graphics.Rect, @NonNull android.graphics.Point, @NonNull java.util.function.Consumer<android.view.ScrollCaptureTarget>);
     method protected void onScrollChanged(int, int, int, int);
     method protected boolean onSetAlpha(int);
     method protected void onSizeChanged(int, int, int, int);
@@ -48712,6 +48453,8 @@
     method public void setScrollBarFadeDuration(int);
     method public void setScrollBarSize(int);
     method public void setScrollBarStyle(int);
+    method public final void setScrollCaptureCallback(@Nullable android.view.ScrollCaptureCallback);
+    method public void setScrollCaptureHint(int);
     method public void setScrollContainer(boolean);
     method public void setScrollIndicators(int);
     method public void setScrollIndicators(int, int);
@@ -48890,6 +48633,10 @@
     field public static final int SCROLL_AXIS_HORIZONTAL = 1; // 0x1
     field public static final int SCROLL_AXIS_NONE = 0; // 0x0
     field public static final int SCROLL_AXIS_VERTICAL = 2; // 0x2
+    field public static final int SCROLL_CAPTURE_HINT_AUTO = 0; // 0x0
+    field public static final int SCROLL_CAPTURE_HINT_EXCLUDE = 1; // 0x1
+    field public static final int SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS = 4; // 0x4
+    field public static final int SCROLL_CAPTURE_HINT_INCLUDE = 2; // 0x2
     field public static final int SCROLL_INDICATOR_BOTTOM = 2; // 0x2
     field public static final int SCROLL_INDICATOR_END = 32; // 0x20
     field public static final int SCROLL_INDICATOR_LEFT = 4; // 0x4
@@ -49674,6 +49421,7 @@
     method public abstract boolean performContextMenuIdentifierAction(int, int);
     method public abstract boolean performPanelIdentifierAction(int, int, int);
     method public abstract boolean performPanelShortcut(int, int, android.view.KeyEvent, int);
+    method public void registerScrollCaptureCallback(@NonNull android.view.ScrollCaptureCallback);
     method public final void removeOnFrameMetricsAvailableListener(android.view.Window.OnFrameMetricsAvailableListener);
     method public boolean requestFeature(int);
     method @NonNull public final <T extends android.view.View> T requireViewById(@IdRes int);
@@ -49753,6 +49501,7 @@
     method public abstract void takeKeyEvents(boolean);
     method public abstract void takeSurface(android.view.SurfaceHolder.Callback2);
     method public abstract void togglePanel(int, android.view.KeyEvent);
+    method public void unregisterScrollCaptureCallback(@NonNull android.view.ScrollCaptureCallback);
     field public static final int DECOR_CAPTION_SHADE_AUTO = 0; // 0x0
     field public static final int DECOR_CAPTION_SHADE_DARK = 2; // 0x2
     field public static final int DECOR_CAPTION_SHADE_LIGHT = 1; // 0x1
@@ -49993,9 +49742,12 @@
   }
 
   public interface WindowManager extends android.view.ViewManager {
+    method public default void addCrossWindowBlurEnabledListener(@NonNull java.util.function.Consumer<java.lang.Boolean>);
     method @NonNull public default android.view.WindowMetrics getCurrentWindowMetrics();
     method @Deprecated public android.view.Display getDefaultDisplay();
     method @NonNull public default android.view.WindowMetrics getMaximumWindowMetrics();
+    method public default boolean isCrossWindowBlurEnabled();
+    method public default void removeCrossWindowBlurEnabledListener(@NonNull java.util.function.Consumer<java.lang.Boolean>);
     method public void removeViewImmediate(android.view.View);
   }
 
@@ -50020,12 +49772,14 @@
     method public final int copyFrom(android.view.WindowManager.LayoutParams);
     method public String debug(String);
     method public int describeContents();
+    method public int getBlurBehindRadius();
     method public int getColorMode();
     method public int getFitInsetsSides();
     method public int getFitInsetsTypes();
     method public final CharSequence getTitle();
     method public boolean isFitInsetsIgnoringVisibility();
     method public static boolean mayUseInputMethod(int);
+    method public void setBlurBehindRadius(@IntRange(from=0) int);
     method public void setColorMode(int);
     method public void setFitInsetsIgnoringVisibility(boolean);
     method public void setFitInsetsSides(int);
@@ -50136,7 +49890,6 @@
     field @Deprecated public static final int TYPE_TOAST = 2005; // 0x7d5
     field public static final int TYPE_WALLPAPER = 2013; // 0x7dd
     field public float alpha;
-    field public int blurBehindRadius;
     field public float buttonBrightness;
     field public float dimAmount;
     field public int flags;
@@ -51186,6 +50939,41 @@
 
 }
 
+package android.view.displayhash {
+
+  public final class DisplayHash implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.view.displayhash.DisplayHash> CREATOR;
+  }
+
+  public final class DisplayHashManager {
+    method @NonNull public java.util.Set<java.lang.String> getSupportedHashAlgorithms();
+    method @Nullable public android.view.displayhash.VerifiedDisplayHash verifyDisplayHash(@NonNull android.view.displayhash.DisplayHash);
+  }
+
+  public interface DisplayHashResultCallback {
+    method public void onDisplayHashError(int);
+    method public void onDisplayHashResult(@NonNull android.view.displayhash.DisplayHash);
+    field public static final int DISPLAY_HASH_ERROR_INVALID_BOUNDS = -2; // 0xfffffffe
+    field public static final int DISPLAY_HASH_ERROR_MISSING_WINDOW = -3; // 0xfffffffd
+    field public static final int DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN = -4; // 0xfffffffc
+    field public static final int DISPLAY_HASH_ERROR_UNKNOWN = -1; // 0xffffffff
+  }
+
+  public final class VerifiedDisplayHash implements android.os.Parcelable {
+    ctor public VerifiedDisplayHash(long, @NonNull android.graphics.Rect, @NonNull String, @NonNull byte[]);
+    method public int describeContents();
+    method @NonNull public android.graphics.Rect getBoundsInWindow();
+    method @NonNull public String getHashAlgorithm();
+    method @NonNull public byte[] getImageHash();
+    method public long getTimeMillis();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.view.displayhash.VerifiedDisplayHash> CREATOR;
+  }
+
+}
+
 package android.view.inputmethod {
 
   public class BaseInputConnection implements android.view.inputmethod.InputConnection {
@@ -53209,6 +52997,7 @@
     method public int getCheckedItemPosition();
     method public android.util.SparseBooleanArray getCheckedItemPositions();
     method public int getChoiceMode();
+    method public int getEdgeEffectType();
     method public int getListPaddingBottom();
     method public int getListPaddingLeft();
     method public int getListPaddingRight();
@@ -53250,6 +53039,7 @@
     method public void setChoiceMode(int);
     method public void setDrawSelectorOnTop(boolean);
     method public void setEdgeEffectColor(@ColorInt int);
+    method public void setEdgeEffectType(int);
     method public void setFastScrollAlwaysVisible(boolean);
     method public void setFastScrollEnabled(boolean);
     method public void setFastScrollStyle(int);
@@ -53540,11 +53330,27 @@
     ctor @Deprecated public AnalogClock(android.content.Context, android.util.AttributeSet);
     ctor @Deprecated public AnalogClock(android.content.Context, android.util.AttributeSet, int);
     ctor @Deprecated public AnalogClock(android.content.Context, android.util.AttributeSet, int, int);
+    method @Deprecated @Nullable public android.graphics.BlendMode getDialTintBlendMode();
+    method @Deprecated @Nullable public android.content.res.ColorStateList getDialTintList();
+    method @Deprecated @Nullable public android.graphics.BlendMode getHourHandTintBlendMode();
+    method @Deprecated @Nullable public android.content.res.ColorStateList getHourHandTintList();
+    method @Deprecated @Nullable public android.graphics.BlendMode getMinuteHandTintBlendMode();
+    method @Deprecated @Nullable public android.content.res.ColorStateList getMinuteHandTintList();
+    method @Deprecated @Nullable public android.graphics.BlendMode getSecondHandTintBlendMode();
+    method @Deprecated @Nullable public android.content.res.ColorStateList getSecondHandTintList();
     method @Deprecated @Nullable public String getTimeZone();
     method @Deprecated public void setDial(@NonNull android.graphics.drawable.Icon);
+    method @Deprecated public void setDialTintBlendMode(@Nullable android.graphics.BlendMode);
+    method @Deprecated public void setDialTintList(@Nullable android.content.res.ColorStateList);
     method @Deprecated public void setHourHand(@NonNull android.graphics.drawable.Icon);
+    method @Deprecated public void setHourHandTintBlendMode(@Nullable android.graphics.BlendMode);
+    method @Deprecated public void setHourHandTintList(@Nullable android.content.res.ColorStateList);
     method @Deprecated public void setMinuteHand(@NonNull android.graphics.drawable.Icon);
+    method @Deprecated public void setMinuteHandTintBlendMode(@Nullable android.graphics.BlendMode);
+    method @Deprecated public void setMinuteHandTintList(@Nullable android.content.res.ColorStateList);
     method @Deprecated public void setSecondHand(@Nullable android.graphics.drawable.Icon);
+    method @Deprecated public void setSecondHandTintBlendMode(@Nullable android.graphics.BlendMode);
+    method @Deprecated public void setSecondHandTintList(@Nullable android.content.res.ColorStateList);
     method @Deprecated public void setTimeZone(@Nullable String);
   }
 
@@ -54242,6 +54048,7 @@
     method public boolean executeKeyEvent(android.view.KeyEvent);
     method public void fling(int);
     method public boolean fullScroll(int);
+    method public int getEdgeEffectType();
     method @ColorInt public int getLeftEdgeEffectColor();
     method public int getMaxScrollAmount();
     method @ColorInt public int getRightEdgeEffectColor();
@@ -54249,6 +54056,7 @@
     method public boolean isSmoothScrollingEnabled();
     method public boolean pageScroll(int);
     method public void setEdgeEffectColor(@ColorInt int);
+    method public void setEdgeEffectType(int);
     method public void setFillViewport(boolean);
     method public void setLeftEdgeEffectColor(@ColorInt int);
     method public void setRightEdgeEffectColor(@ColorInt int);
@@ -54967,6 +54775,9 @@
     method public void setChronometer(@IdRes int, long, String, boolean);
     method public void setChronometerCountDown(@IdRes int, boolean);
     method public void setColor(@IdRes int, @NonNull String, @ColorRes int);
+    method public void setColorInt(@IdRes int, @NonNull String, @ColorInt int, @ColorInt int);
+    method public void setColorStateList(@IdRes int, @NonNull String, @Nullable android.content.res.ColorStateList);
+    method public void setColorStateList(@IdRes int, @NonNull String, @Nullable android.content.res.ColorStateList, @Nullable android.content.res.ColorStateList);
     method public void setColorStateList(@IdRes int, @NonNull String, @ColorRes int);
     method public void setCompoundButtonChecked(@IdRes int, boolean);
     method public void setContentDescription(@IdRes int, CharSequence);
@@ -54977,6 +54788,7 @@
     method public void setFloatDimen(@IdRes int, @NonNull String, @DimenRes int);
     method public void setFloatDimen(@IdRes int, @NonNull String, float, int);
     method public void setIcon(@IdRes int, String, android.graphics.drawable.Icon);
+    method public void setIcon(@IdRes int, @NonNull String, @Nullable android.graphics.drawable.Icon, @Nullable android.graphics.drawable.Icon);
     method public void setImageViewBitmap(@IdRes int, android.graphics.Bitmap);
     method public void setImageViewIcon(@IdRes int, android.graphics.drawable.Icon);
     method public void setImageViewResource(@IdRes int, @DrawableRes int);
@@ -54988,6 +54800,7 @@
     method public void setLabelFor(@IdRes int, @IdRes int);
     method public void setLightBackgroundLayoutId(@LayoutRes int);
     method public void setLong(@IdRes int, String, long);
+    method public void setOnCheckedChangeResponse(@IdRes int, @NonNull android.widget.RemoteViews.RemoteResponse);
     method public void setOnClickFillInIntent(@IdRes int, android.content.Intent);
     method public void setOnClickPendingIntent(@IdRes int, android.app.PendingIntent);
     method public void setOnClickResponse(@IdRes int, @NonNull android.widget.RemoteViews.RemoteResponse);
@@ -55006,6 +54819,12 @@
     method public void setTextViewText(@IdRes int, CharSequence);
     method public void setTextViewTextSize(@IdRes int, int, float);
     method public void setUri(@IdRes int, String, android.net.Uri);
+    method public void setViewLayoutHeight(@IdRes int, float, int);
+    method public void setViewLayoutHeightDimen(@IdRes int, @DimenRes int);
+    method public void setViewLayoutMargin(@IdRes int, int, float, int);
+    method public void setViewLayoutMarginDimen(@IdRes int, int, @DimenRes int);
+    method public void setViewLayoutWidth(@IdRes int, float, int);
+    method public void setViewLayoutWidthDimen(@IdRes int, @DimenRes int);
     method public void setViewOutlinePreferredRadius(@IdRes int, float, int);
     method public void setViewOutlinePreferredRadiusDimen(@IdRes int, @DimenRes int);
     method public void setViewPadding(@IdRes int, @Px int, @Px int, @Px int, @Px int);
@@ -55014,7 +54833,14 @@
     method public void showPrevious(@IdRes int);
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.widget.RemoteViews> CREATOR;
+    field public static final String EXTRA_CHECKED = "android.widget.extra.CHECKED";
     field public static final String EXTRA_SHARED_ELEMENT_BOUNDS = "android.widget.extra.SHARED_ELEMENT_BOUNDS";
+    field public static final int MARGIN_BOTTOM = 3; // 0x3
+    field public static final int MARGIN_END = 5; // 0x5
+    field public static final int MARGIN_LEFT = 0; // 0x0
+    field public static final int MARGIN_RIGHT = 2; // 0x2
+    field public static final int MARGIN_START = 4; // 0x4
+    field public static final int MARGIN_TOP = 1; // 0x1
   }
 
   public static class RemoteViews.ActionException extends java.lang.RuntimeException {
@@ -55084,6 +54910,7 @@
     method public void fling(int);
     method public boolean fullScroll(int);
     method @ColorInt public int getBottomEdgeEffectColor();
+    method public int getEdgeEffectType();
     method public int getMaxScrollAmount();
     method @ColorInt public int getTopEdgeEffectColor();
     method public boolean isFillViewport();
@@ -55092,6 +54919,7 @@
     method public void scrollToDescendant(@NonNull android.view.View);
     method public void setBottomEdgeEffectColor(@ColorInt int);
     method public void setEdgeEffectColor(@ColorInt int);
+    method public void setEdgeEffectType(int);
     method public void setFillViewport(boolean);
     method public void setSmoothScrollingEnabled(boolean);
     method public void setTopEdgeEffectColor(@ColorInt int);
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index de02d0b..7ea7d61 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -135,7 +135,7 @@
   }
 
   public final class MediaSessionManager {
-    method public void addOnActiveSessionsChangedListener(@NonNull android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, @Nullable android.content.ComponentName, @NonNull android.os.UserHandle, @Nullable android.os.Handler);
+    method public void addOnActiveSessionsChangedListener(@Nullable android.content.ComponentName, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull android.media.session.MediaSessionManager.OnActiveSessionsChangedListener);
     method public void dispatchMediaKeyEvent(@NonNull android.view.KeyEvent);
     method public void dispatchMediaKeyEvent(@NonNull android.view.KeyEvent, boolean);
     method public void dispatchMediaKeyEventAsSystemService(@NonNull android.view.KeyEvent);
@@ -163,61 +163,12 @@
 
 package android.net {
 
-  public final class ConnectivityFrameworkInitializer {
-    method public static void registerServiceWrappers();
-  }
-
-  public class ConnectivityManager {
-    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
-    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @Nullable android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback);
-    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle);
-  }
-
   public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable {
     method public int getResourceId();
   }
 
-  public final class NetworkAgentConfig implements android.os.Parcelable {
-    method @Nullable public String getSubscriberId();
-  }
-
-  public static final class NetworkAgentConfig.Builder {
-    method @NonNull public android.net.NetworkAgentConfig.Builder setSubscriberId(@Nullable String);
-  }
-
-  public final class NetworkCapabilities implements android.os.Parcelable {
-    field public static final int TRANSPORT_TEST = 7; // 0x7
-  }
-
-  public final class Proxy {
-    method public static void setHttpProxyConfiguration(@Nullable android.net.ProxyInfo);
-  }
-
-  public final class TcpRepairWindow {
-    ctor public TcpRepairWindow(int, int, int, int, int, int);
-    field public final int maxWindow;
-    field public final int rcvWnd;
-    field public final int rcvWndScale;
-    field public final int rcvWup;
-    field public final int sndWl1;
-    field public final int sndWnd;
-  }
-
-  public final class TestNetworkInterface implements android.os.Parcelable {
-    ctor public TestNetworkInterface(@NonNull android.os.ParcelFileDescriptor, @NonNull String);
-    method public int describeContents();
-    method @NonNull public android.os.ParcelFileDescriptor getFileDescriptor();
-    method @NonNull public String getInterfaceName();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.TestNetworkInterface> CREATOR;
-  }
-
-  public class TestNetworkManager {
-    method @NonNull public android.net.TestNetworkInterface createTapInterface();
-    method @NonNull public android.net.TestNetworkInterface createTunInterface(@NonNull java.util.Collection<android.net.LinkAddress>);
-    method public void setupTestNetwork(@NonNull String, @NonNull android.os.IBinder);
-    method public void teardownTestNetwork(@NonNull android.net.Network);
-    field public static final String TEST_TAP_PREFIX = "testtap";
+  public class NetworkWatchlistManager {
+    method @Nullable public byte[] getWatchlistConfigHash();
   }
 
   public final class UnderlyingNetworkInfo implements android.os.Parcelable {
@@ -230,14 +181,6 @@
     field @NonNull public final java.util.List<java.lang.String> underlyingIfaces;
   }
 
-  public final class VpnTransportInfo implements android.os.Parcelable android.net.TransportInfo {
-    ctor public VpnTransportInfo(int);
-    method public int describeContents();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.VpnTransportInfo> CREATOR;
-    field public final int type;
-  }
-
 }
 
 package android.os {
@@ -271,6 +214,16 @@
 
 }
 
+package android.os.storage {
+
+  public class StorageManager {
+    method public void notifyAppIoBlocked(@NonNull String, int, int, int);
+    method public void notifyAppIoResumed(@NonNull String, int, int, int);
+    field public static final int APP_IO_BLOCKED_REASON_TRANSCODING = 0; // 0x0
+  }
+
+}
+
 package android.provider {
 
   public final class DeviceConfig {
diff --git a/core/api/removed.txt b/core/api/removed.txt
index 990388a..a99178d 100644
--- a/core/api/removed.txt
+++ b/core/api/removed.txt
@@ -241,12 +241,6 @@
 
 package android.net {
 
-  public class ConnectivityManager {
-    method @Deprecated public boolean requestRouteToHost(int, int);
-    method @Deprecated public int startUsingNetworkFeature(int, String);
-    method @Deprecated public int stopUsingNetworkFeature(int, String);
-  }
-
   @Deprecated public class NetworkBadging {
     method @NonNull public static android.graphics.drawable.Drawable getWifiIcon(@IntRange(from=0, to=4) int, int, @Nullable android.content.res.Resources.Theme);
     field public static final int BADGING_4K = 30; // 0x1e
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index deff7b3..c7744a4 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -27,6 +27,7 @@
     field public static final String ALLOW_ANY_CODEC_FOR_PLAYBACK = "android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK";
     field public static final String AMBIENT_WALLPAPER = "android.permission.AMBIENT_WALLPAPER";
     field public static final String APPROVE_INCIDENT_REPORTS = "android.permission.APPROVE_INCIDENT_REPORTS";
+    field public static final String BACKGROUND_CAMERA = "android.permission.BACKGROUND_CAMERA";
     field public static final String BACKUP = "android.permission.BACKUP";
     field public static final String BATTERY_PREDICTION = "android.permission.BATTERY_PREDICTION";
     field public static final String BIND_ATTENTION_SERVICE = "android.permission.BIND_ATTENTION_SERVICE";
@@ -176,6 +177,7 @@
     field public static final String OBSERVE_APP_USAGE = "android.permission.OBSERVE_APP_USAGE";
     field public static final String OBSERVE_NETWORK_POLICY = "android.permission.OBSERVE_NETWORK_POLICY";
     field public static final String OBSERVE_ROLE_HOLDERS = "android.permission.OBSERVE_ROLE_HOLDERS";
+    field public static final String OBSERVE_SENSOR_PRIVACY = "android.permission.OBSERVE_SENSOR_PRIVACY";
     field public static final String OPEN_ACCESSIBILITY_DETAILS_SETTINGS = "android.permission.OPEN_ACCESSIBILITY_DETAILS_SETTINGS";
     field public static final String OVERRIDE_WIFI_CONFIG = "android.permission.OVERRIDE_WIFI_CONFIG";
     field public static final String PACKAGE_VERIFICATION_AGENT = "android.permission.PACKAGE_VERIFICATION_AGENT";
@@ -214,6 +216,7 @@
     field public static final String RECEIVE_DEVICE_CUSTOMIZATION_READY = "android.permission.RECEIVE_DEVICE_CUSTOMIZATION_READY";
     field public static final String RECEIVE_EMERGENCY_BROADCAST = "android.permission.RECEIVE_EMERGENCY_BROADCAST";
     field public static final String RECEIVE_WIFI_CREDENTIAL_CHANGE = "android.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE";
+    field public static final String RECORD_BACKGROUND_AUDIO = "android.permission.RECORD_BACKGROUND_AUDIO";
     field public static final String RECOVERY = "android.permission.RECOVERY";
     field public static final String RECOVER_KEYSTORE = "android.permission.RECOVER_KEYSTORE";
     field public static final String REGISTER_CALL_PROVIDER = "android.permission.REGISTER_CALL_PROVIDER";
@@ -333,6 +336,8 @@
   }
 
   public static final class R.string {
+    field public static final int config_customMediaKeyDispatcher = 17039404; // 0x104002c
+    field public static final int config_customMediaSessionPolicyProvider = 17039405; // 0x104002d
     field public static final int config_defaultAssistant = 17039393; // 0x1040021
     field public static final int config_defaultBrowser = 17039394; // 0x1040022
     field public static final int config_defaultCallRedirection = 17039397; // 0x1040025
@@ -350,6 +355,7 @@
     field public static final int config_systemContacts = 17039403; // 0x104002b
     field public static final int config_systemGallery = 17039399; // 0x1040027
     field public static final int config_systemShell = 17039402; // 0x104002a
+    field public static final int config_systemSpeechRecognizer = 17039406; // 0x104002e
   }
 
   public static final class R.style {
@@ -639,8 +645,8 @@
     method public static android.app.BroadcastOptions makeBasic();
     method @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND) public void setBackgroundActivityStartsAllowed(boolean);
     method public void setDontSendToRestrictedApps(boolean);
-    method @RequiresPermission(anyOf={android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND, android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) public void setTemporaryAppWhitelistDuration(long);
-    method @RequiresPermission(anyOf={android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND, android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) public void setTemporaryAppWhitelistDuration(int, long);
+    method @RequiresPermission(anyOf={android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND, android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) public void setTemporaryAppAllowlist(long, int, int, @Nullable String);
+    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND, android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) public void setTemporaryAppWhitelistDuration(long);
     method public android.os.Bundle toBundle();
   }
 
@@ -851,13 +857,6 @@
     method public void onVrStateChanged(boolean);
   }
 
-  public final class WallpaperColors implements android.os.Parcelable {
-    ctor public WallpaperColors(@NonNull android.graphics.Color, @Nullable android.graphics.Color, @Nullable android.graphics.Color, int);
-    method public int getColorHints();
-    field public static final int HINT_SUPPORTS_DARK_TEXT = 1; // 0x1
-    field public static final int HINT_SUPPORTS_DARK_THEME = 2; // 0x2
-  }
-
   public final class WallpaperInfo implements android.os.Parcelable {
     method public boolean supportsAmbientMode();
   }
@@ -882,7 +881,7 @@
   public class DevicePolicyManager {
     method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public boolean getBluetoothContactSharingDisabled(@NonNull android.os.UserHandle);
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getDeviceOwner();
-    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.content.ComponentName getDeviceOwnerComponentOnAnyUser();
+    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, "android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS"}) public android.content.ComponentName getDeviceOwnerComponentOnAnyUser();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getDeviceOwnerNameOnAnyUser();
     method @Nullable public CharSequence getDeviceOwnerOrganizationName();
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.UserHandle getDeviceOwnerUser();
@@ -955,6 +954,9 @@
 
 package android.app.assist {
 
+  public class ActivityId {
+  }
+
   public static class AssistStructure.ViewNode {
     ctor public AssistStructure.ViewNode();
   }
@@ -1824,7 +1826,7 @@
     method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public android.bluetooth.BufferConstraints getBufferConstraints();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public int getDynamicBufferSupport();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setBufferMillis(int, int);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setBufferLengthMillis(int, int);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
     field public static final int DYNAMIC_BUFFER_SUPPORT_A2DP_OFFLOAD = 1; // 0x1
     field public static final int DYNAMIC_BUFFER_SUPPORT_A2DP_SOFTWARE_ENCODING = 2; // 0x2
@@ -1940,6 +1942,10 @@
     field public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED";
   }
 
+  public final class BluetoothMapClient implements android.bluetooth.BluetoothProfile {
+    method @RequiresPermission(android.Manifest.permission.SEND_SMS) public boolean sendMessage(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.Collection<android.net.Uri>, @NonNull String, @Nullable android.app.PendingIntent, @Nullable android.app.PendingIntent);
+  }
+
   public final class BluetoothPan implements android.bluetooth.BluetoothProfile {
     method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
@@ -1972,6 +1978,7 @@
     field public static final int CONNECTION_POLICY_FORBIDDEN = 0; // 0x0
     field public static final int CONNECTION_POLICY_UNKNOWN = -1; // 0xffffffff
     field public static final int HEADSET_CLIENT = 16; // 0x10
+    field public static final int MAP_CLIENT = 18; // 0x12
     field public static final int PAN = 5; // 0x5
     field public static final int PBAP_CLIENT = 17; // 0x11
     field @Deprecated public static final int PRIORITY_OFF = 0; // 0x0
@@ -2025,7 +2032,7 @@
   public final class BufferConstraints implements android.os.Parcelable {
     ctor public BufferConstraints(@NonNull java.util.List<android.bluetooth.BufferConstraint>);
     method public int describeContents();
-    method @Nullable public android.bluetooth.BufferConstraint getCodec(int);
+    method @Nullable public android.bluetooth.BufferConstraint forCodec(int);
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field public static final int BUFFER_CODEC_MAX_NUM = 32; // 0x20
     field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BufferConstraints> CREATOR;
@@ -2190,6 +2197,7 @@
     field public static final String ACTION_PENDING_INCIDENT_REPORTS_CHANGED = "android.intent.action.PENDING_INCIDENT_REPORTS_CHANGED";
     field public static final String ACTION_PRE_BOOT_COMPLETED = "android.intent.action.PRE_BOOT_COMPLETED";
     field public static final String ACTION_QUERY_PACKAGE_RESTART = "android.intent.action.QUERY_PACKAGE_RESTART";
+    field public static final String ACTION_REBOOT_READY = "android.intent.action.REBOOT_READY";
     field public static final String ACTION_RESOLVE_INSTANT_APP_PACKAGE = "android.intent.action.RESOLVE_INSTANT_APP_PACKAGE";
     field @RequiresPermission(android.Manifest.permission.REVIEW_ACCESSIBILITY_SERVICES) public static final String ACTION_REVIEW_ACCESSIBILITY_SERVICES = "android.intent.action.REVIEW_ACCESSIBILITY_SERVICES";
     field @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public static final String ACTION_REVIEW_ONGOING_PERMISSION_USAGE = "android.intent.action.REVIEW_ONGOING_PERMISSION_USAGE";
@@ -2213,6 +2221,7 @@
     field public static final String EXTRA_INSTANT_APP_HOSTNAME = "android.intent.extra.INSTANT_APP_HOSTNAME";
     field public static final String EXTRA_INSTANT_APP_SUCCESS = "android.intent.extra.INSTANT_APP_SUCCESS";
     field public static final String EXTRA_INSTANT_APP_TOKEN = "android.intent.extra.INSTANT_APP_TOKEN";
+    field public static final String EXTRA_IS_READY_TO_REBOOT = "android.intent.extra.IS_READY_TO_REBOOT";
     field public static final String EXTRA_LONG_VERSION_CODE = "android.intent.extra.LONG_VERSION_CODE";
     field public static final String EXTRA_ORIGINATING_UID = "android.intent.extra.ORIGINATING_UID";
     field public static final String EXTRA_PACKAGES = "android.intent.extra.PACKAGES";
@@ -2452,10 +2461,10 @@
   }
 
   public static class PackageInstaller.Session implements java.io.Closeable {
-    method @RequiresPermission("com.android.permission.USE_INSTALLER_V2") public void addFile(int, @NonNull String, long, @NonNull byte[], @Nullable byte[]);
+    method public void addFile(int, @NonNull String, long, @NonNull byte[], @Nullable byte[]);
     method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void commitTransferred(@NonNull android.content.IntentSender);
-    method @Nullable @RequiresPermission("com.android.permission.USE_INSTALLER_V2") public android.content.pm.DataLoaderParams getDataLoaderParams();
-    method @RequiresPermission("com.android.permission.USE_INSTALLER_V2") public void removeFile(int, @NonNull String);
+    method @Nullable public android.content.pm.DataLoaderParams getDataLoaderParams();
+    method public void removeFile(int, @NonNull String);
   }
 
   public static class PackageInstaller.SessionInfo implements android.os.Parcelable {
@@ -2476,7 +2485,7 @@
   public static class PackageInstaller.SessionParams implements android.os.Parcelable {
     method @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE) public void setAllocateAggressive(boolean);
     method @Deprecated public void setAllowDowngrade(boolean);
-    method @RequiresPermission(allOf={android.Manifest.permission.INSTALL_PACKAGES, "com.android.permission.USE_INSTALLER_V2"}) public void setDataLoaderParams(@NonNull android.content.pm.DataLoaderParams);
+    method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setDataLoaderParams(@NonNull android.content.pm.DataLoaderParams);
     method public void setDontKillApp(boolean);
     method public void setEnableRollback(boolean);
     method public void setEnableRollback(boolean, int);
@@ -2541,10 +2550,11 @@
     field public static final String EXTRA_REQUEST_PERMISSIONS_NAMES = "android.content.pm.extra.REQUEST_PERMISSIONS_NAMES";
     field public static final String EXTRA_REQUEST_PERMISSIONS_RESULTS = "android.content.pm.extra.REQUEST_PERMISSIONS_RESULTS";
     field public static final String FEATURE_BROADCAST_RADIO = "android.hardware.broadcastradio";
+    field public static final String FEATURE_CAMERA_TOGGLE = "android.hardware.camera.toggle";
     field public static final String FEATURE_CONTEXT_HUB = "android.hardware.context_hub";
-    field public static final String FEATURE_CROSS_LAYER_BLUR = "android.software.cross_layer_blur";
     field @Deprecated public static final String FEATURE_INCREMENTAL_DELIVERY = "android.software.incremental_delivery";
     field public static final String FEATURE_INCREMENTAL_DELIVERY_VERSION = "android.software.incremental_delivery_version";
+    field public static final String FEATURE_MICROPHONE_TOGGLE = "android.hardware.microphone.toggle";
     field public static final String FEATURE_REBOOT_ESCROW = "android.hardware.reboot_escrow";
     field public static final String FEATURE_TELEPHONY_CARRIERLOCK = "android.hardware.telephony.carrierlock";
     field public static final String FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION = "android.hardware.telephony.ims.singlereg";
@@ -2556,7 +2566,6 @@
     field public static final int FLAG_PERMISSION_ONE_TIME = 65536; // 0x10000
     field public static final int FLAG_PERMISSION_POLICY_FIXED = 4; // 0x4
     field public static final int FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT = 2048; // 0x800
-    field public static final int FLAG_PERMISSION_RESTRICTION_ROLE_EXEMPT = 262144; // 0x40000
     field public static final int FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT = 4096; // 0x1000
     field public static final int FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT = 8192; // 0x2000
     field public static final int FLAG_PERMISSION_REVIEW_REQUIRED = 64; // 0x40
@@ -2742,6 +2751,15 @@
 
 package android.content.pm.verify.domain {
 
+  public final class DomainOwner implements android.os.Parcelable {
+    ctor public DomainOwner(@NonNull String, boolean);
+    method public int describeContents();
+    method @NonNull public String getPackageName();
+    method public boolean isOverrideable();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.verify.domain.DomainOwner> CREATOR;
+  }
+
   public final class DomainVerificationInfo implements android.os.Parcelable {
     method public int describeContents();
     method @NonNull public java.util.Map<java.lang.String,java.lang.Integer> getHostToStateMap();
@@ -2754,6 +2772,7 @@
   public interface DomainVerificationManager {
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.DOMAIN_VERIFICATION_AGENT, android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION}) public android.content.pm.verify.domain.DomainVerificationInfo getDomainVerificationInfo(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
     method @Nullable @RequiresPermission(android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION) public android.content.pm.verify.domain.DomainVerificationUserSelection getDomainVerificationUserSelection(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION) public java.util.List<android.content.pm.verify.domain.DomainOwner> getOwnersForDomain(@NonNull String);
     method @NonNull @RequiresPermission(android.Manifest.permission.DOMAIN_VERIFICATION_AGENT) public java.util.List<java.lang.String> getValidVerificationPackageNames();
     method public static boolean isStateModifiable(int);
     method public static boolean isStateVerified(int);
@@ -2775,13 +2794,16 @@
 
   public final class DomainVerificationUserSelection implements android.os.Parcelable {
     method public int describeContents();
-    method @NonNull public java.util.Map<java.lang.String,java.lang.Boolean> getHostToUserSelectionMap();
+    method @NonNull public java.util.Map<java.lang.String,java.lang.Integer> getHostToStateMap();
     method @NonNull public java.util.UUID getIdentifier();
     method @NonNull public String getPackageName();
     method @NonNull public android.os.UserHandle getUser();
     method @NonNull public boolean isLinkHandlingAllowed();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.verify.domain.DomainVerificationUserSelection> CREATOR;
+    field public static final int DOMAIN_STATE_NONE = 0; // 0x0
+    field public static final int DOMAIN_STATE_SELECTED = 1; // 0x1
+    field public static final int DOMAIN_STATE_VERIFIED = 2; // 0x2
   }
 
 }
@@ -2865,7 +2887,7 @@
   }
 
   public class FontManager {
-    method @Nullable public android.text.FontConfig getFontConfig();
+    method @NonNull public android.text.FontConfig getFontConfig();
     method @RequiresPermission(android.Manifest.permission.UPDATE_FONTS) public int updateFontFamily(@NonNull android.graphics.fonts.FontFamilyUpdateRequest, @IntRange(from=0) int);
     method @RequiresPermission(android.Manifest.permission.UPDATE_FONTS) public int updateFontFile(@NonNull android.graphics.fonts.FontFileUpdateRequest, @IntRange(from=0) int);
     method @Deprecated @RequiresPermission(android.Manifest.permission.UPDATE_FONTS) public int updateFontFile(@NonNull android.os.ParcelFileDescriptor, @NonNull byte[], @IntRange(from=0) int);
@@ -2899,6 +2921,22 @@
     method public boolean injectSensorData(android.hardware.Sensor, float[], int, long);
   }
 
+  public final class SensorPrivacyManager {
+    method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(int, @NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
+    method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
+    method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public boolean isSensorPrivacyEnabled(int);
+    method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void removeSensorPrivacyListener(@NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
+  }
+
+  public static interface SensorPrivacyManager.OnSensorPrivacyChangedListener {
+    method public void onSensorPrivacyChanged(boolean);
+  }
+
+  public static class SensorPrivacyManager.Sensors {
+    field public static final int CAMERA = 2; // 0x2
+    field public static final int MICROPHONE = 1; // 0x1
+  }
+
 }
 
 package android.hardware.biometrics {
@@ -3394,42 +3432,12 @@
 
 package android.hardware.lights {
 
-  public final class Light implements android.os.Parcelable {
-    method public int describeContents();
-    method public int getId();
-    method public int getOrdinal();
-    method public int getType();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.lights.Light> CREATOR;
-  }
-
   public final class LightState implements android.os.Parcelable {
-    ctor public LightState(@ColorInt int);
-    method public int describeContents();
-    method @ColorInt public int getColor();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.lights.LightState> CREATOR;
+    ctor @Deprecated public LightState(@ColorInt int);
   }
 
-  public final class LightsManager {
-    method @NonNull @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public java.util.List<android.hardware.lights.Light> getLights();
-    method @NonNull @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public android.hardware.lights.LightsManager.LightsSession openSession();
-    field public static final int LIGHT_TYPE_MICROPHONE = 8; // 0x8
-  }
-
-  public final class LightsManager.LightsSession implements java.lang.AutoCloseable {
-    method @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public void close();
-    method @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public void requestLights(@NonNull android.hardware.lights.LightsRequest);
-  }
-
-  public final class LightsRequest {
-  }
-
-  public static final class LightsRequest.Builder {
-    ctor public LightsRequest.Builder();
-    method @NonNull public android.hardware.lights.LightsRequest build();
-    method @NonNull public android.hardware.lights.LightsRequest.Builder clearLight(@NonNull android.hardware.lights.Light);
-    method @NonNull public android.hardware.lights.LightsRequest.Builder setLight(@NonNull android.hardware.lights.Light, @NonNull android.hardware.lights.LightState);
+  public abstract class LightsManager {
+    field @Deprecated public static final int LIGHT_TYPE_MICROPHONE = 8; // 0x8
   }
 
 }
@@ -4709,6 +4717,7 @@
   }
 
   public class LocationManager {
+    method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void addProviderRequestChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.provider.ProviderRequest.ChangedListener);
     method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void flushGnssBatch();
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
     method @Nullable public String getExtraLocationControllerPackage();
@@ -4723,7 +4732,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@Nullable String, @NonNull String, @Nullable String);
     method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.UPDATE_APP_OPS_STATS}) public boolean registerGnssBatchedLocationCallback(long, boolean, @NonNull android.location.BatchedLocationCallback, @Nullable android.os.Handler);
     method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
-    method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean registerProviderRequestListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.provider.ProviderRequest.Listener);
+    method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void removeProviderRequestChangedListener(@NonNull android.location.provider.ProviderRequest.ChangedListener);
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.app.PendingIntent);
@@ -4732,7 +4741,6 @@
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, @NonNull android.os.UserHandle);
     method @Deprecated @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean setProviderEnabledForUser(@NonNull String, boolean, @NonNull android.os.UserHandle);
     method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean unregisterGnssBatchedLocationCallback(@NonNull android.location.BatchedLocationCallback);
-    method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void unregisterProviderRequestListener(@NonNull android.location.provider.ProviderRequest.Listener);
   }
 
   public final class LocationRequest implements android.os.Parcelable {
@@ -4882,7 +4890,7 @@
     method @NonNull public android.location.provider.ProviderRequest.Builder setWorkSource(@NonNull android.os.WorkSource);
   }
 
-  public static interface ProviderRequest.Listener {
+  public static interface ProviderRequest.ChangedListener {
     method public void onProviderRequestChanged(@NonNull String, @NonNull android.location.provider.ProviderRequest);
   }
 
@@ -5074,9 +5082,10 @@
   }
 
   public static class AudioTrack.TunerConfiguration {
-    ctor @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public AudioTrack.TunerConfiguration(@IntRange(from=1) int, @IntRange(from=1) int);
+    ctor @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public AudioTrack.TunerConfiguration(@IntRange(from=0) int, @IntRange(from=1) int);
     method @IntRange(from=1) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getContentId();
     method @IntRange(from=1) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getSyncId();
+    field public static final int CONTENT_ID_NONE = 0; // 0x0
   }
 
   public class HwAudioSource {
@@ -5093,7 +5102,7 @@
   }
 
   public class MediaPlayer implements android.media.AudioRouting android.media.VolumeAutomation {
-    method @RequiresPermission(android.Manifest.permission.BIND_IMS_SERVICE) public void setOnRtpRxNoticeListener(@NonNull android.content.Context, @NonNull android.media.MediaPlayer.OnRtpRxNoticeListener, @Nullable android.os.Handler);
+    method @RequiresPermission(android.Manifest.permission.BIND_IMS_SERVICE) public void setOnRtpRxNoticeListener(@NonNull android.content.Context, @NonNull java.util.concurrent.Executor, @NonNull android.media.MediaPlayer.OnRtpRxNoticeListener);
   }
 
   public static interface MediaPlayer.OnRtpRxNoticeListener {
@@ -5700,7 +5709,7 @@
     method public void updateResourcePriority(int, int);
     field public static final int INVALID_AV_SYNC_ID = -1; // 0xffffffff
     field public static final int INVALID_FILTER_ID = -1; // 0xffffffff
-    field public static final long INVALID_FILTER_ID_64BIT = -1L; // 0xffffffffffffffffL
+    field public static final long INVALID_FILTER_ID_LONG = -1L; // 0xffffffffffffffffL
     field public static final int INVALID_FIRST_MACROBLOCK_IN_SLICE = -1; // 0xffffffff
     field public static final int INVALID_FRONTEND_ID = -1; // 0xffffffff
     field public static final int INVALID_FRONTEND_SETTING_FREQUENCY = -1; // 0xffffffff
@@ -5881,7 +5890,7 @@
     method public int getItemFragmentIndex();
     method public int getItemId();
     method public int getLastItemFragmentIndex();
-    method public int getMpuSequenceNumber();
+    method @IntRange(from=0) public int getMpuSequenceNumber();
   }
 
   public class DownloadSettings extends android.media.tv.tuner.filter.Settings {
@@ -5899,7 +5908,7 @@
     method public int configure(@NonNull android.media.tv.tuner.filter.FilterConfiguration);
     method public int flush();
     method public int getId();
-    method public long getId64Bit();
+    method public long getIdLong();
     method public int read(@NonNull byte[], long, long);
     method public int setDataSource(@Nullable android.media.tv.tuner.filter.Filter);
     method public int setMonitorEventMask(int);
@@ -5990,7 +5999,7 @@
     method public long getDataLength();
     method @Nullable public android.media.tv.tuner.filter.AudioDescriptor getExtraMetaData();
     method @Nullable public android.media.MediaCodec.LinearBlock getLinearBlock();
-    method public int getMpuSequenceNumber();
+    method @IntRange(from=0) public int getMpuSequenceNumber();
     method public long getOffset();
     method public long getPts();
     method public int getStreamId();
@@ -6015,7 +6024,7 @@
   public class MmtpRecordEvent extends android.media.tv.tuner.filter.FilterEvent {
     method public long getDataLength();
     method public int getFirstMacroblockInSlice();
-    method public int getMpuSequenceNumber();
+    method @IntRange(from=0) public int getMpuSequenceNumber();
     method public long getPts();
     method public int getScHevcIndexMask();
     method public int getTsIndexMask();
@@ -6023,7 +6032,7 @@
 
   public class PesEvent extends android.media.tv.tuner.filter.FilterEvent {
     method public int getDataLength();
-    method public int getMpuSequenceNumber();
+    method @IntRange(from=0) public int getMpuSequenceNumber();
     method public int getStreamId();
   }
 
@@ -7084,102 +7093,6 @@
 
 package android.net {
 
-  public class CaptivePortal implements android.os.Parcelable {
-    method public void logEvent(int, @NonNull String);
-    method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void reevaluateNetwork();
-    method public void useNetwork();
-    field public static final int APP_REQUEST_REEVALUATION_REQUIRED = 100; // 0x64
-    field public static final int APP_RETURN_DISMISSED = 0; // 0x0
-    field public static final int APP_RETURN_UNWANTED = 1; // 0x1
-    field public static final int APP_RETURN_WANTED_AS_IS = 2; // 0x2
-  }
-
-  public final class CaptivePortalData implements android.os.Parcelable {
-    method public int describeContents();
-    method public long getByteLimit();
-    method public long getExpiryTimeMillis();
-    method public long getRefreshTimeMillis();
-    method @Nullable public android.net.Uri getUserPortalUrl();
-    method public int getUserPortalUrlSource();
-    method @Nullable public String getVenueFriendlyName();
-    method @Nullable public android.net.Uri getVenueInfoUrl();
-    method public int getVenueInfoUrlSource();
-    method public boolean isCaptive();
-    method public boolean isSessionExtendable();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field public static final int CAPTIVE_PORTAL_DATA_SOURCE_OTHER = 0; // 0x0
-    field public static final int CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT = 1; // 0x1
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.CaptivePortalData> CREATOR;
-  }
-
-  public static class CaptivePortalData.Builder {
-    ctor public CaptivePortalData.Builder();
-    ctor public CaptivePortalData.Builder(@Nullable android.net.CaptivePortalData);
-    method @NonNull public android.net.CaptivePortalData build();
-    method @NonNull public android.net.CaptivePortalData.Builder setBytesRemaining(long);
-    method @NonNull public android.net.CaptivePortalData.Builder setCaptive(boolean);
-    method @NonNull public android.net.CaptivePortalData.Builder setExpiryTime(long);
-    method @NonNull public android.net.CaptivePortalData.Builder setRefreshTime(long);
-    method @NonNull public android.net.CaptivePortalData.Builder setSessionExtendable(boolean);
-    method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri);
-    method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri, int);
-    method @NonNull public android.net.CaptivePortalData.Builder setVenueFriendlyName(@Nullable String);
-    method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri);
-    method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri, int);
-  }
-
-  public class ConnectivityManager {
-    method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createNattKeepalive(@NonNull android.net.Network, @NonNull android.os.ParcelFileDescriptor, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
-    method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull java.net.Socket, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public String getCaptivePortalServerUrl();
-    method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEntitlementResultListener);
-    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported();
-    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_FACTORY}) public int registerNetworkProvider(@NonNull android.net.NetworkProvider);
-    method public void registerQosCallback(@NonNull android.net.QosSocketInfo, @NonNull android.net.QosCallback, @NonNull java.util.concurrent.Executor);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
-    method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void requestNetwork(@NonNull android.net.NetworkRequest, int, int, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback);
-    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_AIRPLANE_MODE, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void setAirplaneMode(boolean);
-    method @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) public void setOemNetworkPreference(@NonNull android.net.OemNetworkPreferences, @Nullable java.util.concurrent.Executor, @Nullable android.net.ConnectivityManager.OnSetOemNetworkPreferenceListener);
-    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public boolean shouldAvoidBadWifi();
-    method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopTethering(int);
-    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_FACTORY}) public void unregisterNetworkProvider(@NonNull android.net.NetworkProvider);
-    method public void unregisterQosCallback(@NonNull android.net.QosCallback);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void unregisterTetheringEventCallback(@NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
-    field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC";
-    field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT";
-    field public static final int TETHERING_BLUETOOTH = 2; // 0x2
-    field public static final int TETHERING_USB = 1; // 0x1
-    field public static final int TETHERING_WIFI = 0; // 0x0
-    field @Deprecated public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13; // 0xd
-    field @Deprecated public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0
-    field @Deprecated public static final int TETHER_ERROR_PROVISION_FAILED = 11; // 0xb
-    field public static final int TYPE_NONE = -1; // 0xffffffff
-    field @Deprecated public static final int TYPE_PROXY = 16; // 0x10
-    field @Deprecated public static final int TYPE_WIFI_P2P = 13; // 0xd
-  }
-
-  public static interface ConnectivityManager.OnSetOemNetworkPreferenceListener {
-    method public void onComplete();
-  }
-
-  @Deprecated public abstract static class ConnectivityManager.OnStartTetheringCallback {
-    ctor @Deprecated public ConnectivityManager.OnStartTetheringCallback();
-    method @Deprecated public void onTetheringFailed();
-    method @Deprecated public void onTetheringStarted();
-  }
-
-  @Deprecated public static interface ConnectivityManager.OnTetheringEntitlementResultListener {
-    method @Deprecated public void onTetheringEntitlementResult(int);
-  }
-
-  @Deprecated public abstract static class ConnectivityManager.OnTetheringEventCallback {
-    ctor @Deprecated public ConnectivityManager.OnTetheringEventCallback();
-    method @Deprecated public void onUpstreamChanged(@Nullable android.net.Network);
-  }
-
   public class DnsResolverServiceManager {
     method @NonNull @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public static android.os.IBinder getService(@NonNull android.content.Context);
   }
@@ -7197,48 +7110,6 @@
     method public void release();
   }
 
-  public final class InvalidPacketException extends java.lang.Exception {
-    ctor public InvalidPacketException(int);
-    method public int getError();
-    field public static final int ERROR_INVALID_IP_ADDRESS = -21; // 0xffffffeb
-    field public static final int ERROR_INVALID_LENGTH = -23; // 0xffffffe9
-    field public static final int ERROR_INVALID_PORT = -22; // 0xffffffea
-  }
-
-  public final class IpConfiguration implements android.os.Parcelable {
-    ctor public IpConfiguration();
-    ctor public IpConfiguration(@NonNull android.net.IpConfiguration);
-    method public int describeContents();
-    method @Nullable public android.net.ProxyInfo getHttpProxy();
-    method @NonNull public android.net.IpConfiguration.IpAssignment getIpAssignment();
-    method @NonNull public android.net.IpConfiguration.ProxySettings getProxySettings();
-    method @Nullable public android.net.StaticIpConfiguration getStaticIpConfiguration();
-    method public void setHttpProxy(@Nullable android.net.ProxyInfo);
-    method public void setIpAssignment(@NonNull android.net.IpConfiguration.IpAssignment);
-    method public void setProxySettings(@NonNull android.net.IpConfiguration.ProxySettings);
-    method public void setStaticIpConfiguration(@Nullable android.net.StaticIpConfiguration);
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.IpConfiguration> CREATOR;
-  }
-
-  public enum IpConfiguration.IpAssignment {
-    enum_constant public static final android.net.IpConfiguration.IpAssignment DHCP;
-    enum_constant public static final android.net.IpConfiguration.IpAssignment STATIC;
-    enum_constant public static final android.net.IpConfiguration.IpAssignment UNASSIGNED;
-  }
-
-  public enum IpConfiguration.ProxySettings {
-    enum_constant public static final android.net.IpConfiguration.ProxySettings NONE;
-    enum_constant public static final android.net.IpConfiguration.ProxySettings PAC;
-    enum_constant public static final android.net.IpConfiguration.ProxySettings STATIC;
-    enum_constant public static final android.net.IpConfiguration.ProxySettings UNASSIGNED;
-  }
-
-  public final class IpPrefix implements android.os.Parcelable {
-    ctor public IpPrefix(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int);
-    ctor public IpPrefix(@NonNull String);
-  }
-
   public final class IpSecManager {
     method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void applyTunnelModeTransform(@NonNull android.net.IpSecManager.IpSecTunnelInterface, int, @NonNull android.net.IpSecTransform) throws java.io.IOException;
     method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public android.net.IpSecManager.IpSecTunnelInterface createIpSecTunnelInterface(@NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull android.net.Network) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
@@ -7256,68 +7127,6 @@
     method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public android.net.IpSecTransform buildTunnelModeTransform(@NonNull java.net.InetAddress, @NonNull android.net.IpSecManager.SecurityParameterIndex) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
   }
 
-  public class KeepalivePacketData {
-    ctor protected KeepalivePacketData(@NonNull java.net.InetAddress, @IntRange(from=0, to=65535) int, @NonNull java.net.InetAddress, @IntRange(from=0, to=65535) int, @NonNull byte[]) throws android.net.InvalidPacketException;
-    method @NonNull public java.net.InetAddress getDstAddress();
-    method public int getDstPort();
-    method @NonNull public byte[] getPacket();
-    method @NonNull public java.net.InetAddress getSrcAddress();
-    method public int getSrcPort();
-  }
-
-  public class LinkAddress implements android.os.Parcelable {
-    ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int);
-    ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int, long, long);
-    ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int);
-    ctor public LinkAddress(@NonNull String);
-    ctor public LinkAddress(@NonNull String, int, int);
-    method public long getDeprecationTime();
-    method public long getExpirationTime();
-    method public boolean isGlobalPreferred();
-    method public boolean isIpv4();
-    method public boolean isIpv6();
-    method public boolean isSameAddressAs(@Nullable android.net.LinkAddress);
-    field public static final long LIFETIME_PERMANENT = 9223372036854775807L; // 0x7fffffffffffffffL
-    field public static final long LIFETIME_UNKNOWN = -1L; // 0xffffffffffffffffL
-  }
-
-  public final class LinkProperties implements android.os.Parcelable {
-    ctor public LinkProperties(@Nullable android.net.LinkProperties);
-    ctor public LinkProperties(@Nullable android.net.LinkProperties, boolean);
-    method public boolean addDnsServer(@NonNull java.net.InetAddress);
-    method public boolean addLinkAddress(@NonNull android.net.LinkAddress);
-    method public boolean addPcscfServer(@NonNull java.net.InetAddress);
-    method @NonNull public java.util.List<java.net.InetAddress> getAddresses();
-    method @NonNull public java.util.List<java.lang.String> getAllInterfaceNames();
-    method @NonNull public java.util.List<android.net.LinkAddress> getAllLinkAddresses();
-    method @NonNull public java.util.List<android.net.RouteInfo> getAllRoutes();
-    method @Nullable public android.net.Uri getCaptivePortalApiUrl();
-    method @Nullable public android.net.CaptivePortalData getCaptivePortalData();
-    method @NonNull public java.util.List<java.net.InetAddress> getPcscfServers();
-    method @Nullable public String getTcpBufferSizes();
-    method @NonNull public java.util.List<java.net.InetAddress> getValidatedPrivateDnsServers();
-    method public boolean hasGlobalIpv6Address();
-    method public boolean hasIpv4Address();
-    method public boolean hasIpv4DefaultRoute();
-    method public boolean hasIpv4DnsServer();
-    method public boolean hasIpv6DefaultRoute();
-    method public boolean hasIpv6DnsServer();
-    method public boolean isIpv4Provisioned();
-    method public boolean isIpv6Provisioned();
-    method public boolean isProvisioned();
-    method public boolean isReachable(@NonNull java.net.InetAddress);
-    method public boolean removeDnsServer(@NonNull java.net.InetAddress);
-    method public boolean removeLinkAddress(@NonNull android.net.LinkAddress);
-    method public boolean removeRoute(@NonNull android.net.RouteInfo);
-    method public void setCaptivePortalApiUrl(@Nullable android.net.Uri);
-    method public void setCaptivePortalData(@Nullable android.net.CaptivePortalData);
-    method public void setPcscfServers(@NonNull java.util.Collection<java.net.InetAddress>);
-    method public void setPrivateDnsServerName(@Nullable String);
-    method public void setTcpBufferSizes(@Nullable String);
-    method public void setUsePrivateDns(boolean);
-    method public void setValidatedPrivateDnsServers(@NonNull java.util.Collection<java.net.InetAddress>);
-  }
-
   public final class MatchAllNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
     ctor public MatchAllNetworkSpecifier();
     method public int describeContents();
@@ -7325,104 +7134,6 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.net.MatchAllNetworkSpecifier> CREATOR;
   }
 
-  public final class NattKeepalivePacketData extends android.net.KeepalivePacketData implements android.os.Parcelable {
-    ctor public NattKeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[]) throws android.net.InvalidPacketException;
-    method public int describeContents();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.NattKeepalivePacketData> CREATOR;
-  }
-
-  public class Network implements android.os.Parcelable {
-    ctor public Network(@NonNull android.net.Network);
-    method public int getNetId();
-    method @NonNull public android.net.Network getPrivateDnsBypassingCopy();
-  }
-
-  public abstract class NetworkAgent {
-    ctor public NetworkAgent(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String, @NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties, int, @NonNull android.net.NetworkAgentConfig, @Nullable android.net.NetworkProvider);
-    method @Nullable public android.net.Network getNetwork();
-    method public void markConnected();
-    method public void onAddKeepalivePacketFilter(int, @NonNull android.net.KeepalivePacketData);
-    method public void onAutomaticReconnectDisabled();
-    method public void onNetworkUnwanted();
-    method public void onQosCallbackRegistered(int, @NonNull android.net.QosFilter);
-    method public void onQosCallbackUnregistered(int);
-    method public void onRemoveKeepalivePacketFilter(int);
-    method public void onSaveAcceptUnvalidated(boolean);
-    method public void onSignalStrengthThresholdsUpdated(@NonNull int[]);
-    method public void onStartSocketKeepalive(int, @NonNull java.time.Duration, @NonNull android.net.KeepalivePacketData);
-    method public void onStopSocketKeepalive(int);
-    method public void onValidationStatus(int, @Nullable android.net.Uri);
-    method @NonNull public android.net.Network register();
-    method public final void sendLinkProperties(@NonNull android.net.LinkProperties);
-    method public final void sendNetworkCapabilities(@NonNull android.net.NetworkCapabilities);
-    method public final void sendNetworkScore(@IntRange(from=0, to=99) int);
-    method public final void sendQosCallbackError(int, int);
-    method public final void sendQosSessionAvailable(int, int, @NonNull android.telephony.data.EpsBearerQosSessionAttributes);
-    method public final void sendQosSessionLost(int, int);
-    method public final void sendSocketKeepaliveEvent(int, int);
-    method public final void setUnderlyingNetworks(@Nullable java.util.List<android.net.Network>);
-    method public void unregister();
-    field public static final int VALIDATION_STATUS_NOT_VALID = 2; // 0x2
-    field public static final int VALIDATION_STATUS_VALID = 1; // 0x1
-  }
-
-  public final class NetworkAgentConfig implements android.os.Parcelable {
-    method public int describeContents();
-    method public int getLegacyType();
-    method @NonNull public String getLegacyTypeName();
-    method public boolean isExplicitlySelected();
-    method public boolean isPartialConnectivityAcceptable();
-    method public boolean isUnvalidatedConnectivityAcceptable();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkAgentConfig> CREATOR;
-  }
-
-  public static final class NetworkAgentConfig.Builder {
-    ctor public NetworkAgentConfig.Builder();
-    method @NonNull public android.net.NetworkAgentConfig build();
-    method @NonNull public android.net.NetworkAgentConfig.Builder setExplicitlySelected(boolean);
-    method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyType(int);
-    method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyTypeName(@NonNull String);
-    method @NonNull public android.net.NetworkAgentConfig.Builder setPartialConnectivityAcceptable(boolean);
-    method @NonNull public android.net.NetworkAgentConfig.Builder setUnvalidatedConnectivityAcceptable(boolean);
-  }
-
-  public final class NetworkCapabilities implements android.os.Parcelable {
-    ctor public NetworkCapabilities(@Nullable android.net.NetworkCapabilities, boolean);
-    method @NonNull public int[] getAdministratorUids();
-    method @Nullable public String getSsid();
-    method @NonNull public int[] getTransportTypes();
-    method public boolean isPrivateDnsBroken();
-    method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities);
-    field public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28; // 0x1c
-    field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16
-    field public static final int NET_CAPABILITY_OEM_PRIVATE = 26; // 0x1a
-    field public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; // 0x18
-    field public static final int NET_CAPABILITY_VEHICLE_INTERNAL = 27; // 0x1b
-  }
-
-  public static final class NetworkCapabilities.Builder {
-    ctor public NetworkCapabilities.Builder();
-    ctor public NetworkCapabilities.Builder(@NonNull android.net.NetworkCapabilities);
-    method @NonNull public android.net.NetworkCapabilities.Builder addCapability(int);
-    method @NonNull public android.net.NetworkCapabilities.Builder addTransportType(int);
-    method @NonNull public android.net.NetworkCapabilities build();
-    method @NonNull public android.net.NetworkCapabilities.Builder clearAll();
-    method @NonNull public android.net.NetworkCapabilities.Builder removeCapability(int);
-    method @NonNull public android.net.NetworkCapabilities.Builder removeTransportType(int);
-    method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setAdministratorUids(@NonNull int[]);
-    method @NonNull public android.net.NetworkCapabilities.Builder setLinkDownstreamBandwidthKbps(int);
-    method @NonNull public android.net.NetworkCapabilities.Builder setLinkUpstreamBandwidthKbps(int);
-    method @NonNull public android.net.NetworkCapabilities.Builder setNetworkSpecifier(@Nullable android.net.NetworkSpecifier);
-    method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setOwnerUid(int);
-    method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorPackageName(@Nullable String);
-    method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorUid(int);
-    method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkCapabilities.Builder setSignalStrength(int);
-    method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setSsid(@Nullable String);
-    method @NonNull public android.net.NetworkCapabilities.Builder setTransportInfo(@Nullable android.net.TransportInfo);
-  }
-
   public class NetworkKey implements android.os.Parcelable {
     ctor public NetworkKey(android.net.WifiKey);
     method @Nullable public static android.net.NetworkKey createFromScanResult(@NonNull android.net.wifi.ScanResult);
@@ -7434,15 +7145,6 @@
     field public final android.net.WifiKey wifiKey;
   }
 
-  public class NetworkProvider {
-    ctor public NetworkProvider(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String);
-    method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void declareNetworkRequestUnfulfillable(@NonNull android.net.NetworkRequest);
-    method public int getProviderId();
-    method public void onNetworkRequestWithdrawn(@NonNull android.net.NetworkRequest);
-    method public void onNetworkRequested(@NonNull android.net.NetworkRequest, @IntRange(from=0, to=99) int, int);
-    field public static final int ID_NONE = -1; // 0xffffffff
-  }
-
   public abstract class NetworkRecommendationProvider {
     ctor public NetworkRecommendationProvider(android.content.Context, java.util.concurrent.Executor);
     method public final android.os.IBinder getBinder();
@@ -7452,15 +7154,6 @@
   public class NetworkReleasedException extends java.lang.Exception {
   }
 
-  public class NetworkRequest implements android.os.Parcelable {
-    method @Nullable public String getRequestorPackageName();
-    method public int getRequestorUid();
-  }
-
-  public static class NetworkRequest.Builder {
-    method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkRequest.Builder setSignalStrength(int);
-  }
-
   public class NetworkScoreManager {
     method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public boolean clearScores() throws java.lang.SecurityException;
     method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public void disableScoring() throws java.lang.SecurityException;
@@ -7585,16 +7278,6 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.net.QosSocketInfo> CREATOR;
   }
 
-  public final class RouteInfo implements android.os.Parcelable {
-    ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int);
-    ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int, int);
-    method public int getMtu();
-    method public int getType();
-    field public static final int RTN_THROW = 9; // 0x9
-    field public static final int RTN_UNICAST = 1; // 0x1
-    field public static final int RTN_UNREACHABLE = 7; // 0x7
-  }
-
   public class RssiCurve implements android.os.Parcelable {
     ctor public RssiCurve(int, int, byte[]);
     ctor public RssiCurve(int, int, byte[], int);
@@ -7626,53 +7309,12 @@
     field public final android.net.RssiCurve rssiCurve;
   }
 
-  public abstract class SocketKeepalive implements java.lang.AutoCloseable {
-    field public static final int SUCCESS = 0; // 0x0
-  }
-
   public class SocketLocalAddressChangedException extends java.lang.Exception {
   }
 
   public class SocketNotBoundException extends java.lang.Exception {
   }
 
-  public final class StaticIpConfiguration implements android.os.Parcelable {
-    ctor public StaticIpConfiguration();
-    ctor public StaticIpConfiguration(@Nullable android.net.StaticIpConfiguration);
-    method public void addDnsServer(@NonNull java.net.InetAddress);
-    method public void clear();
-    method public int describeContents();
-    method @NonNull public java.util.List<java.net.InetAddress> getDnsServers();
-    method @Nullable public String getDomains();
-    method @Nullable public java.net.InetAddress getGateway();
-    method @Nullable public android.net.LinkAddress getIpAddress();
-    method @NonNull public java.util.List<android.net.RouteInfo> getRoutes(@Nullable String);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.StaticIpConfiguration> CREATOR;
-  }
-
-  public static final class StaticIpConfiguration.Builder {
-    ctor public StaticIpConfiguration.Builder();
-    method @NonNull public android.net.StaticIpConfiguration build();
-    method @NonNull public android.net.StaticIpConfiguration.Builder setDnsServers(@NonNull Iterable<java.net.InetAddress>);
-    method @NonNull public android.net.StaticIpConfiguration.Builder setDomains(@Nullable String);
-    method @NonNull public android.net.StaticIpConfiguration.Builder setGateway(@Nullable java.net.InetAddress);
-    method @NonNull public android.net.StaticIpConfiguration.Builder setIpAddress(@Nullable android.net.LinkAddress);
-  }
-
-  public final class TcpKeepalivePacketData extends android.net.KeepalivePacketData implements android.os.Parcelable {
-    ctor public TcpKeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[], int, int, int, int, int, int) throws android.net.InvalidPacketException;
-    method public int describeContents();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.TcpKeepalivePacketData> CREATOR;
-    field public final int ipTos;
-    field public final int ipTtl;
-    field public final int tcpAck;
-    field public final int tcpSeq;
-    field public final int tcpWindow;
-    field public final int tcpWindowScale;
-  }
-
   public class TrafficStats {
     method public static void setThreadStatsTagApp();
     method public static void setThreadStatsTagBackup();
@@ -7685,11 +7327,6 @@
     field public static final int TAG_SYSTEM_IMPERSONATION_RANGE_START = -256; // 0xffffff00
   }
 
-  public interface TransportInfo {
-    method public default boolean hasLocationSensitiveFields();
-    method @NonNull public default android.net.TransportInfo makeCopy(boolean);
-  }
-
   public abstract class Uri implements java.lang.Comparable<android.net.Uri> android.os.Parcelable {
     method @NonNull public String toSafeString();
   }
@@ -7713,23 +7350,6 @@
 
 }
 
-package android.net.apf {
-
-  public final class ApfCapabilities implements android.os.Parcelable {
-    ctor public ApfCapabilities(int, int, int);
-    method public int describeContents();
-    method public static boolean getApfDrop8023Frames();
-    method @NonNull public static int[] getApfEtherTypeBlackList();
-    method public boolean hasDataAccess();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.net.apf.ApfCapabilities> CREATOR;
-    field public final int apfPacketFormat;
-    field public final int apfVersionSupported;
-    field public final int maximumApfProgramSize;
-  }
-
-}
-
 package android.net.metrics {
 
   @Deprecated public final class ApfProgramEvent implements android.net.metrics.IpConnectivityLog.Event {
@@ -7924,15 +7544,24 @@
 
 }
 
-package android.net.util {
+package android.net.vcn {
 
-  public final class SocketUtils {
-    method public static void bindSocketToInterface(@NonNull java.io.FileDescriptor, @NonNull String) throws android.system.ErrnoException;
-    method public static void closeSocket(@Nullable java.io.FileDescriptor) throws java.io.IOException;
-    method @NonNull public static java.net.SocketAddress makeNetlinkSocketAddress(int, int);
-    method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int);
-    method @Deprecated @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]);
-    method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int, @NonNull byte[]);
+  public class VcnManager {
+    method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void addVcnNetworkPolicyListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.vcn.VcnManager.VcnNetworkPolicyListener);
+    method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.vcn.VcnNetworkPolicyResult applyVcnNetworkPolicy(@NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties);
+    method public void removeVcnNetworkPolicyListener(@NonNull android.net.vcn.VcnManager.VcnNetworkPolicyListener);
+  }
+
+  public static interface VcnManager.VcnNetworkPolicyListener {
+    method public void onPolicyChanged();
+  }
+
+  public final class VcnNetworkPolicyResult implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities();
+    method public boolean isTeardownRequested();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.vcn.VcnNetworkPolicyResult> CREATOR;
   }
 
 }
@@ -8284,7 +7913,7 @@
 
   public final class BugreportManager {
     method @RequiresPermission(android.Manifest.permission.DUMP) public void requestBugreport(@NonNull android.os.BugreportParams, @Nullable CharSequence, @Nullable CharSequence);
-    method @RequiresPermission(android.Manifest.permission.DUMP) public void startBugreport(@NonNull android.os.ParcelFileDescriptor, @Nullable android.os.ParcelFileDescriptor, @NonNull android.os.BugreportParams, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback);
+    method @RequiresPermission(android.Manifest.permission.DUMP) @WorkerThread public void startBugreport(@NonNull android.os.ParcelFileDescriptor, @Nullable android.os.ParcelFileDescriptor, @NonNull android.os.BugreportParams, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback);
   }
 
   public final class BugreportParams {
@@ -8576,7 +8205,7 @@
     method @RequiresPermission(allOf={android.Manifest.permission.READ_DREAM_STATE, android.Manifest.permission.WRITE_DREAM_STATE}) public void dream(long);
     method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public boolean forceSuspend();
     method @NonNull public android.os.BatterySaverPolicyConfig getFullPowerSavePolicy();
-    method @RequiresPermission(android.Manifest.permission.POWER_SAVER) public int getPowerSaveModeTrigger();
+    method public int getPowerSaveModeTrigger();
     method @RequiresPermission(android.Manifest.permission.READ_DREAM_STATE) public boolean isAmbientDisplayAvailable();
     method @RequiresPermission(android.Manifest.permission.READ_DREAM_STATE) public boolean isAmbientDisplaySuppressed();
     method @RequiresPermission(android.Manifest.permission.READ_DREAM_STATE) public boolean isAmbientDisplaySuppressedForToken(@NonNull String);
@@ -8606,11 +8235,18 @@
     method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void addToWhitelist(@NonNull String);
     method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void addToWhitelist(@NonNull java.util.List<java.lang.String>);
     method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void removeFromWhitelist(@NonNull String);
-    method @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public void whitelistAppTemporarily(@NonNull String, long);
-    method @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public long whitelistAppTemporarilyForEvent(@NonNull String, int, @NonNull String);
+    method @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public void whitelistAppTemporarily(@NonNull String, long, int, @Nullable String);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public void whitelistAppTemporarily(@NonNull String, long);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public long whitelistAppTemporarilyForEvent(@NonNull String, int, @Nullable String);
+    method @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public long whitelistAppTemporarilyForEvent(@NonNull String, int, int, @Nullable String);
     field public static final int EVENT_MMS = 2; // 0x2
     field public static final int EVENT_SMS = 1; // 0x1
     field public static final int EVENT_UNSPECIFIED = 0; // 0x0
+    field public static final int REASON_ACTIVITY_RECOGNITION = 102; // 0x66
+    field public static final int REASON_GEOFENCING = 100; // 0x64
+    field public static final int REASON_OTHER = 1; // 0x1
+    field public static final int REASON_PUSH_MESSAGING = 101; // 0x65
+    field public static final int REASON_UNKNOWN = 0; // 0x0
     field public static final int TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED = 0; // 0x0
     field public static final int TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED = 1; // 0x1
   }
@@ -8759,13 +8395,13 @@
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.os.UserHandle createProfile(@NonNull String, @NonNull String, @NonNull java.util.Set<java.lang.String>) throws android.os.UserManager.UserOperationException;
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public java.util.List<android.os.UserHandle> getAllProfiles();
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public java.util.List<android.os.UserHandle> getEnabledProfiles();
-    method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.UserHandle getProfileParent(@NonNull android.os.UserHandle);
+    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public android.os.UserHandle getProfileParent(@NonNull android.os.UserHandle);
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.os.UserHandle getRestrictedProfileParent();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getSeedAccountName();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.PersistableBundle getSeedAccountOptions();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getSeedAccountType();
-    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public long[] getSerialNumbersOfUsers(boolean);
-    method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public java.util.List<android.os.UserHandle> getUserHandles(boolean);
+    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public long[] getSerialNumbersOfUsers(boolean);
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public java.util.List<android.os.UserHandle> getUserHandles(boolean);
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED}) public android.graphics.Bitmap getUserIcon();
     method @Deprecated @android.os.UserManager.UserRestrictionSource @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public int getUserRestrictionSource(String, android.os.UserHandle);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public java.util.List<android.os.UserManager.EnforcingUser> getUserRestrictionSources(String, android.os.UserHandle);
@@ -9203,6 +8839,7 @@
     field public static final String NAMESPACE_BIOMETRICS = "biometrics";
     field public static final String NAMESPACE_BLOBSTORE = "blobstore";
     field public static final String NAMESPACE_BLUETOOTH = "bluetooth";
+    field public static final String NAMESPACE_CLIPBOARD = "clipboard";
     field public static final String NAMESPACE_CONNECTIVITY = "connectivity";
     field public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
     field @Deprecated public static final String NAMESPACE_DEX_BOOT = "dex_boot";
@@ -9217,6 +8854,7 @@
     field public static final String NAMESPACE_PERMISSIONS = "permissions";
     field public static final String NAMESPACE_PRIVACY = "privacy";
     field public static final String NAMESPACE_PROFCOLLECT_NATIVE_BOOT = "profcollect_native_boot";
+    field public static final String NAMESPACE_REBOOT_READINESS = "reboot_readiness";
     field public static final String NAMESPACE_ROLLBACK = "rollback";
     field public static final String NAMESPACE_ROLLBACK_BOOT = "rollback_boot";
     field public static final String NAMESPACE_RUNTIME = "runtime";
@@ -9984,6 +9622,18 @@
 
 }
 
+package android.service.displayhash {
+
+  public abstract class DisplayHasherService extends android.app.Service {
+    ctor public DisplayHasherService();
+    method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
+    method @Nullable public abstract void onGenerateDisplayHash(@NonNull byte[], @NonNull android.hardware.HardwareBuffer, @NonNull android.graphics.Rect, @NonNull String, @NonNull android.view.displayhash.DisplayHashResultCallback);
+    method @Nullable public abstract android.view.displayhash.VerifiedDisplayHash onVerifyDisplayHash(@NonNull byte[], @NonNull android.view.displayhash.DisplayHash);
+    field public static final String SERVICE_INTERFACE = "android.service.displayhash.DisplayHasherService";
+  }
+
+}
+
 package android.service.euicc {
 
   public final class DownloadSubscriptionResult implements android.os.Parcelable {
@@ -10168,6 +9818,7 @@
     method @Nullable public android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification, @NonNull android.app.NotificationChannel);
     method @Nullable public android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification, @NonNull android.app.NotificationChannel, @NonNull android.service.notification.NotificationListenerService.RankingMap);
     method public void onNotificationExpansionChanged(@NonNull String, boolean, boolean);
+    method public void onNotificationFeedbackReceived(@NonNull String, @NonNull android.service.notification.NotificationListenerService.RankingMap, @NonNull android.os.Bundle);
     method public abstract void onNotificationSnoozedUntilContext(@NonNull android.service.notification.StatusBarNotification, @NonNull String);
     method public void onNotificationVisibilityChanged(@NonNull String, boolean);
     method public void onNotificationsSeen(@NonNull java.util.List<java.lang.String>);
@@ -10175,6 +9826,7 @@
     method public void onPanelRevealed(int);
     method public void onSuggestedReplySent(@NonNull String, @NonNull CharSequence, int);
     method public final void unsnoozeNotification(@NonNull String);
+    field public static final String FEEDBACK_RATING = "feedback.rating";
     field public static final String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
     field public static final int SOURCE_FROM_APP = 0; // 0x0
     field public static final int SOURCE_FROM_ASSISTANT = 1; // 0x1
@@ -10344,30 +9996,6 @@
 
 }
 
-package android.service.screenshot {
-
-  public final class ScreenshotHash implements android.os.Parcelable {
-    ctor public ScreenshotHash(long, @NonNull android.graphics.Rect, @NonNull String, @NonNull byte[], @NonNull byte[]);
-    method public int describeContents();
-    method @NonNull public android.graphics.Rect getBoundsInWindow();
-    method @NonNull public String getHashingAlgorithm();
-    method @NonNull public byte[] getHmac();
-    method @NonNull public byte[] getImageHash();
-    method public long getScreenshotTimeMillis();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.service.screenshot.ScreenshotHash> CREATOR;
-  }
-
-  public abstract class ScreenshotHasherService extends android.app.Service {
-    ctor public ScreenshotHasherService();
-    method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
-    method @Nullable public abstract android.service.screenshot.ScreenshotHash onGenerateScreenshotHash(@NonNull byte[], @NonNull android.hardware.HardwareBuffer, @NonNull android.graphics.Rect, @NonNull String);
-    method public abstract boolean onVerifyScreenshotHash(@NonNull byte[], @NonNull android.service.screenshot.ScreenshotHash);
-    field public static final String SERVICE_INTERFACE = "android.service.screenshot.ScreenshotHasherService";
-  }
-
-}
-
 package android.service.search {
 
   public abstract class SearchUiService extends android.app.Service {
@@ -10435,10 +10063,10 @@
 
   public abstract class ExternalStorageService extends android.app.Service {
     ctor public ExternalStorageService();
+    method public void onAnrDelayStarted(@NonNull String, int, int, int);
     method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
     method public abstract void onEndSession(@NonNull String) throws java.io.IOException;
     method public void onFreeCache(@NonNull java.util.UUID, long) throws java.io.IOException;
-    method public long onGetAnrDelayMillis(@NonNull String, int);
     method public abstract void onStartSession(@NonNull String, int, @NonNull android.os.ParcelFileDescriptor, @NonNull java.io.File, @NonNull java.io.File) throws java.io.IOException;
     method public abstract void onVolumeStateChanged(@NonNull android.os.storage.StorageVolume) throws java.io.IOException;
     field public static final int FLAG_SESSION_ATTRIBUTE_INDEXABLE = 2; // 0x2
@@ -10636,7 +10264,7 @@
   public abstract class HotwordDetectionService extends android.app.Service {
     ctor public HotwordDetectionService();
     method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
-    method public void onDetectFromDspSource(int, @NonNull android.service.voice.HotwordDetectionService.DspHotwordDetectionCallback);
+    method public void onDetectFromDspSource(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, long, @NonNull android.service.voice.HotwordDetectionService.DspHotwordDetectionCallback);
     field public static final String SERVICE_INTERFACE = "android.service.voice.HotwordDetectionService";
   }
 
@@ -10771,7 +10399,7 @@
     method @Nullable public android.telecom.PhoneAccountHandle getPhoneAccountHandle();
     method @Nullable public final String getTelecomCallId();
     method @Deprecated public void onAudioStateChanged(android.telecom.AudioState);
-    method @RequiresPermission(android.Manifest.permission.READ_CONTACTS) public void onCallFilteringCompleted(boolean, boolean, @Nullable android.telecom.CallScreeningService.CallResponse, boolean);
+    method @RequiresPermission(android.Manifest.permission.READ_CONTACTS) public void onCallFilteringCompleted(@NonNull android.telecom.Connection.CallFilteringCompletionInfo);
     method public final void resetConnectionTime();
     method public void setCallDirection(int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public final void setConnectTimeMillis(@IntRange(from=0) long);
@@ -10787,6 +10415,16 @@
     field public static final int PROPERTY_REMOTELY_HOSTED = 2048; // 0x800
   }
 
+  public static final class Connection.CallFilteringCompletionInfo implements android.os.Parcelable {
+    ctor public Connection.CallFilteringCompletionInfo(boolean, boolean, @Nullable android.telecom.CallScreeningService.CallResponse, @Nullable android.content.ComponentName);
+    method public int describeContents();
+    method @Nullable public android.telecom.CallScreeningService.CallResponse getCallResponse();
+    method @Nullable public android.content.ComponentName getCallScreeningComponent();
+    method public boolean isBlocked();
+    method public boolean isInContacts();
+    field @NonNull public static final android.os.Parcelable.Creator<android.telecom.Connection.CallFilteringCompletionInfo> CREATOR;
+  }
+
   public final class ConnectionRequest implements android.os.Parcelable {
     method @Nullable public String getTelecomCallId();
   }
@@ -10948,7 +10586,7 @@
   }
 
   public final class RemoteConnection {
-    method @RequiresPermission(android.Manifest.permission.READ_CONTACTS) public void onCallFilteringCompleted(boolean, boolean, @Nullable android.telecom.CallScreeningService.CallResponse, boolean);
+    method @RequiresPermission(android.Manifest.permission.READ_CONTACTS) public void onCallFilteringCompleted(@NonNull android.telecom.Connection.CallFilteringCompletionInfo);
     method @Deprecated public void setAudioState(android.telecom.AudioState);
   }
 
@@ -11129,6 +10767,10 @@
     field public static final String KEY_SUPPORT_CDMA_1X_VOICE_CALLS_BOOL = "support_cdma_1x_voice_calls_bool";
   }
 
+  public static final class CarrierConfigManager.Ims {
+    field public static final String KEY_PUBLISH_SERVICE_DESC_FEATURE_TAG_MAP_OVERRIDE_STRING_ARRAY = "ims.publish_service_desc_feature_tag_map_override_string_array";
+  }
+
   public static final class CarrierConfigManager.Wifi {
     field public static final String KEY_AVOID_5GHZ_SOFTAP_FOR_LAA_BOOL = "wifi.avoid_5ghz_softap_for_laa_bool";
     field public static final String KEY_AVOID_5GHZ_WIFI_DIRECT_FOR_LAA_BOOL = "wifi.avoid_5ghz_wifi_direct_for_laa_bool";
@@ -11870,7 +11512,7 @@
   }
 
   public class TelephonyManager {
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void bootstrapAuthenticationRequest(int, @NonNull android.net.Uri, @NonNull android.telephony.gba.UaSecurityProtocolIdentifier, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.BootstrapAuthenticationCallback);
+    method @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) @WorkerThread public void bootstrapAuthenticationRequest(int, @NonNull android.net.Uri, @NonNull android.telephony.gba.UaSecurityProtocolIdentifier, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.BootstrapAuthenticationCallback);
     method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String);
     method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.PinResult changeIccLockPin(@NonNull String, @NonNull String);
     method public int checkCarrierPrivilegesForPackage(String);
@@ -12259,6 +11901,7 @@
     method public long getRetryDurationMillis();
     method @Nullable public android.telephony.data.SliceInfo getSliceInfo();
     method @Deprecated public int getSuggestedRetryTime();
+    method @NonNull public java.util.List<android.telephony.data.TrafficDescriptor> getTrafficDescriptors();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.DataCallResponse> CREATOR;
     field public static final int HANDOVER_FAILURE_MODE_DO_FALLBACK = 1; // 0x1
@@ -12294,6 +11937,7 @@
     method @NonNull public android.telephony.data.DataCallResponse.Builder setRetryDurationMillis(long);
     method @NonNull public android.telephony.data.DataCallResponse.Builder setSliceInfo(@Nullable android.telephony.data.SliceInfo);
     method @Deprecated @NonNull public android.telephony.data.DataCallResponse.Builder setSuggestedRetryTime(int);
+    method @NonNull public android.telephony.data.DataCallResponse.Builder setTrafficDescriptors(@NonNull java.util.List<android.telephony.data.TrafficDescriptor>);
   }
 
   public final class DataProfile implements android.os.Parcelable {
@@ -12364,7 +12008,7 @@
     method public void setDataProfile(@NonNull java.util.List<android.telephony.data.DataProfile>, boolean, @NonNull android.telephony.data.DataServiceCallback);
     method public void setInitialAttachApn(@NonNull android.telephony.data.DataProfile, boolean, @NonNull android.telephony.data.DataServiceCallback);
     method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @NonNull android.telephony.data.DataServiceCallback);
-    method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @IntRange(from=0, to=15) int, @Nullable android.telephony.data.SliceInfo, @NonNull android.telephony.data.DataServiceCallback);
+    method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @IntRange(from=0, to=15) int, @Nullable android.telephony.data.SliceInfo, @Nullable android.telephony.data.TrafficDescriptor, boolean, @NonNull android.telephony.data.DataServiceCallback);
   }
 
   public class DataServiceCallback {
@@ -12463,6 +12107,15 @@
     method @NonNull public android.telephony.data.ThrottleStatus.Builder setTransportType(int);
   }
 
+  public final class TrafficDescriptor implements android.os.Parcelable {
+    ctor public TrafficDescriptor(@Nullable String, @Nullable String);
+    method public int describeContents();
+    method @Nullable public String getDnn();
+    method @Nullable public String getOsAppId();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.TrafficDescriptor> CREATOR;
+  }
+
 }
 
 package android.telephony.euicc {
@@ -12910,6 +12563,7 @@
     field public static final String EXTRA_EMERGENCY_CALL = "e_call";
     field public static final String EXTRA_EXTENDING_TO_CONFERENCE_SUPPORTED = "android.telephony.ims.extra.EXTENDING_TO_CONFERENCE_SUPPORTED";
     field public static final String EXTRA_FORWARDED_NUMBER = "android.telephony.ims.extra.FORWARDED_NUMBER";
+    field public static final String EXTRA_IS_BUSINESS_CALL = "android.telephony.ims.extra.IS_BUSINESS_CALL";
     field public static final String EXTRA_IS_CALL_PULL = "CallPull";
     field public static final String EXTRA_IS_CROSS_SIM_CALL = "android.telephony.ims.extra.IS_CROSS_SIM_CALL";
     field public static final String EXTRA_LOCATION = "android.telephony.ims.extra.LOCATION";
@@ -13318,19 +12972,19 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(int, int);
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public String getProvisioningStringValue(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isRcsVolteSingleRegistrationCapable() throws android.telephony.ims.ImsException;
+    method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public boolean isRcsVolteSingleRegistrationCapable() throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerRcsProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.RcsProvisioningCallback) throws android.telephony.ims.ImsException;
+    method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public void registerRcsProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.RcsProvisioningCallback) throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(int, int, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRcsClientConfiguration(@NonNull android.telephony.ims.RcsClientConfiguration) throws android.telephony.ims.ImsException;
+    method @RequiresPermission(android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void setRcsClientConfiguration(@NonNull android.telephony.ims.RcsClientConfiguration) throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void triggerRcsReconfiguration();
+    method @RequiresPermission(android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void triggerRcsReconfiguration();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterRcsProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.RcsProvisioningCallback);
-    field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE = "android.telephony.ims.action.RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE";
+    method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public void unregisterRcsProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.RcsProvisioningCallback);
+    field @RequiresPermission(android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public static final String ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE = "android.telephony.ims.action.RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE";
     field public static final String EXTRA_STATUS = "android.telephony.ims.extra.STATUS";
     field public static final String EXTRA_SUBSCRIPTION_ID = "android.telephony.ims.extra.SUBSCRIPTION_ID";
     field public static final int KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID = 67; // 0x43
@@ -13595,10 +13249,10 @@
   }
 
   public class SipDelegateManager {
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void createSipDelegate(@NonNull android.telephony.ims.DelegateRequest, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.stub.DelegateConnectionStateCallback, @NonNull android.telephony.ims.stub.DelegateConnectionMessageCallback) throws android.telephony.ims.ImsException;
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void destroySipDelegate(@NonNull android.telephony.ims.SipDelegateConnection, int);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isSupported() throws android.telephony.ims.ImsException;
-    method public void triggerFullNetworkRegistration(@NonNull android.telephony.ims.SipDelegateConnection, @IntRange(from=100, to=699) int, @Nullable String);
+    method @RequiresPermission(android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void createSipDelegate(@NonNull android.telephony.ims.DelegateRequest, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.stub.DelegateConnectionStateCallback, @NonNull android.telephony.ims.stub.DelegateConnectionMessageCallback) throws android.telephony.ims.ImsException;
+    method @RequiresPermission(android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void destroySipDelegate(@NonNull android.telephony.ims.SipDelegateConnection, int);
+    method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public boolean isSupported() throws android.telephony.ims.ImsException;
+    method @RequiresPermission(android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void triggerFullNetworkRegistration(@NonNull android.telephony.ims.SipDelegateConnection, @IntRange(from=100, to=699) int, @Nullable String);
     field public static final int DENIED_REASON_INVALID = 4; // 0x4
     field public static final int DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE = 1; // 0x1
     field public static final int DENIED_REASON_NOT_ALLOWED = 2; // 0x2
@@ -13748,7 +13402,7 @@
   }
 
   public static interface CapabilityExchangeEventListener.OptionsRequestCallback {
-    method public default void onRespondToCapabilityRequest(@NonNull android.telephony.ims.RcsContactUceCapability, boolean);
+    method public void onRespondToCapabilityRequest(@NonNull android.telephony.ims.RcsContactUceCapability, boolean);
     method public void onRespondToCapabilityRequestWithError(@IntRange(from=100, to=699) int, @NonNull String);
   }
 
@@ -14281,21 +13935,10 @@
 
   public final class UwbManager {
     method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public long elapsedRealtimeResolutionNanos();
-    method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public int getAngleOfArrivalSupport();
-    method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public int getMaxRemoteDevicesPerInitiatorSession();
-    method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public int getMaxRemoteDevicesPerResponderSession();
-    method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public int getMaxSimultaneousSessions();
     method @NonNull @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public android.os.PersistableBundle getSpecificationInfo();
-    method @NonNull @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public java.util.List<java.lang.Integer> getSupportedChannelNumbers();
-    method @NonNull @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public java.util.Set<java.lang.Integer> getSupportedPreambleCodeIndices();
-    method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public boolean isRangingSupported();
     method @NonNull @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public AutoCloseable openRangingSession(@NonNull android.os.PersistableBundle, @NonNull java.util.concurrent.Executor, @NonNull android.uwb.RangingSession.Callback);
     method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public void registerAdapterStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.uwb.UwbManager.AdapterStateCallback);
     method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public void unregisterAdapterStateCallback(@NonNull android.uwb.UwbManager.AdapterStateCallback);
-    field public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_2D = 2; // 0x2
-    field public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_HEMISPHERICAL = 3; // 0x3
-    field public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_SPHERICAL = 4; // 0x4
-    field public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_NONE = 1; // 0x1
   }
 
   public static interface UwbManager.AdapterStateCallback {
@@ -14356,6 +13999,7 @@
 
   public final class ContentCaptureContext implements android.os.Parcelable {
     method @Nullable public android.content.ComponentName getActivityComponent();
+    method @Nullable public android.app.assist.ActivityId getActivityId();
     method public int getDisplayId();
     method public int getFlags();
     method @Nullable public android.view.contentcapture.ContentCaptureSessionId getParentSessionId();
@@ -14399,6 +14043,21 @@
 
 }
 
+package android.view.displayhash {
+
+  public final class DisplayHash implements android.os.Parcelable {
+    ctor public DisplayHash(long, @NonNull android.graphics.Rect, @NonNull String, @NonNull byte[], @NonNull byte[]);
+    method public int describeContents();
+    method @NonNull public android.graphics.Rect getBoundsInWindow();
+    method @NonNull public String getHashAlgorithm();
+    method @NonNull public byte[] getHmac();
+    method @NonNull public byte[] getImageHash();
+    method public long getTimeMillis();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+  }
+
+}
+
 package android.view.translation {
 
   public final class UiTranslationManager {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index ff96f92..1e5a6f1 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -5,14 +5,17 @@
     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 BACKGROUND_CAMERA = "android.permission.BACKGROUND_CAMERA";
     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 BROADCAST_CLOSE_SYSTEM_DIALOGS = "android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS";
     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";
+    field public static final String CLEAR_FREEZE_PERIOD = "android.permission.CLEAR_FREEZE_PERIOD";
     field public static final String CONFIGURE_DISPLAY_BRIGHTNESS = "android.permission.CONFIGURE_DISPLAY_BRIGHTNESS";
     field public static final String CONTROL_DEVICE_LIGHTS = "android.permission.CONTROL_DEVICE_LIGHTS";
     field public static final String CONTROL_DEVICE_STATE = "android.permission.CONTROL_DEVICE_STATE";
+    field public static final String FORCE_DEVICE_POLICY_MANAGER_LOGS = "android.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS";
     field public static final String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES";
     field public static final String KEEP_UNINSTALLED_PACKAGES = "android.permission.KEEP_UNINSTALLED_PACKAGES";
     field @Deprecated public static final String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS";
@@ -28,6 +31,7 @@
     field public static final String QUERY_USERS = "android.permission.QUERY_USERS";
     field public static final String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS";
     field public static final String READ_PRIVILEGED_PHONE_STATE = "android.permission.READ_PRIVILEGED_PHONE_STATE";
+    field public static final String RECORD_BACKGROUND_AUDIO = "android.permission.RECORD_BACKGROUND_AUDIO";
     field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
     field public static final String RESET_APP_ERRORS = "android.permission.RESET_APP_ERRORS";
     field public static final String START_TASKS_FROM_RECENTS = "android.permission.START_TASKS_FROM_RECENTS";
@@ -91,6 +95,8 @@
     method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void addHomeVisibilityListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.HomeVisibilityListener);
     method public void alwaysShowUnsupportedCompileSdkWarning(android.content.ComponentName);
     method public long getTotalRam();
+    method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getUidProcessCapabilities(int);
+    method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getUidProcessState(int);
     method public void holdLock(android.os.IBinder, int);
     method public static boolean isHighEndGfx();
     method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void removeHomeVisibilityListener(@NonNull android.app.HomeVisibilityListener);
@@ -100,13 +106,16 @@
     method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public boolean updateMccMncConfiguration(@NonNull String, @NonNull String);
     field public static final long DROP_CLOSE_SYSTEM_DIALOGS = 174664120L; // 0xa6929b8L
     field public static final long LOCK_DOWN_CLOSE_SYSTEM_DIALOGS = 174664365L; // 0xa692aadL
-    field public static final int PROCESS_CAPABILITY_ALL = 7; // 0x7
+    field public static final int PROCESS_CAPABILITY_ALL = 15; // 0xf
     field public static final int PROCESS_CAPABILITY_ALL_EXPLICIT = 1; // 0x1
     field public static final int PROCESS_CAPABILITY_ALL_IMPLICIT = 6; // 0x6
     field public static final int PROCESS_CAPABILITY_FOREGROUND_CAMERA = 2; // 0x2
     field public static final int PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1; // 0x1
     field public static final int PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 4; // 0x4
+    field public static final int PROCESS_CAPABILITY_NETWORK = 8; // 0x8
     field public static final int PROCESS_CAPABILITY_NONE = 0; // 0x0
+    field public static final int PROCESS_STATE_FOREGROUND_SERVICE = 4; // 0x4
+    field public static final int PROCESS_STATE_TOP = 2; // 0x2
   }
 
   public static class ActivityManager.RunningAppProcessInfo implements android.os.Parcelable {
@@ -300,6 +309,7 @@
     method public void clickNotification(@Nullable String, int, int, boolean);
     method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void collapsePanels();
     method public void expandNotificationsPanel();
+    method public void sendNotificationFeedback(@Nullable String, @Nullable android.os.Bundle);
     method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setExpansionDisabledForSimNetworkLock(boolean);
   }
 
@@ -383,18 +393,27 @@
 
   public class DevicePolicyManager {
     method public int checkProvisioningPreCondition(@Nullable String, @NonNull String);
+    method @RequiresPermission(android.Manifest.permission.CLEAR_FREEZE_PERIOD) public void clearSystemUpdatePolicyFreezePeriodRecord();
     method @Nullable public android.os.UserHandle createAndProvisionManagedProfile(@NonNull android.app.admin.ManagedProfileProvisioningParams) throws android.app.admin.ProvisioningException;
+    method @RequiresPermission(android.Manifest.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS) public long forceNetworkLogs();
+    method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public void forceRemoveActiveAdmin(@NonNull android.content.ComponentName, int);
+    method @RequiresPermission(android.Manifest.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS) public long forceSecurityLogs();
     method public void forceUpdateUserSetupComplete();
+    method @NonNull public java.util.Set<java.lang.String> getDefaultCrossProfilePackages();
+    method @NonNull public java.util.Set<java.lang.String> getDisallowedSystemApps(@NonNull android.content.ComponentName, int, @NonNull String);
     method public long getLastBugReportRequestTime();
     method public long getLastNetworkLogRetrievalTime();
     method public long getLastSecurityLogRetrievalTime();
     method public java.util.List<java.lang.String> getOwnerInstalledCaCerts(@NonNull android.os.UserHandle);
     method public boolean isCurrentInputMethodSetByOwner();
     method public boolean isFactoryResetProtectionPolicySupported();
+    method @RequiresPermission(anyOf={"android.permission.MARK_DEVICE_ORGANIZATION_OWNED", "android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS"}, conditional=true) public void markProfileOwnerOnOrganizationOwnedDevice(@NonNull android.content.ComponentName);
     method @NonNull public static String operationSafetyReasonToString(int);
     method @NonNull public static String operationToString(int);
     method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public void provisionFullyManagedDevice(@NonNull android.app.admin.FullyManagedDeviceProvisioningParams) throws android.app.admin.ProvisioningException;
     method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public void resetDefaultCrossProfileIntentFilters(int);
+    method @RequiresPermission(allOf={"android.permission.MANAGE_DEVICE_ADMINS", android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void setActiveAdmin(@NonNull android.content.ComponentName, boolean, int);
+    method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public boolean setDeviceOwner(@NonNull android.content.ComponentName, @Nullable String, int);
     method @RequiresPermission("android.permission.MANAGE_DEVICE_ADMINS") public void setNextOperationSafety(int, int);
     field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED";
     field public static final int CODE_ACCOUNTS_NOT_EMPTY = 6; // 0x6
@@ -527,6 +546,15 @@
 
 }
 
+package android.app.assist {
+
+  public class ActivityId {
+    method public int getTaskId();
+    method @Nullable public android.os.IBinder getToken();
+  }
+
+}
+
 package android.app.blob {
 
   public class BlobStoreManager {
@@ -547,6 +575,16 @@
 
 }
 
+package android.app.contentsuggestions {
+
+  public final class ContentSuggestionsManager {
+    method @RequiresPermission(android.Manifest.permission.MANAGE_CONTENT_SUGGESTIONS) public void resetTemporaryService(int);
+    method @RequiresPermission(android.Manifest.permission.MANAGE_CONTENT_SUGGESTIONS) public void setDefaultServiceEnabled(int, boolean);
+    method @RequiresPermission(android.Manifest.permission.MANAGE_CONTENT_SUGGESTIONS) public void setTemporaryService(int, @NonNull String, int);
+  }
+
+}
+
 package android.app.prediction {
 
   public final class AppPredictor {
@@ -579,6 +617,14 @@
 
 }
 
+package android.appwidget {
+
+  public class AppWidgetManager {
+    method public void setBindAppWidgetPermission(@NonNull String, int, boolean);
+  }
+
+}
+
 package android.bluetooth {
 
   public final class BluetoothClass implements android.os.Parcelable {
@@ -672,6 +718,10 @@
     field public int privateFlags;
   }
 
+  public class CrossProfileApps {
+    method public boolean canConfigureInteractAcrossProfiles(@NonNull String);
+  }
+
   public class LauncherApps {
     ctor public LauncherApps(android.content.Context);
   }
@@ -695,8 +745,10 @@
     method public void holdLock(android.os.IBinder, int);
     method @RequiresPermission(android.Manifest.permission.KEEP_UNINSTALLED_PACKAGES) public void setKeepUninstalledPackages(@NonNull java.util.List<java.lang.String>);
     field public static final String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage";
+    field public static final String FEATURE_CAMERA_TOGGLE = "android.hardware.camera.toggle";
     field public static final String FEATURE_FILE_BASED_ENCRYPTION = "android.software.file_based_encryption";
     field public static final String FEATURE_HDMI_CEC = "android.hardware.hdmi.cec";
+    field public static final String FEATURE_MICROPHONE_TOGGLE = "android.hardware.microphone.toggle";
     field public static final int FLAG_PERMISSION_REVOKE_WHEN_REQUESTED = 128; // 0x80
     field public static final int MATCH_KNOWN_PACKAGES = 4202496; // 0x402000
     field public static final String SYSTEM_SHARED_LIBRARY_SERVICES = "android.ext.services";
@@ -723,6 +775,65 @@
     ctor public ShortcutManager(android.content.Context);
   }
 
+  public class UserInfo implements android.os.Parcelable {
+    ctor public UserInfo(int, String, int);
+    ctor public UserInfo(int, String, String, int);
+    ctor public UserInfo(int, String, String, int, String);
+    ctor @Deprecated public UserInfo();
+    ctor public UserInfo(android.content.pm.UserInfo);
+    method public boolean canHaveProfile();
+    method public int describeContents();
+    method public android.os.UserHandle getUserHandle();
+    method public boolean isAdmin();
+    method public boolean isDemo();
+    method public boolean isEnabled();
+    method public boolean isEphemeral();
+    method public boolean isFull();
+    method public boolean isGuest();
+    method public boolean isInitialized();
+    method public boolean isManagedProfile();
+    method public boolean isPrimary();
+    method public boolean isProfile();
+    method public boolean isQuietModeEnabled();
+    method public boolean isRestricted();
+    method public boolean isSystemOnly();
+    method public static boolean isSystemOnly(int);
+    method public boolean supportsSwitchTo();
+    method public boolean supportsSwitchToByUser();
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.UserInfo> CREATOR;
+    field public static final int FLAG_ADMIN = 2; // 0x2
+    field @Deprecated public static final int FLAG_DEMO = 512; // 0x200
+    field public static final int FLAG_DISABLED = 64; // 0x40
+    field public static final int FLAG_EPHEMERAL = 256; // 0x100
+    field public static final int FLAG_FULL = 1024; // 0x400
+    field @Deprecated public static final int FLAG_GUEST = 4; // 0x4
+    field public static final int FLAG_INITIALIZED = 16; // 0x10
+    field @Deprecated public static final int FLAG_MANAGED_PROFILE = 32; // 0x20
+    field public static final int FLAG_PRIMARY = 1; // 0x1
+    field public static final int FLAG_PROFILE = 4096; // 0x1000
+    field public static final int FLAG_QUIET_MODE = 128; // 0x80
+    field @Deprecated public static final int FLAG_RESTRICTED = 8; // 0x8
+    field public static final int FLAG_SYSTEM = 2048; // 0x800
+    field public static final int NO_PROFILE_GROUP_ID = -10000; // 0xffffd8f0
+    field public boolean convertedFromPreCreated;
+    field public long creationTime;
+    field public int flags;
+    field public boolean guestToRemove;
+    field public String iconPath;
+    field public int id;
+    field public String lastLoggedInFingerprint;
+    field public long lastLoggedInTime;
+    field public String name;
+    field public boolean partial;
+    field public boolean preCreated;
+    field public int profileBadge;
+    field public int profileGroupId;
+    field public int restrictedProfileParentId;
+    field public int serialNumber;
+    field public String userType;
+  }
+
 }
 
 package android.content.res {
@@ -836,7 +947,7 @@
 package android.graphics.fonts {
 
   public class FontManager {
-    method @Nullable public android.text.FontConfig getFontConfig();
+    method @NonNull public android.text.FontConfig getFontConfig();
     method @RequiresPermission(android.Manifest.permission.UPDATE_FONTS) public int updateFontFamily(@NonNull android.graphics.fonts.FontFamilyUpdateRequest, @IntRange(from=0) int);
     method @RequiresPermission(android.Manifest.permission.UPDATE_FONTS) public int updateFontFile(@NonNull android.graphics.fonts.FontFileUpdateRequest, @IntRange(from=0) int);
     method @Deprecated @RequiresPermission(android.Manifest.permission.UPDATE_FONTS) public int updateFontFile(@NonNull android.os.ParcelFileDescriptor, @NonNull byte[], @IntRange(from=0) int);
@@ -857,11 +968,21 @@
 package android.hardware {
 
   public final class SensorPrivacyManager {
-    method public boolean isIndividualSensorPrivacyEnabled(int);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setIndividualSensorPrivacy(int, boolean);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setIndividualSensorPrivacyForProfileGroup(int, boolean);
-    field public static final int INDIVIDUAL_SENSOR_CAMERA = 2; // 0x2
-    field public static final int INDIVIDUAL_SENSOR_MICROPHONE = 1; // 0x1
+    method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(int, @NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
+    method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
+    method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public boolean isSensorPrivacyEnabled(int);
+    method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void removeSensorPrivacyListener(@NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
+    method @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setSensorPrivacy(int, boolean);
+    method @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setSensorPrivacyForProfileGroup(int, boolean);
+  }
+
+  public static interface SensorPrivacyManager.OnSensorPrivacyChangedListener {
+    method public void onSensorPrivacyChanged(boolean);
+  }
+
+  public static class SensorPrivacyManager.Sensors {
+    field public static final int CAMERA = 2; // 0x2
+    field public static final int MICROPHONE = 1; // 0x1
   }
 
 }
@@ -911,17 +1032,19 @@
 package android.hardware.devicestate {
 
   public final class DeviceStateManager {
-    method public void addDeviceStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.devicestate.DeviceStateManager.DeviceStateListener);
     method @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE) public void cancelRequest(@NonNull android.hardware.devicestate.DeviceStateRequest);
     method @NonNull public int[] getSupportedStates();
-    method public void removeDeviceStateListener(@NonNull android.hardware.devicestate.DeviceStateManager.DeviceStateListener);
+    method public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.devicestate.DeviceStateManager.DeviceStateCallback);
     method @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE) public void requestState(@NonNull android.hardware.devicestate.DeviceStateRequest, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.devicestate.DeviceStateRequest.Callback);
+    method public void unregisterCallback(@NonNull android.hardware.devicestate.DeviceStateManager.DeviceStateCallback);
     field public static final int MAXIMUM_DEVICE_STATE = 255; // 0xff
     field public static final int MINIMUM_DEVICE_STATE = 0; // 0x0
   }
 
-  public static interface DeviceStateManager.DeviceStateListener {
-    method public void onDeviceStateChanged(int);
+  public static interface DeviceStateManager.DeviceStateCallback {
+    method public default void onBaseStateChanged(int);
+    method public void onStateChanged(int);
+    method public default void onSupportedStatesChanged(@NonNull int[]);
   }
 
   public final class DeviceStateRequest {
@@ -1000,14 +1123,6 @@
 
 }
 
-package android.hardware.lights {
-
-  public final class LightsManager {
-    method @NonNull @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public android.hardware.lights.LightState getLightState(@NonNull android.hardware.lights.Light);
-  }
-
-}
-
 package android.hardware.soundtrigger {
 
   public class KeyphraseEnrollmentInfo {
@@ -1484,8 +1599,15 @@
   }
 
   public class UserManager {
+    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo createProfileForUser(@Nullable String, @NonNull String, int, int, @Nullable String[]);
+    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo createRestrictedProfile(@Nullable String);
+    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo createUser(@Nullable String, @NonNull String, int);
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public String getUserType();
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public java.util.List<android.content.pm.UserInfo> getUsers(boolean, boolean, boolean);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean hasBaseUserRestriction(@NonNull String, @NonNull android.os.UserHandle);
+    method public static boolean isGuestUserEphemeral();
     method public static boolean isSplitSystemUser();
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo preCreateUser(@NonNull String) throws android.os.UserManager.UserOperationException;
   }
 
   public final class VibrationAttributes implements android.os.Parcelable {
@@ -1639,6 +1761,7 @@
   public class StorageManager {
     method @NonNull public static java.util.UUID convert(@NonNull String);
     method @NonNull public static String convert(@NonNull java.util.UUID);
+    method public static boolean isUserKeyUnlocked(int);
   }
 
   public final class StorageVolume implements android.os.Parcelable {
@@ -2464,6 +2587,9 @@
 package android.view.contentcapture {
 
   public final class ContentCaptureManager {
+    method @RequiresPermission(android.Manifest.permission.MANAGE_CONTENT_CAPTURE) public static void resetTemporaryService(int);
+    method @RequiresPermission(android.Manifest.permission.MANAGE_CONTENT_CAPTURE) public static void setDefaultServiceEnabled(int, boolean);
+    method @RequiresPermission(android.Manifest.permission.MANAGE_CONTENT_CAPTURE) public static void setTemporaryService(int, @NonNull String, int);
     field public static final String DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY = "idle_flush_frequency";
     field public static final String DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL = "logging_level";
     field public static final String DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE = "log_history_size";
diff --git a/core/api/test-lint-baseline.txt b/core/api/test-lint-baseline.txt
index 87fb5b1..a536efb 100644
--- a/core/api/test-lint-baseline.txt
+++ b/core/api/test-lint-baseline.txt
@@ -468,7 +468,7 @@
 GetterSetterNames: android.location.GnssMeasurement#setCarrierFrequencyHz(float):
     
 GetterSetterNames: android.location.GnssMeasurement#setCodeType(String):
-
+    
 GetterSetterNames: android.location.GnssMeasurement#setCorrelationVectors(java.util.Collection<android.location.CorrelationVector>):
     
 GetterSetterNames: android.location.GnssMeasurement#setFullInterSignalBiasNanos(double):
@@ -480,7 +480,7 @@
 GetterSetterNames: android.location.GnssMeasurement#setSatelliteInterSignalBiasUncertaintyNanos(double):
     
 GetterSetterNames: android.location.GnssMeasurement#setSatellitePvt(android.location.SatellitePvt):
-
+    
 GetterSetterNames: android.location.GnssMeasurement#setSnrInDb(double):
     
 GetterSetterNames: android.location.LocationRequest#isLocationSettingsIgnored():
@@ -953,6 +953,32 @@
     
 MissingNullability: android.content.pm.ShortcutManager#ShortcutManager(android.content.Context) parameter #0:
     
+MissingNullability: android.content.pm.UserInfo#UserInfo(android.content.pm.UserInfo) parameter #0:
+    Missing nullability on parameter `orig` in method `UserInfo`
+MissingNullability: android.content.pm.UserInfo#UserInfo(int, String, String, int) parameter #1:
+    Missing nullability on parameter `name` in method `UserInfo`
+MissingNullability: android.content.pm.UserInfo#UserInfo(int, String, String, int) parameter #2:
+    Missing nullability on parameter `iconPath` in method `UserInfo`
+MissingNullability: android.content.pm.UserInfo#UserInfo(int, String, String, int, String) parameter #1:
+    Missing nullability on parameter `name` in method `UserInfo`
+MissingNullability: android.content.pm.UserInfo#UserInfo(int, String, String, int, String) parameter #2:
+    Missing nullability on parameter `iconPath` in method `UserInfo`
+MissingNullability: android.content.pm.UserInfo#UserInfo(int, String, String, int, String) parameter #4:
+    Missing nullability on parameter `userType` in method `UserInfo`
+MissingNullability: android.content.pm.UserInfo#UserInfo(int, String, int) parameter #1:
+    Missing nullability on parameter `name` in method `UserInfo`
+MissingNullability: android.content.pm.UserInfo#getUserHandle():
+    Missing nullability on method `getUserHandle` return
+MissingNullability: android.content.pm.UserInfo#iconPath:
+    Missing nullability on field `iconPath` in class `class android.content.pm.UserInfo`
+MissingNullability: android.content.pm.UserInfo#lastLoggedInFingerprint:
+    Missing nullability on field `lastLoggedInFingerprint` in class `class android.content.pm.UserInfo`
+MissingNullability: android.content.pm.UserInfo#name:
+    Missing nullability on field `name` in class `class android.content.pm.UserInfo`
+MissingNullability: android.content.pm.UserInfo#userType:
+    Missing nullability on field `userType` in class `class android.content.pm.UserInfo`
+MissingNullability: android.content.pm.UserInfo#writeToParcel(android.os.Parcel, int) parameter #0:
+    Missing nullability on parameter `dest` in method `writeToParcel`
 MissingNullability: android.content.res.AssetManager#getOverlayablesToString(String) parameter #0:
     
 MissingNullability: android.content.res.Configuration#windowConfiguration:
@@ -2433,6 +2459,38 @@
     
 MutableBareField: android.content.AutofillOptions#whitelistedActivitiesForAugmentedAutofill:
     
+MutableBareField: android.content.pm.UserInfo#convertedFromPreCreated:
+    Bare field convertedFromPreCreated must be marked final, or moved behind accessors if mutable
+MutableBareField: android.content.pm.UserInfo#creationTime:
+    Bare field creationTime must be marked final, or moved behind accessors if mutable
+MutableBareField: android.content.pm.UserInfo#flags:
+    Bare field flags must be marked final, or moved behind accessors if mutable
+MutableBareField: android.content.pm.UserInfo#guestToRemove:
+    Bare field guestToRemove must be marked final, or moved behind accessors if mutable
+MutableBareField: android.content.pm.UserInfo#iconPath:
+    Bare field iconPath must be marked final, or moved behind accessors if mutable
+MutableBareField: android.content.pm.UserInfo#id:
+    Bare field id must be marked final, or moved behind accessors if mutable
+MutableBareField: android.content.pm.UserInfo#lastLoggedInFingerprint:
+    Bare field lastLoggedInFingerprint must be marked final, or moved behind accessors if mutable
+MutableBareField: android.content.pm.UserInfo#lastLoggedInTime:
+    Bare field lastLoggedInTime must be marked final, or moved behind accessors if mutable
+MutableBareField: android.content.pm.UserInfo#name:
+    Bare field name must be marked final, or moved behind accessors if mutable
+MutableBareField: android.content.pm.UserInfo#partial:
+    Bare field partial must be marked final, or moved behind accessors if mutable
+MutableBareField: android.content.pm.UserInfo#preCreated:
+    Bare field preCreated must be marked final, or moved behind accessors if mutable
+MutableBareField: android.content.pm.UserInfo#profileBadge:
+    Bare field profileBadge must be marked final, or moved behind accessors if mutable
+MutableBareField: android.content.pm.UserInfo#profileGroupId:
+    Bare field profileGroupId must be marked final, or moved behind accessors if mutable
+MutableBareField: android.content.pm.UserInfo#restrictedProfileParentId:
+    Bare field restrictedProfileParentId must be marked final, or moved behind accessors if mutable
+MutableBareField: android.content.pm.UserInfo#serialNumber:
+    Bare field serialNumber must be marked final, or moved behind accessors if mutable
+MutableBareField: android.content.pm.UserInfo#userType:
+    Bare field userType must be marked final, or moved behind accessors if mutable
 MutableBareField: android.database.sqlite.SQLiteDebug.DbStats#cache:
     
 MutableBareField: android.database.sqlite.SQLiteDebug.DbStats#dbName:
@@ -2548,15 +2606,15 @@
 NoSettingsProvider: android.provider.Settings.Global#USE_OPEN_WIFI_PACKAGE:
     
 NoSettingsProvider: android.provider.Settings.Secure#ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED:
-
+    
 NoSettingsProvider: android.provider.Settings.Secure#ACCESSIBILITY_MAGNIFICATION_CAPABILITY:
-
+    
 NoSettingsProvider: android.provider.Settings.Secure#ACCESSIBILITY_MAGNIFICATION_MODE:
-
+    
 NoSettingsProvider: android.provider.Settings.Secure#ACCESSIBILITY_MAGNIFICATION_MODE_ALL:
-
+    
 NoSettingsProvider: android.provider.Settings.Secure#ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN:
-
+    
 NoSettingsProvider: android.provider.Settings.Secure#ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW:
     
 NoSettingsProvider: android.provider.Settings.Secure#ACCESSIBILITY_SHORTCUT_TARGET_SERVICE:
@@ -2619,6 +2677,10 @@
     
 
 
+NullableCollection: android.os.UserManager#createProfileForUser(String, String, int, int, String[]) parameter #4:
+    Type of parameter disallowedPackages in android.os.UserManager.createProfileForUser(String name, String userType, int flags, int userId, String[] disallowedPackages) is a nullable collection (`java.lang.String[]`); must be non-null
+
+
 OnNameExpected: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.PrintWriter, String[]):
     
 OnNameExpected: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]):
@@ -2729,6 +2791,8 @@
 
 ParcelNotFinal: android.app.WindowConfiguration:
     
+ParcelNotFinal: android.content.pm.UserInfo:
+    Parcelable classes must be final: android.content.pm.UserInfo is not final
 ParcelNotFinal: android.net.metrics.IpConnectivityLog.Event:
     
 ParcelNotFinal: android.os.IncidentManager.IncidentReport:
diff --git a/core/java/Android.bp b/core/java/Android.bp
index af5df76..2fdf9c1 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -1,3 +1,14 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-BSD
+    //   legacy_unencumbered
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "IKeyAttestationApplicationIdProvider.aidl",
     srcs: ["android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl"],
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 3c668b2a..f5f0b42 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -156,6 +156,7 @@
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -802,6 +803,7 @@
     @UnsupportedAppUsage
     private IBinder mToken;
     private IBinder mAssistToken;
+    private IBinder mShareableActivityToken;
     @UnsupportedAppUsage
     private int mIdent;
     @UnsupportedAppUsage
@@ -1209,7 +1211,7 @@
                     if (window != null) {
                         cm.updateWindowAttributes(window.getAttributes());
                     }
-                    cm.onActivityCreated(mToken, getComponentName());
+                    cm.onActivityCreated(mToken, mShareableActivityToken, getComponentName());
                     break;
                 case CONTENT_CAPTURE_RESUME:
                     cm.onActivityResumed();
@@ -3811,6 +3813,22 @@
         return false;
     }
 
+    private static final class RequestFinishCallback extends IRequestFinishCallback.Stub {
+        private final WeakReference<Activity> mActivityRef;
+
+        RequestFinishCallback(WeakReference<Activity> activityRef) {
+            mActivityRef = activityRef;
+        }
+
+        @Override
+        public void requestFinish() {
+            Activity activity = mActivityRef.get();
+            if (activity != null) {
+                activity.mHandler.post(activity::finishAfterTransition);
+            }
+        }
+    }
+
     /**
      * Called when the activity has detected the user's press of the back
      * key.  The default implementation simply finishes the current activity,
@@ -3834,7 +3852,8 @@
         // Inform activity task manager that the activity received a back press while at the
         // root of the task. This call allows ActivityTaskManager to intercept or move the task
         // to the back.
-        ActivityClient.getInstance().onBackPressedOnTaskRoot(mToken);
+        ActivityClient.getInstance().onBackPressedOnTaskRoot(mToken,
+                new RequestFinishCallback(new WeakReference<>(this)));
 
         // Activity was launched when user tapped a link in the Autofill Save UI - Save UI must
         // be restored now.
@@ -7832,7 +7851,8 @@
             CharSequence title, Activity parent, String id,
             NonConfigurationInstances lastNonConfigurationInstances,
             Configuration config, String referrer, IVoiceInteractor voiceInteractor,
-            Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
+            Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken,
+            IBinder shareableActivityToken) {
         attachBaseContext(context);
 
         mFragments.attachHost(null /*parent*/);
@@ -7854,6 +7874,7 @@
         mInstrumentation = instr;
         mToken = token;
         mAssistToken = assistToken;
+        mShareableActivityToken = shareableActivityToken;
         mIdent = ident;
         mApplication = application;
         mIntent = intent;
@@ -7912,6 +7933,11 @@
     }
 
     /** @hide */
+    public final IBinder getShareableActivityToken() {
+        return mParent != null ? mParent.getShareableActivityToken() : mShareableActivityToken;
+    }
+
+    /** @hide */
     @VisibleForTesting
     public final ActivityThread getActivityThread() {
         return mMainThread;
diff --git a/core/java/android/app/ActivityClient.java b/core/java/android/app/ActivityClient.java
index e3b5e9a..fbabfac 100644
--- a/core/java/android/app/ActivityClient.java
+++ b/core/java/android/app/ActivityClient.java
@@ -480,9 +480,9 @@
         }
     }
 
-    void onBackPressedOnTaskRoot(IBinder token) {
+    void onBackPressedOnTaskRoot(IBinder token, IRequestFinishCallback callback) {
         try {
-            getActivityClientController().onBackPressedOnTaskRoot(token);
+            getActivityClientController().onBackPressedOnTaskRoot(token, callback);
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/app/ActivityManager.aidl b/core/java/android/app/ActivityManager.aidl
index 341393c..eb7cac07 100644
--- a/core/java/android/app/ActivityManager.aidl
+++ b/core/java/android/app/ActivityManager.aidl
@@ -17,6 +17,7 @@
 package android.app;
 
 parcelable ActivityManager.MemoryInfo;
+parcelable ActivityManager.PendingIntentInfo;
 parcelable ActivityManager.ProcessErrorStateInfo;
 parcelable ActivityManager.RecentTaskInfo;
 parcelable ActivityManager.TaskDescription;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index e2426d1..f905ec8 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -511,6 +511,7 @@
     /** @hide Process is hosting the current top activities.  Note that this covers
      * all activities that are visible to the user. */
     @UnsupportedAppUsage
+    @TestApi
     public static final int PROCESS_STATE_TOP = ProcessStateEnum.TOP;
 
     /** @hide Process is bound to a TOP app. */
@@ -518,6 +519,7 @@
 
     /** @hide Process is hosting a foreground service. */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+    @TestApi
     public static final int PROCESS_STATE_FOREGROUND_SERVICE = ProcessStateEnum.FOREGROUND_SERVICE;
 
     /** @hide Process is hosting a foreground service due to a system binding. */
@@ -616,11 +618,16 @@
     @TestApi
     public static final int PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 1 << 2;
 
+    /** @hide Process can access network despite any power saving resrictions */
+    @TestApi
+    public static final int PROCESS_CAPABILITY_NETWORK = 1 << 3;
+
     /** @hide all capabilities, the ORing of all flags in {@link ProcessCapability}*/
     @TestApi
     public static final int PROCESS_CAPABILITY_ALL = PROCESS_CAPABILITY_FOREGROUND_LOCATION
             | PROCESS_CAPABILITY_FOREGROUND_CAMERA
-            | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
+            | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
+            | PROCESS_CAPABILITY_NETWORK;
     /**
      * All explicit capabilities. These are capabilities that need to be specified from manifest
      * file.
@@ -646,6 +653,15 @@
         pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0 ? 'L' : '-');
         pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0 ? 'C' : '-');
         pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0 ? 'M' : '-');
+        pw.print((caps & PROCESS_CAPABILITY_NETWORK) != 0 ? 'N' : '-');
+    }
+
+    /** @hide */
+    public static void printCapabilitiesSummary(StringBuilder sb, @ProcessCapability int caps) {
+        sb.append((caps & PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0 ? 'L' : '-');
+        sb.append((caps & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0 ? 'C' : '-');
+        sb.append((caps & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0 ? 'M' : '-');
+        sb.append((caps & PROCESS_CAPABILITY_NETWORK) != 0 ? 'N' : '-');
     }
 
     /**
@@ -656,13 +672,21 @@
         printCapabilitiesSummary(pw, caps);
         final int remain = caps & ~(PROCESS_CAPABILITY_FOREGROUND_LOCATION
                 | PROCESS_CAPABILITY_FOREGROUND_CAMERA
-                | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE);
+                | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
+                | PROCESS_CAPABILITY_NETWORK);
         if (remain != 0) {
             pw.print('+');
             pw.print(remain);
         }
     }
 
+    /** @hide */
+    public static String getCapabilitiesSummary(@ProcessCapability int caps) {
+        final StringBuilder sb = new StringBuilder();
+        printCapabilitiesSummary(sb, caps);
+        return sb.toString();
+    }
+
     // NOTE: If PROCESS_STATEs are added, then new fields must be added
     // to frameworks/base/core/proto/android/app/enums.proto and the following method must
     // be updated to correctly map between them.
@@ -3411,6 +3435,36 @@
     }
 
     /**
+     * Returns the process state of this uid.
+     *
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
+    public int getUidProcessState(int uid) {
+        try {
+            return getService().getUidProcessState(uid, mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns the process capability of this uid.
+     *
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
+    public @ProcessCapability int getUidProcessCapabilities(int uid) {
+        try {
+            return getService().getUidProcessCapabilities(uid, mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Return the importance of a given package name, based on the processes that are
      * currently running.  The return value is one of the importance constants defined
      * in {@link RunningAppProcessInfo}, giving you the highest importance of all the
@@ -4485,6 +4539,80 @@
         }
     }
 
+    /** @hide */
+    public static String procStateToString(int procState) {
+        final String procStateStr;
+        switch (procState) {
+            case ActivityManager.PROCESS_STATE_PERSISTENT:
+                procStateStr = "PER ";
+                break;
+            case ActivityManager.PROCESS_STATE_PERSISTENT_UI:
+                procStateStr = "PERU";
+                break;
+            case ActivityManager.PROCESS_STATE_TOP:
+                procStateStr = "TOP ";
+                break;
+            case ActivityManager.PROCESS_STATE_BOUND_TOP:
+                procStateStr = "BTOP";
+                break;
+            case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE:
+                procStateStr = "FGS ";
+                break;
+            case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
+                procStateStr = "BFGS";
+                break;
+            case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND:
+                procStateStr = "IMPF";
+                break;
+            case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND:
+                procStateStr = "IMPB";
+                break;
+            case ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND:
+                procStateStr = "TRNB";
+                break;
+            case ActivityManager.PROCESS_STATE_BACKUP:
+                procStateStr = "BKUP";
+                break;
+            case ActivityManager.PROCESS_STATE_SERVICE:
+                procStateStr = "SVC ";
+                break;
+            case ActivityManager.PROCESS_STATE_RECEIVER:
+                procStateStr = "RCVR";
+                break;
+            case ActivityManager.PROCESS_STATE_TOP_SLEEPING:
+                procStateStr = "TPSL";
+                break;
+            case ActivityManager.PROCESS_STATE_HEAVY_WEIGHT:
+                procStateStr = "HVY ";
+                break;
+            case ActivityManager.PROCESS_STATE_HOME:
+                procStateStr = "HOME";
+                break;
+            case ActivityManager.PROCESS_STATE_LAST_ACTIVITY:
+                procStateStr = "LAST";
+                break;
+            case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
+                procStateStr = "CAC ";
+                break;
+            case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
+                procStateStr = "CACC";
+                break;
+            case ActivityManager.PROCESS_STATE_CACHED_RECENT:
+                procStateStr = "CRE ";
+                break;
+            case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
+                procStateStr = "CEM ";
+                break;
+            case ActivityManager.PROCESS_STATE_NONEXISTENT:
+                procStateStr = "NONE";
+                break;
+            default:
+                procStateStr = "??";
+                break;
+        }
+        return procStateStr;
+    }
+
     /**
      * The AppTask allows you to manage your own application's tasks.
      * See {@link android.app.ActivityManager#getAppTasks()}
@@ -4681,4 +4809,71 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * A subset of immutable pending intent information suitable for caching on the client side.
+     *
+     * @hide
+     */
+    public static final class PendingIntentInfo implements Parcelable {
+
+        private final String mCreatorPackage;
+        private final int mCreatorUid;
+        private final boolean mImmutable;
+        private final int mIntentSenderType;
+
+        public PendingIntentInfo(String creatorPackage, int creatorUid, boolean immutable,
+                int intentSenderType) {
+            mCreatorPackage = creatorPackage;
+            mCreatorUid = creatorUid;
+            mImmutable = immutable;
+            mIntentSenderType = intentSenderType;
+        }
+
+        public String getCreatorPackage() {
+            return mCreatorPackage;
+        }
+
+        public int getCreatorUid() {
+            return mCreatorUid;
+        }
+
+        public boolean isImmutable() {
+            return mImmutable;
+        }
+
+        public int getIntentSenderType() {
+            return mIntentSenderType;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(@NonNull Parcel parcel, int flags) {
+            parcel.writeString(mCreatorPackage);
+            parcel.writeInt(mCreatorUid);
+            parcel.writeBoolean(mImmutable);
+            parcel.writeInt(mIntentSenderType);
+        }
+
+        public static final @NonNull Creator<PendingIntentInfo> CREATOR =
+                new Creator<PendingIntentInfo>() {
+                    @Override
+                    public PendingIntentInfo createFromParcel(Parcel in) {
+                        return new PendingIntentInfo(
+                                /* creatorPackage= */ in.readString(),
+                                /* creatorUid= */ in.readInt(),
+                                /* immutable= */ in.readBoolean(),
+                                /* intentSenderType= */ in.readInt());
+                    }
+
+                    @Override
+                    public PendingIntentInfo[] newArray(int size) {
+                        return new PendingIntentInfo[size];
+                    }
+                };
+    }
 }
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index c31c22c..c812e8e 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -30,6 +30,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.PowerWhitelistManager.ReasonCode;
 import android.os.PowerWhitelistManager.TempAllowListType;
 import android.os.TransactionTooLargeException;
 import android.os.WorkSource;
@@ -102,12 +103,15 @@
      * Sets how long a {@link PendingIntent} can be temporarily allowlisted to bypass restrictions
      * such as Power Save mode.
      * @param target
-     * @param whitelistToken
+     * @param allowlistToken
      * @param duration temp allowlist duration in milliseconds.
      * @param type temp allowlist type defined at {@link TempAllowListType}
+     * @param reasonCode one of {@link ReasonCode}
+     * @param reason A human-readable reason for logging purposes.
      */
-    public abstract void setPendingIntentWhitelistDuration(IIntentSender target,
-            IBinder whitelistToken, long duration, int type);
+    public abstract void setPendingIntentAllowlistDuration(IIntentSender target,
+            IBinder allowlistToken, long duration, @TempAllowListType int type,
+            @ReasonCode int reasonCode, @Nullable String reason);
 
     /**
      * Returns the flags set for a {@link PendingIntent}.
@@ -127,20 +131,26 @@
             IBinder allowlistToken);
 
     /**
-     * Allow DeviceIdleController to tell us about what apps are whitelisted.
+     * Allow DeviceIdleController to tell us about what apps are allowlisted.
      */
-    public abstract void setDeviceIdleWhitelist(int[] allAppids, int[] exceptIdleAppids);
+    public abstract void setDeviceIdleAllowlist(int[] allAppids, int[] exceptIdleAppids);
 
     /**
-     * Update information about which app IDs are on the temp whitelist.
+     * Update information about which app IDs are on the temp allowlist.
      * @param appids the updated list of appIds in temp allowlist.
      * @param changingUid uid to add or remove to temp allowlist.
      * @param adding true to add to temp allowlist, false to remove from temp allowlist.
      * @param durationMs when adding is true, the duration to be in temp allowlist.
      * @param type temp allowlist type defined at {@link TempAllowListType}.
+     * @param reasonCode one of {@link ReasonCode}
+     * @param reason A human-readable reason for logging purposes.
+     * @param callingUid the callingUid that setup this temp allowlist, only valid when param adding
+     *                   is true.
      */
-    public abstract void updateDeviceIdleTempWhitelist(int[] appids, int changingUid,
-            boolean adding, long durationMs, @TempAllowListType int type);
+    public abstract void updateDeviceIdleTempAllowlist(int[] appids, int changingUid,
+            boolean adding, long durationMs, @TempAllowListType int type,
+            @ReasonCode int reasonCode,
+            @Nullable String reason, int callingUid);
 
     /**
      * Get the procstate for the UID.  The return value will be between
@@ -335,10 +345,11 @@
      * @param targetUid the UID that is been temp allowlisted.
      * @param duration temp allowlist duration in milliseconds.
      * @param type temp allowlist type defined at {@link TempAllowListType}
-     * @param tag
+     * @param reasonCode one of {@link ReasonCode}
+     * @param reason
      */
-    public abstract void tempWhitelistForPendingIntent(int callerPid, int callerUid, int targetUid,
-            long duration, int type, String tag);
+    public abstract void tempAllowlistForPendingIntent(int callerPid, int callerUid, int targetUid,
+            long duration, int type, @ReasonCode int reasonCode, String reason);
 
     public abstract int broadcastIntentInPackage(String packageName, @Nullable String featureId,
             int uid, int realCallingUid, int realCallingPid, Intent intent, String resolvedType,
@@ -495,9 +506,9 @@
 
     /**
      * Sends a broadcast, assuming the caller to be the system and allowing the inclusion of an
-     * approved whitelist of app Ids >= {@link android.os.Process#FIRST_APPLICATION_UID} that the
+     * approved allowlist of app Ids >= {@link android.os.Process#FIRST_APPLICATION_UID} that the
      * broadcast my be sent to; any app Ids < {@link android.os.Process#FIRST_APPLICATION_UID} are
-     * automatically whitelisted.
+     * automatically allowlisted.
      *
      * @see com.android.server.am.ActivityManagerService#broadcastIntentWithFeature(
      *      IApplicationThread, String, Intent, String, IIntentReceiver, int, String, Bundle,
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 73cc13c8..a1dce77 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -320,6 +320,10 @@
     private static final String KEY_OVERRIDE_TASK_TRANSITION =
             "android:activity.overrideTaskTransition";
 
+    /** See {@link #setRemoveWithTaskOrganizer(boolean)}. */
+    private static final String KEY_REMOVE_WITH_TASK_ORGANIZER =
+            "android.activity.removeWithTaskOrganizer";
+
     /**
      * @see #setLaunchCookie
      * @hide
@@ -405,6 +409,7 @@
     private IRemoteTransition mRemoteTransition;
     private boolean mOverrideTaskTransition;
     private int mSplashScreenThemeResId;
+    private boolean mRemoveWithTaskOrganizer;
 
     /**
      * Create an ActivityOptions specifying a custom animation to run when
@@ -1155,6 +1160,7 @@
                 KEY_REMOTE_TRANSITION));
         mOverrideTaskTransition = opts.getBoolean(KEY_OVERRIDE_TASK_TRANSITION);
         mSplashScreenThemeResId = opts.getInt(KEY_SPLASH_SCREEN_THEME);
+        mRemoveWithTaskOrganizer = opts.getBoolean(KEY_REMOVE_WITH_TASK_ORGANIZER);
     }
 
     /**
@@ -1624,6 +1630,22 @@
     }
 
     /**
+     * Sets whether to remove the task when TaskOrganizer, which is managing it, is destroyed.
+     * @hide
+     */
+    public void setRemoveWithTaskOrganizer(boolean remove) {
+        mRemoveWithTaskOrganizer = remove;
+    }
+
+    /**
+     * @return whether to remove the task when TaskOrganizer, which is managing it, is destroyed.
+     * @hide
+     */
+    public boolean getRemoveWithTaskOranizer() {
+        return mRemoveWithTaskOrganizer;
+    }
+
+    /**
      * Update the current values in this ActivityOptions from those supplied
      * in <var>otherOptions</var>.  Any values
      * defined in <var>otherOptions</var> replace those in the base options.
@@ -1857,6 +1879,9 @@
         if (mSplashScreenThemeResId != 0) {
             b.putInt(KEY_SPLASH_SCREEN_THEME, mSplashScreenThemeResId);
         }
+        if (mRemoveWithTaskOrganizer) {
+            b.putBoolean(KEY_REMOVE_WITH_TASK_ORGANIZER, mRemoveWithTaskOrganizer);
+        }
         return b;
     }
 
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3d9f612..730fce9 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -517,6 +517,9 @@
         @UnsupportedAppUsage
         public IBinder token;
         public IBinder assistToken;
+        // A reusable token for other purposes, e.g. content capture, translation. It shouldn't be
+        // used without security checks
+        public IBinder shareableActivityToken;
         int ident;
         @UnsupportedAppUsage
         Intent intent;
@@ -604,9 +607,11 @@
                 PersistableBundle persistentState, List<ResultInfo> pendingResults,
                 List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions,
                 boolean isForward, ProfilerInfo profilerInfo, ClientTransactionHandler client,
-                IBinder assistToken, FixedRotationAdjustments fixedRotationAdjustments) {
+                IBinder assistToken, FixedRotationAdjustments fixedRotationAdjustments,
+                IBinder shareableActivityToken) {
             this.token = token;
             this.assistToken = assistToken;
+            this.shareableActivityToken = shareableActivityToken;
             this.ident = ident;
             this.intent = intent;
             this.referrer = referrer;
@@ -3157,11 +3162,13 @@
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public final Activity startActivityNow(Activity parent, String id,
-        Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
-        Activity.NonConfigurationInstances lastNonConfigurationInstances, IBinder assistToken) {
+            Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
+            Activity.NonConfigurationInstances lastNonConfigurationInstances, IBinder assistToken,
+            IBinder shareableActivityToken) {
         ActivityClientRecord r = new ActivityClientRecord();
             r.token = token;
             r.assistToken = assistToken;
+            r.shareableActivityToken = shareableActivityToken;
             r.ident = 0;
             r.intent = intent;
             r.state = state;
@@ -3504,7 +3511,7 @@
                         r.ident, app, r.intent, r.activityInfo, title, r.parent,
                         r.embeddedID, r.lastNonConfigurationInstances, config,
                         r.referrer, r.voiceInteractor, window, r.configCallback,
-                        r.assistToken);
+                        r.assistToken, r.shareableActivityToken);
 
                 if (customIntent != null) {
                     activity.mIntent = customIntent;
@@ -5141,7 +5148,7 @@
     private void onCoreSettingsChange() {
         if (updateDebugViewAttributeState()) {
             // request all activities to relaunch for the changes to take place
-            relaunchAllActivities(false /* preserveWindows */);
+            relaunchAllActivities(false /* preserveWindows */, "onCoreSettingsChange");
         }
     }
 
@@ -5160,7 +5167,8 @@
         return previousState != View.sDebugViewAttributes;
     }
 
-    private void relaunchAllActivities(boolean preserveWindows) {
+    private void relaunchAllActivities(boolean preserveWindows, String reason) {
+        Log.i(TAG, "Relaunch all activities: " + reason);
         for (int i = mActivities.size() - 1; i >= 0; i--) {
             scheduleRelaunchActivityIfPossible(mActivities.valueAt(i), preserveWindows);
         }
@@ -5535,6 +5543,7 @@
     void scheduleRelaunchActivity(IBinder token) {
         final ActivityClientRecord r = mActivities.get(token);
         if (r != null) {
+            Log.i(TAG, "Schedule relaunch activity: " + r.activityInfo.name);
             scheduleRelaunchActivityIfPossible(r, !r.stopped /* preserveWindow */);
         }
     }
@@ -6079,7 +6088,7 @@
         handleConfigurationChanged(newConfig, null);
 
         // Preserve windows to avoid black flickers when overlays change.
-        relaunchAllActivities(true /* preserveWindows */);
+        relaunchAllActivities(true /* preserveWindows */, "handleApplicationInfoChanged");
     }
 
     static void freeTextLayoutCachesIfNeeded(int configDiff) {
diff --git a/core/java/android/app/AnrController.java b/core/java/android/app/AnrController.java
index cfc9d27..a0d4b3a 100644
--- a/core/java/android/app/AnrController.java
+++ b/core/java/android/app/AnrController.java
@@ -23,7 +23,29 @@
 public interface AnrController {
     /**
      * Returns the delay in milliseconds for an ANR dialog that is about to be shown for
-     * {@code packageName}.
+     * {@code packageName} with {@code uid}.
+     *
+     * Implementations should only return a positive value if they actually expect the
+     * {@code packageName} to be delayed due to them.
+
+     * If there are multiple controllers registered, the controller with the max delay will
+     * be selected and will receive an {@link #onAnrDelayStarted} callback at the start of the
+     * delay and an {@link #onAnrDelayCompleted} at the end of the delay.
      */
     long getAnrDelayMillis(String packageName, int uid);
+
+    /**
+     * Notifies the controller at the start of the ANR dialog delay for {@code packageName} with
+     * {@code uid}. The controller can decide to show a progress UI after this notification.
+     */
+    void onAnrDelayStarted(String packageName, int uid);
+
+    /**
+     * Notifies the controller at the end of the ANR dialog delay for {@code packageName} with
+     * {@code uid}.
+     *
+     * @return whether the ANR dialog should be shown or cancelled. {@code true} if the
+     * ANR dialog should be shown, {@code false} if it should be cancelled.
+     */
+    boolean onAnrDelayCompleted(String packageName, int uid);
 }
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index b85b186..160844a 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -795,7 +795,8 @@
     // when adding one of these:
     //  - increment _NUM_OP
     //  - define an OPSTR_* constant (marked as @SystemApi)
-    //  - add rows to sOpToSwitch, sOpToString, sOpNames, sOpToPerms, sOpDefault
+    //  - add rows to sOpToSwitch, sOpToString, sOpNames, sOpPerms, sOpDefaultMode, sOpDisableReset,
+    //      sOpRestrictions, sOpAllowSystemRestrictionBypass
     //  - add descriptive strings to Settings/res/values/arrays.xml
     //  - add the op to the appropriate template in AppOpsState.OpsTemplate (settings app)
 
@@ -1140,23 +1141,20 @@
      *
      * @hide
      */
-    // TODO: Add as AppProtoEnums
-    public static final int OP_PHONE_CALL_MICROPHONE = 100;
+    public static final int OP_PHONE_CALL_MICROPHONE = AppProtoEnums.APP_OP_PHONE_CALL_MICROPHONE;
     /**
      * Phone call is using camera
      *
      * @hide
      */
-    // TODO: Add as AppProtoEnums
-    public static final int OP_PHONE_CALL_CAMERA = 101;
+    public static final int OP_PHONE_CALL_CAMERA = AppProtoEnums.APP_OP_PHONE_CALL_CAMERA;
 
     /**
      * Audio is being recorded for hotword detection.
      *
      * @hide
      */
-    // TODO: Add as AppProtoEnums
-    public static final int OP_RECORD_AUDIO_HOTWORD = 102;
+    public static final int OP_RECORD_AUDIO_HOTWORD = AppProtoEnums.APP_OP_RECORD_AUDIO_HOTWORD;
 
     /**
      * Manage credentials in the system KeyChain.
@@ -1174,13 +1172,38 @@
      *
      * @hide
      */
-    // TODO: Add as AppProtoEnums
-    public static final int OP_RECORD_AUDIO_OUTPUT = 106;
+    public static final int OP_RECORD_AUDIO_OUTPUT = AppProtoEnums.APP_OP_RECORD_AUDIO_OUTPUT;
 
+    /**
+     * App can schedule exact alarm to perform timing based background work
+     *
+     * @hide
+     */
+    public static final int OP_SCHEDULE_EXACT_ALARM = AppProtoEnums.APP_OP_SCHEDULE_EXACT_ALARM;
+
+    /**
+     * Fine location being accessed by a location source, which is
+     * a component that already has location data since it is the one
+     * that produces location, which is it is a data source for
+     * location data.
+     *
+     * @hide
+     */
+    public static final int OP_FINE_LOCATION_SOURCE = AppProtoEnums.APP_OP_FINE_LOCATION_SOURCE;
+
+    /**
+     * Coarse location being accessed by a location source, which is
+     * a component that already has location data since it is the one
+     * that produces location, which is it is a data source for
+     * location data.
+     *
+     * @hide
+     */
+    public static final int OP_COARSE_LOCATION_SOURCE = AppProtoEnums.APP_OP_COARSE_LOCATION_SOURCE;
 
     /** @hide */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public static final int _NUM_OP = 107;
+    public static final int _NUM_OP = 110;
 
     /** Access to coarse location information. */
     public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1553,6 +1576,31 @@
      */
     public static final String OPSTR_RECORD_AUDIO_OUTPUT = "android:record_audio_output";
 
+    /**
+     * App can schedule exact alarm to perform timing based background work.
+     *
+     * @hide
+     */
+    public static final String OPSTR_SCHEDULE_EXACT_ALARM = "android:schedule_exact_alarm";
+
+    /**
+     * Fine location being accessed by a location source, which is
+     * a component that already has location since it is the one that
+     * produces location.
+     *
+     * @hide
+     */
+    public static final String OPSTR_FINE_LOCATION_SOURCE = "android:fine_location_source";
+
+    /**
+     * Coarse location being accessed by a location source, which is
+     * a component that already has location since it is the one that
+     * produces location.
+     *
+     * @hide
+     */
+    public static final String OPSTR_COARSE_LOCATION_SOURCE = "android:coarse_location_source";
+
     /** {@link #sAppOpsToNote} not initialized yet for this op */
     private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
     /** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
@@ -1633,6 +1681,7 @@
             OP_LOADER_USAGE_STATS,
             OP_MANAGE_ONGOING_CALLS,
             OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
+            OP_SCHEDULE_EXACT_ALARM,
     };
 
     /**
@@ -1751,6 +1800,9 @@
             OP_MANAGE_CREDENTIALS,              // MANAGE_CREDENTIALS
             OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
             OP_RECORD_AUDIO_OUTPUT,             // RECORD_AUDIO_OUTPUT
+            OP_SCHEDULE_EXACT_ALARM,            // SCHEDULE_EXACT_ALARM
+            OP_FINE_LOCATION,                   // OP_FINE_LOCATION_SOURCE
+            OP_COARSE_LOCATION,                 // OP_COARSE_LOCATION_SOURCE
     };
 
     /**
@@ -1864,6 +1916,9 @@
             OPSTR_MANAGE_CREDENTIALS,
             OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
             OPSTR_RECORD_AUDIO_OUTPUT,
+            OPSTR_SCHEDULE_EXACT_ALARM,
+            OPSTR_FINE_LOCATION_SOURCE,
+            OPSTR_COARSE_LOCATION_SOURCE,
     };
 
     /**
@@ -1978,6 +2033,9 @@
             "MANAGE_CREDENTIALS",
             "USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER",
             "RECORD_AUDIO_OUTPUT",
+            "SCHEDULE_EXACT_ALARM",
+            "FINE_LOCATION_SOURCE",
+            "COARSE_LOCATION_SOURCE",
     };
 
     /**
@@ -2093,6 +2151,9 @@
             null, // no permission for OP_MANAGE_CREDENTIALS
             Manifest.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
             null, // no permission for OP_RECORD_AUDIO_OUTPUT
+            Manifest.permission.SCHEDULE_EXACT_ALARM,
+            null, // no permission for OP_ACCESS_FINE_LOCATION_SOURCE,
+            null, // no permission for OP_ACCESS_COARSE_LOCATION_SOURCE,
     };
 
     /**
@@ -2208,6 +2269,9 @@
             null, // MANAGE_CREDENTIALS
             null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
             null, // RECORD_AUDIO_OUTPUT
+            null, // SCHEDULE_EXACT_ALARM
+            null, // ACCESS_FINE_LOCATION_SOURCE
+            null, // ACCESS_COARSE_LOCATION_SOURCE
     };
 
     /**
@@ -2322,6 +2386,9 @@
             null, // MANAGE_CREDENTIALS
             null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
             null, // RECORD_AUDIO_OUTPUT
+            null, // SCHEDULE_EXACT_ALARM
+            null, // ACCESS_FINE_LOCATION_SOURCE
+            null, // ACCESS_COARSE_LOCATION_SOURCE
     };
 
     /**
@@ -2435,6 +2502,9 @@
             AppOpsManager.MODE_DEFAULT, // MANAGE_CREDENTIALS
             AppOpsManager.MODE_DEFAULT, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
             AppOpsManager.MODE_ALLOWED, // RECORD_AUDIO_OUTPUT
+            AppOpsManager.MODE_DEFAULT, // SCHEDULE_EXACT_ALARM
+            AppOpsManager.MODE_ALLOWED, // ACCESS_FINE_LOCATION_SOURCE
+            AppOpsManager.MODE_ALLOWED, // ACCESS_COARSE_LOCATION_SOURCE
     };
 
     /**
@@ -2529,9 +2599,9 @@
             false, // READ_MEDIA_AUDIO
             false, // WRITE_MEDIA_AUDIO
             false, // READ_MEDIA_VIDEO
-            false, // WRITE_MEDIA_VIDEO
+            true,  // WRITE_MEDIA_VIDEO
             false, // READ_MEDIA_IMAGES
-            false, // WRITE_MEDIA_IMAGES
+            true,  // WRITE_MEDIA_IMAGES
             true,  // LEGACY_STORAGE
             false, // ACCESS_ACCESSIBILITY
             false, // READ_DEVICE_IDENTIFIERS
@@ -2552,6 +2622,9 @@
             false, // MANAGE_CREDENTIALS
             true, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
             false, // RECORD_AUDIO_OUTPUT
+            false, // SCHEDULE_EXACT_ALARM
+            false, // ACCESS_FINE_LOCATION_SOURCE
+            false, // ACCESS_COARSE_LOCATION_SOURCE
     };
 
     /**
@@ -6530,14 +6603,15 @@
     public interface OnOpNotedListener {
         /**
          * Called when an op was noted.
-         *
          * @param code The op code.
          * @param uid The UID performing the operation.
          * @param packageName The package performing the operation.
+         * @param attributionTag The attribution tag performing the operation.
          * @param flags The flags of this op
          * @param result The result of the note.
          */
-        void onOpNoted(int code, int uid, String packageName, @OpFlags int flags, @Mode int result);
+        void onOpNoted(int code, int uid, String packageName, String attributionTag,
+                @OpFlags int flags, @Mode int result);
     }
 
     /**
@@ -6570,14 +6644,15 @@
          * Called when an op was started.
          *
          * Note: This is only for op starts. It is not called when an op is noted or stopped.
-         *
          * @param op The op code.
          * @param uid The UID performing the operation.
          * @param packageName The package performing the operation.
+         * @param attributionTag The attribution tag performing the operation.
          * @param flags The flags of this op
          * @param result The result of the start.
          */
-        void onOpStarted(int op, int uid, String packageName, @OpFlags int flags, @Mode int result);
+        void onOpStarted(int op, int uid, String packageName, String attributionTag,
+                @OpFlags int flags, @Mode int result);
     }
 
     AppOpsManager(Context context, IAppOpsService service) {
@@ -7160,8 +7235,9 @@
              }
              cb = new IAppOpsStartedCallback.Stub() {
                  @Override
-                 public void opStarted(int op, int uid, String packageName, int flags, int mode) {
-                     callback.onOpStarted(op, uid, packageName, flags, mode);
+                 public void opStarted(int op, int uid, String packageName, String attributionTag,
+                         int flags, int mode) {
+                     callback.onOpStarted(op, uid, packageName, attributionTag, flags, mode);
                  }
              };
              mStartedWatchers.put(callback, cb);
@@ -7227,8 +7303,9 @@
             }
             cb = new IAppOpsNotedCallback.Stub() {
                 @Override
-                public void opNoted(int op, int uid, String packageName, int flags, int mode) {
-                    callback.onOpNoted(op, uid, packageName, flags, mode);
+                public void opNoted(int op, int uid, String packageName, String attributionTag,
+                        int flags, int mode) {
+                    callback.onOpNoted(op, uid, packageName, attributionTag, flags, mode);
                 }
             };
             mNotedWatchers.put(callback, cb);
diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java
index 7410a1c..dfc105a 100644
--- a/core/java/android/app/ApplicationExitInfo.java
+++ b/core/java/android/app/ApplicationExitInfo.java
@@ -428,6 +428,13 @@
      */
     private IAppTraceRetriever mAppTraceRetriever;
 
+    /**
+     * ParcelFileDescriptor pointing to a native tombstone.
+     *
+     * @see #getTraceInputStream
+     */
+    private IParcelFileDescriptorRetriever mNativeTombstoneRetriever;
+
     /** @hide */
     @IntDef(prefix = { "REASON_" }, value = {
         REASON_UNKNOWN,
@@ -603,22 +610,38 @@
      * prior to the death of the process; typically it'll be available when
      * the reason is {@link #REASON_ANR}, though if the process gets an ANR
      * but recovers, and dies for another reason later, this trace will be included
-     * in the record of {@link ApplicationExitInfo} still.
+     * in the record of {@link ApplicationExitInfo} still. Beginning with API 31,
+     * tombstone traces will be returned for
+     * {@link #REASON_CRASH_NATIVE}, with an InputStream containing a protobuf with
+     * <a href="https://android.googlesource.com/platform/system/core/+/refs/heads/master/debuggerd/proto/tombstone.proto">this schema</a>.
+     * Note thatbecause these traces are kept in a separate global circular buffer, crashes may be
+     * overwritten by newer crashes (including from other applications), so this may still return
+     * null.
      *
      * @return The input stream to the traces that was taken by the system
      *         prior to the death of the process.
      */
     public @Nullable InputStream getTraceInputStream() throws IOException {
-        if (mAppTraceRetriever == null) {
+        if (mAppTraceRetriever == null && mNativeTombstoneRetriever == null) {
             return null;
         }
+
         try {
-            final ParcelFileDescriptor fd = mAppTraceRetriever.getTraceFileDescriptor(
-                    mPackageName, mPackageUid, mPid);
-            if (fd == null) {
-                return null;
+            if (mNativeTombstoneRetriever != null) {
+                final ParcelFileDescriptor pfd = mNativeTombstoneRetriever.getPfd();
+                if (pfd == null) {
+                    return null;
+                }
+
+                return new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+            } else {
+                final ParcelFileDescriptor fd = mAppTraceRetriever.getTraceFileDescriptor(
+                        mPackageName, mPackageUid, mPid);
+                if (fd == null) {
+                    return null;
+                }
+                return new GZIPInputStream(new ParcelFileDescriptor.AutoCloseInputStream(fd));
             }
-            return new GZIPInputStream(new ParcelFileDescriptor.AutoCloseInputStream(fd));
         } catch (RemoteException e) {
             return null;
         }
@@ -849,6 +872,15 @@
         mAppTraceRetriever = retriever;
     }
 
+    /**
+     * @see mNativeTombstoneRetriever
+     *
+     * @hide
+     */
+    public void setNativeTombstoneRetriever(final IParcelFileDescriptorRetriever retriever) {
+        mNativeTombstoneRetriever = retriever;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -878,6 +910,12 @@
         } else {
             dest.writeInt(0);
         }
+        if (mNativeTombstoneRetriever != null) {
+            dest.writeInt(1);
+            dest.writeStrongBinder(mNativeTombstoneRetriever.asBinder());
+        } else {
+            dest.writeInt(0);
+        }
     }
 
     /** @hide */
@@ -906,6 +944,7 @@
         mState = other.mState;
         mTraceFile = other.mTraceFile;
         mAppTraceRetriever = other.mAppTraceRetriever;
+        mNativeTombstoneRetriever = other.mNativeTombstoneRetriever;
     }
 
     private ApplicationExitInfo(@NonNull Parcel in) {
@@ -928,6 +967,10 @@
         if (in.readInt() == 1) {
             mAppTraceRetriever = IAppTraceRetriever.Stub.asInterface(in.readStrongBinder());
         }
+        if (in.readInt() == 1) {
+            mNativeTombstoneRetriever = IParcelFileDescriptorRetriever.Stub.asInterface(
+                    in.readStrongBinder());
+        }
     }
 
     public @NonNull static final Creator<ApplicationExitInfo> CREATOR =
@@ -986,6 +1029,7 @@
         sb.append(" state=").append(ArrayUtils.isEmpty(mState)
                 ? "empty" : Integer.toString(mState.length) + " bytes");
         sb.append(" trace=").append(mTraceFile);
+
         return sb.toString();
     }
 
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 062cab4..a6260d6 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1797,6 +1797,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     protected ApplicationPackageManager(ContextImpl context, IPackageManager pm) {
         mContext = context;
         mPM = pm;
diff --git a/core/java/android/app/BackgroundServiceStartNotAllowedException.java b/core/java/android/app/BackgroundServiceStartNotAllowedException.java
new file mode 100644
index 0000000..f6361b5
--- /dev/null
+++ b/core/java/android/app/BackgroundServiceStartNotAllowedException.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Exception thrown when an app tries to start a background {@link Service} when it's not allowed to
+ * do so.
+ */
+public final class BackgroundServiceStartNotAllowedException
+        extends ServiceStartNotAllowedException implements Parcelable {
+    /**
+     * Constructor.
+     */
+    public BackgroundServiceStartNotAllowedException(@NonNull String message) {
+        super(message);
+    }
+
+    BackgroundServiceStartNotAllowedException(@NonNull Parcel source) {
+        super(source.readString());
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString(getMessage());
+    }
+
+    public static final @NonNull Creator<android.app.BackgroundServiceStartNotAllowedException>
+            CREATOR = new Creator<android.app.BackgroundServiceStartNotAllowedException>() {
+                @NonNull
+                public android.app.BackgroundServiceStartNotAllowedException createFromParcel(
+                        Parcel source) {
+                    return new android.app.BackgroundServiceStartNotAllowedException(source);
+                }
+
+                @NonNull
+                public android.app.BackgroundServiceStartNotAllowedException[] newArray(int size) {
+                    return new android.app.BackgroundServiceStartNotAllowedException[size];
+                }
+            };
+}
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index 445fdd8..477e96b 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -16,11 +16,13 @@
 
 package android.app;
 
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.PowerWhitelistManager;
+import android.os.PowerWhitelistManager.ReasonCode;
 import android.os.PowerWhitelistManager.TempAllowListType;
 
 /**
@@ -31,8 +33,11 @@
  */
 @SystemApi
 public class BroadcastOptions {
-    private long mTemporaryAppWhitelistDuration;
-    private @TempAllowListType int mTemporaryAppWhitelistType;
+    private long mTemporaryAppAllowlistDuration;
+    private @TempAllowListType int mTemporaryAppAllowlistType;
+    private @ReasonCode int mTemporaryAppAllowlistReasonCode =
+            PowerWhitelistManager.REASON_UNKNOWN;
+    private @Nullable String mTemporaryAppAllowlistReason;
     private int mMinManifestReceiverApiLevel = 0;
     private int mMaxManifestReceiverApiLevel = Build.VERSION_CODES.CUR_DEVELOPMENT;
     private boolean mDontSendToRestrictedApps = false;
@@ -42,11 +47,17 @@
      * How long to temporarily put an app on the power allowlist when executing this broadcast
      * to it.
      */
-    static final String KEY_TEMPORARY_APP_WHITELIST_DURATION
-            = "android:broadcast.temporaryAppWhitelistDuration";
+    static final String KEY_TEMPORARY_APP_ALLOWLIST_DURATION
+            = "android:broadcast.temporaryAppAllowlistDuration";
 
-    static final String KEY_TEMPORARY_APP_WHITELIST_TYPE
-            = "android:broadcast.temporaryAppWhitelistType";
+    static final String KEY_TEMPORARY_APP_ALLOWLIST_TYPE
+            = "android:broadcast.temporaryAppAllowlistType";
+
+    static final String KEY_TEMPORARY_APP_ALLOWLIST_REASON_CODE =
+            "android:broadcast.temporaryAppAllowlistReasonCode";
+
+    static final String KEY_TEMPORARY_APP_ALLOWLIST_REASON =
+            "android:broadcast.temporaryAppAllowlistReason";
 
     /**
      * Corresponds to {@link #setMinManifestReceiverApiLevel}.
@@ -80,6 +91,7 @@
     @Deprecated
     public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED =
             PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+
     /**
      * @hide
      * @deprecated Use {@link android.os.PowerWhitelistManager#
@@ -99,8 +111,11 @@
 
     /** @hide */
     public BroadcastOptions(Bundle opts) {
-        mTemporaryAppWhitelistDuration = opts.getLong(KEY_TEMPORARY_APP_WHITELIST_DURATION);
-        mTemporaryAppWhitelistType = opts.getInt(KEY_TEMPORARY_APP_WHITELIST_TYPE);
+        mTemporaryAppAllowlistDuration = opts.getLong(KEY_TEMPORARY_APP_ALLOWLIST_DURATION);
+        mTemporaryAppAllowlistType = opts.getInt(KEY_TEMPORARY_APP_ALLOWLIST_TYPE);
+        mTemporaryAppAllowlistReasonCode = opts.getInt(KEY_TEMPORARY_APP_ALLOWLIST_REASON_CODE,
+                PowerWhitelistManager.REASON_UNKNOWN);
+        mTemporaryAppAllowlistReason = opts.getString(KEY_TEMPORARY_APP_ALLOWLIST_REASON);
         mMinManifestReceiverApiLevel = opts.getInt(KEY_MIN_MANIFEST_RECEIVER_API_LEVEL, 0);
         mMaxManifestReceiverApiLevel = opts.getInt(KEY_MAX_MANIFEST_RECEIVER_API_LEVEL,
                 Build.VERSION_CODES.CUR_DEVELOPMENT);
@@ -113,45 +128,70 @@
      * Set a duration for which the system should temporary place an application on the
      * power allowlist when this broadcast is being delivered to it.
      * @param duration The duration in milliseconds; 0 means to not place on allowlist.
+     * @deprecated use {@link #setTemporaryAppAllowlist(long, int, int,  String)} instead.
      */
+    @Deprecated
     @RequiresPermission(anyOf = {android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
             android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
             android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND})
     public void setTemporaryAppWhitelistDuration(long duration) {
-        mTemporaryAppWhitelistDuration = duration;
-        mTemporaryAppWhitelistType =
-                PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+        setTemporaryAppAllowlist(duration,
+                PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+                PowerWhitelistManager.REASON_UNKNOWN, null);
     }
 
     /**
      * Set a duration for which the system should temporary place an application on the
      * power allowlist when this broadcast is being delivered to it, specify the temp allowlist
      * type.
-     * @param type one of {@link TempAllowListType}
      * @param duration the duration in milliseconds; 0 means to not place on allowlist.
+     * @param type one of {@link TempAllowListType}
+     * @param reasonCode one of {@link ReasonCode}, use
+     *                  {@link PowerWhitelistManager#REASON_UNKNOWN} if not sure.
+     * @param reason A human-readable reason explaining why the app is temp allowlisted. Only
+     *               used for logging purposes. Could be null or empty string.
      */
     @RequiresPermission(anyOf = {android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
             android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
             android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND})
-    public void setTemporaryAppWhitelistDuration(@TempAllowListType int type, long duration) {
-        mTemporaryAppWhitelistDuration = duration;
-        mTemporaryAppWhitelistType = type;
+    public void setTemporaryAppAllowlist(long duration, @TempAllowListType int type,
+            @ReasonCode int reasonCode, @Nullable String reason) {
+        mTemporaryAppAllowlistDuration = duration;
+        mTemporaryAppAllowlistType = type;
+        mTemporaryAppAllowlistReasonCode = reasonCode;
+        mTemporaryAppAllowlistReason = reason;
     }
 
     /**
-     * Return {@link #setTemporaryAppWhitelistDuration}.
+     * Return {@link #setTemporaryAppAllowlist}.
      * @hide
      */
-    public long getTemporaryAppWhitelistDuration() {
-        return mTemporaryAppWhitelistDuration;
+    public long getTemporaryAppAllowlistDuration() {
+        return mTemporaryAppAllowlistDuration;
     }
 
     /**
-     * Return {@link #mTemporaryAppWhitelistType}.
+     * Return {@link #mTemporaryAppAllowlistType}.
      * @hide
      */
-    public @TempAllowListType int getTemporaryAppWhitelistType() {
-        return mTemporaryAppWhitelistType;
+    public @TempAllowListType int getTemporaryAppAllowlistType() {
+        return mTemporaryAppAllowlistType;
+    }
+
+    /**
+     * Return {@link #mTemporaryAppAllowlistReasonCode}.
+     * @hide
+     */
+    public @ReasonCode int getTemporaryAppAllowlistReasonCode() {
+        return mTemporaryAppAllowlistReasonCode;
+    }
+
+    /**
+     * Return {@link #mTemporaryAppAllowlistReason}.
+     * @hide
+     */
+    public @Nullable String getTemporaryAppAllowlistReason() {
+        return mTemporaryAppAllowlistReason;
     }
 
     /**
@@ -236,11 +276,17 @@
      */
     public Bundle toBundle() {
         Bundle b = new Bundle();
-        if (mTemporaryAppWhitelistDuration > 0) {
-            b.putLong(KEY_TEMPORARY_APP_WHITELIST_DURATION, mTemporaryAppWhitelistDuration);
+        if (mTemporaryAppAllowlistDuration > 0) {
+            b.putLong(KEY_TEMPORARY_APP_ALLOWLIST_DURATION, mTemporaryAppAllowlistDuration);
         }
-        if (mTemporaryAppWhitelistType != 0) {
-            b.putInt(KEY_TEMPORARY_APP_WHITELIST_TYPE, mTemporaryAppWhitelistType);
+        if (mTemporaryAppAllowlistType != 0) {
+            b.putInt(KEY_TEMPORARY_APP_ALLOWLIST_TYPE, mTemporaryAppAllowlistType);
+        }
+        if (mTemporaryAppAllowlistReasonCode != PowerWhitelistManager.REASON_UNKNOWN) {
+            b.putInt(KEY_TEMPORARY_APP_ALLOWLIST_REASON_CODE, mTemporaryAppAllowlistReasonCode);
+        }
+        if (mTemporaryAppAllowlistReason != null) {
+            b.putString(KEY_TEMPORARY_APP_ALLOWLIST_REASON, mTemporaryAppAllowlistReason);
         }
         if (mMinManifestReceiverApiLevel != 0) {
             b.putInt(KEY_MIN_MANIFEST_RECEIVER_API_LEVEL, mMinManifestReceiverApiLevel);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 85fb543..bc79813 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1796,7 +1796,7 @@
                             "Unable to start service " + service
                             + ": " + cn.getClassName());
                 } else if (cn.getPackageName().equals("?")) {
-                    throw new IllegalStateException(
+                    throw ServiceStartNotAllowedException.newInstance(requireForeground,
                             "Not allowed to start service " + service + ": " + cn.getClassName());
                 }
             }
diff --git a/core/java/android/app/ForegroundServiceStartNotAllowedException.java b/core/java/android/app/ForegroundServiceStartNotAllowedException.java
new file mode 100644
index 0000000..41eeada2
--- /dev/null
+++ b/core/java/android/app/ForegroundServiceStartNotAllowedException.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Exception thrown when an app tries to start a foreground {@link Service} when it's not allowed to
+ * do so.
+ */
+public final class ForegroundServiceStartNotAllowedException
+        extends ServiceStartNotAllowedException implements Parcelable {
+    /**
+     * Constructor.
+     */
+    public ForegroundServiceStartNotAllowedException(@NonNull String message) {
+        super(message);
+    }
+
+    ForegroundServiceStartNotAllowedException(@NonNull Parcel source) {
+        super(source.readString());
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString(getMessage());
+    }
+
+    public static final @NonNull Creator<android.app.ForegroundServiceStartNotAllowedException>
+            CREATOR = new Creator<android.app.ForegroundServiceStartNotAllowedException>() {
+                @NonNull
+                public android.app.ForegroundServiceStartNotAllowedException createFromParcel(
+                        Parcel source) {
+                    return new android.app.ForegroundServiceStartNotAllowedException(source);
+                }
+
+                @NonNull
+                public android.app.ForegroundServiceStartNotAllowedException[] newArray(int size) {
+                    return new android.app.ForegroundServiceStartNotAllowedException[size];
+                }
+            };
+}
diff --git a/core/java/android/app/IActivityClientController.aidl b/core/java/android/app/IActivityClientController.aidl
index bb743b8..573931e 100644
--- a/core/java/android/app/IActivityClientController.aidl
+++ b/core/java/android/app/IActivityClientController.aidl
@@ -17,6 +17,7 @@
 package android.app;
 
 import android.app.ActivityManager;
+import android.app.IRequestFinishCallback;
 import android.app.PictureInPictureParams;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -141,7 +142,8 @@
      * Reports that an Activity received a back key press when there were no additional activities
      * on the back stack.
      */
-    oneway void onBackPressedOnTaskRoot(in IBinder token);
+    oneway void onBackPressedOnTaskRoot(in IBinder activityToken,
+            in IRequestFinishCallback callback);
 
     /** Reports that the splash screen view has attached to activity.  */
     oneway void splashScreenAttached(in IBinder token);
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 4ad13e1..3a8172e 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -17,6 +17,7 @@
 package android.app;
 
 import android.app.ActivityManager;
+import android.app.ActivityManager.PendingIntentInfo;
 import android.app.ActivityTaskManager;
 import android.app.ApplicationErrorReport;
 import android.app.ApplicationExitInfo;
@@ -248,7 +249,7 @@
             in IBinder token, in String resultWho, int requestCode, in Intent[] intents,
             in String[] resolvedTypes, int flags, in Bundle options, int userId);
     void cancelIntentSender(in IIntentSender sender);
-    String getPackageForIntentSender(in IIntentSender sender);
+    ActivityManager.PendingIntentInfo getInfoForIntentSender(in IIntentSender sender);
     void registerIntentSenderCancelListener(in IIntentSender sender, in IResultReceiver receiver);
     void unregisterIntentSenderCancelListener(in IIntentSender sender, in IResultReceiver receiver);
     void enterSafeMode();
@@ -293,7 +294,6 @@
             int operationType);
     void backupAgentCreated(in String packageName, in IBinder agent, int userId);
     void unbindBackupAgent(in ApplicationInfo appInfo);
-    int getUidForIntentSender(in IIntentSender sender);
     int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
             boolean requireFull, in String name, in String callerPackage);
     void addPackageDependency(in String packageName);
@@ -345,7 +345,6 @@
     @UnsupportedAppUsage
     void unregisterProcessObserver(in IProcessObserver observer);
     boolean isIntentSenderTargetedToPackage(in IIntentSender sender);
-    boolean isIntentSenderImmutable(in IIntentSender sender);
     @UnsupportedAppUsage
     void updatePersistentConfiguration(in Configuration values);
     void updatePersistentConfigurationWithAttribution(in Configuration values,
@@ -375,8 +374,6 @@
     void unstableProviderDied(in IBinder connection);
     @UnsupportedAppUsage
     boolean isIntentSenderAnActivity(in IIntentSender sender);
-    boolean isIntentSenderAForegroundService(in IIntentSender sender);
-    boolean isIntentSenderABroadcast(in IIntentSender sender);
     /** @deprecated Use {@link startActivityAsUserWithFeature} instead */
     @UnsupportedAppUsage(maxTargetSdk=29, publicAlternatives="Use {@code android.content.Context#createContextAsUser(android.os.UserHandle, int)} and {@link android.content.Context#startActivity(android.content.Intent)} instead")
     int startActivityAsUser(in IApplicationThread caller, in String callingPackage,
@@ -552,7 +549,7 @@
     /**
      * Add a bare uid to the background restrictions whitelist.  Only the system uid may call this.
      */
-    void backgroundWhitelistUid(int uid);
+    void backgroundAllowlistUid(int uid);
 
     // Start of P transactions
     /**
@@ -711,5 +708,5 @@
     /** Called by PendingIntent.queryIntentComponents() */
     List<ResolveInfo> queryIntentComponentsForIntentSender(in IIntentSender sender, int matchFlags);
 
-    boolean isIntentSenderAService(in IIntentSender sender);
+    int getUidProcessCapabilities(int uid, in String callingPackage);
 }
diff --git a/core/java/android/service/screenshot/ScreenshotHash.aidl b/core/java/android/app/ILocalWallpaperColorConsumer.aidl
similarity index 66%
copy from core/java/android/service/screenshot/ScreenshotHash.aidl
copy to core/java/android/app/ILocalWallpaperColorConsumer.aidl
index a7c50db..28b11ec 100644
--- a/core/java/android/service/screenshot/ScreenshotHash.aidl
+++ b/core/java/android/app/ILocalWallpaperColorConsumer.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,6 +14,14 @@
  * limitations under the License.
  */
 
-package android.service.screenshot;
+package android.app;
 
-parcelable ScreenshotHash;
+import android.app.WallpaperColors;
+import android.graphics.RectF;
+
+/**
+ * @hide
+ */
+oneway interface ILocalWallpaperColorConsumer {
+    void onColorsChanged(in RectF area, in WallpaperColors colors);
+}
\ No newline at end of file
diff --git a/core/java/android/service/screenshot/ScreenshotHash.aidl b/core/java/android/app/IParcelFileDescriptorRetriever.aidl
similarity index 67%
copy from core/java/android/service/screenshot/ScreenshotHash.aidl
copy to core/java/android/app/IParcelFileDescriptorRetriever.aidl
index a7c50db..7e808e7 100644
--- a/core/java/android/service/screenshot/ScreenshotHash.aidl
+++ b/core/java/android/app/IParcelFileDescriptorRetriever.aidl
@@ -14,6 +14,18 @@
  * limitations under the License.
  */
 
-package android.service.screenshot;
+package android.app;
 
-parcelable ScreenshotHash;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * An interface used to lazily provide a ParcelFileDescriptor to apps.
+ *
+ * @hide
+ */
+interface IParcelFileDescriptorRetriever {
+    /**
+     * Retrieve the ParcelFileDescriptor.
+     */
+    ParcelFileDescriptor getPfd();
+}
diff --git a/core/java/android/service/screenshot/ScreenshotHash.aidl b/core/java/android/app/IRequestFinishCallback.aidl
similarity index 64%
copy from core/java/android/service/screenshot/ScreenshotHash.aidl
copy to core/java/android/app/IRequestFinishCallback.aidl
index a7c50db..22c20c8 100644
--- a/core/java/android/service/screenshot/ScreenshotHash.aidl
+++ b/core/java/android/app/IRequestFinishCallback.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,6 +14,14 @@
  * limitations under the License.
  */
 
-package android.service.screenshot;
+package android.app;
 
-parcelable ScreenshotHash;
+/**
+ * This callback allows ActivityTaskManager to ask the calling Activity
+ * to finish in response to a call to onBackPressedOnTaskRoot.
+ *
+ * {@hide}
+ */
+oneway interface IRequestFinishCallback {
+    void requestFinish();
+}
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index a9e28bb..7bb5d9a 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -60,9 +60,9 @@
     void onActivityForcedResizable(String packageName, int taskId, int reason);
 
     /**
-     * Called when we launched an activity that dismissed the docked stack.
+     * Called when we launched an activity that dismissed the docked task.
      */
-    void onActivityDismissingDockedStack();
+    void onActivityDismissingDockedTask();
 
     /**
      * Called when an activity was requested to be launched on a secondary display but was not
@@ -209,4 +209,10 @@
      * @param taskInfo info about the task which moved
      */
     void onTaskMovedToBack(in ActivityManager.RunningTaskInfo taskInfo);
+
+    /**
+     * Called when the lock task mode changes. See ActivityManager#LOCK_TASK_MODE_* and
+     * LockTaskController.
+     */
+    void onLockTaskModeChanged(int mode);
 }
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl
index 101917b..5402381 100644
--- a/core/java/android/app/IWallpaperManager.aidl
+++ b/core/java/android/app/IWallpaperManager.aidl
@@ -17,9 +17,11 @@
 package android.app;
 
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 import android.app.IWallpaperManagerCallback;
+import android.app.ILocalWallpaperColorConsumer;
 import android.app.WallpaperInfo;
 import android.content.ComponentName;
 import android.app.WallpaperColors;
@@ -162,6 +164,18 @@
     WallpaperColors getWallpaperColors(int which, int userId, int displayId);
 
     /**
+    * @hide
+    */
+    void removeOnLocalColorsChangedListener(
+            in ILocalWallpaperColorConsumer callback, int which, int userId, int displayId);
+
+    /**
+    * @hide
+    */
+    void addOnLocalColorsChangedListener(in ILocalWallpaperColorConsumer callback,
+                                    in List<RectF> regions, int which, int userId, int displayId);
+
+    /**
      * Register a callback to receive color updates from a display
      */
     void registerWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId, int displayId);
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 8d1076e..b2184fe 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1247,7 +1247,8 @@
                 info, title, parent, id,
                 (Activity.NonConfigurationInstances)lastNonConfigurationInstance,
                 new Configuration(), null /* referrer */, null /* voiceInteractor */,
-                null /* window */, null /* activityConfigCallback */, null /*assistToken*/);
+                null /* window */, null /* activityConfigCallback */, null /*assistToken*/,
+                null /*shareableActivityToken*/);
         return activity;
     }
 
diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java
index 74e6125..6b5f19a 100644
--- a/core/java/android/app/LocalActivityManager.java
+++ b/core/java/android/app/LocalActivityManager.java
@@ -158,7 +158,7 @@
                 r.activityInfo = mActivityThread.resolveActivityInfo(r.intent);
             }
             r.activity = mActivityThread.startActivityNow(
-                    mParent, r.id, r.intent, r.activityInfo, r, r.instanceState, instance, r);
+                    mParent, r.id, r.intent, r.activityInfo, r, r.instanceState, instance, r, r);
             if (r.activity == null) {
                 return;
             }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 77daf8d..8167622 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1371,6 +1371,18 @@
     public static final String EXTRA_HANG_UP_INTENT = "android.hangUpIntent";
 
     /**
+     * {@link #extras} key: the color used as a hint for the Answer action button of a
+     * {@link android.app.Notification.CallStyle} notification. This extra is a {@link ColorInt}.
+     */
+    public static final String EXTRA_ANSWER_COLOR = "android.answerColor";
+
+    /**
+     * {@link #extras} key: the color used as a hint for the Decline or Hang Up action button of a
+     * {@link android.app.Notification.CallStyle} notification. This extra is a {@link ColorInt}.
+     */
+    public static final String EXTRA_DECLINE_COLOR = "android.declineColor";
+
+    /**
      * {@link #extras} key: whether the notification should be colorized as
      * supplied to {@link Builder#setColorized(boolean)}.
      */
@@ -3624,7 +3636,7 @@
         private Bundle mUserExtras = new Bundle();
         private Style mStyle;
         @UnsupportedAppUsage
-        private ArrayList<Action> mActions = new ArrayList<Action>(MAX_ACTION_BUTTONS);
+        private ArrayList<Action> mActions = new ArrayList<>(MAX_ACTION_BUTTONS);
         private ArrayList<Person> mPersonList = new ArrayList<>();
         private ContrastColorUtil mColorUtil;
         private boolean mIsLegacy;
@@ -4878,6 +4890,16 @@
             return this;
         }
 
+        private void bindPhishingAlertIcon(RemoteViews contentView, StandardTemplateParams p) {
+            // TODO(b/180334837): Get buy-in on this color, or make sure to give this the
+            //  accent color, while still accommodating the colorized state.
+            contentView.setDrawableTint(
+                    R.id.phishing_alert,
+                    false /* targetBackground */,
+                    getPrimaryTextColor(p),
+                    PorterDuff.Mode.SRC_ATOP);
+        }
+
         private Drawable getProfileBadgeDrawable() {
             if (mContext.getUserId() == UserHandle.USER_SYSTEM) {
                 // This user can never be a badged profile,
@@ -4991,6 +5013,7 @@
             bindNotificationHeader(contentView, p);
             bindLargeIconAndApplyMargin(contentView, p, result);
             boolean showProgress = handleProgressBar(contentView, ex, p);
+            boolean hasSecondLine = showProgress;
             if (p.hasTitle()) {
                 contentView.setViewVisibility(R.id.title, View.VISIBLE);
                 contentView.setTextViewText(R.id.title, processTextSpans(p.title));
@@ -5006,11 +5029,27 @@
                 contentView.setTextViewText(textId, processTextSpans(p.text));
                 setTextViewColorSecondary(contentView, textId, p);
                 contentView.setViewVisibility(textId, View.VISIBLE);
+                hasSecondLine = true;
             }
+            setHeaderlessVerticalMargins(contentView, p, hasSecondLine);
 
             return contentView;
         }
 
+        private static void setHeaderlessVerticalMargins(RemoteViews contentView,
+                StandardTemplateParams p, boolean hasSecondLine) {
+            if (!p.mHeaderless) {
+                return;
+            }
+            int marginDimen = hasSecondLine
+                    ? R.dimen.notification_headerless_margin_twoline
+                    : R.dimen.notification_headerless_margin_oneline;
+            contentView.setViewLayoutMarginDimen(R.id.notification_headerless_view_column,
+                    RemoteViews.MARGIN_TOP, marginDimen);
+            contentView.setViewLayoutMarginDimen(R.id.notification_headerless_view_column,
+                    RemoteViews.MARGIN_BOTTOM, marginDimen);
+        }
+
         private CharSequence processTextSpans(CharSequence text) {
             if (hasForegroundColor() || mInNightMode) {
                 return ContrastColorUtil.clearColorSpans(text);
@@ -5279,6 +5318,7 @@
                 hasTextToLeft |= bindHeaderAppName(contentView, p, true /* force */);
             }
             bindHeaderChronometerAndTime(contentView, p, hasTextToLeft);
+            bindPhishingAlertIcon(contentView, p);
             bindProfileBadge(contentView, p);
             bindAlertedIcon(contentView, p);
             bindExpandButton(contentView, p);
@@ -5433,6 +5473,11 @@
             return p.allowColorization && mN.isColorized();
         }
 
+        private boolean isCallActionColorCustomizable(StandardTemplateParams p) {
+            return isColorized(p) && mContext.getResources().getBoolean(
+                    R.bool.config_callNotificationActionColorsRequireColorized);
+        }
+
         private void bindSmallIcon(RemoteViews contentView, StandardTemplateParams p) {
             if (mN.mSmallIcon == null && mN.icon != 0) {
                 mN.mSmallIcon = Icon.createWithResource(mContext, mN.icon);
@@ -5466,23 +5511,42 @@
             big.setViewVisibility(R.id.notification_material_reply_text_3, View.GONE);
             big.setTextViewText(R.id.notification_material_reply_text_3, null);
 
-            final boolean snoozeEnabled = mContext.getContentResolver() != null
-                    && (Settings.Secure.getInt(mContext.getContentResolver(),
-                        Settings.Secure.SHOW_NOTIFICATION_SNOOZE, 0) == 1);
-            int bottomMarginDimen = snoozeEnabled ? 0 : R.dimen.notification_content_margin;
+            // This may get erased by bindSnoozeAction
             big.setViewLayoutMarginDimen(R.id.notification_action_list_margin_target,
-                    RemoteViews.MARGIN_BOTTOM, bottomMarginDimen);
+                    RemoteViews.MARGIN_BOTTOM, R.dimen.notification_content_margin);
         }
 
-        private static List<Notification.Action> filterOutContextualActions(
-                List<Notification.Action> actions) {
-            List<Notification.Action> nonContextualActions = new ArrayList<>();
-            for (Notification.Action action : actions) {
+        private void bindSnoozeAction(RemoteViews big, StandardTemplateParams p) {
+            boolean hideSnoozeButton = mN.isForegroundService() || mN.fullScreenIntent != null
+                    || isColorized(p) || p.mViewType == StandardTemplateParams.VIEW_TYPE_HEADS_UP;
+            big.setBoolean(R.id.snooze_button, "setEnabled", !hideSnoozeButton);
+            if (hideSnoozeButton) {
+                // Only hide; NotificationContentView will show it when it adds the click listener
+                big.setViewVisibility(R.id.snooze_button, View.GONE);
+            }
+
+            final boolean snoozeEnabled = !hideSnoozeButton
+                    && mContext.getContentResolver() != null
+                    && (Settings.Secure.getInt(mContext.getContentResolver(),
+                    Settings.Secure.SHOW_NOTIFICATION_SNOOZE, 0) == 1);
+            if (snoozeEnabled) {
+                big.setViewLayoutMarginDimen(R.id.notification_action_list_margin_target,
+                        RemoteViews.MARGIN_BOTTOM, 0);
+            }
+        }
+
+        /**
+         * Returns the actions that are not contextual.
+         */
+        private @NonNull List<Notification.Action> getNonContextualActions() {
+            if (mActions == null) return Collections.emptyList();
+            List<Notification.Action> contextualActions = new ArrayList<>();
+            for (Notification.Action action : mActions) {
                 if (!action.isContextual()) {
-                    nonContextualActions.add(action);
+                    contextualActions.add(action);
                 }
             }
-            return nonContextualActions;
+            return contextualActions;
         }
 
         private RemoteViews applyStandardTemplateWithActions(int layoutId,
@@ -5490,12 +5554,13 @@
             RemoteViews big = applyStandardTemplate(layoutId, p, result);
 
             resetStandardTemplateWithActions(big);
+            bindSnoozeAction(big, p);
 
             boolean validRemoteInput = false;
 
-            // In the UI contextual actions appear separately from the standard actions, so we
+            // In the UI, contextual actions appear separately from the standard actions, so we
             // filter them out here.
-            List<Notification.Action> nonContextualActions = filterOutContextualActions(mActions);
+            List<Notification.Action> nonContextualActions = getNonContextualActions();
 
             int N = nonContextualActions.size();
             boolean emphazisedMode = mN.fullScreenIntent != null;
@@ -6753,6 +6818,31 @@
     }
 
     /**
+     * @return true if the notification has image
+     */
+    public boolean hasImage() {
+        if (MessagingStyle.class.equals(getNotificationStyle()) && extras != null) {
+            final Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES);
+            if (!ArrayUtils.isEmpty(messages)) {
+                for (MessagingStyle.Message m : MessagingStyle.Message
+                        .getMessagesFromBundleArray(messages)) {
+                    if (m.getDataUri() != null
+                            && m.getDataMimeType() != null
+                            && m.getDataMimeType().startsWith("image/")) {
+                        return true;
+                    }
+                }
+            }
+        } else if (hasLargeIcon()) {
+            return true;
+        } else if (extras.containsKey(EXTRA_BACKGROUND_IMAGE_URI)) {
+            return true;
+        }
+        return false;
+    }
+
+
+    /**
      * @removed
      */
     @SystemApi
@@ -6778,26 +6868,13 @@
                 if (decorationType <= DevFlags.DECORATION_PARTIAL) {
                     template.removeFromParent(R.id.notification_top_line);
                 }
-                if (decorationType != DevFlags.DECORATION_FULL_COMPATIBLE) {
-                    // Change the max content size from 60dp (the compatible size) to 48dp
-                    // (the constrained size).  This is done by increasing the minimum margin
-                    // (implemented as top/bottom margins) and decreasing the extra margin
-                    // (implemented as the height of shrinkable top/bottom views in the column).
-                    template.setViewLayoutMarginDimen(
-                            R.id.notification_headerless_view_column,
-                            RemoteViews.MARGIN_TOP,
-                            R.dimen.notification_headerless_margin_constrained_minimum);
-                    template.setViewLayoutMarginDimen(
-                            R.id.notification_headerless_view_column,
-                            RemoteViews.MARGIN_BOTTOM,
-                            R.dimen.notification_headerless_margin_constrained_minimum);
-                    template.setViewLayoutHeightDimen(
-                            R.id.notification_headerless_margin_extra_top,
-                            R.dimen.notification_headerless_margin_constrained_extra);
-                    template.setViewLayoutHeightDimen(
-                            R.id.notification_headerless_margin_extra_bottom,
-                            R.dimen.notification_headerless_margin_constrained_extra);
-                }
+                // The vertical margins are bigger in the "two-line" scenario than the "one-line"
+                //  scenario, but the 'compatible' decoration state is intended to have 3 lines,
+                //  (1 for the top line views and 2 for the custom views), so in that one case we
+                //  use the smaller 1-line margins. This gives the compatible case 88-16*2=56 dp of
+                //  height, 24dp of which goes to the top line, leaving 32dp for the custom view.
+                boolean hasSecondLine = decorationType != DevFlags.DECORATION_FULL_COMPATIBLE;
+                Builder.setHeaderlessVerticalMargins(template, p, hasSecondLine);
             } else {
                 // also update the end margin to account for the large icon or expander
                 Resources resources = context.getResources();
@@ -9027,6 +9104,8 @@
         private PendingIntent mAnswerIntent;
         private PendingIntent mDeclineIntent;
         private PendingIntent mHangUpIntent;
+        private Integer mAnswerButtonColor;
+        private Integer mDeclineButtonColor;
         private Icon mVerificationIcon;
         private CharSequence mVerificationText;
 
@@ -9137,6 +9216,28 @@
         }
 
         /**
+         * Optional color to be used as a hint for the Answer action button's color.
+         * The system may change this color to ensure sufficient contrast with the background.
+         * The system may choose to disregard this hint if the notification is not colorized.
+         */
+        @NonNull
+        public CallStyle setAnswerButtonColorHint(@ColorInt int color) {
+            mAnswerButtonColor = color;
+            return this;
+        }
+
+        /**
+         * Optional color to be used as a hint for the Decline or Hang Up action button's color.
+         * The system may change this color to ensure sufficient contrast with the background.
+         * The system may choose to disregard this hint if the notification is not colorized.
+         */
+        @NonNull
+        public CallStyle setDeclineButtonColorHint(@ColorInt int color) {
+            mDeclineButtonColor = color;
+            return this;
+        }
+
+        /**
          * @hide
          */
         public boolean displayCustomViewInline() {
@@ -9195,40 +9296,47 @@
         }
 
         @NonNull
-        private Action makeNegativeAction() {
+        private Action makeNegativeAction(@NonNull StandardTemplateParams p) {
             if (mDeclineIntent == null) {
-                return makeAction(R.drawable.ic_call_decline,
+                return makeAction(p, R.drawable.ic_call_decline,
                         R.string.call_notification_hang_up_action,
-                        R.color.call_notification_decline_color, mHangUpIntent);
+                        mDeclineButtonColor, R.color.call_notification_decline_color,
+                        mHangUpIntent);
             } else {
-                return makeAction(R.drawable.ic_call_decline,
+                return makeAction(p, R.drawable.ic_call_decline,
                         R.string.call_notification_decline_action,
-                        R.color.call_notification_decline_color, mDeclineIntent);
+                        mDeclineButtonColor, R.color.call_notification_decline_color,
+                        mDeclineIntent);
             }
         }
 
         @Nullable
-        private Action makeAnswerAction() {
-            return mAnswerIntent == null ? null : makeAction(R.drawable.ic_call_answer,
+        private Action makeAnswerAction(@NonNull StandardTemplateParams p) {
+            return mAnswerIntent == null ? null : makeAction(p, R.drawable.ic_call_answer,
                     R.string.call_notification_answer_action,
-                    R.color.call_notification_answer_color, mAnswerIntent);
+                    mAnswerButtonColor, R.color.call_notification_answer_color,
+                    mAnswerIntent);
         }
 
         @NonNull
-        private Action makeAction(@DrawableRes int icon, @StringRes int title,
-                @ColorRes int colorRes, PendingIntent intent) {
+        private Action makeAction(@NonNull StandardTemplateParams p,
+                @DrawableRes int icon, @StringRes int title,
+                @ColorInt Integer colorInt, @ColorRes int defaultColorRes, PendingIntent intent) {
+            if (colorInt == null || !mBuilder.isCallActionColorCustomizable(p)) {
+                colorInt = mBuilder.mContext.getColor(defaultColorRes);
+            }
             Action action = new Action.Builder(Icon.createWithResource("", icon),
                     new SpannableStringBuilder().append(mBuilder.mContext.getString(title),
-                            new ForegroundColorSpan(mBuilder.mContext.getColor(colorRes)),
+                            new ForegroundColorSpan(colorInt),
                             SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE),
                     intent).build();
             action.getExtras().putBoolean(KEY_ACTION_PRIORITY, true);
             return action;
         }
 
-        private ArrayList<Action> makeActionsList() {
-            final Action negativeAction = makeNegativeAction();
-            final Action answerAction = makeAnswerAction();
+        private ArrayList<Action> makeActionsList(@NonNull StandardTemplateParams p) {
+            final Action negativeAction = makeNegativeAction(p);
+            final Action answerAction = makeAnswerAction(p);
 
             ArrayList<Action> actions = new ArrayList<>(MAX_ACTION_BUTTONS);
             final Action lastAction;
@@ -9241,7 +9349,7 @@
                 lastAction = answerAction;
             }
             // For consistency with the standard actions bar, contextual actions are ignored.
-            for (Action action : Builder.filterOutContextualActions(mBuilder.mActions)) {
+            for (Action action : mBuilder.getNonContextualActions()) {
                 if (actions.size() >= MAX_ACTION_BUTTONS - 1) {
                     break;
                 }
@@ -9271,6 +9379,7 @@
 
             // Bind actions.
             mBuilder.resetStandardTemplateWithActions(contentView);
+            mBuilder.bindSnoozeAction(contentView, p);
             bindCallActions(contentView, p);
 
             // Bind some extra conversation-specific header fields.
@@ -9317,7 +9426,7 @@
 
             // Create the buttons for the generated actions list.
             int i = 0;
-            for (Action action : makeActionsList()) {
+            for (Action action : makeActionsList(p)) {
                 final RemoteViews button = mBuilder.generateActionButton(action, emphasizedMode, p);
                 if (i > 0) {
                     // Clear start margin from non-first buttons to reduce the gap between buttons.
@@ -9330,11 +9439,16 @@
         }
 
         private void bindCallerVerification(RemoteViews contentView, StandardTemplateParams p) {
+            String iconContentDescription = null;
+            boolean showDivider = true;
             if (mVerificationIcon != null) {
                 contentView.setImageViewIcon(R.id.verification_icon, mVerificationIcon);
                 contentView.setDrawableTint(R.id.verification_icon, false /* targetBackground */,
                         mBuilder.getSecondaryTextColor(p), PorterDuff.Mode.SRC_ATOP);
                 contentView.setViewVisibility(R.id.verification_icon, View.VISIBLE);
+                iconContentDescription = mBuilder.mContext.getString(
+                        R.string.notification_verified_content_description);
+                showDivider = false;  // the icon replaces the divider
             } else {
                 contentView.setViewVisibility(R.id.verification_icon, View.GONE);
             }
@@ -9342,8 +9456,17 @@
                 contentView.setTextViewText(R.id.verification_text, mVerificationText);
                 mBuilder.setTextViewColorSecondary(contentView, R.id.verification_text, p);
                 contentView.setViewVisibility(R.id.verification_text, View.VISIBLE);
+                iconContentDescription = null;  // let the app's text take precedence
             } else {
                 contentView.setViewVisibility(R.id.verification_text, View.GONE);
+                showDivider = false;  // no divider if no text
+            }
+            contentView.setContentDescription(R.id.verification_icon, iconContentDescription);
+            if (showDivider) {
+                contentView.setViewVisibility(R.id.verification_divider, View.VISIBLE);
+                mBuilder.setTextViewColorSecondary(contentView, R.id.verification_divider, p);
+            } else {
+                contentView.setViewVisibility(R.id.verification_divider, View.GONE);
             }
         }
 
@@ -9382,6 +9505,12 @@
             if (mHangUpIntent != null) {
                 extras.putParcelable(EXTRA_HANG_UP_INTENT, mHangUpIntent);
             }
+            if (mAnswerButtonColor != null) {
+                extras.putInt(EXTRA_ANSWER_COLOR, mAnswerButtonColor);
+            }
+            if (mDeclineButtonColor != null) {
+                extras.putInt(EXTRA_DECLINE_COLOR, mDeclineButtonColor);
+            }
             fixTitleAndTextExtras(extras);
         }
 
@@ -9408,6 +9537,10 @@
             mAnswerIntent = extras.getParcelable(EXTRA_ANSWER_INTENT);
             mDeclineIntent = extras.getParcelable(EXTRA_DECLINE_INTENT);
             mHangUpIntent = extras.getParcelable(EXTRA_HANG_UP_INTENT);
+            mAnswerButtonColor = extras.containsKey(EXTRA_ANSWER_COLOR)
+                    ? extras.getInt(EXTRA_ANSWER_COLOR) : null;
+            mDeclineButtonColor = extras.containsKey(EXTRA_DECLINE_COLOR)
+                    ? extras.getInt(EXTRA_DECLINE_COLOR) : null;
         }
 
         /**
@@ -11901,6 +12034,7 @@
         boolean mHideTitle;
         boolean mHideActions;
         boolean mHideProgress;
+        boolean mHideSnoozeButton;
         boolean mPromotePicture;
         boolean mAllowActionIcons;
         CharSequence title;
@@ -11918,6 +12052,7 @@
             mHideTitle = false;
             mHideActions = false;
             mHideProgress = false;
+            mHideSnoozeButton = false;
             mPromotePicture = false;
             mAllowActionIcons = false;
             title = null;
@@ -11964,6 +12099,11 @@
             return this;
         }
 
+        final StandardTemplateParams hideSnoozeButton(boolean hideSnoozeButton) {
+            this.mHideSnoozeButton = hideSnoozeButton;
+            return this;
+        }
+
         final StandardTemplateParams promotePicture(boolean promotePicture) {
             this.mPromotePicture = promotePicture;
             return this;
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 671315f..549bd4b 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -16,6 +16,11 @@
 
 package android.app;
 
+import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY;
+import static android.app.ActivityManager.INTENT_SENDER_BROADCAST;
+import static android.app.ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE;
+import static android.app.ActivityManager.INTENT_SENDER_SERVICE;
+
 import android.Manifest.permission;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -25,6 +30,7 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemApi.Client;
 import android.annotation.TestApi;
+import android.app.ActivityManager.PendingIntentInfo;
 import android.compat.Compatibility;
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledAfter;
@@ -55,6 +61,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * A description of an Intent and target action to perform with it.  Instances
@@ -122,6 +129,9 @@
     private IBinder mWhitelistToken;
     private ArraySet<CancelListener> mCancelListeners;
 
+    // cached pending intent information
+    private @Nullable PendingIntentInfo mCachedInfo;
+
     /**
      * It is now required to specify either {@link #FLAG_IMMUTABLE}
      * or {@link #FLAG_MUTABLE} when creating a PendingIntent.
@@ -455,15 +465,14 @@
     public static PendingIntent getActivityAsUser(Context context, int requestCode,
             @NonNull Intent intent, int flags, Bundle options, UserHandle user) {
         String packageName = context.getPackageName();
-        String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
-                context.getContentResolver()) : null;
+        String resolvedType = intent.resolveTypeIfNeeded(context.getContentResolver());
         checkFlags(flags, packageName);
         try {
             intent.migrateExtraStreamToClipData(context);
             intent.prepareToLeaveProcess(context);
             IIntentSender target =
                 ActivityManager.getService().getIntentSenderWithFeature(
-                    ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
+                    INTENT_SENDER_ACTIVITY, packageName,
                     context.getAttributionTag(), null, null, requestCode, new Intent[] { intent },
                     resolvedType != null ? new String[] { resolvedType } : null,
                     flags, options, user.getIdentifier());
@@ -596,7 +605,7 @@
         try {
             IIntentSender target =
                 ActivityManager.getService().getIntentSenderWithFeature(
-                    ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
+                    INTENT_SENDER_ACTIVITY, packageName,
                     context.getAttributionTag(), null, null, requestCode, intents, resolvedTypes,
                     flags, options, user.getIdentifier());
             return target != null ? new PendingIntent(target) : null;
@@ -630,7 +639,7 @@
      */
     @SuppressWarnings("AndroidFrameworkPendingIntentMutability")
     public static PendingIntent getBroadcast(Context context, int requestCode,
-            Intent intent, @Flags int flags) {
+            @NonNull Intent intent, @Flags int flags) {
         return getBroadcastAsUser(context, requestCode, intent, flags, context.getUser());
     }
 
@@ -643,14 +652,13 @@
     public static PendingIntent getBroadcastAsUser(Context context, int requestCode,
             Intent intent, int flags, UserHandle userHandle) {
         String packageName = context.getPackageName();
-        String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
-                context.getContentResolver()) : null;
+        String resolvedType = intent.resolveTypeIfNeeded(context.getContentResolver());
         checkFlags(flags, packageName);
         try {
             intent.prepareToLeaveProcess(context);
             IIntentSender target =
                 ActivityManager.getService().getIntentSenderWithFeature(
-                    ActivityManager.INTENT_SENDER_BROADCAST, packageName,
+                    INTENT_SENDER_BROADCAST, packageName,
                     context.getAttributionTag(), null, null, requestCode, new Intent[] { intent },
                     resolvedType != null ? new String[] { resolvedType } : null,
                     flags, null, userHandle.getIdentifier());
@@ -687,7 +695,7 @@
     public static PendingIntent getService(Context context, int requestCode,
             @NonNull Intent intent, @Flags int flags) {
         return buildServicePendingIntent(context, requestCode, intent, flags,
-                ActivityManager.INTENT_SENDER_SERVICE);
+                INTENT_SENDER_SERVICE);
     }
 
     /**
@@ -717,14 +725,13 @@
     public static PendingIntent getForegroundService(Context context, int requestCode,
             @NonNull Intent intent, @Flags int flags) {
         return buildServicePendingIntent(context, requestCode, intent, flags,
-                ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE);
+                INTENT_SENDER_FOREGROUND_SERVICE);
     }
 
     private static PendingIntent buildServicePendingIntent(Context context, int requestCode,
             Intent intent, int flags, int serviceKind) {
         String packageName = context.getPackageName();
-        String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
-                context.getContentResolver()) : null;
+        String resolvedType = intent.resolveTypeIfNeeded(context.getContentResolver());
         checkFlags(flags, packageName);
         try {
             intent.prepareToLeaveProcess(context);
@@ -746,6 +753,7 @@
      * @return Returns a IntentSender object that wraps the sender of PendingIntent
      *
      */
+    @NonNull
     public IntentSender getIntentSender() {
         return new IntentSender(mTarget, mWhitelistToken);
     }
@@ -758,6 +766,7 @@
         try {
             ActivityManager.getService().cancelIntentSender(mTarget);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1000,13 +1009,9 @@
      * @deprecated Renamed to {@link #getCreatorPackage()}.
      */
     @Deprecated
+    @NonNull
     public String getTargetPackage() {
-        try {
-            return ActivityManager.getService()
-                .getPackageForIntentSender(mTarget);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getCreatorPackage();
     }
 
     /**
@@ -1024,17 +1029,11 @@
      * only use this information to identify who you expect to be interacting with
      * through a {@link #send} call, not who gave you the PendingIntent.</p>
      *
-     * @return The package name of the PendingIntent, or null if there is
-     * none associated with it.
+     * @return The package name of the PendingIntent.
      */
-    @Nullable
+    @NonNull
     public String getCreatorPackage() {
-        try {
-            return ActivityManager.getService()
-                .getPackageForIntentSender(mTarget);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getCachedInfo().getCreatorPackage();
     }
 
     /**
@@ -1056,12 +1055,7 @@
      * none associated with it.
      */
     public int getCreatorUid() {
-        try {
-            return ActivityManager.getService()
-                .getUidForIntentSender(mTarget);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getCachedInfo().getCreatorUid();
     }
 
     /**
@@ -1149,18 +1143,12 @@
      * only use this information to identify who you expect to be interacting with
      * through a {@link #send} call, not who gave you the PendingIntent.</p>
      *
-     * @return The user handle of the PendingIntent, or null if there is
-     * none associated with it.
+     * @return The user handle of the PendingIntent
      */
-    @Nullable
+    @NonNull
     public UserHandle getCreatorUserHandle() {
-        try {
-            int uid = ActivityManager.getService()
-                .getUidForIntentSender(mTarget);
-            return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        int uid = getCachedInfo().getCreatorUid();
+        return UserHandle.getUserHandleForUid(uid);
     }
 
     /**
@@ -1180,12 +1168,7 @@
      * Check if this PendingIntent is marked with {@link #FLAG_IMMUTABLE}.
      */
     public boolean isImmutable() {
-        try {
-            return ActivityManager.getService()
-                    .isIntentSenderImmutable(mTarget);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getCachedInfo().isImmutable();
     }
 
     /**
@@ -1193,48 +1176,28 @@
      * {@link #getActivity} or {@link #getActivities}.
      */
     public boolean isActivity() {
-        try {
-            return ActivityManager.getService()
-                .isIntentSenderAnActivity(mTarget);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getCachedInfo().getIntentSenderType() == INTENT_SENDER_ACTIVITY;
     }
 
     /**
      * @return TRUE if this {@link PendingIntent} was created with {@link #getForegroundService}.
      */
     public boolean isForegroundService() {
-        try {
-            return ActivityManager.getService()
-                    .isIntentSenderAForegroundService(mTarget);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getCachedInfo().getIntentSenderType() == INTENT_SENDER_FOREGROUND_SERVICE;
     }
 
     /**
      * @return TRUE if this {@link PendingIntent} was created with {@link #getService}.
      */
     public boolean isService() {
-        try {
-            return ActivityManager.getService()
-                    .isIntentSenderAService(mTarget);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getCachedInfo().getIntentSenderType() == INTENT_SENDER_SERVICE;
     }
 
     /**
      * @return TRUE if this {@link PendingIntent} was created with {@link #getBroadcast}.
      */
     public boolean isBroadcast() {
-        try {
-            return ActivityManager.getService()
-                .isIntentSenderABroadcast(mTarget);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getCachedInfo().getIntentSenderType() == INTENT_SENDER_BROADCAST;
     }
 
     /**
@@ -1318,7 +1281,7 @@
         sb.append("PendingIntent{");
         sb.append(Integer.toHexString(System.identityHashCode(this)));
         sb.append(": ");
-        sb.append(mTarget != null ? mTarget.asBinder() : null);
+        sb.append(mTarget.asBinder());
         sb.append('}');
         return sb.toString();
     }
@@ -1326,9 +1289,7 @@
     /** @hide */
     public void dumpDebug(ProtoOutputStream proto, long fieldId) {
         final long token = proto.start(fieldId);
-        if (mTarget != null) {
-            proto.write(PendingIntentProto.TARGET, mTarget.asBinder().toString());
-        }
+        proto.write(PendingIntentProto.TARGET, mTarget.asBinder().toString());
         proto.end(token);
     }
 
@@ -1345,8 +1306,7 @@
 
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<PendingIntent> CREATOR
-            = new Parcelable.Creator<PendingIntent>() {
+    public static final @NonNull Creator<PendingIntent> CREATOR = new Creator<PendingIntent>() {
         public PendingIntent createFromParcel(Parcel in) {
             IBinder target = in.readStrongBinder();
             return target != null
@@ -1400,11 +1360,11 @@
      * @hide
      */
     public PendingIntent(IIntentSender target) {
-        mTarget = target;
+        mTarget = Objects.requireNonNull(target);
     }
 
     /*package*/ PendingIntent(IBinder target, Object cookie) {
-        mTarget = IIntentSender.Stub.asInterface(target);
+        mTarget = Objects.requireNonNull(IIntentSender.Stub.asInterface(target));
         if (cookie != null) {
             mWhitelistToken = (IBinder)cookie;
         }
@@ -1433,4 +1393,16 @@
          */
         void onCancelled(PendingIntent intent);
     }
+
+    private PendingIntentInfo getCachedInfo() {
+        if (mCachedInfo == null) {
+            try {
+                mCachedInfo = ActivityManager.getService().getInfoForIntentSender(mTarget);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        return mCachedInfo;
+    }
 }
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 3798de9..2ceea7f 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -697,7 +697,8 @@
      * service element of manifest file. The value of attribute
      * {@link android.R.attr#foregroundServiceType} can be multiple flags ORed together.</p>
      *
-     * @throws IllegalStateException If the app targeting API is
+     * @throws ForegroundServiceStartNotAllowedException
+     * If the app targeting API is
      * {@link android.os.Build.VERSION_CODES#S} or later, and the service is restricted from
      * becoming foreground service due to background restriction.
      *
@@ -738,8 +739,14 @@
    * @param notification The Notification to be displayed.
    * @param foregroundServiceType must be a subset flags of manifest attribute
    * {@link android.R.attr#foregroundServiceType} flags.
+   *
    * @throws IllegalArgumentException if param foregroundServiceType is not subset of manifest
    *     attribute {@link android.R.attr#foregroundServiceType}.
+   * @throws ForegroundServiceStartNotAllowedException
+   * If the app targeting API is
+   * {@link android.os.Build.VERSION_CODES#S} or later, and the service is restricted from
+   * becoming foreground service due to background restriction.
+   *
    * @see android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_MANIFEST
    */
     public final void startForeground(int id, @NonNull Notification notification,
diff --git a/core/java/android/app/ServiceStartNotAllowedException.java b/core/java/android/app/ServiceStartNotAllowedException.java
new file mode 100644
index 0000000..33285b2
--- /dev/null
+++ b/core/java/android/app/ServiceStartNotAllowedException.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.annotation.NonNull;
+
+/**
+ * Exception thrown when an app tries to start a {@link Service} when it's not allowed to do so.
+ */
+public abstract class ServiceStartNotAllowedException extends IllegalStateException {
+    ServiceStartNotAllowedException(@NonNull String message) {
+        super(message);
+    }
+
+    /**
+     * Return either {@link ForegroundServiceStartNotAllowedException} or
+     * {@link BackgroundServiceStartNotAllowedException}
+     * @hide
+     */
+    @NonNull
+    public static ServiceStartNotAllowedException newInstance(boolean foreground,
+            @NonNull String message) {
+        if (foreground) {
+            return new ForegroundServiceStartNotAllowedException(message);
+        } else {
+            return new BackgroundServiceStartNotAllowedException(message);
+        }
+    }
+}
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 7d2bc1a..afcf63b 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -27,6 +27,7 @@
 import android.content.Context;
 import android.os.Binder;
 import android.os.Build;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -286,6 +287,23 @@
     }
 
     /**
+     * Simulate notification feedback for testing
+     *
+     * @hide
+     */
+    @TestApi
+    public void sendNotificationFeedback(@Nullable String key, @Nullable Bundle feedback) {
+        try {
+            final IStatusBarService svc = getService();
+            if (svc != null) {
+                svc.onNotificationFeedbackReceived(key, feedback);
+            }
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Expand the notifications panel.
      *
      * @hide
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index c47b546..e16e40b 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -47,6 +47,7 @@
 import android.app.usage.NetworkStatsManager;
 import android.app.usage.StorageStatsManager;
 import android.app.usage.UsageStatsManager;
+import android.apphibernation.AppHibernationManager;
 import android.appwidget.AppWidgetManager;
 import android.bluetooth.BluetoothManager;
 import android.companion.CompanionDeviceManager;
@@ -99,6 +100,7 @@
 import android.hardware.iris.IIrisService;
 import android.hardware.iris.IrisManager;
 import android.hardware.lights.LightsManager;
+import android.hardware.lights.SystemLightsManager;
 import android.hardware.location.ContextHubManager;
 import android.hardware.radio.RadioManager;
 import android.hardware.usb.IUsbManager;
@@ -211,6 +213,7 @@
 import android.view.autofill.IAutoFillManager;
 import android.view.contentcapture.ContentCaptureManager;
 import android.view.contentcapture.IContentCaptureManager;
+import android.view.displayhash.DisplayHashManager;
 import android.view.inputmethod.InputMethodManager;
 import android.view.textclassifier.TextClassificationManager;
 import android.view.textservice.TextServicesManager;
@@ -1343,7 +1346,7 @@
                 @Override
                 public LightsManager createService(ContextImpl ctx)
                     throws ServiceNotFoundException {
-                    return new LightsManager(ctx);
+                    return new SystemLightsManager(ctx);
                 }});
         registerService(Context.INCREMENTAL_SERVICE, IncrementalManager.class,
                 new CachedServiceFetcher<IncrementalManager>() {
@@ -1376,6 +1379,13 @@
                         IBinder b = ServiceManager.getServiceOrThrow(Context.APP_INTEGRITY_SERVICE);
                         return new AppIntegrityManager(IAppIntegrityManager.Stub.asInterface(b));
                     }});
+        registerService(Context.APP_HIBERNATION_SERVICE, AppHibernationManager.class,
+                new CachedServiceFetcher<AppHibernationManager>() {
+                    @Override
+                    public AppHibernationManager createService(ContextImpl ctx) {
+                        IBinder b = ServiceManager.getService(Context.APP_HIBERNATION_SERVICE);
+                        return b == null ? null : new AppHibernationManager(ctx);
+                    }});
         registerService(Context.DREAM_SERVICE, DreamManager.class,
                 new CachedServiceFetcher<DreamManager>() {
                     @Override
@@ -1426,6 +1436,13 @@
                     }
                 });
 
+        registerService(Context.DISPLAY_HASH_SERVICE, DisplayHashManager.class,
+                new CachedServiceFetcher<DisplayHashManager>() {
+                    @Override
+                    public DisplayHashManager createService(ContextImpl ctx) {
+                        return new DisplayHashManager();
+                    }});
+
         sInitializing = true;
         try {
             // Note: the following functions need to be @SystemApis, once they become mainline
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 517ae24..f523a7d 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -43,7 +43,7 @@
 
     @Override
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public void onActivityPinned(String packageName, int userId, int taskId, int stackId)
+    public void onActivityPinned(String packageName, int userId, int taskId, int rootTaskId)
             throws RemoteException {
     }
 
@@ -66,7 +66,7 @@
 
     @Override
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public void onActivityDismissingDockedStack() throws RemoteException {
+    public void onActivityDismissingDockedTask() throws RemoteException {
     }
 
     @Override
@@ -193,4 +193,8 @@
     @Override
     public void onTaskMovedToBack(RunningTaskInfo taskInfo) {
     }
+
+    @Override
+    public void onLockTaskModeChanged(int mode) {
+    }
 }
diff --git a/core/java/android/app/WallpaperColors.java b/core/java/android/app/WallpaperColors.java
index 2d203f57..0a8a734 100644
--- a/core/java/android/app/WallpaperColors.java
+++ b/core/java/android/app/WallpaperColors.java
@@ -16,9 +16,9 @@
 
 package android.app;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.SystemApi;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -30,14 +30,19 @@
 import android.util.Size;
 
 import com.android.internal.graphics.ColorUtils;
+import com.android.internal.graphics.palette.CelebiQuantizer;
 import com.android.internal.graphics.palette.Palette;
-import com.android.internal.graphics.palette.VariationalKMeansQuantizer;
 import com.android.internal.util.ContrastColorUtil;
 
 import java.io.FileOutputStream;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * Provides information about the colors of a wallpaper.
@@ -47,6 +52,13 @@
  * or {@link WallpaperColors#getTertiaryColor()}.
  */
 public final class WallpaperColors implements Parcelable {
+    /**
+     * @hide
+     */
+    @IntDef(prefix = "HINT_", value = {HINT_SUPPORTS_DARK_TEXT, HINT_SUPPORTS_DARK_THEME},
+            flag = true)
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ColorsHints {}
 
     private static final boolean DEBUG_DARK_PIXELS = false;
 
@@ -54,18 +66,14 @@
      * Specifies that dark text is preferred over the current wallpaper for best presentation.
      * <p>
      * eg. A launcher may set its text color to black if this flag is specified.
-     * @hide
      */
-    @SystemApi
     public static final int HINT_SUPPORTS_DARK_TEXT = 1 << 0;
 
     /**
      * Specifies that dark theme is preferred over the current wallpaper for best presentation.
      * <p>
      * eg. A launcher may set its drawer color to black if this flag is specified.
-     * @hide
      */
-    @SystemApi
     public static final int HINT_SUPPORTS_DARK_THEME = 1 << 1;
 
     /**
@@ -94,16 +102,21 @@
     private static final float DARK_PIXEL_CONTRAST = 6f;
     private static final float MAX_DARK_AREA = 0.025f;
 
-    private final ArrayList<Color> mMainColors;
+    private final List<Color> mMainColors;
+    private final Map<Integer, Integer> mAllColors;
     private int mColorHints;
 
     public WallpaperColors(Parcel parcel) {
         mMainColors = new ArrayList<>();
+        mAllColors = new HashMap<>();
         final int count = parcel.readInt();
         for (int i = 0; i < count; i++) {
             final int colorInt = parcel.readInt();
             Color color = Color.valueOf(colorInt);
             mMainColors.add(color);
+
+            final int population = parcel.readInt();
+            mAllColors.put(colorInt, population);
         }
         mColorHints = parcel.readInt();
     }
@@ -166,39 +179,22 @@
         }
 
         final Palette palette = Palette
-                .from(bitmap)
-                .setQuantizer(new VariationalKMeansQuantizer())
-                .maximumColorCount(5)
-                .clearFilters()
+                .from(bitmap, new CelebiQuantizer())
+                .maximumColorCount(256)
                 .resizeBitmapArea(MAX_WALLPAPER_EXTRACTION_AREA)
                 .generate();
-
         // Remove insignificant colors and sort swatches by population
         final ArrayList<Palette.Swatch> swatches = new ArrayList<>(palette.getSwatches());
-        final float minColorArea = bitmap.getWidth() * bitmap.getHeight() * MIN_COLOR_OCCURRENCE;
-        swatches.removeIf(s -> s.getPopulation() < minColorArea);
         swatches.sort((a, b) -> b.getPopulation() - a.getPopulation());
 
         final int swatchesSize = swatches.size();
-        Color primary = null, secondary = null, tertiary = null;
 
-        swatchLoop:
+        final Map<Integer, Integer> populationByColor = new HashMap<>();
         for (int i = 0; i < swatchesSize; i++) {
-            Color color = Color.valueOf(swatches.get(i).getRgb());
-            switch (i) {
-                case 0:
-                    primary = color;
-                    break;
-                case 1:
-                    secondary = color;
-                    break;
-                case 2:
-                    tertiary = color;
-                    break;
-                default:
-                    // out of bounds
-                    break swatchLoop;
-            }
+            Palette.Swatch swatch = swatches.get(i);
+            int colorInt = swatch.getInt();
+            populationByColor.put(colorInt, swatch.getPopulation());
+
         }
 
         int hints = calculateDarkHints(bitmap);
@@ -207,7 +203,7 @@
             bitmap.recycle();
         }
 
-        return new WallpaperColors(primary, secondary, tertiary, HINT_FROM_BITMAP | hints);
+        return new WallpaperColors(populationByColor, HINT_FROM_BITMAP | hints);
     }
 
     /**
@@ -238,24 +234,25 @@
      * @param primaryColor Primary color.
      * @param secondaryColor Secondary color.
      * @param tertiaryColor Tertiary color.
-     * @param colorHints A combination of WallpaperColor hints.
-     * @see WallpaperColors#HINT_SUPPORTS_DARK_TEXT
+     * @param colorHints A combination of color hints.
      * @see WallpaperColors#fromBitmap(Bitmap)
      * @see WallpaperColors#fromDrawable(Drawable)
-     * @hide
      */
-    @SystemApi
     public WallpaperColors(@NonNull Color primaryColor, @Nullable Color secondaryColor,
-            @Nullable Color tertiaryColor, int colorHints) {
+            @Nullable Color tertiaryColor, @ColorsHints int colorHints) {
 
         if (primaryColor == null) {
             throw new IllegalArgumentException("Primary color should never be null.");
         }
 
         mMainColors = new ArrayList<>(3);
+        mAllColors = new HashMap<>();
+
         mMainColors.add(primaryColor);
+        mAllColors.put(primaryColor.toArgb(), 0);
         if (secondaryColor != null) {
             mMainColors.add(secondaryColor);
+            mAllColors.put(secondaryColor.toArgb(), 0);
         }
         if (tertiaryColor != null) {
             if (secondaryColor == null) {
@@ -263,8 +260,33 @@
                         + "secondaryColor is null");
             }
             mMainColors.add(tertiaryColor);
+            mAllColors.put(tertiaryColor.toArgb(), 0);
         }
+        mColorHints = colorHints;
+    }
 
+    /**
+     * Constructs a new object from a set of colors, where hints can be specified.
+     *
+     * @param populationByColor Map with keys of colors, and value representing the number of
+     *                          occurrences of color in the wallpaper.
+     * @param colorHints        A combination of color hints.
+     * @hide
+     * @see WallpaperColors#HINT_SUPPORTS_DARK_TEXT
+     * @see WallpaperColors#fromBitmap(Bitmap)
+     * @see WallpaperColors#fromDrawable(Drawable)
+     */
+    public WallpaperColors(@NonNull Map<Integer, Integer> populationByColor,
+            @ColorsHints int colorHints) {
+        mAllColors = populationByColor;
+
+        ArrayList<Map.Entry<Integer, Integer>> mapEntries = new ArrayList(
+                populationByColor.entrySet());
+        mapEntries.sort((a, b) ->
+                a.getValue().compareTo(b.getValue())
+        );
+        mMainColors = mapEntries.stream().map(entry -> Color.valueOf(entry.getKey())).collect(
+                Collectors.toList());
         mColorHints = colorHints;
     }
 
@@ -293,6 +315,9 @@
         for (int i = 0; i < count; i++) {
             Color color = mainColors.get(i);
             dest.writeInt(color.toArgb());
+            Integer population = mAllColors.get(color.toArgb());
+            int populationInt = (population != null) ? population : 0;
+            dest.writeInt(populationInt);
         }
         dest.writeInt(mColorHints);
     }
@@ -336,6 +361,17 @@
         return Collections.unmodifiableList(mMainColors);
     }
 
+    /**
+     * Map of all colors. Key is rgb integer, value is importance of color.
+     *
+     * @return List of colors.
+     * @hide
+     */
+    public @NonNull Map<Integer, Integer> getAllColors() {
+        return Collections.unmodifiableMap(mAllColors);
+    }
+
+
     @Override
     public boolean equals(@Nullable Object o) {
         if (o == null || getClass() != o.getClass()) {
@@ -353,27 +389,14 @@
     }
 
     /**
-     * Combination of WallpaperColor hints.
-     *
-     * @see WallpaperColors#HINT_SUPPORTS_DARK_TEXT
-     * @return True if dark text is supported.
-     * @hide
+     * Returns the color hints for this instance.
+     * @return The color hints.
      */
-    @SystemApi
-    public int getColorHints() {
+    public @ColorsHints int getColorHints() {
         return mColorHints;
     }
 
     /**
-     * @param colorHints Combination of WallpaperColors hints.
-     * @see WallpaperColors#HINT_SUPPORTS_DARK_TEXT
-     * @hide
-     */
-    public void setColorHints(int colorHints) {
-        mColorHints = colorHints;
-    }
-
-    /**
      * Checks if image is bright and clean enough to support light text.
      *
      * @param source What to read.
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index ac2f223..bd99348 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -66,6 +66,7 @@
 import android.os.StrictMode;
 import android.os.SystemProperties;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Pair;
 import android.view.Display;
@@ -107,6 +108,8 @@
     private static boolean DEBUG = false;
     private float mWallpaperXStep = -1;
     private float mWallpaperYStep = -1;
+    private static final @NonNull RectF LOCAL_COLOR_BOUNDS =
+            new RectF(0, 0, 1, 1);
 
     /** {@hide} */
     private static final String PROP_WALLPAPER = "ro.config.wallpaper";
@@ -114,6 +117,9 @@
     private static final String PROP_LOCK_WALLPAPER = "ro.config.lock_wallpaper";
     /** {@hide} */
     private static final String PROP_WALLPAPER_COMPONENT = "ro.config.wallpaper_component";
+    /** {@hide} */
+    private static final String VALUE_CMF_COLOR =
+            android.os.SystemProperties.get("ro.boot.hardware.color");
 
     /**
      * Activity Action: Show settings for choosing wallpaper. Do not use directly to construct
@@ -309,6 +315,8 @@
         private int mCachedWallpaperUserId;
         private Bitmap mDefaultWallpaper;
         private Handler mMainLooperHandler;
+        private ArrayMap<LocalWallpaperColorConsumer, ILocalWallpaperColorConsumer>
+                mLocalColorCallbacks = new ArrayMap<>();
 
         Globals(IWallpaperManager service, Looper looper) {
             mService = service;
@@ -350,6 +358,40 @@
             }
         }
 
+        private ILocalWallpaperColorConsumer wrap(LocalWallpaperColorConsumer callback) {
+            ILocalWallpaperColorConsumer callback2 = new ILocalWallpaperColorConsumer.Stub() {
+                @Override
+                public void onColorsChanged(RectF area, WallpaperColors colors) {
+                    callback.onColorsChanged(area, colors);
+                }
+            };
+            mLocalColorCallbacks.put(callback, callback2);
+            return callback2;
+        }
+
+        public void addOnColorsChangedListener(@NonNull LocalWallpaperColorConsumer callback,
+                @NonNull List<RectF> regions, int which, int userId, int displayId) {
+            try {
+                mService.addOnLocalColorsChangedListener(wrap(callback) , regions, which,
+                                                         userId, displayId);
+            } catch (RemoteException e) {
+                // Can't get colors, connection lost.
+            }
+        }
+
+        public void removeOnColorsChangedListener(
+                @NonNull LocalWallpaperColorConsumer callback, int which, int userId,
+                int displayId) {
+            ILocalWallpaperColorConsumer callback2 = mLocalColorCallbacks.remove(callback);
+            if (callback2 == null) return;
+            try {
+                mService.removeOnLocalColorsChangedListener(
+                        callback2, which, userId, displayId);
+            } catch (RemoteException e) {
+                // Can't get colors, connection lost.
+            }
+        }
+
         /**
          * Stop listening to wallpaper color events.
          *
@@ -1057,6 +1099,29 @@
     }
 
     /**
+     * @hide
+     */
+    public void addOnColorsChangedListener(@NonNull LocalWallpaperColorConsumer callback,
+            List<RectF> regions) throws IllegalArgumentException {
+        for (RectF region : regions) {
+            if (!LOCAL_COLOR_BOUNDS.contains(region)) {
+                throw new IllegalArgumentException("Regions must be within bounds "
+                        + LOCAL_COLOR_BOUNDS);
+            }
+        }
+        sGlobals.addOnColorsChangedListener(callback, regions, FLAG_SYSTEM,
+                                                 mContext.getUserId(), mContext.getDisplayId());
+    }
+
+    /**
+     * @hide
+     */
+    public void removeOnColorsChangedListener(@NonNull LocalWallpaperColorConsumer callback) {
+        sGlobals.removeOnColorsChangedListener(callback, FLAG_SYSTEM, mContext.getUserId(),
+                mContext.getDisplayId());
+    }
+
+    /**
      * Version of {@link #getWallpaperFile(int)} that can access the wallpaper data
      * for a given user.  The caller must hold the INTERACT_ACROSS_USERS_FULL
      * permission to access another user's wallpaper data.
@@ -2002,7 +2067,11 @@
             return null;
         } else {
             whichProp = PROP_WALLPAPER;
-            defaultResId = com.android.internal.R.drawable.default_wallpaper;
+            final int defaultColorResId = context.getResources().getIdentifier(
+                    "default_wallpaper_" + VALUE_CMF_COLOR, "drawable", "android");
+            defaultResId =
+                    defaultColorResId == 0 ? com.android.internal.R.drawable.default_wallpaper
+                            : defaultColorResId;
         }
         final String path = SystemProperties.get(whichProp);
         if (!TextUtils.isEmpty(path)) {
@@ -2202,4 +2271,18 @@
             onColorsChanged(colors, which);
         }
     }
+
+    /**
+     * Callback to update a consumer with a local color change
+     * @hide
+     */
+    public interface LocalWallpaperColorConsumer {
+
+        /**
+         * Gets called when a color of an area gets updated
+         * @param area
+         * @param colors
+         */
+        void onColorsChanged(RectF area, WallpaperColors colors);
+    }
 }
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index 4ae1670..d04ca1d9 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -57,7 +57,7 @@
      * TODO: Investigate combining with {@link #mAppBounds}. Can the latter be a product of the
      * former?
      */
-    private Rect mBounds = new Rect();
+    private final Rect mBounds = new Rect();
 
     /**
      * {@link android.graphics.Rect} defining app bounds. The dimensions override usages of
@@ -71,7 +71,7 @@
      * The maximum {@link Rect} bounds that an app can expect. It is used to report value of
      * {@link WindowManager#getMaximumWindowMetrics()}.
      */
-    private Rect mMaxBounds = new Rect();
+    private final Rect mMaxBounds = new Rect();
 
     /**
      * The current rotation of this window container relative to the default
@@ -240,9 +240,9 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeParcelable(mBounds, flags);
-        dest.writeParcelable(mAppBounds, flags);
-        dest.writeParcelable(mMaxBounds, flags);
+        mBounds.writeToParcel(dest, flags);
+        dest.writeTypedObject(mAppBounds, flags);
+        mMaxBounds.writeToParcel(dest, flags);
         dest.writeInt(mWindowingMode);
         dest.writeInt(mActivityType);
         dest.writeInt(mAlwaysOnTop);
@@ -250,10 +250,11 @@
         dest.writeInt(mDisplayWindowingMode);
     }
 
-    private void readFromParcel(Parcel source) {
-        mBounds = source.readParcelable(Rect.class.getClassLoader());
-        mAppBounds = source.readParcelable(Rect.class.getClassLoader());
-        mMaxBounds = source.readParcelable(Rect.class.getClassLoader());
+    /** @hide */
+    public void readFromParcel(@NonNull Parcel source) {
+        mBounds.readFromParcel(source);
+        mAppBounds = source.readTypedObject(Rect.CREATOR);
+        mMaxBounds.readFromParcel(source);
         mWindowingMode = source.readInt();
         mActivityType = source.readInt();
         mAlwaysOnTop = source.readInt();
@@ -693,9 +694,7 @@
         }
         protoOutputStream.write(WINDOWING_MODE, mWindowingMode);
         protoOutputStream.write(ACTIVITY_TYPE, mActivityType);
-        if (mBounds != null) {
-            mBounds.dumpDebug(protoOutputStream, BOUNDS);
-        }
+        mBounds.dumpDebug(protoOutputStream, BOUNDS);
         mMaxBounds.dumpDebug(protoOutputStream, MAX_BOUNDS);
         protoOutputStream.end(token);
     }
@@ -719,11 +718,9 @@
                         mAppBounds.readFromProto(proto, APP_BOUNDS);
                         break;
                     case (int) BOUNDS:
-                        mBounds = new Rect();
                         mBounds.readFromProto(proto, BOUNDS);
                         break;
                     case (int) MAX_BOUNDS:
-                        mMaxBounds = new Rect();
                         mMaxBounds.readFromProto(proto, MAX_BOUNDS);
                         break;
                     case (int) WINDOWING_MODE:
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index 4dbff0c..cccc929 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -585,6 +585,9 @@
      * @param intent The received intent as per {@link #onReceive}.
      */
     public void onEnabled(@NonNull Context context, @NonNull Intent intent) {
+        if (LOCAL_LOGV) {
+            Log.v(TAG, getClass().getName() + ".onEnabled() on user " + context.getUserId());
+        }
     }
 
     /**
@@ -600,6 +603,10 @@
      */
     public @Nullable CharSequence onDisableRequested(@NonNull Context context,
             @NonNull Intent intent) {
+        if (LOCAL_LOGV) {
+            Log.v(TAG, getClass().getName() + ".onDisableRequested() on user "
+                    + context.getUserId());
+        }
         return null;
     }
 
@@ -612,6 +619,9 @@
      * @param intent The received intent as per {@link #onReceive}.
      */
     public void onDisabled(@NonNull Context context, @NonNull Intent intent) {
+        if (LOCAL_LOGV) {
+            Log.v(TAG, getClass().getName() + ".onDisabled() on user " + context.getUserId());
+        }
     }
 
     /**
@@ -786,6 +796,10 @@
      * @param intent The received intent as per {@link #onReceive}.
      */
     public void onProfileProvisioningComplete(@NonNull Context context, @NonNull Intent intent) {
+        if (LOCAL_LOGV) {
+            Log.v(TAG, getClass().getName() + ".onProfileProvisioningComplete() on user "
+                    + context.getUserId());
+        }
     }
 
     /**
@@ -961,6 +975,9 @@
      */
     public void onUserAdded(@NonNull Context context, @NonNull Intent intent,
             @NonNull UserHandle addedUser) {
+        if (LOCAL_LOGV) {
+            Log.v(TAG, getClass().getName() + ".onUserAdded() on user " + context.getUserId());
+        }
     }
 
     /**
@@ -974,6 +991,9 @@
      */
     public void onUserRemoved(@NonNull Context context, @NonNull Intent intent,
             @NonNull UserHandle removedUser) {
+        if (LOCAL_LOGV) {
+            Log.v(TAG, getClass().getName() + ".onUserRemoved() on user " + context.getUserId());
+        }
     }
 
     /**
@@ -987,6 +1007,9 @@
      */
     public void onUserStarted(@NonNull Context context, @NonNull Intent intent,
             @NonNull UserHandle startedUser) {
+        if (LOCAL_LOGV) {
+            Log.v(TAG, getClass().getName() + ".onUserStarted() on user " + context.getUserId());
+        }
     }
 
     /**
@@ -1000,6 +1023,9 @@
      */
     public void onUserStopped(@NonNull Context context, @NonNull Intent intent,
             @NonNull UserHandle stoppedUser) {
+        if (LOCAL_LOGV) {
+            Log.v(TAG, getClass().getName() + ".onUserStopped() on user " + context.getUserId());
+        }
     }
 
     /**
@@ -1013,6 +1039,9 @@
      */
     public void onUserSwitched(@NonNull Context context, @NonNull Intent intent,
             @NonNull UserHandle switchedUser) {
+        if (LOCAL_LOGV) {
+            Log.v(TAG, getClass().getName() + ".onUserSwitched() on user " + context.getUserId());
+        }
     }
 
     /**
@@ -1073,6 +1102,7 @@
     private void onOperationSafetyStateChanged(Context context, Intent intent) {
         if (!hasRequiredExtra(intent, EXTRA_OPERATION_SAFETY_REASON)
                 || !hasRequiredExtra(intent, EXTRA_OPERATION_SAFETY_STATE)) {
+            Log.w(TAG, "Igoring intent that's missing required extras");
             return;
         }
 
@@ -1084,7 +1114,6 @@
         }
         boolean isSafe = intent.getBooleanExtra(EXTRA_OPERATION_SAFETY_STATE,
                 /* defaultValue=*/ false);
-
         onOperationSafetyStateChanged(context, reason, isSafe);
     }
 
@@ -1104,7 +1133,8 @@
     public void onReceive(@NonNull Context context, @NonNull Intent intent) {
         String action = intent.getAction();
         if (LOCAL_LOGV) {
-            Log.v(TAG, "onReceive(): received " + action + " on user " + context.getUserId());
+            Log.v(TAG, getClass().getName() + ".onReceive(): received " + action + " on user "
+                    + context.getUserId());
         }
 
         if (ACTION_PASSWORD_CHANGED.equals(action)) {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 59e5144..b919bfc 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2746,6 +2746,32 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface PersonalAppsSuspensionReason {}
 
+    /**
+     * The default device owner type for a managed device.
+     *
+     * @hide
+     */
+    public static final int DEVICE_OWNER_TYPE_DEFAULT = 0;
+
+    /**
+     * The device owner type for a financed device.
+     *
+     * @hide
+     */
+    public static final int DEVICE_OWNER_TYPE_FINANCED = 1;
+
+    /**
+     * Different device owner types for a managed device.
+     *
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "DEVICE_OWNER_TYPE_" }, value = {
+            DEVICE_OWNER_TYPE_DEFAULT,
+            DEVICE_OWNER_TYPE_FINANCED
+    })
+    public @interface DeviceOwnerType {}
+
     /** @hide */
     @TestApi
     public static final int OPERATION_LOCK_NOW = 1;
@@ -7276,7 +7302,12 @@
     /**
      * @hide
      */
+    @TestApi
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.MANAGE_DEVICE_ADMINS,
+            android.Manifest.permission.INTERACT_ACROSS_USERS_FULL
+    })
     public void setActiveAdmin(@NonNull ComponentName policyReceiver, boolean refreshing,
             int userHandle) {
         if (mService != null) {
@@ -7453,8 +7484,10 @@
      * @throws IllegalArgumentException if the package name is null or invalid
      * @throws IllegalStateException If the preconditions mentioned are not met.
      */
-    public boolean setDeviceOwner(ComponentName who, String ownerName, int userId)
-            throws IllegalArgumentException, IllegalStateException {
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
+    public boolean setDeviceOwner(
+            @NonNull ComponentName who, @Nullable String ownerName, @UserIdInt int userId) {
         if (mService != null) {
             try {
                 return mService.setDeviceOwner(who, ownerName, userId);
@@ -7521,7 +7554,10 @@
      * @hide
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS,
+    })
     public ComponentName getDeviceOwnerComponentOnAnyUser() {
         return getDeviceOwnerComponentInner(/* callingUserOnly =*/ false);
     }
@@ -10477,9 +10513,10 @@
 
     /**
      * Reset record of previous system update freeze period the device went through.
-     * Only callable by ADB.
      * @hide
      */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.CLEAR_FREEZE_PERIOD)
     public void clearSystemUpdatePolicyFreezePeriodRecord() {
         throwIfParentInstance("clearSystemUpdatePolicyFreezePeriodRecord");
         if (mService == null) {
@@ -11207,9 +11244,11 @@
 
     /**
      * Makes all accumulated network logs available to DPC in a new batch.
-     * Only callable by ADB. If throttled, returns time to wait in milliseconds, otherwise 0.
+     * If throttled, returns time to wait in milliseconds, otherwise 0.
      * @hide
      */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS)
     public long forceNetworkLogs() {
         if (mService == null) {
             return -1;
@@ -11223,9 +11262,11 @@
 
     /**
      * Forces a batch of security logs to be fetched from logd and makes it available for DPC.
-     * Only callable by ADB. If throttled, returns time to wait in milliseconds, otherwise 0.
+     * If throttled, returns time to wait in milliseconds, otherwise 0.
      * @hide
      */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS)
     public long forceSecurityLogs() {
         if (mService == null) {
             return 0;
@@ -11657,7 +11698,10 @@
      * @throws SecurityException if the caller is not shell / root or the admin package
      *         isn't a test application see {@link ApplicationInfo#FLAG_TEST_APP}.
      */
-    public void forceRemoveActiveAdmin(ComponentName adminReceiver, int userHandle) {
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
+    public void forceRemoveActiveAdmin(
+            @NonNull ComponentName adminReceiver, @UserIdInt int userHandle) {
         try {
             mService.forceRemoveActiveAdmin(adminReceiver, userHandle);
         } catch (RemoteException re) {
@@ -12195,8 +12239,9 @@
      *
      * @hide
      */
-    public Set<String> getDisallowedSystemApps(ComponentName admin, int userId,
-            String provisioningAction) {
+    @TestApi
+    public @NonNull Set<String> getDisallowedSystemApps(@NonNull ComponentName admin,
+            @UserIdInt int userId, @NonNull String provisioningAction) {
         try {
             return new ArraySet<>(
                     mService.getDisallowedSystemApps(admin, userId, provisioningAction));
@@ -12727,8 +12772,11 @@
      *
      * @hide
      */
-    @RequiresPermission(value = android.Manifest.permission.MARK_DEVICE_ORGANIZATION_OWNED,
-            conditional = true)
+    @TestApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MARK_DEVICE_ORGANIZATION_OWNED,
+            android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS
+    }, conditional = true)
     public void markProfileOwnerOnOrganizationOwnedDevice(@NonNull ComponentName who) {
         if (mService == null) {
             return;
@@ -12957,6 +13005,7 @@
      *
      * @hide
      */
+    @TestApi
     public @NonNull Set<String> getDefaultCrossProfilePackages() {
         throwIfParentInstance("getDefaultCrossProfilePackages");
         if (mService != null) {
@@ -13460,6 +13509,57 @@
     }
 
     /**
+     * Sets the device owner type for a managed device (e.g. financed device).
+     *
+     * @param admin The {@link DeviceAdminReceiver} that is the device owner.
+     * @param deviceOwnerType The device owner type is set to. Use
+     * {@link #DEVICE_OWNER_TYPE_DEFAULT} for the default device owner type. Use
+     * {@link #DEVICE_OWNER_TYPE_FINANCED} for the financed device owner type.
+     *
+     * @throws IllegalStateException When admin is not the device owner, or there is no device
+     *     owner, or attempting to set the device owner type again for the same admin.
+     * @throws SecurityException If the caller does not have the permission
+     *     {@link permission#MANAGE_PROFILE_AND_DEVICE_OWNERS}.
+     *
+     * @hide
+     */
+    public void setDeviceOwnerType(@NonNull ComponentName admin,
+            @DeviceOwnerType int deviceOwnerType) {
+        throwIfParentInstance("setDeviceOwnerType");
+        if (mService != null) {
+            try {
+                mService.setDeviceOwnerType(admin, deviceOwnerType);
+            } catch (RemoteException re) {
+                throw re.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * Returns the device owner type for the admin used in
+     * {@link #setDeviceOwnerType(ComponentName, int)}. {@link #DEVICE_OWNER_TYPE_DEFAULT}
+     * would be returned when the device owner type is not set for the device owner admin.
+     *
+     * @param admin The {@link DeviceAdminReceiver} that is the device owner.
+     *
+     * @throws IllegalStateException When admin is not the device owner or there is no device owner.
+     *
+     * @hide
+     */
+    @DeviceOwnerType
+    public int getDeviceOwnerType(@NonNull ComponentName admin) {
+        throwIfParentInstance("getDeviceOwnerType");
+        if (mService != null) {
+            try {
+                return mService.getDeviceOwnerType(admin);
+            } catch (RemoteException re) {
+                throw re.rethrowFromSystemServer();
+            }
+        }
+        return DEVICE_OWNER_TYPE_DEFAULT;
+    }
+
+    /**
      * Called by device owner or profile owner of an organization-owned managed profile to
      * enable or disable USB data signaling for the device. When disabled, USB data connections
      * (except from charging functions) are prohibited.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 8a87b16..ac1592d 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -503,6 +503,9 @@
     UserHandle createAndProvisionManagedProfile(in ManagedProfileProvisioningParams provisioningParams, in String callerPackage);
     void provisionFullyManagedDevice(in FullyManagedDeviceProvisioningParams provisioningParams, in String callerPackage);
 
+    void setDeviceOwnerType(in ComponentName admin, in int deviceOwnerType);
+    int getDeviceOwnerType(in ComponentName admin);
+
     void resetDefaultCrossProfileIntentFilters(int userId);
     boolean canAdminGrantSensorsPermissionsForUser(int userId);
 
diff --git a/core/java/android/app/assist/ActivityId.java b/core/java/android/app/assist/ActivityId.java
new file mode 100644
index 0000000..fb0d056
--- /dev/null
+++ b/core/java/android/app/assist/ActivityId.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.assist;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.service.contentcapture.ContentCaptureService;
+import android.view.contentcapture.ContentCaptureContext;
+import android.view.translation.UiTranslationManager;
+
+import com.android.internal.annotations.Immutable;
+
+/**
+ * The class is used to identify an instance of an Activity. The system provides this to services
+ * that need to request operations on a specific Activity. For example, the system provides this in
+ * {@link ContentCaptureContext} to {@link ContentCaptureService} which can use it to issue requests
+ * like {@link UiTranslationManager#startTranslation}.
+ *
+ * @hide
+ */
+@Immutable
+@SystemApi
+public class ActivityId {
+
+    /**
+     * The identifier of the task this activity is in.
+     */
+    private final int mTaskId;
+    /**
+     * The identifier of the activity.
+     */
+    @Nullable
+    private final IBinder mActivityId;
+
+    /**
+     * @hide
+     */
+    public ActivityId(int taskId, @Nullable IBinder activityId) {
+        mTaskId = taskId;
+        mActivityId = activityId;
+    }
+
+    /**
+     * @hide
+     */
+    public ActivityId(@NonNull Parcel source) {
+        mTaskId = source.readInt();
+        mActivityId = source.readStrongBinder();
+    }
+
+    /**
+     * The identifier of the task this activity is in.
+     * @hide
+     */
+    @TestApi
+    public int getTaskId() {
+        return mTaskId;
+    }
+
+    /**
+     * The identifier of the activity. In some case, this value may be null, e.g. the child session
+     * of content capture.
+     * @hide
+     */
+    @Nullable
+    @TestApi
+    public IBinder getToken() {
+        return mActivityId;
+    }
+
+    /**
+     * @hide
+     */
+    public void writeToParcel(@NonNull Parcel dest, int parcelableFlags) {
+        dest.writeInt(mTaskId);
+        dest.writeStrongBinder(mActivityId);
+    }
+
+    @Override
+    public String toString() {
+        return "ActivityId { taskId = " + mTaskId + ", activityId = " + mActivityId + " }";
+    }
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        ActivityId that = (ActivityId) o;
+        if (mTaskId != that.mTaskId) {
+            return false;
+        }
+        return mActivityId != null
+                ? mActivityId.equals(that.mActivityId)
+                : that.mActivityId == null;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = mTaskId;
+        result = 31 * result + (mActivityId != null ? mActivityId.hashCode() : 0);
+        return result;
+    }
+}
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 85cfe83..22492cc 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -564,10 +564,6 @@
     @VisibleForTesting
     public IncludeExcludeRules getIncludeExcludeRules(FullBackup.BackupScheme backupScheme)
             throws IOException, XmlPullParserException {
-        if (isDeviceToDeviceMigration()) {
-            return IncludeExcludeRules.emptyRules();
-        }
-
         Map<String, Set<PathWithRequiredFlags>> manifestIncludeMap;
         ArraySet<PathWithRequiredFlags> manifestExcludeSet;
 
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 673de8f..dae565e 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -361,36 +361,7 @@
             try {
                 // All packages, current transport
                 IRestoreSession binder =
-                        sService.beginRestoreSessionForUser(mContext.getUserId(), null, null,
-                                OperationType.BACKUP);
-                if (binder != null) {
-                    session = new RestoreSession(mContext, binder);
-                }
-            } catch (RemoteException e) {
-                Log.e(TAG, "beginRestoreSession() couldn't connect");
-            }
-        }
-        return session;
-    }
-
-    /**
-     * Begin the process of restoring data from backup.  See the
-     * {@link android.app.backup.RestoreSession} class for documentation on that process.
-     *
-     * @param operationType Type of the operation, see {@link OperationType}
-     *
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.BACKUP)
-    public RestoreSession beginRestoreSession(@OperationType int operationType) {
-        RestoreSession session = null;
-        checkServiceBinder();
-        if (sService != null) {
-            try {
-                // All packages, current transport
-                IRestoreSession binder =
-                        sService.beginRestoreSessionForUser(mContext.getUserId(), null, null,
-                                operationType);
+                        sService.beginRestoreSessionForUser(mContext.getUserId(), null, null);
                 if (binder != null) {
                     session = new RestoreSession(mContext, binder);
                 }
@@ -801,7 +772,7 @@
     @SystemApi
     @RequiresPermission(android.Manifest.permission.BACKUP)
     public int requestBackup(String[] packages, BackupObserver observer) {
-        return requestBackup(packages, observer, null, 0, OperationType.BACKUP);
+        return requestBackup(packages, observer, null, 0);
     }
 
     /**
@@ -826,31 +797,6 @@
     @RequiresPermission(android.Manifest.permission.BACKUP)
     public int requestBackup(String[] packages, BackupObserver observer,
             BackupManagerMonitor monitor, int flags) {
-        return requestBackup(packages, observer, monitor, flags, OperationType.BACKUP);
-    }
-
-    /**
-     * Request an immediate backup, providing an observer to which results of the backup operation
-     * will be published. The Android backup system will decide for each package whether it will
-     * be full app data backup or key/value-pair-based backup.
-     *
-     * <p>If this method returns {@link BackupManager#SUCCESS}, the OS will attempt to backup all
-     * provided packages using the remote transport.
-     *
-     * @param packages List of package names to backup.
-     * @param observer The {@link BackupObserver} to receive callbacks during the backup
-     *                 operation. Could be {@code null}.
-     * @param monitor  The {@link BackupManagerMonitorWrapper} to receive callbacks of important
-     *                 events during the backup operation. Could be {@code null}.
-     * @param flags    {@link #FLAG_NON_INCREMENTAL_BACKUP}.
-     * @param operationType {@link OperationType}
-     * @return {@link BackupManager#SUCCESS} on success; nonzero on error.
-     * @throws IllegalArgumentException on null or empty {@code packages} param.
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.BACKUP)
-    public int requestBackup(String[] packages, BackupObserver observer,
-            BackupManagerMonitor monitor, int flags, @OperationType int operationType) {
         checkServiceBinder();
         if (sService != null) {
             try {
@@ -860,8 +806,7 @@
                 BackupManagerMonitorWrapper monitorWrapper = monitor == null
                         ? null
                         : new BackupManagerMonitorWrapper(monitor);
-                return sService.requestBackup(packages, observerWrapper, monitorWrapper, flags,
-                        operationType);
+                return sService.requestBackup(packages, observerWrapper, monitorWrapper, flags);
             } catch (RemoteException e) {
                 Log.e(TAG, "requestBackup() couldn't connect");
             }
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index f7ed6f1f..829b6cd 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -19,10 +19,16 @@
 import static android.app.backup.BackupManager.OperationType;
 
 import android.annotation.Nullable;
+import android.annotation.StringDef;
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.res.XmlResourceParser;
+import android.os.Build;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.storage.StorageManager;
@@ -33,6 +39,7 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
+import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -94,6 +101,23 @@
             "fakeClientSideEncryption";
 
     /**
+     * When  this change is enabled, include / exclude rules specified via
+     * {@code android:fullBackupContent} are ignored during D2D transfers.
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S)
+    private static final long IGNORE_FULL_BACKUP_CONTENT_IN_D2D = 180523564L;
+
+    @StringDef({
+        ConfigSection.CLOUD_BACKUP,
+        ConfigSection.DEVICE_TRANSFER
+    })
+    private @interface ConfigSection {
+        String CLOUD_BACKUP = "cloud-backup";
+        String DEVICE_TRANSFER = "device-transfer";
+    }
+
+    /**
      * Identify {@link BackupScheme} object by package and operation type
      * (see {@link OperationType}) it corresponds to.
      */
@@ -273,6 +297,7 @@
         private final static String TAG_INCLUDE = "include";
         private final static String TAG_EXCLUDE = "exclude";
 
+        final int mDataExtractionRules;
         final int mFullBackupContent;
         @OperationType final int mOperationType;
         final PackageManager mPackageManager;
@@ -394,7 +419,10 @@
         ArraySet<PathWithRequiredFlags> mExcludes;
 
         BackupScheme(Context context, @OperationType int operationType) {
-            mFullBackupContent = context.getApplicationInfo().fullBackupContent;
+            ApplicationInfo applicationInfo = context.getApplicationInfo();
+
+            mDataExtractionRules = applicationInfo.dataExtractionRulesRes;
+            mFullBackupContent = applicationInfo.fullBackupContent;
             mOperationType = operationType;
             mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
             mPackageManager = context.getPackageManager();
@@ -468,34 +496,101 @@
             mIncludes = new ArrayMap<String, Set<PathWithRequiredFlags>>();
             mExcludes = new ArraySet<PathWithRequiredFlags>();
 
-            if (mFullBackupContent == 0) {
-                // android:fullBackupContent="true" which means that we'll do everything.
+            if (mFullBackupContent == 0 && mDataExtractionRules == 0) {
+                // No scheme specified via either new or legacy config, will copy everything.
                 if (Log.isLoggable(FullBackup.TAG_XML_PARSER, Log.VERBOSE)) {
                     Log.v(FullBackup.TAG_XML_PARSER, "android:fullBackupContent - \"true\"");
                 }
             } else {
-                // android:fullBackupContent="@xml/some_resource".
+                // Scheme is present.
                 if (Log.isLoggable(FullBackup.TAG_XML_PARSER, Log.VERBOSE)) {
-                    Log.v(FullBackup.TAG_XML_PARSER,
-                            "android:fullBackupContent - found xml resource");
+                    Log.v(FullBackup.TAG_XML_PARSER, "Found xml scheme: "
+                            + "android:fullBackupContent=" + mFullBackupContent
+                            + "; android:dataExtractionRules=" + mDataExtractionRules);
                 }
-                XmlResourceParser parser = null;
+
                 try {
-                    parser = mPackageManager
-                            .getResourcesForApplication(mPackageName)
-                            .getXml(mFullBackupContent);
-                    parseBackupSchemeFromXmlLocked(parser, mExcludes, mIncludes);
+                    parseSchemeForOperationType(mOperationType);
                 } catch (PackageManager.NameNotFoundException e) {
                     // Throw it as an IOException
                     throw new IOException(e);
-                } finally {
-                    if (parser != null) {
-                        parser.close();
-                    }
                 }
             }
         }
 
+        private void parseSchemeForOperationType(@OperationType int operationType)
+                throws PackageManager.NameNotFoundException, IOException, XmlPullParserException {
+            String configSection = getConfigSectionForOperationType(operationType);
+            if (configSection == null) {
+                Slog.w(TAG, "Given operation type isn't supported by backup scheme: "
+                        + operationType);
+                return;
+            }
+
+            if (mDataExtractionRules != 0) {
+                // New config is present. Use it if it has configuration for this operation
+                // type.
+                try (XmlResourceParser parser = getParserForResource(mDataExtractionRules)) {
+                    parseNewBackupSchemeFromXmlLocked(parser, configSection, mExcludes, mIncludes);
+                }
+                if (!mExcludes.isEmpty() || !mIncludes.isEmpty()) {
+                    // Found configuration in the new config, we will use it.
+                    return;
+                }
+            }
+
+            if (operationType == OperationType.MIGRATION
+                    && CompatChanges.isChangeEnabled(IGNORE_FULL_BACKUP_CONTENT_IN_D2D)) {
+                return;
+            }
+
+            if (mFullBackupContent != 0) {
+                // Fall back to the old config.
+                try (XmlResourceParser parser = getParserForResource(mFullBackupContent)) {
+                    parseBackupSchemeFromXmlLocked(parser, mExcludes, mIncludes);
+                }
+            }
+        }
+
+        @Nullable
+        private String getConfigSectionForOperationType(@OperationType int operationType)  {
+            switch (operationType) {
+                case OperationType.BACKUP:
+                    return ConfigSection.CLOUD_BACKUP;
+                case OperationType.MIGRATION:
+                    return ConfigSection.DEVICE_TRANSFER;
+                default:
+                    return null;
+            }
+        }
+
+        private XmlResourceParser getParserForResource(int resourceId)
+                throws PackageManager.NameNotFoundException {
+            return mPackageManager
+                    .getResourcesForApplication(mPackageName)
+                    .getXml(resourceId);
+        }
+
+        private void parseNewBackupSchemeFromXmlLocked(XmlPullParser parser,
+                @ConfigSection  String configSection,
+                Set<PathWithRequiredFlags> excludes,
+                Map<String, Set<PathWithRequiredFlags>> includes)
+                throws IOException, XmlPullParserException {
+            verifyTopLevelTag(parser, "data-extraction-rules");
+
+            int event;
+            while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+                if (event != XmlPullParser.START_TAG || !configSection.equals(parser.getName())) {
+                    continue;
+                }
+
+                // TODO(b/180523028): Parse required attributes for rules (e.g. encryption).
+                parseRules(parser, excludes, includes, Optional.of(0), configSection);
+            }
+
+            logParsingResults(excludes, includes);
+        }
+
         @VisibleForTesting
         public void parseBackupSchemeFromXmlLocked(XmlPullParser parser,
                                                    Set<PathWithRequiredFlags> excludes,
@@ -503,7 +598,7 @@
                 throws IOException, XmlPullParserException {
             verifyTopLevelTag(parser, "full-backup-content");
 
-            parseRules(parser, excludes, includes, Optional.empty());
+            parseRules(parser, excludes, includes, Optional.empty(), "full-backup-content");
 
             logParsingResults(excludes, includes);
         }
@@ -532,10 +627,12 @@
         private void parseRules(XmlPullParser parser,
                 Set<PathWithRequiredFlags> excludes,
                 Map<String, Set<PathWithRequiredFlags>> includes,
-                Optional<Integer> maybeRequiredFlags)
+                Optional<Integer> maybeRequiredFlags,
+                String endingTag)
                 throws IOException, XmlPullParserException {
             int event;
-            while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+            while ((event = parser.next()) != XmlPullParser.END_DOCUMENT
+                    && !parser.getName().equals(endingTag)) {
                 switch (event) {
                     case XmlPullParser.START_TAG:
                         validateInnerTagContents(parser);
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index e1bbc08..bf5be95 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -547,11 +547,9 @@
      *        set can be restored.
      * @param transportID The name of the transport to use for the restore operation.
      *        May be null, in which case the current active transport is used.
-     * @param operationType Type of the operation, see {@link BackupManager#OperationType}
      * @return An interface to the restore session, or null on error.
      */
-    IRestoreSession beginRestoreSessionForUser(int userId, String packageName, String transportID,
-            int operationType);
+    IRestoreSession beginRestoreSessionForUser(int userId, String packageName, String transportID);
 
     /**
      * Notify the backup manager that a BackupAgent has completed the operation
@@ -680,7 +678,7 @@
      * {@link android.app.backup.IBackupManager.requestBackupForUser} for the calling user id.
      */
     int requestBackup(in String[] packages, IBackupObserver observer, IBackupManagerMonitor monitor,
-        int flags, int operationType);
+            int flags);
 
     /**
      * Cancel all running backups. After this call returns, no currently running backups will
diff --git a/core/java/android/app/contentsuggestions/ContentSuggestionsManager.java b/core/java/android/app/contentsuggestions/ContentSuggestionsManager.java
index b3f9e31..33f8302 100644
--- a/core/java/android/app/contentsuggestions/ContentSuggestionsManager.java
+++ b/core/java/android/app/contentsuggestions/ContentSuggestionsManager.java
@@ -19,7 +19,9 @@
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.annotation.UserIdInt;
 import android.graphics.Bitmap;
 import android.os.Binder;
@@ -220,6 +222,72 @@
     }
 
     /**
+     * Resets the temporary service implementation to the default component.
+     *
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_CONTENT_SUGGESTIONS)
+    public void resetTemporaryService(@UserIdInt int userId) {
+        if (mService == null) {
+            Log.e(TAG, "resetTemporaryService called, but no ContentSuggestionsManager "
+                    + "configured");
+            return;
+        }
+        try {
+            mService.resetTemporaryService(userId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Temporarily sets the service implementation.
+     *
+     * @param userId user Id to set the temporary service on.
+     * @param serviceName name of the new component
+     * @param duration how long the change will be valid (the service will be automatically reset
+     *            to the default component after this timeout expires).
+     *
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_CONTENT_SUGGESTIONS)
+    public void setTemporaryService(
+            @UserIdInt int userId, @NonNull String serviceName, int duration) {
+        if (mService == null) {
+            Log.e(TAG, "setTemporaryService called, but no ContentSuggestionsManager "
+                    + "configured");
+            return;
+        }
+        try {
+            mService.setTemporaryService(userId, serviceName, duration);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Sets whether the default service should be used.
+     *
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_CONTENT_SUGGESTIONS)
+    public void setDefaultServiceEnabled(@UserIdInt int userId, boolean enabled) {
+        if (mService == null) {
+            Log.e(TAG, "setDefaultServiceEnabled called, but no ContentSuggestionsManager "
+                    + "configured");
+            return;
+        }
+        try {
+            mService.setDefaultServiceEnabled(userId, enabled);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Callback to receive content selections from
      *  {@link #suggestContentSelections(SelectionsRequest, Executor, SelectionsCallback)}.
      */
diff --git a/core/java/android/app/contentsuggestions/IContentSuggestionsManager.aidl b/core/java/android/app/contentsuggestions/IContentSuggestionsManager.aidl
index 8e6338b..9350eeb 100644
--- a/core/java/android/app/contentsuggestions/IContentSuggestionsManager.aidl
+++ b/core/java/android/app/contentsuggestions/IContentSuggestionsManager.aidl
@@ -45,4 +45,7 @@
             in IClassificationsCallback callback);
     void notifyInteraction(int userId, in String requestId, in Bundle interaction);
     void isEnabled(int userId, in IResultReceiver receiver);
+    void resetTemporaryService(int userId);
+    void setTemporaryService(int userId, in String serviceName, int duration);
+    void setDefaultServiceEnabled(int userId, boolean enabled);
 }
diff --git a/core/java/android/app/people/PeopleSpaceTile.java b/core/java/android/app/people/PeopleSpaceTile.java
index 9a53b99..dd2ba7d 100644
--- a/core/java/android/app/people/PeopleSpaceTile.java
+++ b/core/java/android/app/people/PeopleSpaceTile.java
@@ -29,6 +29,7 @@
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.UserHandle;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -45,7 +46,7 @@
     private String mId;
     private CharSequence mUserName;
     private Icon mUserIcon;
-    private int mUid;
+    private UserHandle mUserHandle;
     private Uri mContactUri;
     private String mPackageName;
     private String mBirthdayText;
@@ -53,6 +54,7 @@
     private boolean mIsImportantConversation;
     private String mNotificationKey;
     private CharSequence mNotificationContent;
+    private String mNotificationCategory;
     private Uri mNotificationDataUri;
     private Intent mIntent;
     private long mNotificationTimestamp;
@@ -63,13 +65,14 @@
         mUserName = b.mUserName;
         mUserIcon = b.mUserIcon;
         mContactUri = b.mContactUri;
-        mUid = b.mUid;
+        mUserHandle = b.mUserHandle;
         mPackageName = b.mPackageName;
         mBirthdayText = b.mBirthdayText;
         mLastInteractionTimestamp = b.mLastInteractionTimestamp;
         mIsImportantConversation = b.mIsImportantConversation;
         mNotificationKey = b.mNotificationKey;
         mNotificationContent = b.mNotificationContent;
+        mNotificationCategory = b.mNotificationCategory;
         mNotificationDataUri = b.mNotificationDataUri;
         mIntent = b.mIntent;
         mNotificationTimestamp = b.mNotificationTimestamp;
@@ -93,8 +96,8 @@
         return mContactUri;
     }
 
-    public int getUid() {
-        return mUid;
+    public UserHandle getUserHandle() {
+        return mUserHandle;
     }
 
     public String getPackageName() {
@@ -129,6 +132,10 @@
         return mNotificationContent;
     }
 
+    public String getNotificationCategory() {
+        return mNotificationCategory;
+    }
+
     public Uri getNotificationDataUri() {
         return mNotificationDataUri;
     }
@@ -159,13 +166,14 @@
         Builder builder =
                 new Builder(mId, mUserName.toString(), mUserIcon, mIntent);
         builder.setContactUri(mContactUri);
-        builder.setUid(mUid);
+        builder.setUserHandle(mUserHandle);
         builder.setPackageName(mPackageName);
         builder.setBirthdayText(mBirthdayText);
         builder.setLastInteractionTimestamp(mLastInteractionTimestamp);
         builder.setIsImportantConversation(mIsImportantConversation);
         builder.setNotificationKey(mNotificationKey);
         builder.setNotificationContent(mNotificationContent);
+        builder.setNotificationCategory(mNotificationCategory);
         builder.setNotificationDataUri(mNotificationDataUri);
         builder.setIntent(mIntent);
         builder.setNotificationTimestamp(mNotificationTimestamp);
@@ -179,13 +187,14 @@
         private CharSequence mUserName;
         private Icon mUserIcon;
         private Uri mContactUri;
-        private int mUid;
+        private UserHandle mUserHandle;
         private String mPackageName;
         private String mBirthdayText;
         private long mLastInteractionTimestamp;
         private boolean mIsImportantConversation;
         private String mNotificationKey;
         private CharSequence mNotificationContent;
+        private String mNotificationCategory;
         private Uri mNotificationDataUri;
         private Intent mIntent;
         private long mNotificationTimestamp;
@@ -204,7 +213,7 @@
             mId = info.getId();
             mUserName = info.getLabel();
             mUserIcon = convertDrawableToIcon(launcherApps.getShortcutIconDrawable(info, 0));
-            mUid = info.getUserId();
+            mUserHandle = info.getUserHandle();
             mPackageName = info.getPackage();
             mContactUri = getContactUri(info);
         }
@@ -214,7 +223,7 @@
             mId = info.getId();
             mUserName = info.getLabel();
             mUserIcon = convertDrawableToIcon(launcherApps.getShortcutIconDrawable(info, 0));
-            mUid = info.getUserId();
+            mUserHandle = info.getUserHandle();
             mPackageName = info.getPackage();
             mContactUri = getContactUri(info);
             mStatuses = channel.getStatuses();
@@ -257,9 +266,9 @@
             return this;
         }
 
-        /** Sets the associated uid. */
-        public Builder setUid(int uid) {
-            mUid = uid;
+        /** Sets the associated {@code userHandle}. */
+        public Builder setUserHandle(UserHandle userHandle) {
+            mUserHandle = userHandle;
             return this;
         }
 
@@ -299,6 +308,12 @@
             return this;
         }
 
+        /** Sets the associated notification's category. */
+        public Builder setNotificationCategory(String notificationCategory) {
+            mNotificationCategory = notificationCategory;
+            return this;
+        }
+
         /** Sets the associated notification's data URI. */
         public Builder setNotificationDataUri(Uri notificationDataUri) {
             mNotificationDataUri = notificationDataUri;
@@ -335,13 +350,14 @@
         mUserName = in.readCharSequence();
         mUserIcon = in.readParcelable(Icon.class.getClassLoader());
         mContactUri = in.readParcelable(Uri.class.getClassLoader());
-        mUid = in.readInt();
+        mUserHandle = in.readParcelable(UserHandle.class.getClassLoader());
         mPackageName = in.readString();
         mBirthdayText = in.readString();
         mLastInteractionTimestamp = in.readLong();
         mIsImportantConversation = in.readBoolean();
         mNotificationKey = in.readString();
         mNotificationContent = in.readCharSequence();
+        mNotificationCategory = in.readString();
         mNotificationDataUri = in.readParcelable(Uri.class.getClassLoader());
         mIntent = in.readParcelable(Intent.class.getClassLoader());
         mNotificationTimestamp = in.readLong();
@@ -360,13 +376,14 @@
         dest.writeCharSequence(mUserName);
         dest.writeParcelable(mUserIcon, flags);
         dest.writeParcelable(mContactUri, flags);
-        dest.writeInt(mUid);
+        dest.writeParcelable(mUserHandle, flags);
         dest.writeString(mPackageName);
         dest.writeString(mBirthdayText);
         dest.writeLong(mLastInteractionTimestamp);
         dest.writeBoolean(mIsImportantConversation);
         dest.writeString(mNotificationKey);
         dest.writeCharSequence(mNotificationContent);
+        dest.writeString(mNotificationCategory);
         dest.writeParcelable(mNotificationDataUri, flags);
         dest.writeParcelable(mIntent, flags);
         dest.writeLong(mNotificationTimestamp);
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index 73a9cec..94ab0dd 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -71,6 +71,7 @@
     private boolean mIsForward;
     private ProfilerInfo mProfilerInfo;
     private IBinder mAssistToken;
+    private IBinder mShareableActivityToken;
     /**
      * It is only non-null if the process is the first time to launch activity. It is only an
      * optimization for quick look up of the interface so the field is ignored for comparison.
@@ -95,7 +96,7 @@
         ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                 mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
                 mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
-                client, mAssistToken, mFixedRotationAdjustments);
+                client, mAssistToken, mFixedRotationAdjustments, mShareableActivityToken);
         client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
         Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
     }
@@ -119,7 +120,7 @@
             List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions,
             boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken,
             IActivityClientController activityClientController,
-            FixedRotationAdjustments fixedRotationAdjustments) {
+            FixedRotationAdjustments fixedRotationAdjustments, IBinder shareableActivityToken) {
         LaunchActivityItem instance = ObjectPool.obtain(LaunchActivityItem.class);
         if (instance == null) {
             instance = new LaunchActivityItem();
@@ -127,7 +128,7 @@
         setValues(instance, intent, ident, info, curConfig, overrideConfig, compatInfo, referrer,
                 voiceInteractor, procState, state, persistentState, pendingResults,
                 pendingNewIntents, activityOptions, isForward, profilerInfo, assistToken,
-                activityClientController, fixedRotationAdjustments);
+                activityClientController, fixedRotationAdjustments, shareableActivityToken);
 
         return instance;
     }
@@ -135,7 +136,7 @@
     @Override
     public void recycle() {
         setValues(this, null, 0, null, null, null, null, null, null, 0, null, null, null, null,
-                null, false, null, null, null, null);
+                null, false, null, null, null, null, null);
         ObjectPool.recycle(this);
     }
 
@@ -164,6 +165,7 @@
         dest.writeStrongBinder(mAssistToken);
         dest.writeStrongInterface(mActivityClientController);
         dest.writeTypedObject(mFixedRotationAdjustments, flags);
+        dest.writeStrongBinder(mShareableActivityToken);
     }
 
     /** Read from Parcel. */
@@ -181,7 +183,7 @@
                 in.readTypedObject(ProfilerInfo.CREATOR),
                 in.readStrongBinder(),
                 IActivityClientController.Stub.asInterface(in.readStrongBinder()),
-                in.readTypedObject(FixedRotationAdjustments.CREATOR));
+                in.readTypedObject(FixedRotationAdjustments.CREATOR), in.readStrongBinder());
     }
 
     public static final @NonNull Creator<LaunchActivityItem> CREATOR =
@@ -219,7 +221,8 @@
                 && mIsForward == other.mIsForward
                 && Objects.equals(mProfilerInfo, other.mProfilerInfo)
                 && Objects.equals(mAssistToken, other.mAssistToken)
-                && Objects.equals(mFixedRotationAdjustments, other.mFixedRotationAdjustments);
+                && Objects.equals(mFixedRotationAdjustments, other.mFixedRotationAdjustments)
+                && Objects.equals(mShareableActivityToken, other.mShareableActivityToken);
     }
 
     @Override
@@ -241,6 +244,7 @@
         result = 31 * result + Objects.hashCode(mProfilerInfo);
         result = 31 * result + Objects.hashCode(mAssistToken);
         result = 31 * result + Objects.hashCode(mFixedRotationAdjustments);
+        result = 31 * result + Objects.hashCode(mShareableActivityToken);
         return result;
     }
 
@@ -277,7 +281,8 @@
                 + ",persistentState=" + mPersistentState + ",pendingResults=" + mPendingResults
                 + ",pendingNewIntents=" + mPendingNewIntents + ",options=" + mActivityOptions
                 + ",profilerInfo=" + mProfilerInfo + ",assistToken=" + mAssistToken
-                + ",rotationAdj=" + mFixedRotationAdjustments + "}";
+                + ",rotationAdj=" + mFixedRotationAdjustments
+                + ",shareableActivityToken=" + mShareableActivityToken + "}";
     }
 
     // Using the same method to set and clear values to make sure we don't forget anything
@@ -288,7 +293,7 @@
             List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
             ActivityOptions activityOptions, boolean isForward, ProfilerInfo profilerInfo,
             IBinder assistToken, IActivityClientController activityClientController,
-            FixedRotationAdjustments fixedRotationAdjustments) {
+            FixedRotationAdjustments fixedRotationAdjustments, IBinder shareableActivityToken) {
         instance.mIntent = intent;
         instance.mIdent = ident;
         instance.mInfo = info;
@@ -308,5 +313,6 @@
         instance.mAssistToken = assistToken;
         instance.mActivityClientController = activityClientController;
         instance.mFixedRotationAdjustments = fixedRotationAdjustments;
+        instance.mShareableActivityToken = shareableActivityToken;
     }
 }
diff --git a/core/java/android/app/time/ExternalTimeSuggestion.java b/core/java/android/app/time/ExternalTimeSuggestion.java
index b566eab..61defb5 100644
--- a/core/java/android/app/time/ExternalTimeSuggestion.java
+++ b/core/java/android/app/time/ExternalTimeSuggestion.java
@@ -16,6 +16,8 @@
 
 package android.app.time;
 
+import android.annotation.CurrentTimeMillisLong;
+import android.annotation.ElapsedRealtimeLong;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Parcel;
@@ -31,9 +33,9 @@
 /**
  * A time signal from an External source.
  *
- * External time suggestions are for use in situations where the Android device is part of a wider
- * network of devices that are required to use a single time source, and where authority for the
- * time is external to the Android device. For example, for the Android Auto use case where the
+ * <p>External time suggestions are for use in situations where the Android device is part of a
+ * wider network of devices that are required to use a single time source, and where authority for
+ * the time is external to the Android device. For example, for the Android Auto use case where the
  * Android device is part of a wider in-car network of devices that should display the same time.
  *
  * <p>Android allows for a single external source for time. If there are several external sources
@@ -49,19 +51,19 @@
  * capture the elapsed realtime reference clock, e.g. via {@link SystemClock#elapsedRealtime()},
  * when the UTC time is first obtained (usually under a wakelock). This enables Android to adjust
  * for latency introduced between suggestion creation and eventual use. Adjustments for other
- * sources of latency, i.e. those before the external time suggestion is created, must be handled
- * by the creator.
+ * sources of latency, i.e. those before the external time suggestion is created, must be handled by
+ * the creator.
  *
- * <p>{@code utcTime} is the suggested time. The {@code utcTime.value} is the number of milliseconds
- * elapsed since 1/1/1970 00:00:00 UTC. The {@code utcTime.referenceTimeMillis} is the value of the
- * elapsed realtime clock when the {@code utcTime.value} was established.
- * Note that the elapsed realtime clock is considered accurate but it is volatile, so time
- * suggestions cannot be persisted across device resets.
+ * <p>{@code elapsedRealtimeMillis} and {@code suggestionMillis} represent the suggested time.
+ * {@code suggestionMillis} is the number of milliseconds elapsed since 1/1/1970 00:00:00 UTC.
+ * {@code elapsedRealtimeMillis} is the value of the elapsed realtime clock when {@code
+ * suggestionMillis} was established. Note that the elapsed realtime clock is considered accurate
+ * but it is volatile, so time suggestions cannot be persisted across device resets.
  *
  * <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
  * record why the suggestion exists and how it was entered. This information exists only to aid in
- * debugging and therefore is used by {@link #toString()}, but it is not for use in detection
- * logic and is not considered in {@link #hashCode()} or {@link #equals(Object)}.
+ * debugging and therefore is used by {@link #toString()}, but it is not for use in detection logic
+ * and is not considered in {@link #hashCode()} or {@link #equals(Object)}.
  *
  * @hide
  */
@@ -78,17 +80,28 @@
                 }
             };
 
-    @NonNull private final TimestampedValue<Long> mUtcTime;
-    @Nullable private ArrayList<String> mDebugInfo;
+    @NonNull
+    private final TimestampedValue<Long> mUtcTime;
+    @Nullable
+    private ArrayList<String> mDebugInfo;
 
-    public ExternalTimeSuggestion(@NonNull TimestampedValue<Long> utcTime) {
-        mUtcTime = Objects.requireNonNull(utcTime);
-        Objects.requireNonNull(utcTime.getValue());
+    /**
+     * Creates a time suggestion cross-referenced to the elapsed realtime clock. See {@link
+     * ExternalTimeSuggestion} for more details.
+     *
+     * @param elapsedRealtimeMillis the elapsed realtime clock reference for the suggestion
+     * @param suggestionMillis      the suggested UTC time in milliseconds since the start of the
+     *                              Unix epoch
+     */
+    public ExternalTimeSuggestion(@ElapsedRealtimeLong long elapsedRealtimeMillis,
+            @CurrentTimeMillisLong long suggestionMillis) {
+        mUtcTime = new TimestampedValue(elapsedRealtimeMillis, suggestionMillis);
     }
 
     private static ExternalTimeSuggestion createFromParcel(Parcel in) {
         TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
-        ExternalTimeSuggestion suggestion = new ExternalTimeSuggestion(utcTime);
+        ExternalTimeSuggestion suggestion =
+                new ExternalTimeSuggestion(utcTime.getReferenceTimeMillis(), utcTime.getValue());
         @SuppressWarnings("unchecked")
         ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
         suggestion.mDebugInfo = debugInfo;
@@ -106,23 +119,31 @@
         dest.writeList(mDebugInfo);
     }
 
+    /**
+     * {@hide}
+     */
     @NonNull
     public TimestampedValue<Long> getUtcTime() {
         return mUtcTime;
     }
 
+    /**
+     * Returns information that can be useful for debugging / logging. See {@link #addDebugInfo}.
+     * {@hide}
+     */
     @NonNull
     public List<String> getDebugInfo() {
         return mDebugInfo == null
-                ? Collections.emptyList() : Collections.unmodifiableList(mDebugInfo);
+                ? Collections.emptyList()
+                : Collections.unmodifiableList(mDebugInfo);
     }
 
     /**
      * Associates information with the instance that can be useful for debugging / logging. The
-     * information is present in {@link #toString()} but is not considered for
-     * {@link #equals(Object)} and {@link #hashCode()}.
+     * information is present in {@link #toString()} but is not considered for {@link
+     * #equals(Object)} and {@link #hashCode()}.
      */
-    public void addDebugInfo(String... debugInfos) {
+    public void addDebugInfo(@NonNull String... debugInfos) {
         if (mDebugInfo == null) {
             mDebugInfo = new ArrayList<>();
         }
@@ -148,9 +169,7 @@
 
     @Override
     public String toString() {
-        return "ExternalTimeSuggestion{"
-                + "mUtcTime=" + mUtcTime
-                + ", mDebugInfo=" + mDebugInfo
+        return "ExternalTimeSuggestion{" + "mUtcTime=" + mUtcTime + ", mDebugInfo=" + mDebugInfo
                 + '}';
     }
 }
diff --git a/core/java/android/app/time/LocationTimeZoneManager.java b/core/java/android/app/time/LocationTimeZoneManager.java
index 71a800f..066aada 100644
--- a/core/java/android/app/time/LocationTimeZoneManager.java
+++ b/core/java/android/app/time/LocationTimeZoneManager.java
@@ -37,7 +37,7 @@
     /**
      * The name of the service for shell commands
      */
-    public static final String SHELL_COMMAND_SERVICE_NAME = "location_time_zone_manager";
+    public static final String SERVICE_NAME = "location_time_zone_manager";
 
     /**
      * A shell command that starts the service (after stop).
diff --git a/core/java/android/app/time/TimeManager.java b/core/java/android/app/time/TimeManager.java
index 262d244..430960f 100644
--- a/core/java/android/app/time/TimeManager.java
+++ b/core/java/android/app/time/TimeManager.java
@@ -20,6 +20,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.app.timedetector.ITimeDetectorService;
 import android.app.timezonedetector.ITimeZoneDetectorService;
 import android.content.Context;
 import android.os.RemoteException;
@@ -45,6 +46,7 @@
 
     private final Object mLock = new Object();
     private final ITimeZoneDetectorService mITimeZoneDetectorService;
+    private final ITimeDetectorService mITimeDetectorService;
 
     @GuardedBy("mLock")
     private ITimeZoneDetectorListener mTimeZoneDetectorReceiver;
@@ -62,6 +64,8 @@
         // internal refactoring.
         mITimeZoneDetectorService = ITimeZoneDetectorService.Stub.asInterface(
                 ServiceManager.getServiceOrThrow(Context.TIME_ZONE_DETECTOR_SERVICE));
+        mITimeDetectorService = ITimeDetectorService.Stub.asInterface(
+                ServiceManager.getServiceOrThrow(Context.TIME_DETECTOR_SERVICE));
     }
 
     /**
@@ -214,4 +218,23 @@
             }
         }
     }
+
+    /**
+     * Suggests the current time from an external time source. For example, a form factor-specific
+     * HAL. This time <em>may</em> be used to set the device system clock, depending on the device
+     * configuration and user settings. This method call is processed asynchronously.
+     * See {@link ExternalTimeSuggestion} for more details.
+     * {@hide}
+     */
+    @RequiresPermission(android.Manifest.permission.SET_TIME)
+    public void suggestExternalTime(@NonNull ExternalTimeSuggestion timeSuggestion) {
+        if (DEBUG) {
+            Log.d(TAG, "suggestExternalTime called: " + timeSuggestion);
+        }
+        try {
+            mITimeDetectorService.suggestExternalTime(timeSuggestion);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/app/timedetector/TimeDetector.java b/core/java/android/app/timedetector/TimeDetector.java
index 76f3785..52016b6 100644
--- a/core/java/android/app/timedetector/TimeDetector.java
+++ b/core/java/android/app/timedetector/TimeDetector.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemService;
-import android.app.time.ExternalTimeSuggestion;
 import android.content.Context;
 import android.os.SystemClock;
 import android.os.TimestampedValue;
@@ -80,12 +79,4 @@
      */
     @RequiresPermission(android.Manifest.permission.SET_TIME)
     void suggestGnssTime(GnssTimeSuggestion timeSuggestion);
-
-    /**
-     * Suggests the time according to an external time source (form factor specific HAL, etc).
-     *
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.SET_TIME)
-    void suggestExternalTime(ExternalTimeSuggestion timeSuggestion);
 }
diff --git a/core/java/android/app/timedetector/TimeDetectorImpl.java b/core/java/android/app/timedetector/TimeDetectorImpl.java
index ef818ef..b0aa3c8 100644
--- a/core/java/android/app/timedetector/TimeDetectorImpl.java
+++ b/core/java/android/app/timedetector/TimeDetectorImpl.java
@@ -17,7 +17,6 @@
 package android.app.timedetector;
 
 import android.annotation.NonNull;
-import android.app.time.ExternalTimeSuggestion;
 import android.content.Context;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -87,16 +86,4 @@
             throw e.rethrowFromSystemServer();
         }
     }
-
-    @Override
-    public void suggestExternalTime(ExternalTimeSuggestion timeSuggestion) {
-        if (DEBUG) {
-            Log.d(TAG, "suggestExternalTime called: " + timeSuggestion);
-        }
-        try {
-            mITimeDetectorService.suggestExternalTime(timeSuggestion);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
 }
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 565e4cd..a72877e 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -37,7 +37,7 @@
 import android.util.DisplayMetrics;
 import android.util.SparseArray;
 import android.widget.RemoteViews;
-import android.widget.RemoteViews.OnClickHandler;
+import android.widget.RemoteViews.InteractionHandler;
 
 import com.android.internal.R;
 import com.android.internal.appwidget.IAppWidgetHost;
@@ -71,7 +71,7 @@
     private final int mHostId;
     private final Callbacks mCallbacks;
     private final SparseArray<AppWidgetHostView> mViews = new SparseArray<>();
-    private OnClickHandler mOnClickHandler;
+    private InteractionHandler mInteractionHandler;
 
     static class Callbacks extends IAppWidgetHost.Stub {
         private final WeakReference<Handler> mWeakHandler;
@@ -175,10 +175,10 @@
      * @hide
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public AppWidgetHost(Context context, int hostId, OnClickHandler handler, Looper looper) {
+    public AppWidgetHost(Context context, int hostId, InteractionHandler handler, Looper looper) {
         mContextOpPackageName = context.getOpPackageName();
         mHostId = hostId;
-        mOnClickHandler = handler;
+        mInteractionHandler = handler;
         mHandler = new UpdateHandler(looper);
         mCallbacks = new Callbacks(mHandler);
         mDisplayMetrics = context.getResources().getDisplayMetrics();
@@ -401,7 +401,7 @@
             return null;
         }
         AppWidgetHostView view = onCreateView(context, appWidgetId, appWidget);
-        view.setOnClickHandler(mOnClickHandler);
+        view.setInteractionHandler(mInteractionHandler);
         view.setAppWidget(appWidgetId, appWidget);
         synchronized (mViews) {
             mViews.put(appWidgetId, view);
@@ -423,7 +423,7 @@
      */
     protected AppWidgetHostView onCreateView(Context context, int appWidgetId,
             AppWidgetProviderInfo appWidget) {
-        return new AppWidgetHostView(context, mOnClickHandler);
+        return new AppWidgetHostView(context, mInteractionHandler);
     }
 
     /**
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 42d90a7..fc54c71 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -40,6 +40,7 @@
 import android.util.Log;
 import android.util.Pair;
 import android.util.SparseArray;
+import android.util.SparseIntArray;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -49,7 +50,7 @@
 import android.widget.BaseAdapter;
 import android.widget.FrameLayout;
 import android.widget.RemoteViews;
-import android.widget.RemoteViews.OnClickHandler;
+import android.widget.RemoteViews.InteractionHandler;
 import android.widget.RemoteViewsAdapter.RemoteAdapterConnectionCallback;
 import android.widget.TextView;
 
@@ -90,9 +91,12 @@
     View mView;
     int mViewMode = VIEW_MODE_NOINIT;
     int mLayoutId = -1;
-    private OnClickHandler mOnClickHandler;
+    private InteractionHandler mInteractionHandler;
     private boolean mOnLightBackground;
-    PointF mCurrentSize = null;
+    private PointF mCurrentSize = null;
+    private RemoteViews.ColorResources mColorResources = null;
+    // Stores the last remote views last inflated.
+    private RemoteViews mLastInflatedRemoteViews = null;
 
     private Executor mAsyncExecutor;
     private CancellationSignal mLastExecutionSignal;
@@ -107,9 +111,9 @@
     /**
      * @hide
      */
-    public AppWidgetHostView(Context context, OnClickHandler handler) {
+    public AppWidgetHostView(Context context, InteractionHandler handler) {
         this(context, android.R.anim.fade_in, android.R.anim.fade_out);
-        mOnClickHandler = getHandler(handler);
+        mInteractionHandler = getHandler(handler);
     }
 
     /**
@@ -135,8 +139,8 @@
      * @param handler
      * @hide
      */
-    public void setOnClickHandler(OnClickHandler handler) {
-        mOnClickHandler = getHandler(handler);
+    public void setInteractionHandler(InteractionHandler handler) {
+        mInteractionHandler = getHandler(handler);
     }
 
     /**
@@ -358,7 +362,7 @@
         PointF newSize = new PointF(size.x - xPaddingDips, size.y - yPaddingDips);
         if (!newSize.equals(mCurrentSize)) {
             mCurrentSize = newSize;
-            mLayoutId = -1; // Prevents recycling the view.
+            reapplyLastRemoteViews();
         }
     }
 
@@ -368,7 +372,7 @@
     public void clearCurrentSize() {
         if (mCurrentSize != null) {
             mCurrentSize = null;
-            mLayoutId = -1;
+            reapplyLastRemoteViews();
         }
     }
 
@@ -477,10 +481,18 @@
      * AppWidget provider. Will animate into these new views as needed
      */
     public void updateAppWidget(RemoteViews remoteViews) {
+        this.mLastInflatedRemoteViews = remoteViews;
         applyRemoteViews(remoteViews, true);
     }
 
     /**
+     * Reapply the last inflated remote views, or the default view is none was inflated.
+     */
+    private void reapplyLastRemoteViews() {
+        applyRemoteViews(mLastInflatedRemoteViews, true);
+    }
+
+    /**
      * @hide
      */
     protected void applyRemoteViews(RemoteViews remoteViews, boolean useAsyncIfPossible) {
@@ -518,7 +530,8 @@
             // layout matches, try recycling it
             if (content == null && layoutId == mLayoutId) {
                 try {
-                    remoteViews.reapply(mContext, mView, mOnClickHandler);
+                    remoteViews.reapply(mContext, mView, mInteractionHandler, mCurrentSize,
+                            mColorResources);
                     content = mView;
                     recycled = true;
                     if (LOGD) Log.d(TAG, "was able to recycle existing layout");
@@ -530,7 +543,8 @@
             // Try normal RemoteView inflation
             if (content == null) {
                 try {
-                    content = remoteViews.apply(mContext, this, mOnClickHandler, mCurrentSize);
+                    content = remoteViews.apply(mContext, this, mInteractionHandler,
+                            mCurrentSize, mColorResources);
                     if (LOGD) Log.d(TAG, "had to inflate new layout");
                 } catch (RuntimeException e) {
                     exception = e;
@@ -582,8 +596,9 @@
                         mView,
                         mAsyncExecutor,
                         new ViewApplyListener(remoteViews, layoutId, true),
-                        mOnClickHandler,
-                        mCurrentSize);
+                        mInteractionHandler,
+                        mCurrentSize,
+                        mColorResources);
             } catch (Exception e) {
                 // Reapply failed. Try apply
             }
@@ -593,8 +608,9 @@
                     this,
                     mAsyncExecutor,
                     new ViewApplyListener(remoteViews, layoutId, false),
-                    mOnClickHandler,
-                    mCurrentSize);
+                    mInteractionHandler,
+                    mCurrentSize,
+                    mColorResources);
         }
     }
 
@@ -625,7 +641,7 @@
                         AppWidgetHostView.this,
                         mAsyncExecutor,
                         new ViewApplyListener(mViews, mLayoutId, false),
-                        mOnClickHandler,
+                        mInteractionHandler,
                         mCurrentSize);
             } else {
                 applyContent(null, false, e);
@@ -662,9 +678,13 @@
     protected Context getRemoteContext() {
         try {
             // Return if cloned successfully, otherwise default
-            return mContext.createApplicationContext(
+            Context newContext = mContext.createApplicationContext(
                     mInfo.providerInfo.applicationInfo,
                     Context.CONTEXT_RESTRICTED);
+            if (mColorResources != null) {
+                mColorResources.apply(newContext);
+            }
+            return newContext;
         } catch (NameNotFoundException e) {
             Log.e(TAG, "Package name " +  mInfo.providerInfo.packageName + " not found");
             return mContext;
@@ -808,15 +828,48 @@
         return null;
     }
 
-    private OnClickHandler getHandler(OnClickHandler handler) {
+    private InteractionHandler getHandler(InteractionHandler handler) {
         return (view, pendingIntent, response) -> {
             AppWidgetManager.getInstance(mContext).noteAppWidgetTapped(mAppWidgetId);
             if (handler != null) {
-                return handler.onClickHandler(view, pendingIntent, response);
+                return handler.onInteraction(view, pendingIntent, response);
             } else {
                 return RemoteViews.startPendingIntent(view, pendingIntent,
                         response.getLaunchOptions(view));
             }
         };
     }
+
+    /**
+     * Set the dynamically overloaded color resources.
+     *
+     * {@code colorMapping} maps a predefined set of color resources to their ARGB
+     * representation. Any entry not in the predefined set of colors will be ignored.
+     *
+     * Calling this method will trigger a full re-inflation of the App Widget.
+     *
+     * The color resources that can be overloaded are the ones whose name is prefixed with
+     * {@code system_primary_}, {@code system_secondary_} or {@code system_neutral_}, for example
+     * {@link android.R.color#system_primary_500}.
+     */
+    public void setColorResources(@NonNull SparseIntArray colorMapping) {
+        mColorResources = RemoteViews.ColorResources.create(mContext, colorMapping);
+        mLayoutId = -1;
+        reapplyLastRemoteViews();
+    }
+
+    /**
+     * Reset the dynamically overloaded resources, reverting to the default values for
+     * all the colors.
+     *
+     * If colors were defined before, calling this method will trigger a full re-inflation of the
+     * App Widget.
+     */
+    public void resetColorResources() {
+        if (mColorResources != null) {
+            mColorResources = null;
+            mLayoutId = -1;
+            reapplyLastRemoteViews();
+        }
+    }
 }
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index aac8710..38919f6 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -23,6 +23,8 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemService;
+import android.annotation.TestApi;
+import android.annotation.UserIdInt;
 import android.app.IServiceConnection;
 import android.app.PendingIntent;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -1095,7 +1097,9 @@
      *
      * @hide
      */
-    public void setBindAppWidgetPermission(String packageName, int userId, boolean permission) {
+    @TestApi
+    public void setBindAppWidgetPermission(
+            @NonNull String packageName, @UserIdInt int userId, boolean permission) {
         if (mService == null) {
             return;
         }
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index d893a5e..6ac1c1a 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -332,12 +332,13 @@
 
     /**
      * Resource id for the description of the AppWidget.
+     *
      * <p>This field corresponds to the <code>android:description</code> attribute in the AppWidget
      * meta-data file.
      */
     @SuppressLint("MutableBareField")
     @IdRes
-    public int descriptionResource;
+    public int descriptionRes;
 
     /**
      * Flags indicating various features supported by the widget. These are hints to the widget
@@ -385,7 +386,7 @@
         this.widgetCategory = in.readInt();
         this.providerInfo = in.readTypedObject(ActivityInfo.CREATOR);
         this.widgetFeatures = in.readInt();
-        this.descriptionResource = in.readInt();
+        this.descriptionRes = in.readInt();
     }
 
     /**
@@ -442,14 +443,22 @@
         return loadDrawable(context, density, previewImage, false);
     }
 
-    /** Loads localized description for the app widget. */
+    /**
+     * Loads localized description for the app widget.
+     *
+     * <p>Description is intended to be displayed in the UI of the widget picker.
+     *
+     * @param context Context for accessing resources.
+     *
+     * @return CharSequence for app widget description for the current locale.
+     */
     @Nullable
-    public final String loadDescription(@NonNull Context context) {
-        if (ResourceId.isValid(descriptionResource)) {
+    public final CharSequence loadDescription(@NonNull Context context) {
+        if (ResourceId.isValid(descriptionRes)) {
             return context.getPackageManager()
                     .getText(
                             providerInfo.packageName,
-                            descriptionResource,
+                            descriptionRes,
                             providerInfo.applicationInfo)
                     .toString()
                     .trim();
@@ -499,7 +508,7 @@
         out.writeInt(this.widgetCategory);
         out.writeTypedObject(this.providerInfo, flags);
         out.writeInt(this.widgetFeatures);
-        out.writeInt(this.descriptionResource);
+        out.writeInt(this.descriptionRes);
     }
 
     @Override
@@ -528,7 +537,7 @@
         that.widgetCategory = this.widgetCategory;
         that.providerInfo = this.providerInfo;
         that.widgetFeatures = this.widgetFeatures;
-        that.descriptionResource = this.descriptionResource;
+        that.descriptionRes = this.descriptionRes;
         return that;
     }
 
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index cd91aa9..53aaae0 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -943,12 +943,13 @@
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
-    public boolean setBufferMillis(@BluetoothCodecConfig.SourceCodecType int codec, int value) {
-        if (VDBG) log("setBufferMillis(" + codec + ", " + value + ")");
+    public boolean setBufferLengthMillis(@BluetoothCodecConfig.SourceCodecType int codec,
+            int value) {
+        if (VDBG) log("setBufferLengthMillis(" + codec + ", " + value + ")");
         try {
             final IBluetoothA2dp service = getService();
             if (service != null && isEnabled()) {
-                return service.setBufferMillis(codec, value);
+                return service.setBufferLengthMillis(codec, value);
             }
             if (service == null) Log.w(TAG, "Proxy not attached to service");
             return false;
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index ec46da0..8d41572 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -3654,12 +3654,12 @@
         }
 
         @Override
-        public void onDeviceDisconnected(BluetoothDevice device) {
+        public void onDeviceDisconnected(BluetoothDevice device, int hciReason) {
             for (Map.Entry<BluetoothConnectionCallback, Executor> callbackExecutorEntry:
                     mBluetoothConnectionCallbackExecutorMap.entrySet()) {
                 BluetoothConnectionCallback callback = callbackExecutorEntry.getKey();
                 Executor executor = callbackExecutorEntry.getValue();
-                executor.execute(() -> callback.onDeviceDisconnected(device));
+                executor.execute(() -> callback.onDeviceDisconnected(device, hciReason));
             }
         }
     };
@@ -3764,8 +3764,155 @@
         /**
          * Callback triggered when a bluetooth device (classic or BLE) is disconnected
          * @param device is the disconnected bluetooth device
+         * @param reason is the disconnect reason
          */
-        public void onDeviceDisconnected(BluetoothDevice device) {}
+        public void onDeviceDisconnected(BluetoothDevice device, @DisconnectReason int reason) {}
+
+        /**
+         * @hide
+         */
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef(prefix = { "REASON_" }, value = {
+                REASON_UNKNOWN,
+                REASON_LOCAL_REQUEST,
+                REASON_REMOTE_REQUEST,
+                REASON_LOCAL_ERROR,
+                REASON_REMOTE_ERROR,
+                REASON_TIMEOUT,
+                REASON_SECURITY,
+                REASON_SYSTEM_POLICY,
+                REASON_RESOURCE_LIMIT_REACHED,
+                REASON_CONNECTION_EXISTS,
+                REASON_BAD_PARAMETERS})
+        public @interface DisconnectReason {}
+
+        /**
+         * Indicates that the ACL disconnected due to an unknown reason.
+         */
+        public static final int REASON_UNKNOWN = 0;
+
+        /**
+         * Indicates that the ACL disconnected due to an explicit request from the local device.
+         * <p>
+         * Example cause: This is a normal disconnect reason, e.g., user/app initiates
+         * disconnection.
+         */
+        public static final int REASON_LOCAL_REQUEST = 1;
+
+        /**
+         * Indicates that the ACL disconnected due to an explicit request from the remote device.
+         * <p>
+         * Example cause: This is a normal disconnect reason, e.g., user/app initiates
+         * disconnection.
+         * <p>
+         * Example solution: The app can also prompt the user to check their remote device.
+         */
+        public static final int REASON_REMOTE_REQUEST = 2;
+
+        /**
+         * Generic disconnect reason indicating the ACL disconnected due to an error on the local
+         * device.
+         * <p>
+         * Example solution: Prompt the user to check their local device (e.g., phone, car
+         * headunit).
+         */
+        public static final int REASON_LOCAL_ERROR = 3;
+
+        /**
+         * Generic disconnect reason indicating the ACL disconnected due to an error on the remote
+         * device.
+         * <p>
+         * Example solution: Prompt the user to check their remote device (e.g., headset, car
+         * headunit, watch).
+         */
+        public static final int REASON_REMOTE_ERROR = 4;
+
+        /**
+         * Indicates that the ACL disconnected due to a timeout.
+         * <p>
+         * Example cause: remote device might be out of range.
+         * <p>
+         * Example solution: Prompt user to verify their remote device is on or in
+         * connection/pairing mode.
+         */
+        public static final int REASON_TIMEOUT = 5;
+
+        /**
+         * Indicates that the ACL disconnected due to link key issues.
+         * <p>
+         * Example cause: Devices are either unpaired or remote device is refusing our pairing
+         * request.
+         * <p>
+         * Example solution: Prompt user to unpair and pair again.
+         */
+        public static final int REASON_SECURITY = 6;
+
+        /**
+         * Indicates that the ACL disconnected due to the local device's system policy.
+         * <p>
+         * Example cause: privacy policy, power management policy, permissions, etc.
+         * <p>
+         * Example solution: Prompt the user to check settings, or check with their system
+         * administrator (e.g. some corp-managed devices do not allow OPP connection).
+         */
+        public static final int REASON_SYSTEM_POLICY = 7;
+
+        /**
+         * Indicates that the ACL disconnected due to resource constraints, either on the local
+         * device or the remote device.
+         * <p>
+         * Example cause: controller is busy, memory limit reached, maximum number of connections
+         * reached.
+         * <p>
+         * Example solution: The app should wait and try again. If still failing, prompt the user
+         * to disconnect some devices, or toggle Bluetooth on the local and/or the remote device.
+         */
+        public static final int REASON_RESOURCE_LIMIT_REACHED = 8;
+
+        /**
+         * Indicates that the ACL disconnected because another ACL connection already exists.
+         */
+        public static final int REASON_CONNECTION_EXISTS = 9;
+
+        /**
+         * Indicates that the ACL disconnected due to incorrect parameters passed in from the app.
+         * <p>
+         * Example solution: Change parameters and try again. If error persists, the app can report
+         * telemetry and/or log the error in a bugreport.
+         */
+        public static final int REASON_BAD_PARAMETERS = 10;
+
+        /**
+         * Returns human-readable strings corresponding to {@link DisconnectReason}.
+         */
+        public static String disconnectReasonText(@DisconnectReason int reason) {
+            switch (reason) {
+                case REASON_UNKNOWN:
+                    return "Reason unknown";
+                case REASON_LOCAL_REQUEST:
+                    return "Local request";
+                case REASON_REMOTE_REQUEST:
+                    return "Remote request";
+                case REASON_LOCAL_ERROR:
+                    return "Local error";
+                case REASON_REMOTE_ERROR:
+                    return "Remote error";
+                case REASON_TIMEOUT:
+                    return "Timeout";
+                case REASON_SECURITY:
+                    return "Security";
+                case REASON_SYSTEM_POLICY:
+                    return "System policy";
+                case REASON_RESOURCE_LIMIT_REACHED:
+                    return "Resource constrained";
+                case REASON_CONNECTION_EXISTS:
+                    return "Connection already exists";
+                case REASON_BAD_PARAMETERS:
+                    return "Bad parameters";
+                default:
+                    return "Unrecognized disconnect reason: " + reason;
+            }
+        }
     }
 
     /**
diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java
index ff6cffb..0312a21 100644
--- a/core/java/android/bluetooth/BluetoothMapClient.java
+++ b/core/java/android/bluetooth/BluetoothMapClient.java
@@ -18,7 +18,9 @@
 
 import android.Manifest;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.app.PendingIntent;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
@@ -30,6 +32,7 @@
 import android.util.Log;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -37,44 +40,60 @@
  *
  * @hide
  */
+@SystemApi
 public final class BluetoothMapClient implements BluetoothProfile {
 
     private static final String TAG = "BluetoothMapClient";
     private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
     private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE);
 
+    /** @hide */
     public static final String ACTION_CONNECTION_STATE_CHANGED =
             "android.bluetooth.mapmce.profile.action.CONNECTION_STATE_CHANGED";
+    /** @hide */
     public static final String ACTION_MESSAGE_RECEIVED =
             "android.bluetooth.mapmce.profile.action.MESSAGE_RECEIVED";
     /* Actions to be used for pending intents */
+    /** @hide */
     public static final String ACTION_MESSAGE_SENT_SUCCESSFULLY =
             "android.bluetooth.mapmce.profile.action.MESSAGE_SENT_SUCCESSFULLY";
+    /** @hide */
     public static final String ACTION_MESSAGE_DELIVERED_SUCCESSFULLY =
             "android.bluetooth.mapmce.profile.action.MESSAGE_DELIVERED_SUCCESSFULLY";
 
     /**
      * Action to notify read status changed
+     *
+     * @hide
      */
     public static final String ACTION_MESSAGE_READ_STATUS_CHANGED =
             "android.bluetooth.mapmce.profile.action.MESSAGE_READ_STATUS_CHANGED";
 
     /**
      * Action to notify deleted status changed
+     *
+     * @hide
      */
     public static final String ACTION_MESSAGE_DELETED_STATUS_CHANGED =
             "android.bluetooth.mapmce.profile.action.MESSAGE_DELETED_STATUS_CHANGED";
 
-    /* Extras used in ACTION_MESSAGE_RECEIVED intent.
-     * NOTE: HANDLE is only valid for a single session with the device. */
+    /**
+     * Extras used in ACTION_MESSAGE_RECEIVED intent.
+     * NOTE: HANDLE is only valid for a single session with the device.
+     */
+    /** @hide */
     public static final String EXTRA_MESSAGE_HANDLE =
             "android.bluetooth.mapmce.profile.extra.MESSAGE_HANDLE";
+    /** @hide */
     public static final String EXTRA_MESSAGE_TIMESTAMP =
             "android.bluetooth.mapmce.profile.extra.MESSAGE_TIMESTAMP";
+    /** @hide */
     public static final String EXTRA_MESSAGE_READ_STATUS =
             "android.bluetooth.mapmce.profile.extra.MESSAGE_READ_STATUS";
+    /** @hide */
     public static final String EXTRA_SENDER_CONTACT_URI =
             "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_URI";
+    /** @hide */
     public static final String EXTRA_SENDER_CONTACT_NAME =
             "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_NAME";
 
@@ -84,6 +103,8 @@
      * Possible values are:
      * true: deleted
      * false: undeleted
+     *
+     * @hide
      */
     public static final String EXTRA_MESSAGE_DELETED_STATUS =
             "android.bluetooth.mapmce.profile.extra.MESSAGE_DELETED_STATUS";
@@ -93,24 +114,42 @@
      * Possible values are:
      * 0: failure
      * 1: success
+     *
+     * @hide
      */
     public static final String EXTRA_RESULT_CODE =
             "android.bluetooth.device.extra.RESULT_CODE";
 
-    /** There was an error trying to obtain the state */
+    /**
+     * There was an error trying to obtain the state
+     * @hide
+     */
     public static final int STATE_ERROR = -1;
 
+    /** @hide */
     public static final int RESULT_FAILURE = 0;
+    /** @hide */
     public static final int RESULT_SUCCESS = 1;
-    /** Connection canceled before completion. */
+    /**
+     * Connection canceled before completion.
+     * @hide
+     */
     public static final int RESULT_CANCELED = 2;
-
+    /** @hide */
     private static final int UPLOADING_FEATURE_BITMASK = 0x08;
 
-    /** Parameters in setMessageStatus */
+    /*
+     * UNREAD, READ, UNDELETED, DELETED are passed as parameters
+     * to setMessageStatus to indicate the messages new state.
+     */
+
+    /** @hide */
     public static final int UNREAD = 0;
+    /** @hide */
     public static final int READ = 1;
+    /** @hide */
     public static final int UNDELETED = 2;
+    /** @hide */
     public static final int DELETED = 3;
 
     private BluetoothAdapter mAdapter;
@@ -132,19 +171,12 @@
         mProfileConnector.connect(context, listener);
     }
 
-    protected void finalize() throws Throwable {
-        try {
-            close();
-        } finally {
-            super.finalize();
-        }
-    }
-
     /**
      * Close the connection to the backing service.
      * Other public functions of BluetoothMap will return default error
      * results once close() has been called. Multiple invocations of close()
      * are ok.
+     * @hide
      */
     public void close() {
         mProfileConnector.disconnect();
@@ -158,6 +190,7 @@
      * Returns true if the specified Bluetooth device is connected.
      * Returns false if not connected, or if this proxy object is not
      * currently connected to the Map service.
+     * @hide
      */
     public boolean isConnected(BluetoothDevice device) {
         if (VDBG) Log.d(TAG, "isConnected(" + device + ")");
@@ -225,6 +258,7 @@
      * Get the list of connected devices. Currently at most one.
      *
      * @return list of connected devices
+     * @hide
      */
     @Override
     public List<BluetoothDevice> getConnectedDevices() {
@@ -246,6 +280,7 @@
      * Get the list of devices matching specified states. Currently at most one.
      *
      * @return list of matching devices
+     * @hide
      */
     @Override
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
@@ -267,6 +302,7 @@
      * Get connection state of device
      *
      * @return device connection state
+     * @hide
      */
     @Override
     public int getConnectionState(BluetoothDevice device) {
@@ -383,11 +419,44 @@
      * Send an SMS message to either the contacts primary number or the telephone number specified.
      *
      * @param device Bluetooth device
+     * @param contacts Uri Collection of the contacts
+     * @param message Message to be sent
+     * @param sentIntent intent issued when message is sent
+     * @param deliveredIntent intent issued when message is delivered
+     * @return true if the message is enqueued, false on error
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.SEND_SMS)
+    public boolean sendMessage(@NonNull BluetoothDevice device, @NonNull Collection<Uri> contacts,
+            @NonNull String message, @Nullable PendingIntent sentIntent,
+            @Nullable PendingIntent deliveredIntent) {
+        if (DBG) Log.d(TAG, "sendMessage(" + device + ", " + contacts + ", " + message);
+        final IBluetoothMapClient service = getService();
+        if (service != null && isEnabled() && isValidDevice(device)) {
+            try {
+                return service.sendMessage(device, contacts.toArray(new Uri[contacts.size()]),
+                        message, sentIntent, deliveredIntent);
+            } catch (RemoteException e) {
+                Log.e(TAG, Log.getStackTraceString(new Throwable()));
+                return false;
+            }
+        }
+        return false;
+    }
+
+     /**
+     * Send a message.
+     *
+     * Send an SMS message to either the contacts primary number or the telephone number specified.
+     *
+     * @param device Bluetooth device
      * @param contacts Uri[] of the contacts
      * @param message Message to be sent
      * @param sentIntent intent issued when message is sent
      * @param deliveredIntent intent issued when message is delivered
      * @return true if the message is enqueued, false on error
+     * @hide
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public boolean sendMessage(BluetoothDevice device, Uri[] contacts, String message,
@@ -410,6 +479,7 @@
      *
      * @param device Bluetooth device
      * @return true if the message is enqueued, false on error
+     * @hide
      */
     public boolean getUnreadMessages(BluetoothDevice device) {
         if (DBG) Log.d(TAG, "getUnreadMessages(" + device + ")");
@@ -431,6 +501,7 @@
      * @param device The Bluetooth device to get this value for.
      * @return Returns true if the Uploading bit value in SDP record's
      *         MapSupportedFeatures field is set. False is returned otherwise.
+     * @hide
      */
     public boolean isUploadingSupported(BluetoothDevice device) {
         final IBluetoothMapClient service = getService();
@@ -457,7 +528,7 @@
      *            "read", <code>UNDELETED</code> for "undeleted", <code>DELETED</code> for
      *            "deleted", otherwise return error
      * @return <code>true</code> if request has been sent, <code>false</code> on error
-     *
+     * @hide
      */
     @RequiresPermission(Manifest.permission.READ_SMS)
     public boolean setMessageStatus(BluetoothDevice device, String handle, int status) {
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index c31b04e..201d6c4 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -186,6 +186,7 @@
      *
      * @hide
      */
+    @SystemApi
     int MAP_CLIENT = 18;
 
     /**
diff --git a/core/java/android/bluetooth/BufferConstraints.java b/core/java/android/bluetooth/BufferConstraints.java
index 7e5ec1e..97d9723 100644
--- a/core/java/android/bluetooth/BufferConstraints.java
+++ b/core/java/android/bluetooth/BufferConstraints.java
@@ -90,7 +90,7 @@
      * @hide
      */
     @SystemApi
-    public @Nullable BufferConstraint getCodec(@BluetoothCodecConfig.SourceCodecType int codec) {
+    public @Nullable BufferConstraint forCodec(@BluetoothCodecConfig.SourceCodecType int codec) {
         return mBufferConstraints.get(codec);
     }
 }
diff --git a/core/java/android/companion/DeviceNotAssociatedException.java b/core/java/android/companion/DeviceNotAssociatedException.java
index bebb6c9..f8a7a7c 100644
--- a/core/java/android/companion/DeviceNotAssociatedException.java
+++ b/core/java/android/companion/DeviceNotAssociatedException.java
@@ -23,7 +23,7 @@
  * An exception for a case when a given device was not
  * {@link CompanionDeviceManager#associate associated} to the calling app.
  */
-public class DeviceNotAssociatedException extends Exception {
+public class DeviceNotAssociatedException extends RuntimeException {
     /** @hide */
     public DeviceNotAssociatedException(@Nullable String deviceName) {
         super("Device not associated with the current app: " + deviceName);
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 46d8900..230c985 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -132,8 +132,11 @@
     public static final String SYNC_EXTRAS_ACCOUNT = "account";
 
     /**
-     * If this extra is set to true, the sync request will be scheduled
-     * at the front of the sync request queue and without any delay
+     * If this extra is set to true, the sync request will be scheduled at the front of the
+     * sync request queue, but it is still subject to JobScheduler quota and throttling due to
+     * App Standby buckets.
+     *
+     * <p>This is different from {@link #SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB}.
      */
     public static final String SYNC_EXTRAS_EXPEDITED = "expedited";
 
@@ -145,6 +148,29 @@
     public static final String SYNC_EXTRAS_REQUIRE_CHARGING = "require_charging";
 
     /**
+     * Run this sync operation as an "expedited job"
+     * (see {@link android.app.job.JobInfo.Builder#setExpedited(boolean)}).
+     * Normally (if this flag isn't specified), sync operations are executed as regular
+     * {@link android.app.job.JobService} jobs.
+     *
+     * <p> Because Expedited Jobs have various restrictions compared to regular jobs, this flag
+     * cannot be combined with certain other flags, otherwise an
+     * <code>IllegalArgumentException</code> will be thrown. Notably, because Expedited Jobs do not
+     * support various constraints, the following restriction apply:
+     * <ul>
+     *  <li>Can't be used with {@link #SYNC_EXTRAS_REQUIRE_CHARGING}
+     *  <li>Can't be used with {@link #SYNC_EXTRAS_EXPEDITED}
+     *  <li>Can't be used on periodic syncs.
+     *  <li>When an expedited-job-sync fails and a retry is scheduled, the retried sync will be
+     *  scheduled as a regular job unless {@link #SYNC_EXTRAS_IGNORE_BACKOFF} is set.
+     * </ul>
+     *
+     * <p>This is different from {@link #SYNC_EXTRAS_EXPEDITED}.
+     */
+    @SuppressLint("IntentName")
+    public static final String SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB = "schedule_as_expedited_job";
+
+    /**
      * @deprecated instead use
      * {@link #SYNC_EXTRAS_MANUAL}
      */
@@ -3220,6 +3246,18 @@
     }
 
     /**
+     * {@hide}
+     * Helper function to throw an <code>IllegalArgumentException</code> if any illegal
+     * extras were set for a sync scheduled as an expedited job.
+     *
+     * @param extras bundle to validate.
+     */
+    public static boolean hasInvalidScheduleAsEjExtras(Bundle extras) {
+        return extras.getBoolean(ContentResolver.SYNC_EXTRAS_REQUIRE_CHARGING)
+                || extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED);
+    }
+
+    /**
      * Specifies that a sync should be requested with the specified the account, authority,
      * and extras at the given frequency. If there is already another periodic sync scheduled
      * with the account, authority and extras then a new periodic sync won't be added, instead
@@ -3233,7 +3271,8 @@
      * Periodic syncs are not allowed to have any of {@link #SYNC_EXTRAS_DO_NOT_RETRY},
      * {@link #SYNC_EXTRAS_IGNORE_BACKOFF}, {@link #SYNC_EXTRAS_IGNORE_SETTINGS},
      * {@link #SYNC_EXTRAS_INITIALIZE}, {@link #SYNC_EXTRAS_FORCE},
-     * {@link #SYNC_EXTRAS_EXPEDITED}, {@link #SYNC_EXTRAS_MANUAL} set to true.
+     * {@link #SYNC_EXTRAS_EXPEDITED}, {@link #SYNC_EXTRAS_MANUAL},
+     * {@link #SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB} set to true.
      * If any are supplied then an {@link IllegalArgumentException} will be thrown.
      *
      * <p>This method requires the caller to hold the permission
@@ -3273,16 +3312,14 @@
      * @param extras bundle to validate.
      */
     public static boolean invalidPeriodicExtras(Bundle extras) {
-        if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false)
+        return extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false)
                 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, false)
                 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, false)
                 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false)
                 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false)
                 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false)
-                || extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false)) {
-            return true;
-        }
-        return false;
+                || extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false)
+                || extras.getBoolean(ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB, false);
     }
 
     /**
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 10b00f2..f3a4e1f 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -370,6 +370,25 @@
     /***********    Hidden flags below this line ***********/
 
     /**
+     * Flag for {@link #bindService}: allow the process hosting the target service to be treated
+     * as if it's as important as a perceptible app to the user and avoid the oom killer killing
+     * this process in low memory situations until there aren't any other processes left but the
+     * ones which are user-perceptible.
+     *
+     * @hide
+     */
+    public static final int BIND_ALMOST_PERCEPTIBLE = 0x000010000;
+
+    /**
+     * Flag for {@link #bindService}: allow the process hosting the target service to gain
+     * {@link ActivityManager#PROCESS_CAPABILITY_NETWORK}, which allows it be able
+     * to access network regardless of any power saving restrictions.
+     *
+     * @hide
+     */
+    public static final int BIND_ALLOW_NETWORK_ACCESS = 0x00020000;
+
+    /**
      * Flag for {@link #bindService}: allow background foreground service starts from the bound
      * service's process.
      * This flag is only respected if the caller is holding
@@ -3118,8 +3137,18 @@
      *
      * @throws SecurityException If the caller does not have permission to access the service
      * or the service can not be found.
-     * @throws IllegalStateException If the application is in a state where the service
-     * can not be started (such as not in the foreground in a state when services are allowed).
+     * @throws IllegalStateException
+     * Before Android {@link android.os.Build.VERSION_CODES#S},
+     * if the application is in a state where the service
+     * can not be started (such as not in the foreground in a state when services are allowed),
+     * {@link IllegalStateException} was thrown.
+     * @throws android.app.BackgroundServiceStartNotAllowedException
+     * On Android {@link android.os.Build.VERSION_CODES#S} and later,
+     * if the application is in a state where the service
+     * can not be started (such as not in the foreground in a state when services are allowed),
+     * {@link android.app.BackgroundServiceStartNotAllowedException} is thrown
+     * This excemption extends {@link IllegalStateException}, so apps can
+     * use {@code catch (IllegalStateException)} to catch both.
      *
      * @see #stopService
      * @see #bindService
@@ -3150,7 +3179,8 @@
      * @throws SecurityException If the caller does not have permission to access the service
      * or the service can not be found.
      *
-     * @throws IllegalStateException If the caller app's targeting API is
+     * @throws android.app.ForegroundServiceStartNotAllowedException
+     * If the caller app's targeting API is
      * {@link android.os.Build.VERSION_CODES#S} or later, and the foreground service is restricted
      * from start due to background restriction.
      *
@@ -4753,7 +4783,7 @@
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve an
-     * {@link android.app.scheduling.RebootReadinessManagerService} for communicating
+     * {@link android.scheduling.RebootReadinessManagerService} for communicating
      * with the reboot readiness detector.
      *
      * @see #getSystemService(String)
@@ -5499,6 +5529,14 @@
     public static final String DOMAIN_VERIFICATION_SERVICE = "domain_verification";
 
     /**
+     * Use with {@link #getSystemService(String)} to access
+     * {@link android.view.displayhash.DisplayHashManager} to handle display hashes.
+     *
+     * @see #getSystemService(String)
+     */
+    public static final String DISPLAY_HASH_SERVICE = "display_hash";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
@@ -6655,15 +6693,6 @@
     }
 
     /**
-     * Indicates if this context is a visual context such as {@link android.app.Activity} or
-     * a context created from {@link #createWindowContext(int, Bundle)}.
-     * @hide
-     */
-    public boolean isUiContext() {
-        throw new RuntimeException("Not implemented. Must override in a subclass.");
-    }
-
-    /**
      * Returns {@code true} if the context is a UI context which can access UI components such as
      * {@link WindowManager}, {@link android.view.LayoutInflater LayoutInflater} or
      * {@link android.app.WallpaperManager WallpaperManager}. Accessing UI components from non-UI
@@ -6675,12 +6704,16 @@
      * {@link #createWindowContext(int, Bundle)} or
      * {@link android.inputmethodservice.InputMethodService InputMethodService}
      * </p>
+     * <p>
+     * Note that even if it is allowed programmatically, it is not suggested to override this
+     * method to bypass {@link android.os.strictmode.IncorrectContextUseViolation} verification.
+     * </p>
      *
      * @see #getDisplay()
      * @see #getSystemService(String)
      * @see android.os.StrictMode.VmPolicy.Builder#detectIncorrectContextUse()
      */
-    public static boolean isUiContext(@NonNull Context context) {
-        return context.isUiContext();
+    public boolean isUiContext() {
+        throw new RuntimeException("Not implemented. Must override in a subclass.");
     }
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 4abd8cd..d352b27 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -4754,6 +4754,32 @@
     public static final String ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION =
             "android.intent.action.PACKAGE_NEEDS_INTEGRITY_VERIFICATION";
 
+    /**
+     * Broadcast Action: Indicates that the device's reboot readiness has changed.
+     *
+     * <p>This broadcast will be sent with an extra that indicates whether or not the device is
+     * ready to reboot.
+     * <p>
+     * The receiver <em>must</em> have the {@link android.Manifest.permission#REBOOT} permission.
+     * <p class="note">
+     * This is a protected intent that can only be sent by the system.
+     *
+     * @see #EXTRA_IS_READY_TO_REBOOT
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_REBOOT_READY = "android.intent.action.REBOOT_READY";
+
+    /**
+     * A boolean extra used with {@link #ACTION_REBOOT_READY} which indicates if the
+     * device is ready to reboot.
+     * Will be {@code true} if ready to reboot, {@code false} otherwise.
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_IS_READY_TO_REBOOT = "android.intent.extra.IS_READY_TO_REBOOT";
+
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Standard intent categories (see addCategory()).
@@ -6729,6 +6755,12 @@
      */
     private static final int LOCAL_FLAG_FROM_PROTECTED_COMPONENT = 1 << 2;
 
+    /**
+     * Local flag indicating this instance had unfiltered extras copied into it. This could be
+     * from either {@link #putExtras(Intent)} when an unparceled Intent is provided or {@link
+     * #putExtras(Bundle)} when the provided Bundle has not been unparceled.
+     */
+    private static final int LOCAL_FLAG_UNFILTERED_EXTRAS = 1 << 3;
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // toUri() and parseUri() options.
@@ -9983,6 +10015,15 @@
                 mExtras.putAll(src.mExtras);
             }
         }
+        // If the provided Intent was unparceled and this is not an Intent delivered to a protected
+        // component then mark the extras as unfiltered. An Intent delivered to a protected
+        // component had to come from a trusted component, and if unfiltered data was copied to the
+        // delivered Intent then it would have been reported when that Intent left the sending
+        // process.
+        if ((src.mLocalFlags & LOCAL_FLAG_FROM_PARCEL) != 0
+                && (src.mLocalFlags & LOCAL_FLAG_FROM_PROTECTED_COMPONENT) == 0) {
+            mLocalFlags |= LOCAL_FLAG_UNFILTERED_EXTRAS;
+        }
         return this;
     }
 
@@ -9997,6 +10038,10 @@
      * @see #removeExtra
      */
     public @NonNull Intent putExtras(@NonNull Bundle extras) {
+        // If the provided Bundle has not yet been unparceled then treat this as unfiltered extras.
+        if (extras.isParcelled()) {
+            mLocalFlags |= LOCAL_FLAG_UNFILTERED_EXTRAS;
+        }
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -11302,10 +11347,13 @@
         }
 
         // Detect cases where we're about to launch a potentially unsafe intent
-        if ((mLocalFlags & LOCAL_FLAG_FROM_PARCEL) != 0
-                && (mLocalFlags & LOCAL_FLAG_FROM_PROTECTED_COMPONENT) == 0
-                && StrictMode.vmUnsafeIntentLaunchEnabled()) {
-            StrictMode.onUnsafeIntentLaunch(this);
+        if (StrictMode.vmUnsafeIntentLaunchEnabled()) {
+            if ((mLocalFlags & LOCAL_FLAG_FROM_PARCEL) != 0
+                    && (mLocalFlags & LOCAL_FLAG_FROM_PROTECTED_COMPONENT) == 0) {
+                StrictMode.onUnsafeIntentLaunch(this);
+            } else if ((mLocalFlags & LOCAL_FLAG_UNFILTERED_EXTRAS) != 0) {
+                StrictMode.onUnsafeIntentLaunch(this);
+            }
         }
     }
 
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index 858d1e4..b1252fd 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -18,6 +18,7 @@
 
 import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.ActivityManager.PendingIntentInfo;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Handler;
@@ -60,6 +61,9 @@
     private final IIntentSender mTarget;
     IBinder mWhitelistToken;
 
+    // cached pending intent information
+    private @Nullable PendingIntentInfo mCachedInfo;
+
     /**
      * Exception thrown when trying to send through a PendingIntent that
      * has been canceled or is otherwise no longer able to execute the request.
@@ -209,13 +213,7 @@
      */
     @Deprecated
     public String getTargetPackage() {
-        try {
-            return ActivityManager.getService()
-                .getPackageForIntentSender(mTarget);
-        } catch (RemoteException e) {
-            // Should never happen.
-            return null;
-        }
+        return getCreatorPackage();
     }
 
     /**
@@ -228,13 +226,7 @@
      * none associated with it.
      */
     public String getCreatorPackage() {
-        try {
-            return ActivityManager.getService()
-                .getPackageForIntentSender(mTarget);
-        } catch (RemoteException e) {
-            // Should never happen.
-            return null;
-        }
+        return getCachedInfo().getCreatorPackage();
     }
 
     /**
@@ -247,13 +239,7 @@
      * none associated with it.
      */
     public int getCreatorUid() {
-        try {
-            return ActivityManager.getService()
-                .getUidForIntentSender(mTarget);
-        } catch (RemoteException e) {
-            // Should never happen.
-            return -1;
-        }
+        return getCachedInfo().getCreatorUid();
     }
 
     /**
@@ -268,14 +254,8 @@
      * none associated with it.
      */
     public UserHandle getCreatorUserHandle() {
-        try {
-            int uid = ActivityManager.getService()
-                .getUidForIntentSender(mTarget);
-            return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
-        } catch (RemoteException e) {
-            // Should never happen.
-            return null;
-        }
+        int uid = getCachedInfo().getCreatorUid();
+        return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
     }
 
     /**
@@ -384,4 +364,16 @@
     public IntentSender(IBinder target) {
         mTarget = IIntentSender.Stub.asInterface(target);
     }
+
+    private PendingIntentInfo getCachedInfo() {
+        if (mCachedInfo == null) {
+            try {
+                mCachedInfo = ActivityManager.getService().getInfoForIntentSender(mTarget);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        return mCachedInfo;
+    }
 }
diff --git a/core/java/android/content/SyncRequest.java b/core/java/android/content/SyncRequest.java
index 9e568a4..e1e6f75 100644
--- a/core/java/android/content/SyncRequest.java
+++ b/core/java/android/content/SyncRequest.java
@@ -17,6 +17,7 @@
 package android.content;
 
 import android.accounts.Account;
+import android.annotation.NonNull;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
 import android.os.Bundle;
@@ -58,6 +59,8 @@
     private final boolean mIsAuthority;
     /** Sync should be run in lieu of other syncs. */
     private final boolean mIsExpedited;
+    /** Sync sound be ran as an expedited job. */
+    private final boolean mIsScheduledAsExpeditedJob;
 
     /**
      * {@hide}
@@ -79,6 +82,14 @@
 
     /**
      * {@hide}
+     * @return whether this sync is scheduled as an expedited job.
+     */
+    public boolean isScheduledAsExpeditedJob() {
+        return mIsScheduledAsExpeditedJob;
+    }
+
+    /**
+     * {@hide}
      *
      * @return account object for this sync.
      * @throws IllegalArgumentException if this function is called for a request that targets a
@@ -149,6 +160,7 @@
         parcel.writeInt((mDisallowMetered ? 1 : 0));
         parcel.writeInt((mIsAuthority ? 1 : 0));
         parcel.writeInt((mIsExpedited? 1 : 0));
+        parcel.writeInt(mIsScheduledAsExpeditedJob ? 1 : 0);
         parcel.writeParcelable(mAccountToSync, flags);
         parcel.writeString(mAuthority);
     }
@@ -161,6 +173,7 @@
         mDisallowMetered = (in.readInt() != 0);
         mIsAuthority = (in.readInt() != 0);
         mIsExpedited = (in.readInt() != 0);
+        mIsScheduledAsExpeditedJob = (in.readInt() != 0);
         mAccountToSync = in.readParcelable(null);
         mAuthority = in.readString();
     }
@@ -174,6 +187,7 @@
         mIsPeriodic = (b.mSyncType == Builder.SYNC_TYPE_PERIODIC);
         mIsAuthority = (b.mSyncTarget == Builder.SYNC_TARGET_ADAPTER);
         mIsExpedited = b.mExpedited;
+        mIsScheduledAsExpeditedJob = b.mScheduleAsExpeditedJob;
         mExtras = new Bundle(b.mCustomExtras);
         // For now we merge the sync config extras & the custom extras into one bundle.
         // TODO: pass the configuration extras through separately.
@@ -258,6 +272,11 @@
          */
         private boolean mRequiresCharging;
 
+        /**
+         * Whether the sync should be scheduled as an expedited job.
+         */
+        private boolean mScheduleAsExpeditedJob;
+
         public Builder() {
         }
 
@@ -309,7 +328,8 @@
          * {@link ContentResolver#SYNC_EXTRAS_INITIALIZE},
          * {@link ContentResolver#SYNC_EXTRAS_FORCE},
          * {@link ContentResolver#SYNC_EXTRAS_EXPEDITED},
-         * {@link ContentResolver#SYNC_EXTRAS_MANUAL}
+         * {@link ContentResolver#SYNC_EXTRAS_MANUAL},
+         * {@link ContentResolver#SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB}
          * set to true. If any are supplied then an <code>IllegalArgumentException</code> will
          * be thrown.
          *
@@ -500,6 +520,22 @@
         }
 
         /**
+         * Convenience function for setting
+         * {@link ContentResolver#SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB}.
+         *
+         * <p> Not to be confused with {@link ContentResolver#SYNC_EXTRAS_EXPEDITED}.
+         *
+         * <p> Not valid for periodic syncs, expedited syncs, and syncs that require charging - an
+         * <code>IllegalArgumentException</code> will be thrown in {@link #build()}.
+         *
+         * @param scheduleAsExpeditedJob whether to schedule as an expedited job. Default false.
+         */
+        public @NonNull Builder setScheduleAsExpeditedJob(boolean scheduleAsExpeditedJob) {
+            mScheduleAsExpeditedJob = scheduleAsExpeditedJob;
+            return this;
+        }
+
+        /**
          * Performs validation over the request and throws the runtime exception
          * <code>IllegalArgumentException</code> if this validation fails.
          *
@@ -507,11 +543,6 @@
          *         builder.
          */
         public SyncRequest build() {
-            // Validate the extras bundle
-            ContentResolver.validateSyncExtrasBundle(mCustomExtras);
-            if (mCustomExtras == null) {
-                mCustomExtras = new Bundle();
-            }
             // Combine builder extra flags into the config bundle.
             mSyncConfigExtras = new Bundle();
             if (mIgnoreBackoff) {
@@ -532,17 +563,35 @@
             if (mExpedited) {
                 mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
             }
+            if (mScheduleAsExpeditedJob) {
+                mSyncConfigExtras.putBoolean(
+                        ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB, true);
+            }
             if (mIsManual) {
                 mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, true);
                 mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, true);
             }
+
+            if (mCustomExtras == null) {
+                mCustomExtras = new Bundle();
+            }
+            // Validate the extras bundles
+            ContentResolver.validateSyncExtrasBundle(mCustomExtras);
+            // If this is a periodic sync ensure than invalid extras were not set.
             if (mSyncType == SYNC_TYPE_PERIODIC) {
-                // If this is a periodic sync ensure than invalid extras were not set.
                 if (ContentResolver.invalidPeriodicExtras(mCustomExtras) ||
                         ContentResolver.invalidPeriodicExtras(mSyncConfigExtras)) {
                     throw new IllegalArgumentException("Illegal extras were set");
                 }
             }
+            // If this sync is scheduled as an EJ, ensure that invalid extras were not set.
+            if (mCustomExtras.getBoolean(ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB)
+                    || mScheduleAsExpeditedJob) {
+                if (ContentResolver.hasInvalidScheduleAsEjExtras(mCustomExtras)
+                        || ContentResolver.hasInvalidScheduleAsEjExtras(mSyncConfigExtras)) {
+                    throw new IllegalArgumentException("Illegal extras were set");
+                }
+            }
             // Ensure that a target for the sync has been set.
             if (mSyncTarget == SYNC_TARGET_UNKNOWN) {
                 throw new IllegalArgumentException("Must specify an adapter with" +
diff --git a/core/java/android/content/pm/AppSearchPerson.java b/core/java/android/content/pm/AppSearchPerson.java
index d70ac91..66295eb 100644
--- a/core/java/android/content/pm/AppSearchPerson.java
+++ b/core/java/android/content/pm/AppSearchPerson.java
@@ -42,7 +42,7 @@
     public static final String KEY_IS_BOT = "isBot";
     public static final String KEY_IS_IMPORTANT = "isImportant";
 
-    private AppSearchPerson(@NonNull GenericDocument document) {
+    public AppSearchPerson(@NonNull GenericDocument document) {
         super(document);
     }
 
diff --git a/core/java/android/content/pm/AppSearchShortcutInfo.java b/core/java/android/content/pm/AppSearchShortcutInfo.java
index ebe202b..5af3b5a 100644
--- a/core/java/android/content/pm/AppSearchShortcutInfo.java
+++ b/core/java/android/content/pm/AppSearchShortcutInfo.java
@@ -28,7 +28,6 @@
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
 import android.os.PersistableBundle;
-import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.ArraySet;
 
@@ -53,17 +52,23 @@
     /** The name of the schema type for {@link ShortcutInfo} documents.*/
     public static final String SCHEMA_TYPE = "Shortcut";
 
-    public static final String KEY_PACKAGE_NAME = "packageName";
     public static final String KEY_ACTIVITY = "activity";
-    public static final String KEY_TITLE = "title";
-    public static final String KEY_TEXT = "text";
+    public static final String KEY_SHORT_LABEL = "shortLabel";
+    public static final String KEY_SHORT_LABEL_RES_ID = "shortLabelResId";
+    public static final String KEY_SHORT_LABEL_RES_NAME = "shortLabelResName";
+    public static final String KEY_LONG_LABEL = "longLabel";
+    public static final String KEY_LONG_LABEL_RES_ID = "longLabelResId";
+    public static final String KEY_LONG_LABEL_RES_NAME = "longLabelResName";
     public static final String KEY_DISABLED_MESSAGE = "disabledMessage";
+    public static final String KEY_DISABLED_MESSAGE_RES_ID = "disabledMessageResId";
+    public static final String KEY_DISABLED_MESSAGE_RES_NAME = "disabledMessageResName";
     public static final String KEY_CATEGORIES = "categories";
     public static final String KEY_INTENTS = "intents";
     public static final String KEY_INTENT_PERSISTABLE_EXTRAS = "intentPersistableExtras";
     public static final String KEY_PERSON = "person";
     public static final String KEY_LOCUS_ID = "locusId";
     public static final String KEY_RANK = "rank";
+    public static final String KEY_IMPLICIT_RANK = "implicitRank";
     public static final String KEY_EXTRAS = "extras";
     public static final String KEY_FLAGS = "flags";
     public static final String KEY_ICON_RES_ID = "iconResId";
@@ -73,36 +78,62 @@
     public static final String KEY_DISABLED_REASON = "disabledReason";
 
     public static final AppSearchSchema SCHEMA = new AppSearchSchema.Builder(SCHEMA_TYPE)
-            .addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_PACKAGE_NAME)
-                    .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REQUIRED)
-                    .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
-                    .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS)
-                    .build()
-
-            ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_ACTIVITY)
+            .addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_ACTIVITY)
                     .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
                     .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
                     .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS)
                     .build()
 
-            ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_TITLE)
+            ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_SHORT_LABEL)
                     .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
                     .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
                     .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_PREFIXES)
                     .build()
 
-            ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_TEXT)
+            ).addProperty(new AppSearchSchema.Int64PropertyConfig.Builder(KEY_SHORT_LABEL_RES_ID)
+                    .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
+                    .build()
+
+            ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_SHORT_LABEL_RES_NAME)
+                    .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
+                    .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_NONE)
+                    .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE)
+                    .build()
+
+            ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_LONG_LABEL)
                     .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
                     .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
                     .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_PREFIXES)
                     .build()
 
+            ).addProperty(new AppSearchSchema.Int64PropertyConfig.Builder(KEY_LONG_LABEL_RES_ID)
+                    .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
+                    .build()
+
+            ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_LONG_LABEL_RES_NAME)
+                    .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
+                    .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_NONE)
+                    .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE)
+                    .build()
+
             ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_DISABLED_MESSAGE)
                     .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
                     .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_NONE)
                     .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE)
                     .build()
 
+            ).addProperty(new AppSearchSchema.Int64PropertyConfig.Builder(
+                    KEY_DISABLED_MESSAGE_RES_ID)
+                    .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
+                    .build()
+
+            ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(
+                    KEY_DISABLED_MESSAGE_RES_NAME)
+                    .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
+                    .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_NONE)
+                    .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE)
+                    .build()
+
             ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_CATEGORIES)
                     .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED)
                     .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
@@ -135,6 +166,10 @@
                     .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
                     .build()
 
+            ).addProperty(new AppSearchSchema.Int64PropertyConfig.Builder(KEY_IMPLICIT_RANK)
+                    .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
+                    .build()
+
             ).addProperty(new AppSearchSchema.BytesPropertyConfig.Builder(KEY_EXTRAS)
                     .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
                     .build()
@@ -183,13 +218,21 @@
         Objects.requireNonNull(shortcutInfo);
         return new Builder(shortcutInfo.getId())
                 .setActivity(shortcutInfo.getActivity())
-                .setPackageName(shortcutInfo.getPackage())
-                .setTitle(shortcutInfo.getShortLabel())
-                .setText(shortcutInfo.getLongLabel())
+                .setNamespace(shortcutInfo.getPackage())
+                .setShortLabel(shortcutInfo.getShortLabel())
+                .setShortLabelResId(shortcutInfo.getShortLabelResourceId())
+                .setShortLabelResName(shortcutInfo.getTitleResName())
+                .setLongLabel(shortcutInfo.getLongLabel())
+                .setLongLabelResId(shortcutInfo.getLongLabelResourceId())
+                .setLongLabelResName(shortcutInfo.getTextResName())
                 .setDisabledMessage(shortcutInfo.getDisabledMessage())
+                .setDisabledMessageResId(shortcutInfo.getDisabledMessageResourceId())
+                .setDisabledMessageResName(shortcutInfo.getDisabledMessageResName())
                 .setCategories(shortcutInfo.getCategories())
                 .setIntents(shortcutInfo.getIntents())
                 .setRank(shortcutInfo.getRank())
+                .setImplicitRank(shortcutInfo.getImplicitRank()
+                        | (shortcutInfo.isRankChanged() ? ShortcutInfo.RANK_CHANGED_BIT : 0))
                 .setExtras(shortcutInfo.getExtras())
                 .setCreationTimestampMillis(shortcutInfo.getLastChangedTimestamp())
                 .setFlags(shortcutInfo.getFlags())
@@ -207,17 +250,8 @@
      * @hide
      */
     @NonNull
-    public ShortcutInfo toShortcutInfo() {
-        return toShortcutInfo(UserHandle.myUserId());
-    }
-
-    /**
-     * @hide
-     * TODO: This should be @SystemApi when AppSearchShortcutInfo unhides.
-     */
-    @NonNull
-    public ShortcutInfo toShortcutInfo(@UserIdInt final int userId) {
-        final String packageName = getPropertyString(KEY_PACKAGE_NAME);
+    public ShortcutInfo toShortcutInfo(@UserIdInt int userId) {
+        final String packageName = getNamespace();
         final String activityString = getPropertyString(KEY_ACTIVITY);
         final ComponentName activity = activityString == null
                 ? null : ComponentName.unflattenFromString(activityString);
@@ -228,15 +262,24 @@
         // @hide and @UnsupportedAppUsage, we could migrate existing usage in platform with
         // LauncherApps#getShortcutIconDrawable instead.
         final Icon icon = null;
-        final String title = getPropertyString(KEY_TITLE);
-        final String text = getPropertyString(KEY_TEXT);
+        final String shortLabel = getPropertyString(KEY_SHORT_LABEL);
+        final int shortLabelResId = (int) getPropertyLong(KEY_SHORT_LABEL_RES_ID);
+        final String shortLabelResName = getPropertyString(KEY_SHORT_LABEL_RES_NAME);
+        final String longLabel = getPropertyString(KEY_LONG_LABEL);
+        final int longLabelResId = (int) getPropertyLong(KEY_LONG_LABEL_RES_ID);
+        final String longLabelResName = getPropertyString(KEY_LONG_LABEL_RES_NAME);
         final String disabledMessage = getPropertyString(KEY_DISABLED_MESSAGE);
+        final int disabledMessageResId = (int) getPropertyLong(KEY_DISABLED_MESSAGE_RES_ID);
+        final String disabledMessageResName = getPropertyString(KEY_DISABLED_MESSAGE_RES_NAME);
         final String[] categories = getPropertyStringArray(KEY_CATEGORIES);
         final Set<String> categoriesSet = categories == null
-                ? new ArraySet<>() : new ArraySet<>(Arrays.asList(categories));
+                ? null : new ArraySet<>(Arrays.asList(categories));
         final String[] intentsStrings = getPropertyStringArray(KEY_INTENTS);
         final Intent[] intents = intentsStrings == null
-                ? null : Arrays.stream(intentsStrings).map(uri -> {
+                ? new Intent[0] : Arrays.stream(intentsStrings).map(uri -> {
+                    if (TextUtils.isEmpty(uri)) {
+                        return new Intent(Intent.ACTION_VIEW);
+                    }
                     try {
                         return Intent.parseUri(uri, /* flags =*/ 0);
                     } catch (URISyntaxException e) {
@@ -251,15 +294,18 @@
         if (intents != null) {
             for (int i = 0; i < intents.length; i++) {
                 final Intent intent = intents[i];
-                if (intent != null) {
-                    intent.replaceExtras(intentExtrases[i].size() == 0 ? null : intentExtrases[i]);
+                if (intent == null || intentExtrases == null || intentExtrases.length <= i
+                        || intentExtrases[i] == null || intentExtrases[i].size() == 0) {
+                    continue;
                 }
+                intent.replaceExtras(intentExtrases[i]);
             }
         }
         final Person[] persons = parsePerson(getPropertyDocumentArray(KEY_PERSON));
         final String locusIdString = getPropertyString(KEY_LOCUS_ID);
         final LocusId locusId = locusIdString == null ? null : new LocusId(locusIdString);
         final int rank = (int) getPropertyLong(KEY_RANK);
+        final int implicitRank = (int) getPropertyLong(KEY_IMPLICIT_RANK);
         final byte[] extrasByte = getPropertyBytes(KEY_EXTRAS);
         final PersistableBundle extras = transformToPersistableBundle(extrasByte);
         final int flags = parseFlags(getPropertyLongArray(KEY_FLAGS));
@@ -268,12 +314,17 @@
         final String iconUri = getPropertyString(KEY_ICON_URI);
         final String bitmapPath = getPropertyString(KEY_BITMAP_PATH);
         final int disabledReason = (int) getPropertyLong(KEY_DISABLED_REASON);
-        return new ShortcutInfo(
-                userId, getUri(), packageName, activity, icon, title, 0, null,
-                text, 0, null, disabledMessage, 0, null,
-                categoriesSet, intents, rank, extras,
+        final ShortcutInfo si = new ShortcutInfo(
+                userId, getUri(), packageName, activity, icon, shortLabel, shortLabelResId,
+                shortLabelResName, longLabel, longLabelResId, longLabelResName, disabledMessage,
+                disabledMessageResId, disabledMessageResName, categoriesSet, intents, rank, extras,
                 getCreationTimestampMillis(), flags, iconResId, iconResName, bitmapPath, iconUri,
                 disabledReason, persons, locusId, 0);
+        si.setImplicitRank(implicitRank);
+        if ((implicitRank & ShortcutInfo.RANK_CHANGED_BIT) != 0) {
+            si.setRankChanged();
+        }
+        return si;
     }
 
     /** @hide */
@@ -310,9 +361,9 @@
          * @hide
          */
         @NonNull
-        public Builder setTitle(@Nullable final CharSequence shortLabel) {
+        public Builder setShortLabel(@Nullable final CharSequence shortLabel) {
             if (!TextUtils.isEmpty(shortLabel)) {
-                setPropertyString(KEY_TITLE, Preconditions.checkStringNotEmpty(
+                setPropertyString(KEY_SHORT_LABEL, Preconditions.checkStringNotEmpty(
                         shortLabel, "shortLabel cannot be empty").toString());
             }
             return this;
@@ -322,13 +373,50 @@
          * @hide
          */
         @NonNull
-        public Builder setText(@Nullable final CharSequence longLabel) {
+        public Builder setShortLabelResId(@Nullable final int shortLabelResId) {
+            setPropertyLong(KEY_SHORT_LABEL_RES_ID, shortLabelResId);
+            return this;
+        }
+
+        /**
+         * @hide
+         */
+        public Builder setShortLabelResName(@Nullable final String shortLabelResName) {
+            if (!TextUtils.isEmpty(shortLabelResName)) {
+                setPropertyString(KEY_SHORT_LABEL_RES_NAME, shortLabelResName);
+            }
+            return this;
+        }
+
+        /**
+         * @hide
+         */
+        @NonNull
+        public Builder setLongLabel(@Nullable final CharSequence longLabel) {
             if (!TextUtils.isEmpty(longLabel)) {
-                setPropertyString(KEY_TEXT, Preconditions.checkStringNotEmpty(
+                setPropertyString(KEY_LONG_LABEL, Preconditions.checkStringNotEmpty(
                         longLabel, "longLabel cannot be empty").toString());
             }
             return this;
+        }
 
+        /**
+         * @hide
+         */
+        @NonNull
+        public Builder setLongLabelResId(@Nullable final int longLabelResId) {
+            setPropertyLong(KEY_LONG_LABEL_RES_ID, longLabelResId);
+            return this;
+        }
+
+        /**
+         * @hide
+         */
+        public Builder setLongLabelResName(@Nullable final String longLabelResName) {
+            if (!TextUtils.isEmpty(longLabelResName)) {
+                setPropertyString(KEY_LONG_LABEL_RES_NAME, longLabelResName);
+            }
+            return this;
         }
 
         /**
@@ -347,6 +435,25 @@
          * @hide
          */
         @NonNull
+        public Builder setDisabledMessageResId(@Nullable final int disabledMessageResId) {
+            setPropertyLong(KEY_DISABLED_MESSAGE_RES_ID, disabledMessageResId);
+            return this;
+        }
+
+        /**
+         * @hide
+         */
+        public Builder setDisabledMessageResName(@Nullable final String disabledMessageResName) {
+            if (!TextUtils.isEmpty(disabledMessageResName)) {
+                setPropertyString(KEY_DISABLED_MESSAGE_RES_NAME, disabledMessageResName);
+            }
+            return this;
+        }
+
+        /**
+         * @hide
+         */
+        @NonNull
         public Builder setCategories(@Nullable final Set<String> categories) {
             if (categories != null && !categories.isEmpty()) {
                 setPropertyString(KEY_CATEGORIES, categories.stream().toArray(String[]::new));
@@ -384,9 +491,8 @@
                 intentExtrases[i] = extras == null
                         ? new byte[0] : transformToByteArray(new PersistableBundle(extras));
             }
-
-            setPropertyString(KEY_INTENTS, Arrays.stream(intents).map(it ->
-                    it.toUri(0)).toArray(String[]::new));
+            setPropertyString(KEY_INTENTS, Arrays.stream(intents).map(it -> it.toUri(0))
+                    .toArray(String[]::new));
             setPropertyBytes(KEY_INTENT_PERSISTABLE_EXTRAS, intentExtrases);
             return this;
         }
@@ -410,10 +516,14 @@
             if (persons == null || persons.length == 0) {
                 return this;
             }
-            setPropertyDocument(KEY_PERSON,
-                    Arrays.stream(persons).map(person -> AppSearchPerson.instance(
-                            Objects.requireNonNull(person, "persons cannot contain null"))
-                    ).toArray(AppSearchPerson[]::new));
+            final GenericDocument[] documents = new GenericDocument[persons.length];
+            for (int i = 0; i < persons.length; i++) {
+                final Person person = persons[i];
+                if (person == null) continue;
+                final AppSearchPerson appSearchPerson = AppSearchPerson.instance(person);
+                documents[i] = appSearchPerson;
+            }
+            setPropertyDocument(KEY_PERSON, documents);
             return this;
         }
 
@@ -422,8 +532,7 @@
          */
         @NonNull
         public Builder setRank(final int rank) {
-            Preconditions.checkArgument((0 <= rank),
-                    "Rank cannot be negative or bigger than MAX_RANK");
+            Preconditions.checkArgument((0 <= rank), "Rank cannot be negative");
             setPropertyLong(KEY_RANK, rank);
             return this;
         }
@@ -432,6 +541,15 @@
          * @hide
          */
         @NonNull
+        public Builder setImplicitRank(final int rank) {
+            setPropertyLong(KEY_IMPLICIT_RANK, rank);
+            return this;
+        }
+
+        /**
+         * @hide
+         */
+        @NonNull
         public Builder setExtras(@Nullable final PersistableBundle extras) {
             if (extras != null) {
                 setPropertyBytes(KEY_EXTRAS, transformToByteArray(extras));
@@ -444,7 +562,7 @@
          */
         public Builder setPackageName(@Nullable final String packageName) {
             if (!TextUtils.isEmpty(packageName)) {
-                setPropertyString(KEY_PACKAGE_NAME, packageName);
+                setNamespace(packageName);
             }
             return this;
         }
@@ -579,7 +697,14 @@
 
     @NonNull
     private static Person[] parsePerson(@Nullable final GenericDocument[] persons) {
-        return persons == null ? new Person[0] : Arrays.stream(persons).map(it ->
-                ((AppSearchPerson) it).toPerson()).toArray(Person[]::new);
+        if (persons == null) return new Person[0];
+        final Person[] ret = new Person[persons.length];
+        for (int i = 0; i < persons.length; i++) {
+            final GenericDocument document = persons[i];
+            if (document == null) continue;
+            final AppSearchPerson person = new AppSearchPerson(document);
+            ret[i] = person.toPerson();
+        }
+        return ret;
     }
 }
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 01ff432..0aa1be9 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -136,6 +136,18 @@
     public int fullBackupContent = 0;
 
     /**
+     * Applications can set this attribute to an xml resource within their app where they specified
+     * the rules determining which files and directories can be copied from the device as part of
+     * backup or transfer operations.
+     *<p>
+     * Set from the {@link android.R.styleable#AndroidManifestApplication_dataExtractionRules}
+     * attribute in the manifest.
+     *
+     * @hide
+     */
+    public int dataExtractionRulesRes = 0;
+
+    /**
      * <code>true</code> if the package is capable of presenting a unified interface representing
      * multiple profiles.
      * @hide
@@ -1105,19 +1117,15 @@
      * <p>
      * This property is the compile-time equivalent of
      * {@link android.os.Build.VERSION#CODENAME Build.VERSION.SDK_INT}.
-     *
-     * @hide For platform use only; we don't expect developers to need to read this value.
      */
     public int compileSdkVersion;
 
     /**
-     * The development codename (ex. "O", "REL") of the framework against which the application
+     * The development codename (ex. "S", "REL") of the framework against which the application
      * claims to have been compiled, or {@code null} if not specified.
      * <p>
      * This property is the compile-time equivalent of
      * {@link android.os.Build.VERSION#CODENAME Build.VERSION.CODENAME}.
-     *
-     * @hide For platform use only; we don't expect developers to need to read this value.
      */
     @Nullable
     public String compileSdkVersionCodename;
@@ -1524,6 +1532,9 @@
                 pw.println(prefix + "fullBackupContent="
                         + (fullBackupContent < 0 ? "false" : "true"));
             }
+            if (dataExtractionRulesRes != 0) {
+                pw.println(prefix + "dataExtractionRules=@xml/" + dataExtractionRulesRes);
+            }
             pw.println(prefix + "crossProfile=" + (crossProfile ? "true" : "false"));
             if (networkSecurityConfigRes != 0) {
                 pw.println(prefix + "networkSecurityConfigRes=0x"
@@ -1753,6 +1764,7 @@
         uiOptions = orig.uiOptions;
         backupAgentName = orig.backupAgentName;
         fullBackupContent = orig.fullBackupContent;
+        dataExtractionRulesRes = orig.dataExtractionRulesRes;
         crossProfile = orig.crossProfile;
         networkSecurityConfigRes = orig.networkSecurityConfigRes;
         category = orig.category;
@@ -1840,6 +1852,7 @@
         dest.writeInt(descriptionRes);
         dest.writeInt(uiOptions);
         dest.writeInt(fullBackupContent);
+        dest.writeInt(dataExtractionRulesRes);
         dest.writeBoolean(crossProfile);
         dest.writeInt(networkSecurityConfigRes);
         dest.writeInt(category);
@@ -1924,6 +1937,7 @@
         descriptionRes = source.readInt();
         uiOptions = source.readInt();
         fullBackupContent = source.readInt();
+        dataExtractionRulesRes = source.readInt();
         crossProfile = source.readBoolean();
         networkSecurityConfigRes = source.readInt();
         category = source.readInt();
diff --git a/core/java/android/content/pm/CrossProfileApps.java b/core/java/android/content/pm/CrossProfileApps.java
index b290679..48b634e 100644
--- a/core/java/android/content/pm/CrossProfileApps.java
+++ b/core/java/android/content/pm/CrossProfileApps.java
@@ -19,6 +19,7 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.app.Activity;
 import android.app.AppOpsManager.Mode;
 import android.content.ComponentName;
@@ -418,6 +419,7 @@
      *
      * @hide
      */
+    @TestApi
     public boolean canConfigureInteractAcrossProfiles(@NonNull String packageName) {
         try {
             return mService.canConfigureInteractAcrossProfiles(packageName);
diff --git a/core/java/android/content/pm/DataLoaderParamsParcel.aidl b/core/java/android/content/pm/DataLoaderParamsParcel.aidl
index d40012fd..29d472e 100644
--- a/core/java/android/content/pm/DataLoaderParamsParcel.aidl
+++ b/core/java/android/content/pm/DataLoaderParamsParcel.aidl
@@ -23,7 +23,7 @@
  * @hide
  */
 parcelable DataLoaderParamsParcel {
-    DataLoaderType type;
+    DataLoaderType type = DataLoaderType.NONE;
     @utf8InCpp String packageName;
     @utf8InCpp String className;
     @utf8InCpp String arguments;
diff --git a/core/java/android/content/pm/IShortcutService.aidl b/core/java/android/content/pm/IShortcutService.aidl
index 29a55b7..b345748 100644
--- a/core/java/android/content/pm/IShortcutService.aidl
+++ b/core/java/android/content/pm/IShortcutService.aidl
@@ -78,4 +78,7 @@
     ParceledListSlice getShortcuts(String packageName, int matchFlags, int userId);
 
     void pushDynamicShortcut(String packageName, in ShortcutInfo shortcut, int userId);
+
+    void updateShortcutVisibility(String callingPkg, String packageName, in byte[] certificate,
+            in boolean visible, int userId);
 }
\ No newline at end of file
diff --git a/core/java/android/content/pm/InstallationFileParcel.aidl b/core/java/android/content/pm/InstallationFileParcel.aidl
index b7efc19..09d1a32 100644
--- a/core/java/android/content/pm/InstallationFileParcel.aidl
+++ b/core/java/android/content/pm/InstallationFileParcel.aidl
@@ -24,7 +24,7 @@
  */
 parcelable InstallationFileParcel {
     String name;
-    InstallationFileLocation location;
+    InstallationFileLocation location = InstallationFileLocation.UNKNOWN;
     long size;
     byte[] metadata;
     byte[] signature;
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 567501c..42cbe35 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1173,7 +1173,6 @@
          * {@hide}
          */
         @SystemApi
-        @RequiresPermission(android.Manifest.permission.USE_INSTALLER_V2)
         public @Nullable DataLoaderParams getDataLoaderParams() {
             try {
                 DataLoaderParamsParcel data = mSession.getDataLoaderParams();
@@ -1213,7 +1212,6 @@
          * {@hide}
          */
         @SystemApi
-        @RequiresPermission(android.Manifest.permission.USE_INSTALLER_V2)
         public void addFile(@FileLocation int location, @NonNull String name, long lengthBytes,
                 @NonNull byte[] metadata, @Nullable byte[] signature) {
             try {
@@ -1237,7 +1235,6 @@
          * {@hide}
          */
         @SystemApi
-        @RequiresPermission(android.Manifest.permission.USE_INSTALLER_V2)
         public void removeFile(@FileLocation int location, @NonNull String name) {
             try {
                 mSession.removeFile(location, name);
@@ -2050,9 +2047,7 @@
          * {@hide}
          */
         @SystemApi
-        @RequiresPermission(allOf = {
-                Manifest.permission.INSTALL_PACKAGES,
-                Manifest.permission.USE_INSTALLER_V2})
+        @RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
         public void setDataLoaderParams(@NonNull DataLoaderParams dataLoaderParams) {
             this.dataLoaderParams = dataLoaderParams;
         }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index fdb00c6..3bc6144 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3601,7 +3601,7 @@
      * 1 - IncFs v1, core features, no PerUid support. Optional in R.
      * 2 - IncFs v2, PerUid support, fs-verity support. Required in S.
      *
-     * @see IncrementalManager#isFeatureEnabled and IncrementalManager#isV2()
+     * @see IncrementalManager#getVersion()
      * @hide
      */
     @SystemApi
@@ -3623,11 +3623,26 @@
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device supports a enabling/disabling sensor privacy for
-     * camera. When sensory privacy for the camera is enabled no camera data is send to clients,
+     * microphone. When sensory privacy for the microphone is enabled no microphone data is sent to
+     * clients, e.g. all audio data is silent.
+     *
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_MICROPHONE_TOGGLE = "android.hardware.microphone.toggle";
+
+    /**
+     * Feature for {@link #getSystemAvailableFeatures} and
+     * {@link #hasSystemFeature}: The device supports a enabling/disabling sensor privacy for
+     * camera. When sensory privacy for the camera is enabled no camera data is sent to clients,
      * e.g. the view finder in a camera app would appear blank.
      *
      * @hide
      */
+    @SystemApi
+    @TestApi
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_CAMERA_TOGGLE = "android.hardware.camera.toggle";
 
@@ -3641,17 +3656,6 @@
     public static final String FEATURE_APP_ENUMERATION = "android.software.app_enumeration";
 
     /**
-     * Feature for {@link android.view.WindowManager.LayoutParams.backgroundBlurRedius} and
-     * {@link android.graphics.drawable.BackgroundBlurDrawable}: the device supports cross-layer
-     * blurring.
-     *
-     * @hide
-     */
-    @SystemApi
-    @SdkConstant(SdkConstantType.FEATURE)
-    public static final String FEATURE_CROSS_LAYER_BLUR = "android.software.cross_layer_blur";
-
-    /**
      * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device has
      * a Keystore implementation that can only enforce limited use key in hardware with max usage
      * count equals to 1.
@@ -4060,18 +4064,10 @@
     public static final int FLAG_PERMISSION_AUTO_REVOKED = 1 << 17;
 
     /**
-     * Permission flag: The permission is restricted but the app is exempt
-     * from the restriction and is allowed to hold this permission in its
-     * full form and the exemption is provided by the held roles.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int FLAG_PERMISSION_RESTRICTION_ROLE_EXEMPT =  1 << 18;
-
-    /**
      * Permission flag: This location permission is selected as the level of granularity of
      * location accuracy.
+     * Example: If this flag is set for ACCESS_FINE_LOCATION, FINE location is the selected location
+     *          accuracy for location permissions.
      *
      * @hide
      */
@@ -4096,8 +4092,7 @@
     public static final int FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT =
             FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT
                     | FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT
-                    | FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT
-                    | FLAG_PERMISSION_RESTRICTION_ROLE_EXEMPT;
+                    | FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
 
     /**
      * Mask for all permission flags.
@@ -4182,20 +4177,11 @@
      */
     public static final int FLAG_PERMISSION_WHITELIST_UPGRADE = 1 << 2;
 
-    /**
-     * Permission allowlist flag: permissions exempted by the system
-     * when being granted a role.
-     * Permissions can also be exempted by the installer, the system, or on
-     * upgrade.
-     */
-    public static final int FLAG_PERMISSION_ALLOWLIST_ROLE = 1 << 3;
-
     /** @hide */
     @IntDef(flag = true, prefix = {"FLAG_PERMISSION_WHITELIST_"}, value = {
             FLAG_PERMISSION_WHITELIST_SYSTEM,
             FLAG_PERMISSION_WHITELIST_INSTALLER,
-            FLAG_PERMISSION_WHITELIST_UPGRADE,
-            FLAG_PERMISSION_ALLOWLIST_ROLE
+            FLAG_PERMISSION_WHITELIST_UPGRADE
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface PermissionWhitelistFlags {}
@@ -5227,10 +5213,6 @@
      * This list corresponds to the {@link #FLAG_PERMISSION_WHITELIST_INSTALLER} flag.
      * Can be accessed by pre-installed holders of a dedicated permission or the
      * installer on record.
-     *
-     * <li>one for cases where the system exempts the permission when granting a role.
-     * This list corresponds to the {@link #FLAG_PERMISSION_ALLOWLIST_ROLE} flag. Can
-     * be accessed by pre-installed holders of a dedicated permission.
      * </ol>
      *
      * <p>
@@ -5249,7 +5231,6 @@
      * @see #FLAG_PERMISSION_WHITELIST_SYSTEM
      * @see #FLAG_PERMISSION_WHITELIST_UPGRADE
      * @see #FLAG_PERMISSION_WHITELIST_INSTALLER
-     * @see #FLAG_PERMISSION_ALLOWLIST_ROLE
      *
      * @throws SecurityException if you try to access a whitelist that you have no access to.
      */
@@ -5289,10 +5270,6 @@
      * This list corresponds to the {@link #FLAG_PERMISSION_WHITELIST_INSTALLER} flag.
      * Can be modified by pre-installed holders of a dedicated permission or the installer
      * on record.
-     *
-     * <li>one for cases where the system exempts the permission when permission when
-     * granting a role. This list corresponds to the {@link #FLAG_PERMISSION_ALLOWLIST_ROLE}
-     * flag. Can be modified by pre-installed holders of a dedicated permission.
      * </ol>
      *
      * <p>You need to specify the whitelists for which to set the whitelisted permissions
@@ -5316,7 +5293,6 @@
      * @see #FLAG_PERMISSION_WHITELIST_SYSTEM
      * @see #FLAG_PERMISSION_WHITELIST_UPGRADE
      * @see #FLAG_PERMISSION_WHITELIST_INSTALLER
-     * @see #FLAG_PERMISSION_ALLOWLIST_ROLE
      *
      * @throws SecurityException if you try to modify a whitelist that you have no access to.
      */
@@ -5386,7 +5362,6 @@
      * @see #FLAG_PERMISSION_WHITELIST_SYSTEM
      * @see #FLAG_PERMISSION_WHITELIST_UPGRADE
      * @see #FLAG_PERMISSION_WHITELIST_INSTALLER
-     * @see #FLAG_PERMISSION_ALLOWLIST_ROLE
      *
      * @throws SecurityException if you try to modify a whitelist that you have no access to.
      */
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 0e70a3e..83baca6 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -411,14 +411,6 @@
     public static final int FLAG_IMMUTABLY_RESTRICTED = 1<<4;
 
     /**
-     * Flag for {@link #flags}, corresponding to <code>installerExemptIgnored</code>
-     * value of {@link android.R.attr#permissionFlags}.
-     *
-     * <p> Modifier for permission restriction. This permission cannot be exempted by the installer.
-     */
-    public static final int FLAG_INSTALLER_EXEMPT_IGNORED = 1 << 5;
-
-    /**
      * Flag for {@link #flags}, indicating that this permission has been
      * installed into the system's globally defined permissions.
      */
@@ -724,11 +716,6 @@
     }
 
     /** @hide */
-    public boolean isInstallerExemptIgnored() {
-        return (flags & PermissionInfo.FLAG_INSTALLER_EXEMPT_IGNORED) != 0;
-    }
-
-    /** @hide */
     public boolean isAppOp() {
         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0;
     }
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 5f80ba1..275e81c 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -68,7 +68,8 @@
 
     private static final int IMPLICIT_RANK_MASK = 0x7fffffff;
 
-    private static final int RANK_CHANGED_BIT = ~IMPLICIT_RANK_MASK;
+    /** @hide */
+    public static final int RANK_CHANGED_BIT = ~IMPLICIT_RANK_MASK;
 
     /** @hide */
     public static final int RANK_NOT_SET = Integer.MAX_VALUE;
@@ -1595,6 +1596,9 @@
      */
     @Nullable
     public Intent[] getIntents() {
+        if (mIntents == null) {
+            return null;
+        }
         final Intent[] ret = new Intent[mIntents.length];
 
         for (int i = 0; i < ret.length; i++) {
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index 35c99a1..d3bac79 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -39,6 +39,7 @@
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -771,4 +772,20 @@
         }
     }
 
+    /**
+     * Granting another app the access to the shortcuts you own. You must provide the package name
+     * and their SHA256 certificate digest in order to granting the access.
+     *
+     * Once granted, the other app can retain a copy of all the shortcuts you own when calling
+     * {@link LauncherApps#getShortcuts(LauncherApps.ShortcutQuery, UserHandle)}.
+     */
+    public void updateShortcutVisibility(@NonNull final String packageName,
+            @Nullable final byte[] certificate, final boolean visible) {
+        try {
+            mService.updateShortcutVisibility(mContext.getPackageName(), packageName, certificate,
+                    visible, injectMyUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index d81dff8..cfb6e1b 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.TestApi;
 import android.annotation.UserIdInt;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
@@ -47,6 +48,7 @@
  *
  * @hide
  */
+@TestApi
 public class UserInfo implements Parcelable {
 
     /**
diff --git a/core/java/android/content/pm/dex/DexMetadataHelper.java b/core/java/android/content/pm/dex/DexMetadataHelper.java
index bc5d14a..0d5b33c 100644
--- a/core/java/android/content/pm/dex/DexMetadataHelper.java
+++ b/core/java/android/content/pm/dex/DexMetadataHelper.java
@@ -24,16 +24,16 @@
 import android.content.pm.parsing.PackageLite;
 import android.os.SystemProperties;
 import android.util.ArrayMap;
-import android.util.jar.StrictJarFile;
 import android.util.JsonReader;
 import android.util.Log;
+import android.util.jar.StrictJarFile;
 
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.io.File;
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
-import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.nio.file.Files;
 import java.nio.file.Paths;
@@ -53,7 +53,10 @@
     /** $> adb shell 'setprop log.tag.DexMetadataHelper VERBOSE' */
     public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     /** $> adb shell 'setprop pm.dexopt.dm.require_manifest true' */
-    private static String PROPERTY_DM_JSON_MANIFEST_REQUIRED = "pm.dexopt.dm.require_manifest";
+    private static final String PROPERTY_DM_JSON_MANIFEST_REQUIRED =
+            "pm.dexopt.dm.require_manifest";
+    /** $> adb shell 'setprop pm.dexopt.dm.require_fsverity true' */
+    private static final String PROPERTY_DM_FSVERITY_REQUIRED = "pm.dexopt.dm.require_fsverity";
 
     private static final String DEX_METADATA_FILE_EXTENSION = ".dm";
 
@@ -70,6 +73,13 @@
     }
 
     /**
+     * Returns whether fs-verity is required to install a dex metadata
+     */
+    public static boolean isFsVerityRequired() {
+        return SystemProperties.getBoolean(PROPERTY_DM_FSVERITY_REQUIRED, false);
+    }
+
+    /**
      * Return the size (in bytes) of all dex metadata files associated with the given package.
      */
     public static long getPackageDexMetadataSize(PackageLite pkg) {
diff --git a/core/java/android/content/pm/parsing/ParsingPackage.java b/core/java/android/content/pm/parsing/ParsingPackage.java
index 7a01392..29edd40 100644
--- a/core/java/android/content/pm/parsing/ParsingPackage.java
+++ b/core/java/android/content/pm/parsing/ParsingPackage.java
@@ -260,6 +260,8 @@
 
     ParsingPackage setFullBackupContent(int fullBackupContent);
 
+    ParsingPackage setDataExtractionRules(int dataExtractionRules);
+
     ParsingPackage setHasDomainUrls(boolean hasDomainUrls);
 
     ParsingPackage setIconRes(int iconRes);
diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
index c1a93d8..067787d 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
@@ -334,6 +334,7 @@
     private int descriptionRes;
 
     private int fullBackupContent;
+    private int dataExtractionRules;
     private int iconRes;
     private int installLocation = ParsingPackageUtils.PARSE_DEFAULT_INSTALL_LOCATION;
     private int labelRes;
@@ -1015,6 +1016,7 @@
         appInfo.enabled = getBoolean(Booleans.ENABLED);
 //        appInfo.enabledSetting
         appInfo.fullBackupContent = fullBackupContent;
+        appInfo.dataExtractionRulesRes = dataExtractionRules;
         // TODO(b/135203078): See ParsingPackageImpl#getHiddenApiEnforcementPolicy
 //        appInfo.mHiddenApiPolicy
 //        appInfo.hiddenUntilInstalled
@@ -1163,6 +1165,7 @@
         dest.writeInt(this.compatibleWidthLimitDp);
         dest.writeInt(this.descriptionRes);
         dest.writeInt(this.fullBackupContent);
+        dest.writeInt(this.dataExtractionRules);
         dest.writeInt(this.iconRes);
         dest.writeInt(this.installLocation);
         dest.writeInt(this.labelRes);
@@ -1284,6 +1287,7 @@
         this.compatibleWidthLimitDp = in.readInt();
         this.descriptionRes = in.readInt();
         this.fullBackupContent = in.readInt();
+        this.dataExtractionRules = in.readInt();
         this.iconRes = in.readInt();
         this.installLocation = in.readInt();
         this.labelRes = in.readInt();
@@ -1808,6 +1812,11 @@
     }
 
     @Override
+    public int getDataExtractionRules() {
+        return dataExtractionRules;
+    }
+
+    @Override
     public int getIconRes() {
         return iconRes;
     }
@@ -2264,6 +2273,12 @@
     }
 
     @Override
+    public ParsingPackageImpl setDataExtractionRules(int value) {
+        dataExtractionRules = value;
+        return this;
+    }
+
+    @Override
     public ParsingPackageImpl setIconRes(int value) {
         iconRes = value;
         return this;
diff --git a/core/java/android/content/pm/parsing/ParsingPackageRead.java b/core/java/android/content/pm/parsing/ParsingPackageRead.java
index ff4cebd..f7f3e19 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageRead.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageRead.java
@@ -587,6 +587,11 @@
      */
     int getFullBackupContent();
 
+    /**
+     * @see R.styleable#AndroidManifestApplication_dataExtractionRules
+     */
+    int getDataExtractionRules();
+
     /** @see ApplicationInfo#PRIVATE_FLAG_HAS_DOMAIN_URLS */
     boolean isHasDomainUrls();
 
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index b7aa30f..0c033fd 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -2168,6 +2168,8 @@
                 .setNetworkSecurityConfigRes(resId(R.styleable.AndroidManifestApplication_networkSecurityConfig, sa))
                 .setRoundIconRes(resId(R.styleable.AndroidManifestApplication_roundIcon, sa))
                 .setTheme(resId(R.styleable.AndroidManifestApplication_theme, sa))
+                .setDataExtractionRules(
+                        resId(R.styleable.AndroidManifestApplication_dataExtractionRules, sa))
                 // Strings
                 .setClassLoaderName(string(R.styleable.AndroidManifestApplication_classLoader, sa))
                 .setRequiredAccountType(string(R.styleable.AndroidManifestApplication_requiredAccountType, sa))
diff --git a/core/java/android/service/screenshot/ScreenshotHash.aidl b/core/java/android/content/pm/verify/domain/DomainOwner.aidl
similarity index 81%
copy from core/java/android/service/screenshot/ScreenshotHash.aidl
copy to core/java/android/content/pm/verify/domain/DomainOwner.aidl
index a7c50db..41366d1 100644
--- a/core/java/android/service/screenshot/ScreenshotHash.aidl
+++ b/core/java/android/content/pm/verify/domain/DomainOwner.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.service.screenshot;
+package android.content.pm.verify.domain;
 
-parcelable ScreenshotHash;
+parcelable DomainOwner;
diff --git a/core/java/android/content/pm/verify/domain/DomainOwner.java b/core/java/android/content/pm/verify/domain/DomainOwner.java
new file mode 100644
index 0000000..b050f5d
--- /dev/null
+++ b/core/java/android/content/pm/verify/domain/DomainOwner.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm.verify.domain;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * @hide
+ */
+@SystemApi
+@DataClass(genParcelable = true, genEqualsHashCode = true, genAidl = true, genToString = true)
+public final class DomainOwner implements Parcelable {
+
+    /**
+     * Package name of that owns the domain.
+     */
+    @NonNull
+    private final String mPackageName;
+
+    /**
+     * Whether or not this owner can be automatically overridden.
+     *
+     * @see DomainVerificationManager#setDomainVerificationUserSelection(UUID, Set, boolean)
+     */
+    private final boolean mOverrideable;
+
+
+
+    // Code below generated by codegen v1.0.22.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/verify/domain/DomainOwner.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    /**
+     * Creates a new DomainOwner.
+     *
+     * @param packageName
+     *   Package name of that owns the domain.
+     * @param overrideable
+     *   Whether or not this owner can be automatically overridden. If all owners for a domain are
+     *   overrideable, then calling
+     *   {@link DomainVerificationManager#setDomainVerificationUserSelection(UUID,
+     *   Set, boolean)} to enable the domain will disable all other owners. On the other hand, if any
+     *   of the owners are non-overrideable, then
+     *   {@link DomainVerificationManager#setDomainVerificationLinkHandlingAllowed(String,
+     *   boolean)} must be called with false to disable all of the other owners before this domain can
+     *   be taken by a new owner through
+     *   {@link DomainVerificationManager#setDomainVerificationUserSelection(UUID,
+     *   Set, boolean)}.
+     */
+    @DataClass.Generated.Member
+    public DomainOwner(
+            @NonNull String packageName,
+            boolean overrideable) {
+        this.mPackageName = packageName;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mPackageName);
+        this.mOverrideable = overrideable;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    /**
+     * Package name of that owns the domain.
+     */
+    @DataClass.Generated.Member
+    public @NonNull String getPackageName() {
+        return mPackageName;
+    }
+
+    /**
+     * Whether or not this owner can be automatically overridden. If all owners for a domain are
+     * overrideable, then calling
+     * {@link DomainVerificationManager#setDomainVerificationUserSelection(UUID,
+     * Set, boolean)} to enable the domain will disable all other owners. On the other hand, if any
+     * of the owners are non-overrideable, then
+     * {@link DomainVerificationManager#setDomainVerificationLinkHandlingAllowed(String,
+     * boolean)} must be called with false to disable all of the other owners before this domain can
+     * be taken by a new owner through
+     * {@link DomainVerificationManager#setDomainVerificationUserSelection(UUID,
+     * Set, boolean)}.
+     */
+    @DataClass.Generated.Member
+    public boolean isOverrideable() {
+        return mOverrideable;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "DomainOwner { " +
+                "packageName = " + mPackageName + ", " +
+                "overrideable = " + mOverrideable +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public boolean equals(@android.annotation.Nullable Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(DomainOwner other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        DomainOwner that = (DomainOwner) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && java.util.Objects.equals(mPackageName, that.mPackageName)
+                && mOverrideable == that.mOverrideable;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int hashCode() {
+        // You can override field hashCode logic by defining methods like:
+        // int fieldNameHashCode() { ... }
+
+        int _hash = 1;
+        _hash = 31 * _hash + java.util.Objects.hashCode(mPackageName);
+        _hash = 31 * _hash + Boolean.hashCode(mOverrideable);
+        return _hash;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        byte flg = 0;
+        if (mOverrideable) flg |= 0x2;
+        dest.writeByte(flg);
+        dest.writeString(mPackageName);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ DomainOwner(@NonNull android.os.Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        byte flg = in.readByte();
+        boolean overrideable = (flg & 0x2) != 0;
+        String packageName = in.readString();
+
+        this.mPackageName = packageName;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mPackageName);
+        this.mOverrideable = overrideable;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<DomainOwner> CREATOR
+            = new Parcelable.Creator<DomainOwner>() {
+        @Override
+        public DomainOwner[] newArray(int size) {
+            return new DomainOwner[size];
+        }
+
+        @Override
+        public DomainOwner createFromParcel(@NonNull android.os.Parcel in) {
+            return new DomainOwner(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1614119379978L,
+            codegenVersion = "1.0.22",
+            sourceFile = "frameworks/base/core/java/android/content/pm/verify/domain/DomainOwner.java",
+            inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final  boolean mOverrideable\nclass DomainOwner extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genEqualsHashCode=true, genAidl=true, genToString=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/service/screenshot/ScreenshotHash.aidl b/core/java/android/content/pm/verify/domain/DomainSet.aidl
similarity index 82%
rename from core/java/android/service/screenshot/ScreenshotHash.aidl
rename to core/java/android/content/pm/verify/domain/DomainSet.aidl
index a7c50db..fab131d 100644
--- a/core/java/android/service/screenshot/ScreenshotHash.aidl
+++ b/core/java/android/content/pm/verify/domain/DomainSet.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.service.screenshot;
+package android.content.pm.verify.domain;
 
-parcelable ScreenshotHash;
+parcelable DomainSet;
diff --git a/core/java/android/content/pm/verify/domain/DomainSet.java b/core/java/android/content/pm/verify/domain/DomainSet.java
new file mode 100644
index 0000000..243ff08
--- /dev/null
+++ b/core/java/android/content/pm/verify/domain/DomainSet.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm.verify.domain;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+import java.util.Set;
+
+/**
+ * Wraps an input set of domains from the client process, to be sent to the server. Handles cases
+ * where the data size is too large by writing data using {@link Parcel#writeBlob(byte[])}.
+ *
+ * @hide
+ */
+@DataClass(genParcelable = true, genAidl = true, genEqualsHashCode = true)
+public class DomainSet implements Parcelable {
+
+    @NonNull
+    private final Set<String> mDomains;
+
+    private void parcelDomains(@NonNull Parcel dest, @SuppressWarnings("unused") int flags) {
+        DomainVerificationUtils.writeHostSet(dest, mDomains);
+    }
+
+    private Set<String> unparcelDomains(@NonNull Parcel in) {
+        return DomainVerificationUtils.readHostSet(in);
+    }
+
+
+
+    // Code below generated by codegen v1.0.22.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/verify/domain
+    // /DomainSet.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    @DataClass.Generated.Member
+    public DomainSet(
+            @NonNull Set<String> domains) {
+        this.mDomains = domains;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mDomains);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull Set<String> getDomains() {
+        return mDomains;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public boolean equals(@android.annotation.Nullable Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(DomainSet other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        DomainSet that = (DomainSet) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && java.util.Objects.equals(mDomains, that.mDomains);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int hashCode() {
+        // You can override field hashCode logic by defining methods like:
+        // int fieldNameHashCode() { ... }
+
+        int _hash = 1;
+        _hash = 31 * _hash + java.util.Objects.hashCode(mDomains);
+        return _hash;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        parcelDomains(dest, flags);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    protected DomainSet(@NonNull Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        Set<String> domains = unparcelDomains(in);
+
+        this.mDomains = domains;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mDomains);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<DomainSet> CREATOR
+            = new Parcelable.Creator<DomainSet>() {
+        @Override
+        public DomainSet[] newArray(int size) {
+            return new DomainSet[size];
+        }
+
+        @Override
+        public DomainSet createFromParcel(@NonNull Parcel in) {
+            return new DomainSet(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1613169242020L,
+            codegenVersion = "1.0.22",
+            sourceFile = "frameworks/base/core/java/android/content/pm/verify/domain/DomainSet.java",
+            inputSignatures = "private final @android.annotation.NonNull java.util.Set<java.lang.String> mDomains\nprivate  void parcelDomains(android.os.Parcel,int)\nprivate  java.util.Set<java.lang.String> unparcelDomains(android.os.Parcel)\nclass DomainSet extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genAidl=true, genEqualsHashCode=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/content/pm/verify/domain/DomainVerificationInfo.java b/core/java/android/content/pm/verify/domain/DomainVerificationInfo.java
index 7afbe1f..8095875 100644
--- a/core/java/android/content/pm/verify/domain/DomainVerificationInfo.java
+++ b/core/java/android/content/pm/verify/domain/DomainVerificationInfo.java
@@ -19,7 +19,9 @@
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.content.pm.PackageManager;
+import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.ArrayMap;
 
 import com.android.internal.util.DataClass;
 import com.android.internal.util.Parcelling;
@@ -34,12 +36,12 @@
  * against the digital asset links response from the server hosting that domain.
  * <p>
  * These values for each domain can be modified through
- * {@link DomainVerificationManager#setDomainVerificationStatus(UUID, Set, int)}.
+ * {@link DomainVerificationManager#setDomainVerificationStatus(UUID,
+ * Set, int)}.
  *
  * @hide
  */
 @SystemApi
-@SuppressWarnings("DefaultAnnotationParam")
 @DataClass(genAidl = true, genHiddenConstructor = true, genParcelable = true, genToString = true,
         genEqualsHashCode = true)
 public final class DomainVerificationInfo implements Parcelable {
@@ -71,22 +73,30 @@
     private final String mPackageName;
 
     /**
-     * Map of host names to their current state. State is an integer, which defaults to
-     * {@link DomainVerificationManager#STATE_NO_RESPONSE}. State can be modified by the
-     * domain verification agent (the intended consumer of this API), which can be equal
-     * to {@link DomainVerificationManager#STATE_SUCCESS} when verified, or equal to or
-     * greater than {@link DomainVerificationManager#STATE_FIRST_VERIFIER_DEFINED} for
-     * any unsuccessful response.
+     * Map of host names to their current state. State is an integer, which defaults to {@link
+     * DomainVerificationManager#STATE_NO_RESPONSE}. State can be modified by the domain
+     * verification agent (the intended consumer of this API), which can be equal to {@link
+     * DomainVerificationManager#STATE_SUCCESS} when verified, or equal to or greater than {@link
+     * DomainVerificationManager#STATE_FIRST_VERIFIER_DEFINED} for any unsuccessful response.
      * <p>
-     * Any value non-inclusive between those 2 values are reserved for use by the system.
-     * The domain verification agent may be able to act on these reserved values, and this
-     * ability can be queried using {@link DomainVerificationManager#isStateModifiable(int)}.
-     * It is expected that the agent attempt to verify all domains that it can modify the
-     * state of, even if it does not understand the meaning of those values.
+     * Any value non-inclusive between those 2 values are reserved for use by the system. The domain
+     * verification agent may be able to act on these reserved values, and this ability can be
+     * queried using {@link DomainVerificationManager#isStateModifiable(int)}. It is expected that
+     * the agent attempt to verify all domains that it can modify the state of, even if it does not
+     * understand the meaning of those values.
      */
     @NonNull
     private final Map<String, Integer> mHostToStateMap;
 
+    private void parcelHostToStateMap(Parcel dest, @SuppressWarnings("unused") int flags) {
+        DomainVerificationUtils.writeHostMap(dest, mHostToStateMap);
+    }
+
+    private Map<String, Integer> unparcelHostToStateMap(Parcel in) {
+        return DomainVerificationUtils.readHostMap(in, new ArrayMap<>(),
+                DomainVerificationUserSelection.class.getClassLoader());
+    }
+
 
 
     // Code below generated by codegen v1.0.22.
@@ -95,7 +105,8 @@
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/verify/domain/DomainVerificationInfo.java
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/verify/domain
+    // /DomainVerificationInfo.java
     //
     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
     //   Settings > Editor > Code Style > Formatter Control
@@ -123,18 +134,17 @@
      * @param packageName
      *   The package name that this data corresponds to.
      * @param hostToStateMap
-     *   Map of host names to their current state. State is an integer, which defaults to
-     *   {@link DomainVerificationManager#STATE_NO_RESPONSE}. State can be modified by the
-     *   domain verification agent (the intended consumer of this API), which can be equal
-     *   to {@link DomainVerificationManager#STATE_SUCCESS} when verified, or equal to or
-     *   greater than {@link DomainVerificationManager#STATE_FIRST_VERIFIER_DEFINED} for
-     *   any unsuccessful response.
+     *   Map of host names to their current state. State is an integer, which defaults to {@link
+     *   DomainVerificationManager#STATE_NO_RESPONSE}. State can be modified by the domain
+     *   verification agent (the intended consumer of this API), which can be equal to {@link
+     *   DomainVerificationManager#STATE_SUCCESS} when verified, or equal to or greater than {@link
+     *   DomainVerificationManager#STATE_FIRST_VERIFIER_DEFINED} for any unsuccessful response.
      *   <p>
-     *   Any value non-inclusive between those 2 values are reserved for use by the system.
-     *   The domain verification agent may be able to act on these reserved values, and this
-     *   ability can be queried using {@link DomainVerificationManager#isStateModifiable(int)}.
-     *   It is expected that the agent attempt to verify all domains that it can modify the
-     *   state of, even if it does not understand the meaning of those values.
+     *   Any value non-inclusive between those 2 values are reserved for use by the system. The domain
+     *   verification agent may be able to act on these reserved values, and this ability can be
+     *   queried using {@link DomainVerificationManager#isStateModifiable(int)}. It is expected that
+     *   the agent attempt to verify all domains that it can modify the state of, even if it does not
+     *   understand the meaning of those values.
      * @hide
      */
     @DataClass.Generated.Member
@@ -185,18 +195,17 @@
     }
 
     /**
-     * Map of host names to their current state. State is an integer, which defaults to
-     * {@link DomainVerificationManager#STATE_NO_RESPONSE}. State can be modified by the
-     * domain verification agent (the intended consumer of this API), which can be equal
-     * to {@link DomainVerificationManager#STATE_SUCCESS} when verified, or equal to or
-     * greater than {@link DomainVerificationManager#STATE_FIRST_VERIFIER_DEFINED} for
-     * any unsuccessful response.
+     * Map of host names to their current state. State is an integer, which defaults to {@link
+     * DomainVerificationManager#STATE_NO_RESPONSE}. State can be modified by the domain
+     * verification agent (the intended consumer of this API), which can be equal to {@link
+     * DomainVerificationManager#STATE_SUCCESS} when verified, or equal to or greater than {@link
+     * DomainVerificationManager#STATE_FIRST_VERIFIER_DEFINED} for any unsuccessful response.
      * <p>
-     * Any value non-inclusive between those 2 values are reserved for use by the system.
-     * The domain verification agent may be able to act on these reserved values, and this
-     * ability can be queried using {@link DomainVerificationManager#isStateModifiable(int)}.
-     * It is expected that the agent attempt to verify all domains that it can modify the
-     * state of, even if it does not understand the meaning of those values.
+     * Any value non-inclusive between those 2 values are reserved for use by the system. The domain
+     * verification agent may be able to act on these reserved values, and this ability can be
+     * queried using {@link DomainVerificationManager#isStateModifiable(int)}. It is expected that
+     * the agent attempt to verify all domains that it can modify the state of, even if it does not
+     * understand the meaning of those values.
      */
     @DataClass.Generated.Member
     public @NonNull Map<String,Integer> getHostToStateMap() {
@@ -260,13 +269,13 @@
 
     @Override
     @DataClass.Generated.Member
-    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         // You can override field parcelling by defining methods like:
         // void parcelFieldName(Parcel dest, int flags) { ... }
 
         sParcellingForIdentifier.parcel(mIdentifier, dest, flags);
         dest.writeString(mPackageName);
-        dest.writeMap(mHostToStateMap);
+        parcelHostToStateMap(dest, flags);
     }
 
     @Override
@@ -276,14 +285,13 @@
     /** @hide */
     @SuppressWarnings({"unchecked", "RedundantCast"})
     @DataClass.Generated.Member
-    /* package-private */ DomainVerificationInfo(@NonNull android.os.Parcel in) {
+    /* package-private */ DomainVerificationInfo(@NonNull Parcel in) {
         // You can override field unparcelling by defining methods like:
         // static FieldType unparcelFieldName(Parcel in) { ... }
 
         UUID identifier = sParcellingForIdentifier.unparcel(in);
         String packageName = in.readString();
-        Map<String,Integer> hostToStateMap = new java.util.LinkedHashMap<>();
-        in.readMap(hostToStateMap, Integer.class.getClassLoader());
+        Map<String,Integer> hostToStateMap = unparcelHostToStateMap(in);
 
         this.mIdentifier = identifier;
         com.android.internal.util.AnnotationValidations.validate(
@@ -307,16 +315,16 @@
         }
 
         @Override
-        public DomainVerificationInfo createFromParcel(@NonNull android.os.Parcel in) {
+        public DomainVerificationInfo createFromParcel(@NonNull Parcel in) {
             return new DomainVerificationInfo(in);
         }
     };
 
     @DataClass.Generated(
-            time = 1611862790369L,
+            time = 1613002530369L,
             codegenVersion = "1.0.22",
             sourceFile = "frameworks/base/core/java/android/content/pm/verify/domain/DomainVerificationInfo.java",
-            inputSignatures = "private final @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForUUID.class) java.util.UUID mIdentifier\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,java.lang.Integer> mHostToStateMap\nclass DomainVerificationInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genAidl=true, genHiddenConstructor=true, genParcelable=true, genToString=true, genEqualsHashCode=true)")
+            inputSignatures = "private final @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForUUID.class) java.util.UUID mIdentifier\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,java.lang.Integer> mHostToStateMap\nprivate  void parcelHostToStateMap(android.os.Parcel,int)\nprivate  java.util.Map<java.lang.String,java.lang.Integer> unparcelHostToStateMap(android.os.Parcel)\nclass DomainVerificationInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genAidl=true, genHiddenConstructor=true, genParcelable=true, genToString=true, genEqualsHashCode=true)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/content/pm/verify/domain/DomainVerificationManager.java b/core/java/android/content/pm/verify/domain/DomainVerificationManager.java
index cbb3baa..11402af 100644
--- a/core/java/android/content/pm/verify/domain/DomainVerificationManager.java
+++ b/core/java/android/content/pm/verify/domain/DomainVerificationManager.java
@@ -239,7 +239,15 @@
      * {@link Context#createPackageContextAsUser(String, int, UserHandle)} should be used.
      *
      * Enabling an unverified domain will allow an application to open it, but this can only occur
-     * if no other app on the device is approved for the domain.
+     * if no other app on the device is approved for a higher approval level. This can queried
+     * using {@link #getOwnersForDomain(String)}.
+     *
+     * If all owners for a domain are {@link DomainOwner#isOverrideable()}, then calling this to
+     * enable that domain will disable all other owners.
+     *
+     * On the other hand, if any of the owners are non-overrideable, then this must be called with
+     * false for all of the other owners to disable them before the domain can be taken by a new
+     * owner.
      *
      * @param domainSetId See {@link DomainVerificationInfo#getIdentifier()}.
      * @param domains     The domains to toggle the state of.
@@ -276,6 +284,19 @@
             throws NameNotFoundException;
 
     /**
+     * For the given domain, return all apps which are approved to open it in a
+     * greater than 0 priority. This does not mean that all apps can actually open
+     * an Intent with that domain. That will be decided by the set of apps which
+     * are the highest priority level, ignoring all lower priority levels.
+     *
+     * By default the list will be returned ordered from lowest to highest
+     * priority.
+     */
+    @NonNull
+    @RequiresPermission(android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION)
+    List<DomainOwner> getOwnersForDomain(@NonNull String domain);
+
+    /**
      * Thrown if a {@link DomainVerificationInfo#getIdentifier()}} or an associated set of domains
      * provided by the caller is no longer valid. This may be recoverable, and the caller should
      * re-query the package name associated with the ID using
diff --git a/core/java/android/content/pm/verify/domain/DomainVerificationManagerImpl.java b/core/java/android/content/pm/verify/domain/DomainVerificationManagerImpl.java
index 5938def..8b9865c 100644
--- a/core/java/android/content/pm/verify/domain/DomainVerificationManagerImpl.java
+++ b/core/java/android/content/pm/verify/domain/DomainVerificationManagerImpl.java
@@ -21,11 +21,9 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.verify.domain.IDomainVerificationManager;
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
 
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 import java.util.UUID;
@@ -89,7 +87,7 @@
             int state) throws IllegalArgumentException, NameNotFoundException {
         try {
             mDomainVerificationManager.setDomainVerificationStatus(domainSetId.toString(),
-                    new ArrayList<>(domains), state);
+                    new DomainSet(domains), state);
         } catch (Exception e) {
             Exception converted = rethrow(e, domainSetId);
             if (converted instanceof NameNotFoundException) {
@@ -126,7 +124,7 @@
             throws IllegalArgumentException, NameNotFoundException {
         try {
             mDomainVerificationManager.setDomainVerificationUserSelection(domainSetId.toString(),
-                    new ArrayList<>(domains), enabled, mContext.getUserId());
+                    new DomainSet(domains), enabled, mContext.getUserId());
         } catch (Exception e) {
             Exception converted = rethrow(e, domainSetId);
             if (converted instanceof NameNotFoundException) {
@@ -158,6 +156,16 @@
         }
     }
 
+    @NonNull
+    @Override
+    public List<DomainOwner> getOwnersForDomain(@NonNull String domain) {
+        try {
+            return mDomainVerificationManager.getOwnersForDomain(domain, mContext.getUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     private Exception rethrow(Exception exception, @Nullable UUID domainSetId) {
         return rethrow(exception, domainSetId, null);
     }
diff --git a/core/java/android/content/pm/verify/domain/DomainVerificationRequest.java b/core/java/android/content/pm/verify/domain/DomainVerificationRequest.java
index 473abce..65f6d7c 100644
--- a/core/java/android/content/pm/verify/domain/DomainVerificationRequest.java
+++ b/core/java/android/content/pm/verify/domain/DomainVerificationRequest.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.content.Intent;
+import android.os.Parcel;
 import android.os.Parcelable;
 
 import com.android.internal.util.DataClass;
@@ -27,11 +28,11 @@
 import java.util.Set;
 
 /**
- * Request object sent in the {@link Intent} that's broadcast to the domain verification
- * agent, retrieved through {@link DomainVerificationManager#EXTRA_VERIFICATION_REQUEST}.
+ * Request object sent in the {@link Intent} that's broadcast to the domain verification agent,
+ * retrieved through {@link DomainVerificationManager#EXTRA_VERIFICATION_REQUEST}.
  * <p>
- * This contains the set of packages which have been invalidated and will require
- * re-verification. The exact domains can be retrieved with
+ * This contains the set of packages which have been invalidated and will require re-verification.
+ * The exact domains can be retrieved with
  * {@link DomainVerificationManager#getDomainVerificationInfo(String)}
  *
  * @hide
@@ -42,14 +43,22 @@
 public final class DomainVerificationRequest implements Parcelable {
 
     /**
-     * The package names of the apps that need to be verified. The receiver should call
-     * {@link DomainVerificationManager#getDomainVerificationInfo(String)} with each of
-     * these values to get the actual set of domains that need to be acted on.
+     * The package names of the apps that need to be verified. The receiver should call {@link
+     * DomainVerificationManager#getDomainVerificationInfo(String)} with each of these values to get
+     * the actual set of domains that need to be acted on.
      */
     @NonNull
     @DataClass.ParcelWith(Parcelling.BuiltIn.ForStringSet.class)
     private final Set<String> mPackageNames;
 
+    private void parcelPackageNames(@NonNull Parcel dest, @SuppressWarnings("unused") int flags) {
+        DomainVerificationUtils.writeHostSet(dest, mPackageNames);
+    }
+
+    private Set<String> unparcelPackageNames(@NonNull Parcel in) {
+        return DomainVerificationUtils.readHostSet(in);
+    }
+
 
 
     // Code below generated by codegen v1.0.22.
@@ -58,7 +67,8 @@
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/verify/domain/DomainVerificationRequest.java
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/verify/domain
+    // /DomainVerificationRequest.java
     //
     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
     //   Settings > Editor > Code Style > Formatter Control
@@ -69,9 +79,9 @@
      * Creates a new DomainVerificationRequest.
      *
      * @param packageNames
-     *   The package names of the apps that need to be verified. The receiver should call
-     *   {@link DomainVerificationManager#getDomainVerificationInfo(String)} with each of
-     *   these values to get the actual set of domains that need to be acted on.
+     *   The package names of the apps that need to be verified. The receiver should call {@link
+     *   DomainVerificationManager#getDomainVerificationInfo(String)} with each of these values to get
+     *   the actual set of domains that need to be acted on.
      * @hide
      */
     @DataClass.Generated.Member
@@ -85,9 +95,9 @@
     }
 
     /**
-     * The package names of the apps that need to be verified. The receiver should call
-     * {@link DomainVerificationManager#getDomainVerificationInfo(String)} with each of
-     * these values to get the actual set of domains that need to be acted on.
+     * The package names of the apps that need to be verified. The receiver should call {@link
+     * DomainVerificationManager#getDomainVerificationInfo(String)} with each of these values to get
+     * the actual set of domains that need to be acted on.
      */
     @DataClass.Generated.Member
     public @NonNull Set<String> getPackageNames() {
@@ -134,11 +144,11 @@
 
     @Override
     @DataClass.Generated.Member
-    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         // You can override field parcelling by defining methods like:
         // void parcelFieldName(Parcel dest, int flags) { ... }
 
-        sParcellingForPackageNames.parcel(mPackageNames, dest, flags);
+        parcelPackageNames(dest, flags);
     }
 
     @Override
@@ -148,11 +158,11 @@
     /** @hide */
     @SuppressWarnings({"unchecked", "RedundantCast"})
     @DataClass.Generated.Member
-    /* package-private */ DomainVerificationRequest(@NonNull android.os.Parcel in) {
+    /* package-private */ DomainVerificationRequest(@NonNull Parcel in) {
         // You can override field unparcelling by defining methods like:
         // static FieldType unparcelFieldName(Parcel in) { ... }
 
-        Set<String> packageNames = sParcellingForPackageNames.unparcel(in);
+        Set<String> packageNames = unparcelPackageNames(in);
 
         this.mPackageNames = packageNames;
         com.android.internal.util.AnnotationValidations.validate(
@@ -170,16 +180,16 @@
         }
 
         @Override
-        public DomainVerificationRequest createFromParcel(@NonNull android.os.Parcel in) {
+        public DomainVerificationRequest createFromParcel(@NonNull Parcel in) {
             return new DomainVerificationRequest(in);
         }
     };
 
     @DataClass.Generated(
-            time = 1611862814990L,
+            time = 1613169505495L,
             codegenVersion = "1.0.22",
             sourceFile = "frameworks/base/core/java/android/content/pm/verify/domain/DomainVerificationRequest.java",
-            inputSignatures = "private final @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForStringSet.class) java.util.Set<java.lang.String> mPackageNames\nclass DomainVerificationRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true, genAidl=false, genEqualsHashCode=true)")
+            inputSignatures = "private final @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForStringSet.class) java.util.Set<java.lang.String> mPackageNames\nprivate  void parcelPackageNames(android.os.Parcel,int)\nprivate  java.util.Set<java.lang.String> unparcelPackageNames(android.os.Parcel)\nclass DomainVerificationRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true, genAidl=false, genEqualsHashCode=true)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/content/pm/verify/domain/DomainVerificationUserSelection.java b/core/java/android/content/pm/verify/domain/DomainVerificationUserSelection.java
index 73346ef..d23f5f1 100644
--- a/core/java/android/content/pm/verify/domain/DomainVerificationUserSelection.java
+++ b/core/java/android/content/pm/verify/domain/DomainVerificationUserSelection.java
@@ -20,8 +20,10 @@
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.content.Context;
+import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.UserHandle;
+import android.util.ArrayMap;
 
 import com.android.internal.util.DataClass;
 import com.android.internal.util.Parcelling;
@@ -40,29 +42,46 @@
  * toggle affects <b>all</b> links and is not based on the verification state of the domains.
  * <p>
  * Assuming the toggle is enabled, the user can also select additional unverified domains to grant
- * to the application to open, which is reflected in {@link #getHostToUserSelectionMap()}. But only
- * a single application can be approved for a domain unless the applications are both approved. If
- * another application is approved, the user will not be allowed to enable the domain.
+ * to the application to open, which is reflected in {@link #getHostToStateMap()}. But only a single
+ * application can be approved for a domain unless the applications are both approved. If another
+ * application is approved, the user will not be allowed to enable the domain.
  * <p>
  * These values can be changed through the
  * {@link DomainVerificationManager#setDomainVerificationLinkHandlingAllowed(String,
- * boolean)} and
- * {@link DomainVerificationManager#setDomainVerificationUserSelection(UUID, Set,
+ * boolean)} and {@link DomainVerificationManager#setDomainVerificationUserSelection(UUID, Set,
  * boolean)} APIs.
  * <p>
- * Note that because state is per user, if a different user needs to be changed, one will
- * need to use {@link Context#createContextAsUser(UserHandle, int)} and hold the
- * {@link android.Manifest.permission#INTERACT_ACROSS_USERS} permission.
+ * Note that because state is per user, if a different user needs to be changed, one will need to
+ * use {@link Context#createContextAsUser(UserHandle, int)} and hold the {@link
+ * android.Manifest.permission#INTERACT_ACROSS_USERS} permission.
  *
  * @hide
  */
 @SystemApi
 @SuppressWarnings("DefaultAnnotationParam")
 @DataClass(genAidl = true, genHiddenConstructor = true, genParcelable = true, genToString = true,
-        genEqualsHashCode = true)
+        genEqualsHashCode = true, genHiddenConstDefs = true)
 public final class DomainVerificationUserSelection implements Parcelable {
 
     /**
+     * The domain is unverified and unselected, and the application is unable to open web links
+     * that resolve to the domain.
+     */
+    public static final int DOMAIN_STATE_NONE = 0;
+
+    /**
+     * The domain has been selected through the
+     * {@link DomainVerificationManager#setDomainVerificationUserSelection(UUID, Set, boolean)}
+     * API, under the assumption it has not been reset by the system.
+     */
+    public static final int DOMAIN_STATE_SELECTED = 1;
+
+    /**
+     * The domain has been previously verified by the domain verification agent.
+     */
+    public static final int DOMAIN_STATE_VERIFIED = 2;
+
+    /**
      * @see DomainVerificationInfo#getIdentifier
      */
     @NonNull
@@ -88,15 +107,20 @@
     private final boolean mLinkHandlingAllowed;
 
     /**
-     * Retrieve the existing user selection state for the matching
-     * {@link #getPackageName()}, as was previously set by
-     * {@link DomainVerificationManager#setDomainVerificationUserSelection(UUID, Set,
-     * boolean)}.
-     *
-     * @return Map of hosts to enabled state for the given package and user.
+     * Mapping of domain host to state, as defined by {@link DomainState}.
      */
     @NonNull
-    private final Map<String, Boolean> mHostToUserSelectionMap;
+    private final Map<String, Integer> mHostToStateMap;
+
+    private void parcelHostToStateMap(Parcel dest, @SuppressWarnings("unused") int flags) {
+        DomainVerificationUtils.writeHostMap(dest, mHostToStateMap);
+    }
+
+    @NonNull
+    private Map<String, Integer> unparcelHostToStateMap(Parcel in) {
+        return DomainVerificationUtils.readHostMap(in, new ArrayMap<>(),
+                DomainVerificationUserSelection.class.getClassLoader());
+    }
 
 
 
@@ -106,14 +130,37 @@
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/verify/domain
-    // /DomainVerificationUserSelection.java
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/verify/domain/DomainVerificationUserSelection.java
     //
     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
     //   Settings > Editor > Code Style > Formatter Control
     //@formatter:off
 
 
+    /** @hide */
+    @android.annotation.IntDef(prefix = "DOMAIN_STATE_", value = {
+        DOMAIN_STATE_NONE,
+        DOMAIN_STATE_SELECTED,
+        DOMAIN_STATE_VERIFIED
+    })
+    @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
+    @DataClass.Generated.Member
+    public @interface DomainState {}
+
+    /** @hide */
+    @DataClass.Generated.Member
+    public static String domainStateToString(@DomainState int value) {
+        switch (value) {
+            case DOMAIN_STATE_NONE:
+                    return "DOMAIN_STATE_NONE";
+            case DOMAIN_STATE_SELECTED:
+                    return "DOMAIN_STATE_SELECTED";
+            case DOMAIN_STATE_VERIFIED:
+                    return "DOMAIN_STATE_VERIFIED";
+            default: return Integer.toHexString(value);
+        }
+    }
+
     /**
      * Creates a new DomainVerificationUserSelection.
      *
@@ -123,11 +170,8 @@
      *   The user that this data corresponds to.
      * @param linkHandlingAllowed
      *   Whether or not this package is allowed to open links.
-     * @param hostToUserSelectionMap
-     *   Retrieve the existing user selection state for the matching
-     *   {@link #getPackageName()}, as was previously set by
-     *   {@link DomainVerificationManager#setDomainVerificationUserSelection(UUID, Set,
-     *   boolean)}.
+     * @param hostToStateMap
+     *   Mapping of domain host to state, as defined by {@link DomainState}.
      * @hide
      */
     @DataClass.Generated.Member
@@ -136,7 +180,7 @@
             @NonNull String packageName,
             @NonNull UserHandle user,
             @NonNull boolean linkHandlingAllowed,
-            @NonNull Map<String,Boolean> hostToUserSelectionMap) {
+            @NonNull Map<String,Integer> hostToStateMap) {
         this.mIdentifier = identifier;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mIdentifier);
@@ -149,9 +193,9 @@
         this.mLinkHandlingAllowed = linkHandlingAllowed;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mLinkHandlingAllowed);
-        this.mHostToUserSelectionMap = hostToUserSelectionMap;
+        this.mHostToStateMap = hostToStateMap;
         com.android.internal.util.AnnotationValidations.validate(
-                NonNull.class, null, mHostToUserSelectionMap);
+                NonNull.class, null, mHostToStateMap);
 
         // onConstructed(); // You can define this method to get a callback
     }
@@ -189,16 +233,11 @@
     }
 
     /**
-     * Retrieve the existing user selection state for the matching
-     * {@link #getPackageName()}, as was previously set by
-     * {@link DomainVerificationManager#setDomainVerificationUserSelection(UUID, Set,
-     * boolean)}.
-     *
-     * @return Map of hosts to enabled state for the given package and user.
+     * Mapping of domain host to state, as defined by {@link DomainState}.
      */
     @DataClass.Generated.Member
-    public @NonNull Map<String,Boolean> getHostToUserSelectionMap() {
-        return mHostToUserSelectionMap;
+    public @NonNull Map<String,Integer> getHostToStateMap() {
+        return mHostToStateMap;
     }
 
     @Override
@@ -212,7 +251,7 @@
                 "packageName = " + mPackageName + ", " +
                 "user = " + mUser + ", " +
                 "linkHandlingAllowed = " + mLinkHandlingAllowed + ", " +
-                "hostToUserSelectionMap = " + mHostToUserSelectionMap +
+                "hostToStateMap = " + mHostToStateMap +
         " }";
     }
 
@@ -233,7 +272,7 @@
                 && java.util.Objects.equals(mPackageName, that.mPackageName)
                 && java.util.Objects.equals(mUser, that.mUser)
                 && mLinkHandlingAllowed == that.mLinkHandlingAllowed
-                && java.util.Objects.equals(mHostToUserSelectionMap, that.mHostToUserSelectionMap);
+                && java.util.Objects.equals(mHostToStateMap, that.mHostToStateMap);
     }
 
     @Override
@@ -247,7 +286,7 @@
         _hash = 31 * _hash + java.util.Objects.hashCode(mPackageName);
         _hash = 31 * _hash + java.util.Objects.hashCode(mUser);
         _hash = 31 * _hash + Boolean.hashCode(mLinkHandlingAllowed);
-        _hash = 31 * _hash + java.util.Objects.hashCode(mHostToUserSelectionMap);
+        _hash = 31 * _hash + java.util.Objects.hashCode(mHostToStateMap);
         return _hash;
     }
 
@@ -264,7 +303,7 @@
 
     @Override
     @DataClass.Generated.Member
-    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         // You can override field parcelling by defining methods like:
         // void parcelFieldName(Parcel dest, int flags) { ... }
 
@@ -274,7 +313,7 @@
         sParcellingForIdentifier.parcel(mIdentifier, dest, flags);
         dest.writeString(mPackageName);
         dest.writeTypedObject(mUser, flags);
-        dest.writeMap(mHostToUserSelectionMap);
+        parcelHostToStateMap(dest, flags);
     }
 
     @Override
@@ -284,7 +323,7 @@
     /** @hide */
     @SuppressWarnings({"unchecked", "RedundantCast"})
     @DataClass.Generated.Member
-    /* package-private */ DomainVerificationUserSelection(@NonNull android.os.Parcel in) {
+    /* package-private */ DomainVerificationUserSelection(@NonNull Parcel in) {
         // You can override field unparcelling by defining methods like:
         // static FieldType unparcelFieldName(Parcel in) { ... }
 
@@ -293,8 +332,7 @@
         UUID identifier = sParcellingForIdentifier.unparcel(in);
         String packageName = in.readString();
         UserHandle user = (UserHandle) in.readTypedObject(UserHandle.CREATOR);
-        Map<String,Boolean> hostToUserSelectionMap = new java.util.LinkedHashMap<>();
-        in.readMap(hostToUserSelectionMap, Boolean.class.getClassLoader());
+        Map<String,Integer> hostToStateMap = unparcelHostToStateMap(in);
 
         this.mIdentifier = identifier;
         com.android.internal.util.AnnotationValidations.validate(
@@ -308,9 +346,9 @@
         this.mLinkHandlingAllowed = linkHandlingAllowed;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mLinkHandlingAllowed);
-        this.mHostToUserSelectionMap = hostToUserSelectionMap;
+        this.mHostToStateMap = hostToStateMap;
         com.android.internal.util.AnnotationValidations.validate(
-                NonNull.class, null, mHostToUserSelectionMap);
+                NonNull.class, null, mHostToStateMap);
 
         // onConstructed(); // You can define this method to get a callback
     }
@@ -324,16 +362,16 @@
         }
 
         @Override
-        public DomainVerificationUserSelection createFromParcel(@NonNull android.os.Parcel in) {
+        public DomainVerificationUserSelection createFromParcel(@NonNull Parcel in) {
             return new DomainVerificationUserSelection(in);
         }
     };
 
     @DataClass.Generated(
-            time = 1612829797220L,
+            time = 1613683603297L,
             codegenVersion = "1.0.22",
             sourceFile = "frameworks/base/core/java/android/content/pm/verify/domain/DomainVerificationUserSelection.java",
-            inputSignatures = "private final @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForUUID.class) java.util.UUID mIdentifier\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull android.os.UserHandle mUser\nprivate final @android.annotation.NonNull boolean mLinkHandlingAllowed\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,java.lang.Boolean> mHostToUserSelectionMap\nclass DomainVerificationUserSelection extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genAidl=true, genHiddenConstructor=true, genParcelable=true, genToString=true, genEqualsHashCode=true)")
+            inputSignatures = "public static final  int DOMAIN_STATE_NONE\npublic static final  int DOMAIN_STATE_SELECTED\npublic static final  int DOMAIN_STATE_VERIFIED\nprivate final @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForUUID.class) java.util.UUID mIdentifier\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull android.os.UserHandle mUser\nprivate final @android.annotation.NonNull boolean mLinkHandlingAllowed\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,java.lang.Integer> mHostToStateMap\nprivate  void parcelHostToStateMap(android.os.Parcel,int)\nprivate @android.annotation.NonNull java.util.Map<java.lang.String,java.lang.Integer> unparcelHostToStateMap(android.os.Parcel)\nclass DomainVerificationUserSelection extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genAidl=true, genHiddenConstructor=true, genParcelable=true, genToString=true, genEqualsHashCode=true, genHiddenConstDefs=true)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/content/pm/verify/domain/DomainVerificationUtils.java b/core/java/android/content/pm/verify/domain/DomainVerificationUtils.java
new file mode 100644
index 0000000..93005fa
--- /dev/null
+++ b/core/java/android/content/pm/verify/domain/DomainVerificationUtils.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm.verify.domain;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.util.ArraySet;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @hide
+ */
+public class DomainVerificationUtils {
+
+    private static final int STRINGS_TARGET_BYTE_SIZE = IBinder.getSuggestedMaxIpcSizeBytes() / 2;
+
+    /**
+     * Write a map containing web hosts to the given parcel, using {@link Parcel#writeBlob(byte[])}
+     * if the limit exceeds {@link IBinder#getSuggestedMaxIpcSizeBytes()} / 2. This assumes that the
+     * written map is the only data structure in the caller that varies based on the host data set.
+     * Other data that will be written to the parcel after this method will not be considered in the
+     * calculation.
+     */
+    public static void writeHostMap(@NonNull Parcel dest, @NonNull Map<String, ?> map) {
+        boolean targetSizeExceeded = false;
+        int totalSize = dest.dataSize();
+        for (String host : map.keySet()) {
+            totalSize += estimatedByteSizeOf(host);
+            if (totalSize > STRINGS_TARGET_BYTE_SIZE) {
+                targetSizeExceeded = true;
+                break;
+            }
+        }
+
+        dest.writeBoolean(targetSizeExceeded);
+
+        if (!targetSizeExceeded) {
+            dest.writeMap(map);
+            return;
+        }
+
+        Parcel data = Parcel.obtain();
+        try {
+            data.writeMap(map);
+            dest.writeBlob(data.marshall());
+        } finally {
+            data.recycle();
+        }
+    }
+
+    /**
+     * Retrieve a map previously written by {@link #writeHostMap(Parcel, Map)}.
+     */
+    @NonNull
+    @SuppressWarnings("rawtypes")
+    public static <T extends Map> T readHostMap(@NonNull Parcel in, @NonNull T map,
+            @NonNull ClassLoader classLoader) {
+        boolean targetSizeExceeded = in.readBoolean();
+
+        if (!targetSizeExceeded) {
+            in.readMap(map, classLoader);
+            return map;
+        }
+
+        Parcel data = Parcel.obtain();
+        try {
+            byte[] blob = in.readBlob();
+            data.unmarshall(blob, 0, blob.length);
+            data.setDataPosition(0);
+            data.readMap(map, classLoader);
+        } finally {
+            data.recycle();
+        }
+
+        return map;
+    }
+
+    /**
+     * {@link ArraySet} variant of {@link #writeHostMap(Parcel, Map)}.
+     */
+    public static void writeHostSet(@NonNull Parcel dest, @NonNull Set<String> set) {
+        boolean targetSizeExceeded = false;
+        int totalSize = dest.dataSize();
+        for (String host : set) {
+            totalSize += estimatedByteSizeOf(host);
+            if (totalSize > STRINGS_TARGET_BYTE_SIZE) {
+                targetSizeExceeded = true;
+                break;
+            }
+        }
+
+        dest.writeBoolean(targetSizeExceeded);
+
+        if (!targetSizeExceeded) {
+            writeSet(dest, set);
+            return;
+        }
+
+        Parcel data = Parcel.obtain();
+        try {
+            writeSet(data, set);
+            dest.writeBlob(data.marshall());
+        } finally {
+            data.recycle();
+        }
+    }
+
+    /**
+     * {@link ArraySet} variant of {@link #readHostMap(Parcel, Map, ClassLoader)}.
+     */
+    @NonNull
+    public static Set<String> readHostSet(@NonNull Parcel in) {
+        boolean targetSizeExceeded = in.readBoolean();
+
+        if (!targetSizeExceeded) {
+            return readSet(in);
+        }
+
+        Parcel data = Parcel.obtain();
+        try {
+            byte[] blob = in.readBlob();
+            data.unmarshall(blob, 0, blob.length);
+            data.setDataPosition(0);
+            return readSet(data);
+        } finally {
+            data.recycle();
+        }
+    }
+
+    private static void writeSet(@NonNull Parcel dest, @Nullable Set<String> set) {
+        if (set == null) {
+            dest.writeInt(-1);
+            return;
+        }
+        dest.writeInt(set.size());
+        for (String string : set) {
+            dest.writeString(string);
+        }
+    }
+
+    @NonNull
+    private static Set<String> readSet(@NonNull Parcel in) {
+        int size = in.readInt();
+        if (size == -1) {
+            return Collections.emptySet();
+        }
+
+        ArraySet<String> set = new ArraySet<>(size);
+        for (int count = 0; count < size; count++) {
+            set.add(in.readString());
+        }
+        return set;
+    }
+
+    /**
+     * Ballpark the size of domains to avoid unnecessary allocation of ashmem when sending domains
+     * across the client-server API.
+     */
+    public static int estimatedByteSizeOf(String string) {
+        return string.length() * 2 + 12;
+    }
+}
diff --git a/core/java/android/content/pm/verify/domain/IDomainVerificationManager.aidl b/core/java/android/content/pm/verify/domain/IDomainVerificationManager.aidl
index 21dd623b..701af32 100644
--- a/core/java/android/content/pm/verify/domain/IDomainVerificationManager.aidl
+++ b/core/java/android/content/pm/verify/domain/IDomainVerificationManager.aidl
@@ -16,6 +16,8 @@
 
 package android.content.pm.verify.domain;
 
+import android.content.pm.verify.domain.DomainOwner;
+import android.content.pm.verify.domain.DomainSet;
 import android.content.pm.verify.domain.DomainVerificationInfo;
 import android.content.pm.verify.domain.DomainVerificationUserSelection;
 import java.util.List;
@@ -35,10 +37,13 @@
     DomainVerificationUserSelection getDomainVerificationUserSelection(String packageName,
             int userId);
 
-    void setDomainVerificationStatus(String domainSetId, in List<String> domains, int state);
+    @nullable
+    List<DomainOwner> getOwnersForDomain(String domain, int userId);
+
+    void setDomainVerificationStatus(String domainSetId, in DomainSet domains, int state);
 
     void setDomainVerificationLinkHandlingAllowed(String packageName, boolean allowed, int userId);
 
-    void setDomainVerificationUserSelection(String domainSetId, in List<String> domains,
+    void setDomainVerificationUserSelection(String domainSetId, in DomainSet domains,
             boolean enabled, int userId);
 }
diff --git a/core/java/android/content/pm/verify/domain/OWNERS b/core/java/android/content/pm/verify/domain/OWNERS
new file mode 100644
index 0000000..c669112
--- /dev/null
+++ b/core/java/android/content/pm/verify/domain/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 36137
+
+chiuwinson@google.com
+patb@google.com
+toddke@google.com
\ No newline at end of file
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 2f7aeb8..b66f048 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1956,7 +1956,7 @@
         dest.writeInt(mnc);
 
         fixUpLocaleList();
-        dest.writeParcelable(mLocaleList, flags);
+        dest.writeTypedObject(mLocaleList, flags);
 
         if(userSetLocale) {
             dest.writeInt(1);
@@ -1980,7 +1980,7 @@
         dest.writeInt(compatScreenWidthDp);
         dest.writeInt(compatScreenHeightDp);
         dest.writeInt(compatSmallestScreenWidthDp);
-        dest.writeValue(windowConfiguration);
+        windowConfiguration.writeToParcel(dest, flags);
         dest.writeInt(assetsSeq);
         dest.writeInt(seq);
         dest.writeInt(fontWeightAdjustment);
@@ -1991,7 +1991,7 @@
         mcc = source.readInt();
         mnc = source.readInt();
 
-        mLocaleList = source.readParcelable(LocaleList.class.getClassLoader());
+        mLocaleList = source.readTypedObject(LocaleList.CREATOR);
         locale = mLocaleList.get(0);
 
         userSetLocale = (source.readInt()==1);
@@ -2012,7 +2012,7 @@
         compatScreenWidthDp = source.readInt();
         compatScreenHeightDp = source.readInt();
         compatSmallestScreenWidthDp = source.readInt();
-        windowConfiguration.setTo((WindowConfiguration) source.readValue(null));
+        windowConfiguration.readFromParcel(source);
         assetsSeq = source.readInt();
         seq = source.readInt();
         fontWeightAdjustment = source.readInt();
diff --git a/core/java/android/graphics/fonts/FontManager.java b/core/java/android/graphics/fonts/FontManager.java
index e512cf1..429eef9 100644
--- a/core/java/android/graphics/fonts/FontManager.java
+++ b/core/java/android/graphics/fonts/FontManager.java
@@ -20,7 +20,6 @@
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
@@ -29,7 +28,6 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.text.FontConfig;
-import android.util.Log;
 
 import com.android.internal.graphics.fonts.IFontManager;
 
@@ -198,12 +196,11 @@
      * @return The current font configuration. null if failed to fetch information from the system
      *         service.
      */
-    public @Nullable FontConfig getFontConfig() {
+    public @NonNull FontConfig getFontConfig() {
         try {
             return mIFontManager.getFontConfig();
         } catch (RemoteException e) {
-            Log.e(TAG, "Failed to call getFontConfig", e);
-            return null;
+            throw e.rethrowAsRuntimeException();
         }
     }
 
diff --git a/core/java/android/hardware/OWNERS b/core/java/android/hardware/OWNERS
index 3295042..2b4e4a1 100644
--- a/core/java/android/hardware/OWNERS
+++ b/core/java/android/hardware/OWNERS
@@ -3,3 +3,6 @@
 
 # Sensor Privacy
 per-file *SensorPrivacy* = file:platform/frameworks/native:/libs/sensorprivacy/OWNERS
+
+# Sensors framework
+per-file *Sensor*,*Trigger* = file:platform/frameworks/native:/services/sensorservice/OWNERS
diff --git a/core/java/android/hardware/SensorPrivacyManager.java b/core/java/android/hardware/SensorPrivacyManager.java
index f4f9e17..e03c1f4 100644
--- a/core/java/android/hardware/SensorPrivacyManager.java
+++ b/core/java/android/hardware/SensorPrivacyManager.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.content.Context;
@@ -33,6 +34,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
 
 /**
  * This class provides access to the sensor privacy services; sensor privacy allows the
@@ -42,9 +44,21 @@
  *
  * @hide
  */
+@SystemApi
 @TestApi
 @SystemService(Context.SENSOR_PRIVACY_SERVICE)
 public final class SensorPrivacyManager {
+
+    /**
+     * @hide
+     */
+    public static final boolean USE_MICROPHONE_TOGGLE = true;
+
+    /**
+     * @hide
+     */
+    public static final boolean USE_CAMERA_TOGGLE = true;
+
     /**
      * Unique Id of this manager to identify to the service
      * @hide
@@ -58,28 +72,39 @@
     public static final String EXTRA_SENSOR = SensorPrivacyManager.class.getName()
             + ".extra.sensor";
 
-    /** Microphone
-     * @hide */
-    @TestApi
-    public static final int INDIVIDUAL_SENSOR_MICROPHONE =
-            SensorPrivacyIndividualEnabledSensorProto.MICROPHONE;
-
-    /** Camera
-     * @hide */
-    @TestApi
-    public static final int INDIVIDUAL_SENSOR_CAMERA =
-            SensorPrivacyIndividualEnabledSensorProto.CAMERA;
-
     /**
-     * Individual sensors not listed in {@link Sensor}
+     * Individual sensors not listed in {@link Sensors}
      * @hide
      */
-    @IntDef(prefix = "INDIVIDUAL_SENSOR_", value = {
-            INDIVIDUAL_SENSOR_MICROPHONE,
-            INDIVIDUAL_SENSOR_CAMERA
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface IndividualSensor {}
+    @SystemApi
+    @TestApi
+    public static class Sensors {
+
+        private Sensors() {}
+
+        /** Microphone
+         * @hide */
+        @SystemApi
+        @TestApi
+        public static final int MICROPHONE = SensorPrivacyIndividualEnabledSensorProto.MICROPHONE;
+        /** Camera
+         * @hide */
+        @SystemApi
+        @TestApi
+        public static final int CAMERA = SensorPrivacyIndividualEnabledSensorProto.CAMERA;
+
+        /**
+         * Individual sensors not listed in {@link Sensors}
+         *
+         * @hide
+         */
+        @IntDef(value = {
+                MICROPHONE,
+                CAMERA
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface Sensor {}
+    }
 
     /**
      * A class implementing this interface can register with the {@link
@@ -88,6 +113,8 @@
      *
      * @hide
      */
+    @SystemApi
+    @TestApi
     public interface OnSensorPrivacyChangedListener {
         /**
          * Callback invoked when the sensor privacy state changes.
@@ -165,7 +192,8 @@
      *
      * @hide
      */
-    public void addSensorPrivacyListener(final OnSensorPrivacyChangedListener listener) {
+    @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
+    public void addSensorPrivacyListener(@NonNull final OnSensorPrivacyChangedListener listener) {
         synchronized (mListeners) {
             ISensorPrivacyListener iListener = mListeners.get(listener);
             if (iListener == null) {
@@ -196,15 +224,37 @@
      *
      * @hide
      */
-    public void addSensorPrivacyListener(@IndividualSensor int sensor,
-            final OnSensorPrivacyChangedListener listener) {
+    @SystemApi
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
+    public void addSensorPrivacyListener(@Sensors.Sensor int sensor,
+            @NonNull OnSensorPrivacyChangedListener listener) {
+        addSensorPrivacyListener(sensor, mContext.getMainExecutor(), listener);
+    }
+
+    /**
+     * Registers a new listener to receive notification when the state of sensor privacy
+     * changes.
+     *
+     * @param sensor the sensor to listen to changes to
+     * @param executor the executor to dispatch the callback on
+     * @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor
+     *                 privacy changes.
+     *
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
+    public void addSensorPrivacyListener(@Sensors.Sensor int sensor, @NonNull Executor executor,
+            @NonNull OnSensorPrivacyChangedListener listener) {
         synchronized (mListeners) {
             ISensorPrivacyListener iListener = mListeners.get(listener);
             if (iListener == null) {
                 iListener = new ISensorPrivacyListener.Stub() {
                     @Override
                     public void onSensorPrivacyChanged(boolean enabled) {
-                        listener.onSensorPrivacyChanged(enabled);
+                        executor.execute(() -> listener.onSensorPrivacyChanged(enabled));
                     }
                 };
                 mListeners.put(listener, iListener);
@@ -228,7 +278,10 @@
      *
      * @hide
      */
-    public void removeSensorPrivacyListener(OnSensorPrivacyChangedListener listener) {
+    @SystemApi
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
+    public void removeSensorPrivacyListener(@NonNull OnSensorPrivacyChangedListener listener) {
         synchronized (mListeners) {
             ISensorPrivacyListener iListener = mListeners.get(listener);
             if (iListener != null) {
@@ -249,6 +302,7 @@
      *
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
     public boolean isSensorPrivacyEnabled() {
         try {
             return mService.isSensorPrivacyEnabled();
@@ -264,8 +318,10 @@
      *
      * @hide
      */
+    @SystemApi
     @TestApi
-    public boolean isIndividualSensorPrivacyEnabled(@IndividualSensor int sensor) {
+    @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
+    public boolean isSensorPrivacyEnabled(@Sensors.Sensor int sensor) {
         try {
             return mService.isIndividualSensorPrivacyEnabled(mContext.getUserId(), sensor);
         } catch (RemoteException e) {
@@ -283,8 +339,7 @@
      */
     @TestApi
     @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
-    public void setIndividualSensorPrivacy(@IndividualSensor int sensor,
-            boolean enable) {
+    public void setSensorPrivacy(@Sensors.Sensor int sensor, boolean enable) {
         try {
             mService.setIndividualSensorPrivacy(mContext.getUserId(), sensor, enable);
         } catch (RemoteException e) {
@@ -303,7 +358,7 @@
      */
     @TestApi
     @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
-    public void setIndividualSensorPrivacyForProfileGroup(@IndividualSensor int sensor,
+    public void setSensorPrivacyForProfileGroup(@Sensors.Sensor int sensor,
             boolean enable) {
         try {
             mService.setIndividualSensorPrivacyForProfileGroup(mContext.getUserId(), sensor,
@@ -321,7 +376,8 @@
      *
      * @hide
      */
-    public void suppressIndividualSensorPrivacyReminders(@NonNull String packageName,
+    @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
+    public void suppressSensorPrivacyReminders(@NonNull String packageName,
             boolean suppress) {
         try {
             mService.suppressIndividualSensorPrivacyReminders(mContext.getUserId(), packageName,
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 1ffd18f..788afe3 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -667,7 +667,7 @@
     private abstract static class BaseEventQueue {
         private static native long nativeInitBaseEventQueue(long nativeManager,
                 WeakReference<BaseEventQueue> eventQWeak, MessageQueue msgQ,
-                String packageName, int mode, String opPackageName);
+                String packageName, int mode, String opPackageName, String attributionTag);
         private static native int nativeEnableSensor(long eventQ, int handle, int rateUs,
                 int maxBatchReportLatencyUs);
         private static native int nativeDisableSensor(long eventQ, int handle);
@@ -689,7 +689,8 @@
             if (packageName == null) packageName = "";
             mNativeSensorEventQueue = nativeInitBaseEventQueue(manager.mNativeInstance,
                     new WeakReference<>(this), looper.getQueue(),
-                    packageName, mode, manager.mContext.getOpPackageName());
+                    packageName, mode, manager.mContext.getOpPackageName(),
+                    manager.mContext.getAttributionTag());
             mCloseGuard.open("dispose");
             mManager = manager;
         }
diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java
index 76d50bd..43ef33e 100644
--- a/core/java/android/hardware/biometrics/BiometricConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricConstants.java
@@ -145,6 +145,12 @@
     int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15;
 
     /**
+     * Authentication cannot proceed because re-enrollment is required.
+     * @hide
+     */
+    int BIOMETRIC_ERROR_RE_ENROLL = 16;
+
+    /**
      * This constant is only used by SystemUI. It notifies SystemUI that authentication was paused
      * because the authentication attempt was unsuccessful.
      * @hide
diff --git a/core/java/android/hardware/biometrics/BiometricFaceConstants.java b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
index eafcf52..4385b1da 100644
--- a/core/java/android/hardware/biometrics/BiometricFaceConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
@@ -153,6 +153,12 @@
     int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15;
 
     /**
+     * Authentication cannot proceed because re-enrollment is required.
+     * @hide
+     */
+    int BIOMETRIC_ERROR_RE_ENROLL = 16;
+
+    /**
      * @hide
      */
     int FACE_ERROR_VENDOR_BASE = 1000;
diff --git a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
index 01f0e71..30e24d2e 100644
--- a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
@@ -166,6 +166,12 @@
     public static final int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15;
 
     /**
+     * Authentication cannot proceed because re-enrollment is required.
+     * @hide
+     */
+    int BIOMETRIC_ERROR_RE_ENROLL = 16;
+
+    /**
      * @hide
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index f9eecae..ac6ba0a 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -378,9 +378,10 @@
      * released, continuous repeating requests stopped and any pending
      * multi-frame capture requests flushed.</p>
      *
-     * <p>Note that the CameraExtensionSession currently supports at most two
-     * multi frame capture surface formats: ImageFormat.YUV_420_888 and
-     * ImageFormat.JPEG. Clients must query the multi-frame capture format support using
+     * <p>Note that the CameraExtensionSession currently supports at most wo
+     * multi frame capture surface formats: ImageFormat.JPEG will be supported
+     * by all extensions and ImageFormat.YUV_420_888 may or may not be supported.
+     * Clients must query the multi-frame capture format support using
      * {@link CameraExtensionCharacteristics#getExtensionSupportedSizes(int, int)}.
      * For repeating requests CameraExtensionSession supports only
      * {@link android.graphics.SurfaceTexture} as output. Clients can query the supported resolution
diff --git a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
index d3eb377..6121cd2 100644
--- a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
@@ -35,6 +35,7 @@
 import android.util.Pair;
 import android.util.Size;
 
+import java.util.HashSet;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -153,12 +154,8 @@
         mChars = chars;
     }
 
-    private static List<Size> generateSupportedSizes(List<SizeList> sizesList,
-                                                     Integer format,
-                                                     StreamConfigurationMap streamMap) {
-        // Per API contract it is assumed that the extension is able to support all
-        // camera advertised sizes for a given format in case it doesn't return
-        // a valid non-empty size list.
+    private static ArrayList<Size> getSupportedSizes(List<SizeList> sizesList,
+            Integer format) {
         ArrayList<Size> ret = new ArrayList<>();
         if ((sizesList != null) && (!sizesList.isEmpty())) {
             for (SizeList entry : sizesList) {
@@ -170,13 +167,36 @@
                 }
             }
         }
+
+        return ret;
+    }
+
+    private static List<Size> generateSupportedSizes(List<SizeList> sizesList,
+                                                     Integer format,
+                                                     StreamConfigurationMap streamMap) {
+        // Per API contract it is assumed that the extension is able to support all
+        // camera advertised sizes for a given format in case it doesn't return
+        // a valid non-empty size list.
+        ArrayList<Size> ret = getSupportedSizes(sizesList, format);
         Size[] supportedSizes = streamMap.getOutputSizes(format);
-        if (supportedSizes != null) {
+        if ((ret.isEmpty()) && (supportedSizes != null)) {
             ret.addAll(Arrays.asList(supportedSizes));
         }
         return ret;
     }
 
+    private static List<Size> generateJpegSupportedSizes(List<SizeList> sizesList,
+            StreamConfigurationMap streamMap) {
+        ArrayList<Size> extensionSizes = getSupportedSizes(sizesList, ImageFormat.YUV_420_888);
+        HashSet<Size> supportedSizes = extensionSizes.isEmpty() ? new HashSet<>(Arrays.asList(
+                streamMap.getOutputSizes(ImageFormat.YUV_420_888))) : new HashSet<>(extensionSizes);
+        HashSet<Size> supportedJpegSizes = new HashSet<>(Arrays.asList(streamMap.getOutputSizes(
+                ImageFormat.JPEG)));
+        supportedSizes.retainAll(supportedJpegSizes);
+
+        return new ArrayList<>(supportedSizes);
+    }
+
     /**
      * A per-process global camera extension manager instance, to track and
      * initialize/release extensions depending on client activity.
@@ -488,8 +508,8 @@
      * {@link StreamConfigurationMap#getOutputSizes}.</p>
      *
      * <p>Device-specific extensions currently support at most two
-     * multi-frame capture surface formats, ImageFormat.YUV_420_888 or
-     * ImageFormat.JPEG.</p>
+     * multi-frame capture surface formats. ImageFormat.JPEG will be supported by all
+     * extensions and ImageFormat.YUV_420_888 may or may not be supported.</p>
      *
      * @param extension the extension type
      * @param format    device-specific extension output format
@@ -526,14 +546,17 @@
                             format, streamMap);
                 } else if (format == ImageFormat.JPEG) {
                     extenders.second.init(mCameraId, mChars.getNativeMetadata());
-                    if (extenders.second.getCaptureProcessor() == null) {
+                    if (extenders.second.getCaptureProcessor() != null) {
+                        // The framework will perform the additional encoding pass on the
+                        // processed YUV_420 buffers.
+                        return generateJpegSupportedSizes(
+                                extenders.second.getSupportedResolutions(), streamMap);
+                    } else {
                         return generateSupportedSizes(null, format, streamMap);
                     }
-
-                    return new ArrayList<>();
+                } else {
+                    throw new IllegalArgumentException("Unsupported format: " + format);
                 }
-
-                throw new IllegalArgumentException("Unsupported format: " + format);
             } finally {
                 unregisterClient(clientId);
             }
diff --git a/core/java/android/hardware/camera2/CameraExtensionSession.java b/core/java/android/hardware/camera2/CameraExtensionSession.java
index 877dfbc..e1b8177 100644
--- a/core/java/android/hardware/camera2/CameraExtensionSession.java
+++ b/core/java/android/hardware/camera2/CameraExtensionSession.java
@@ -238,8 +238,10 @@
      * from the camera device, to produce a single high-quality output result.
      *
      * <p>Note that single capture requests currently do not support
-     * client parameters. Settings included in the request will
-     * be entirely overridden by the device-specific extension. </p>
+     * client parameters except for {@link CaptureRequest#JPEG_ORIENTATION orientation} and
+     * {@link CaptureRequest#JPEG_QUALITY quality} in case of ImageFormat.JPEG output target.
+     * The rest of the settings included in the request will be entirely overridden by
+     * the device-specific extension. </p>
      *
      * <p>The {@link CaptureRequest.Builder#addTarget} supports only one
      * ImageFormat.YUV_420_888 or ImageFormat.JPEG target surface. {@link CaptureRequest}
diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionJpegProcessor.java b/core/java/android/hardware/camera2/impl/CameraExtensionJpegProcessor.java
new file mode 100644
index 0000000..936734b
--- /dev/null
+++ b/core/java/android/hardware/camera2/impl/CameraExtensionJpegProcessor.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.impl;
+
+import android.annotation.NonNull;
+import android.graphics.ImageFormat;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.extension.CaptureBundle;
+import android.hardware.camera2.extension.ICaptureProcessorImpl;
+import android.media.Image;
+import android.media.Image.Plane;
+import android.media.ImageReader;
+import android.media.ImageWriter;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.Surface;
+
+import java.nio.ByteBuffer;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+// Jpeg compress input YUV and queue back in the client target surface.
+public class CameraExtensionJpegProcessor implements ICaptureProcessorImpl {
+    public final static String TAG = "CameraExtensionJpeg";
+    private final static int JPEG_QUEUE_SIZE = 1;
+    private final static int JPEG_DEFAULT_QUALITY = 100;
+    private final static int JPEG_DEFAULT_ROTATION = 0;
+
+    private final Handler mHandler;
+    private final HandlerThread mHandlerThread;
+    private final ICaptureProcessorImpl mProcessor;
+
+    private ImageReader mYuvReader = null;
+    private android.hardware.camera2.extension.Size mResolution = null;
+    private int mFormat = -1;
+    private Surface mOutputSurface = null;
+    private ImageWriter mOutputWriter = null;
+
+    private static final class JpegParameters {
+        public HashSet<Long> mTimeStamps = new HashSet<>();
+        public int mRotation = JPEG_DEFAULT_ROTATION; // CCW multiple of 90 degrees
+        public int mQuality = JPEG_DEFAULT_QUALITY; // [0..100]
+    }
+
+    private ConcurrentLinkedQueue<JpegParameters> mJpegParameters = new ConcurrentLinkedQueue<>();
+
+    public CameraExtensionJpegProcessor(@NonNull ICaptureProcessorImpl processor) {
+        mProcessor = processor;
+        mHandlerThread = new HandlerThread(TAG);
+        mHandlerThread.start();
+        mHandler = new Handler(mHandlerThread.getLooper());
+    }
+
+    public void close() {
+        mHandlerThread.quitSafely();
+
+        if (mOutputWriter != null) {
+            mOutputWriter.close();
+            mOutputWriter = null;
+        }
+
+        if (mYuvReader != null) {
+            mYuvReader.close();
+            mYuvReader = null;
+        }
+    }
+
+    private static JpegParameters getJpegParameters(List<CaptureBundle> captureBundles) {
+        JpegParameters ret = new JpegParameters();
+        if (!captureBundles.isEmpty()) {
+            // The quality and orientation settings must be equal for requests in a burst
+
+            Byte jpegQuality = captureBundles.get(0).captureResult.get(CaptureResult.JPEG_QUALITY);
+            if (jpegQuality != null) {
+                ret.mQuality = jpegQuality;
+            } else {
+                Log.w(TAG, "No jpeg quality set, using default: " + JPEG_DEFAULT_QUALITY);
+            }
+
+            Integer orientation = captureBundles.get(0).captureResult.get(
+                    CaptureResult.JPEG_ORIENTATION);
+            if (orientation != null) {
+                ret.mRotation = orientation / 90;
+            } else {
+                Log.w(TAG, "No jpeg rotation set, using default: " + JPEG_DEFAULT_ROTATION);
+            }
+
+            for (CaptureBundle bundle : captureBundles) {
+                Long timeStamp = bundle.captureResult.get(CaptureResult.SENSOR_TIMESTAMP);
+                if (timeStamp != null) {
+                    ret.mTimeStamps.add(timeStamp);
+                } else {
+                    Log.e(TAG, "Capture bundle without valid sensor timestamp!");
+                }
+            }
+        }
+
+        return ret;
+    }
+
+    /**
+     * Compresses a YCbCr image to jpeg, applying a crop and rotation.
+     * <p>
+     * The input is defined as a set of 3 planes of 8-bit samples, one plane for
+     * each channel of Y, Cb, Cr.<br>
+     * The Y plane is assumed to have the same width and height of the entire
+     * image.<br>
+     * The Cb and Cr planes are assumed to be downsampled by a factor of 2, to
+     * have dimensions (floor(width / 2), floor(height / 2)).<br>
+     * Each plane is specified by a direct java.nio.ByteBuffer, a pixel-stride,
+     * and a row-stride. So, the sample at coordinate (x, y) can be retrieved
+     * from byteBuffer[x * pixel_stride + y * row_stride].
+     * <p>
+     * The pre-compression transformation is applied as follows:
+     * <ol>
+     * <li>The image is cropped to the rectangle from (cropLeft, cropTop) to
+     * (cropRight - 1, cropBottom - 1). So, a cropping-rectangle of (0, 0) -
+     * (width, height) is a no-op.</li>
+     * <li>The rotation is applied counter-clockwise relative to the coordinate
+     * space of the image, so a CCW rotation will appear CW when the image is
+     * rendered in scanline order. Only rotations which are multiples of
+     * 90-degrees are suppored, so the parameter 'rot90' specifies which
+     * multiple of 90 to rotate the image.</li>
+     * </ol>
+     *
+     * @param width          the width of the image to compress
+     * @param height         the height of the image to compress
+     * @param yBuf           the buffer containing the Y component of the image
+     * @param yPStride       the stride between adjacent pixels in the same row in
+     *                       yBuf
+     * @param yRStride       the stride between adjacent rows in yBuf
+     * @param cbBuf          the buffer containing the Cb component of the image
+     * @param cbPStride      the stride between adjacent pixels in the same row in
+     *                       cbBuf
+     * @param cbRStride      the stride between adjacent rows in cbBuf
+     * @param crBuf          the buffer containing the Cr component of the image
+     * @param crPStride      the stride between adjacent pixels in the same row in
+     *                       crBuf
+     * @param crRStride      the stride between adjacent rows in crBuf
+     * @param outBuf         a direct java.nio.ByteBuffer to hold the compressed jpeg.
+     *                       This must have enough capacity to store the result, or an
+     *                       error code will be returned.
+     * @param outBufCapacity the capacity of outBuf
+     * @param quality        the jpeg-quality (1-100) to use
+     * @param cropLeft       left-edge of the bounds of the image to crop to before
+     *                       rotation
+     * @param cropTop        top-edge of the bounds of the image to crop to before
+     *                       rotation
+     * @param cropRight      right-edge of the bounds of the image to crop to before
+     *                       rotation
+     * @param cropBottom     bottom-edge of the bounds of the image to crop to
+     *                       before rotation
+     * @param rot90          the multiple of 90 to rotate the image CCW (after cropping)
+     */
+    private static native int compressJpegFromYUV420pNative(
+            int width, int height,
+            ByteBuffer yBuf, int yPStride, int yRStride,
+            ByteBuffer cbBuf, int cbPStride, int cbRStride,
+            ByteBuffer crBuf, int crPStride, int crRStride,
+            ByteBuffer outBuf, int outBufCapacity,
+            int quality,
+            int cropLeft, int cropTop, int cropRight, int cropBottom,
+            int rot90);
+
+    public void process(List<CaptureBundle> captureBundle) throws RemoteException {
+        JpegParameters jpegParams = getJpegParameters(captureBundle);
+        try {
+            mJpegParameters.add(jpegParams);
+            mProcessor.process(captureBundle);
+        } catch (Exception e) {
+            mJpegParameters.remove(jpegParams);
+            throw e;
+        }
+    }
+
+    public void onOutputSurface(Surface surface, int format) throws RemoteException {
+        if (format != ImageFormat.JPEG) {
+            Log.e(TAG, "Unsupported output format: " + format);
+            return;
+        }
+        mOutputSurface = surface;
+        initializePipeline();
+    }
+
+    @Override
+    public void onResolutionUpdate(android.hardware.camera2.extension.Size size)
+            throws RemoteException {
+        mResolution = size;
+        initializePipeline();
+    }
+
+    public void onImageFormatUpdate(int format) throws RemoteException {
+        if (format != ImageFormat.YUV_420_888) {
+            Log.e(TAG, "Unsupported input format: " + format);
+            return;
+        }
+        mFormat = format;
+        initializePipeline();
+    }
+
+    private void initializePipeline() throws RemoteException {
+        if ((mFormat != -1) && (mOutputSurface != null) && (mResolution != null) &&
+                (mYuvReader == null)) {
+            // Jpeg/blobs are expected to be configured with (w*h)x1
+            mOutputWriter = ImageWriter.newInstance(mOutputSurface, 1 /*maxImages*/,
+                    ImageFormat.JPEG, mResolution.width * mResolution.height, 1);
+            mYuvReader = ImageReader.newInstance(mResolution.width, mResolution.height, mFormat,
+                    JPEG_QUEUE_SIZE);
+            mYuvReader.setOnImageAvailableListener(new YuvCallback(), mHandler);
+            mProcessor.onOutputSurface(mYuvReader.getSurface(), mFormat);
+            mProcessor.onResolutionUpdate(mResolution);
+            mProcessor.onImageFormatUpdate(mFormat);
+        }
+    }
+
+    @Override
+    public IBinder asBinder() {
+        throw new UnsupportedOperationException("Binder IPC not supported!");
+    }
+
+    private class YuvCallback implements ImageReader.OnImageAvailableListener {
+        @Override
+        public void onImageAvailable(ImageReader reader) {
+            Image yuvImage = null;
+            Image jpegImage = null;
+            try {
+                yuvImage = mYuvReader.acquireNextImage();
+                jpegImage = mOutputWriter.dequeueInputImage();
+            } catch (IllegalStateException e) {
+                if (yuvImage != null) {
+                    yuvImage.close();
+                }
+                if (jpegImage != null) {
+                    jpegImage.close();
+                }
+                Log.e(TAG, "Failed to acquire processed yuv image or jpeg image!");
+                return;
+            }
+
+            ByteBuffer jpegBuffer = jpegImage.getPlanes()[0].getBuffer();
+            jpegBuffer.clear();
+            // Jpeg/blobs are expected to be configured with (w*h)x1
+            int jpegCapacity = jpegImage.getWidth();
+
+            Plane lumaPlane = yuvImage.getPlanes()[0];
+            Plane crPlane = yuvImage.getPlanes()[1];
+            Plane cbPlane = yuvImage.getPlanes()[2];
+
+            Iterator<JpegParameters> jpegIter = mJpegParameters.iterator();
+            JpegParameters jpegParams = null;
+            while(jpegIter.hasNext()) {
+                JpegParameters currentParams = jpegIter.next();
+                if (currentParams.mTimeStamps.contains(yuvImage.getTimestamp())) {
+                    jpegParams = currentParams;
+                    jpegIter.remove();
+                    break;
+                }
+            }
+            if (jpegParams == null) {
+                if (mJpegParameters.isEmpty()) {
+                    Log.w(TAG, "Empty jpeg settings queue! Using default jpeg orientation"
+                            + " and quality!");
+                    jpegParams = new JpegParameters();
+                    jpegParams.mRotation = JPEG_DEFAULT_ROTATION;
+                    jpegParams.mQuality = JPEG_DEFAULT_QUALITY;
+                } else {
+                    Log.w(TAG, "No jpeg settings found with matching timestamp for current"
+                            + " processed input!");
+                    Log.w(TAG, "Using values from the top of the queue!");
+                    jpegParams = mJpegParameters.poll();
+                }
+            }
+
+            compressJpegFromYUV420pNative(
+                    yuvImage.getWidth(), yuvImage.getHeight(),
+                    lumaPlane.getBuffer(), lumaPlane.getPixelStride(), lumaPlane.getRowStride(),
+                    crPlane.getBuffer(), crPlane.getPixelStride(), crPlane.getRowStride(),
+                    cbPlane.getBuffer(), cbPlane.getPixelStride(), cbPlane.getRowStride(),
+                    jpegBuffer, jpegCapacity, jpegParams.mQuality,
+                    0, 0, yuvImage.getWidth(), yuvImage.getHeight(),
+                    jpegParams.mRotation);
+            yuvImage.close();
+
+            try {
+                mOutputWriter.queueInputImage(jpegImage);
+            } catch (IllegalStateException e) {
+                Log.e(TAG, "Failed to queue encoded result!");
+            } finally {
+                jpegImage.close();
+            }
+        }
+    }
+}
diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
index 8451ded..0a56171 100644
--- a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
@@ -91,6 +91,7 @@
     private ImageReader mStubCaptureImageReader = null;
     private ImageWriter mRepeatingRequestImageWriter = null;
 
+    private CameraExtensionJpegProcessor mImageJpegProcessor = null;
     private ICaptureProcessorImpl mImageProcessor = null;
     private CameraExtensionForwardProcessor mPreviewImageProcessor = null;
     private IRequestUpdateProcessorImpl mPreviewRequestUpdateProcessor = null;
@@ -413,6 +414,10 @@
         if (mImageProcessor != null) {
             if (mClientCaptureSurface != null) {
                 SurfaceInfo surfaceInfo = querySurface(mClientCaptureSurface);
+                if (surfaceInfo.mFormat == ImageFormat.JPEG) {
+                    mImageJpegProcessor = new CameraExtensionJpegProcessor(mImageProcessor);
+                    mImageProcessor = mImageJpegProcessor;
+                }
                 mBurstCaptureImageReader = ImageReader.newInstance(surfaceInfo.mWidth,
                         surfaceInfo.mHeight, CameraExtensionCharacteristics.PROCESSING_INPUT_FORMAT,
                         mImageExtender.getMaxCaptureStage());
@@ -570,14 +575,16 @@
                 return null;
             }
 
-            // Set user supported jpeg quality and rotation parameters
+            // This will override the extension capture stage jpeg parameters with the user set
+            // jpeg quality and rotation. This will guarantee that client configured jpeg
+            // parameters always have highest priority.
             Integer jpegRotation = clientRequest.get(CaptureRequest.JPEG_ORIENTATION);
             if (jpegRotation != null) {
-                requestBuilder.set(CaptureRequest.JPEG_ORIENTATION, jpegRotation);
+                captureStage.parameters.set(CaptureRequest.JPEG_ORIENTATION, jpegRotation);
             }
             Byte jpegQuality = clientRequest.get(CaptureRequest.JPEG_QUALITY);
             if (jpegQuality != null) {
-                requestBuilder.set(CaptureRequest.JPEG_QUALITY, jpegQuality);
+                captureStage.parameters.set(CaptureRequest.JPEG_QUALITY, jpegQuality);
             }
 
             requestBuilder.addTarget(target);
@@ -753,6 +760,11 @@
                 mPreviewImageProcessor = null;
             }
 
+            if (mImageJpegProcessor != null) {
+                mImageJpegProcessor.close();
+                mImageJpegProcessor = null;
+            }
+
             mCaptureSession = null;
             mImageProcessor = null;
             mCameraRepeatingSurface = mClientRepeatingRequestSurface = null;
@@ -1014,7 +1026,10 @@
                 mCaptureRequestMap.clear();
                 mCapturePendingMap.clear();
                 boolean processStatus = true;
-                List<CaptureBundle> captureList = initializeParcelable(mCaptureStageMap);
+                Byte jpegQuality = mClientRequest.get(CaptureRequest.JPEG_QUALITY);
+                Integer jpegOrientation = mClientRequest.get(CaptureRequest.JPEG_ORIENTATION);
+                List<CaptureBundle> captureList = initializeParcelable(mCaptureStageMap,
+                        jpegOrientation, jpegQuality);
                 try {
                     mImageProcessor.process(captureList);
                 } catch (RemoteException e) {
@@ -1444,10 +1459,8 @@
             }
             for (int i = idx; i >= 0; i--) {
                 if (previewMap.valueAt(i).first != null) {
-                    Log.w(TAG, "Discard pending buffer with timestamp: " + previewMap.keyAt(i));
                     previewMap.valueAt(i).first.close();
                 } else {
-                    Log.w(TAG, "Discard pending result with timestamp: " + previewMap.keyAt(i));
                     if (mClientNotificationsEnabled && ((i != idx) || notifyCurrentIndex)) {
                         Log.w(TAG, "Preview frame drop with timestamp: " + previewMap.keyAt(i));
                         final long ident = Binder.clearCallingIdentity();
@@ -1639,7 +1652,8 @@
     }
 
     private static List<CaptureBundle> initializeParcelable(
-            HashMap<Integer, Pair<Image, TotalCaptureResult>> captureMap) {
+            HashMap<Integer, Pair<Image, TotalCaptureResult>> captureMap, Integer jpegOrientation,
+            Byte jpegQuality) {
         ArrayList<CaptureBundle> ret = new ArrayList<>();
         for (Integer stagetId : captureMap.keySet()) {
             Pair<Image, TotalCaptureResult> entry = captureMap.get(stagetId);
@@ -1648,6 +1662,12 @@
             bundle.captureImage = initializeParcelImage(entry.first);
             bundle.sequenceId = entry.second.getSequenceId();
             bundle.captureResult = entry.second.getNativeMetadata();
+            if (jpegOrientation != null) {
+                bundle.captureResult.set(CaptureResult.JPEG_ORIENTATION, jpegOrientation);
+            }
+            if (jpegQuality != null) {
+                bundle.captureResult.set(CaptureResult.JPEG_QUALITY, jpegQuality);
+            }
             ret.add(bundle);
         }
 
diff --git a/core/java/android/service/screenshot/ScreenshotHash.aidl b/core/java/android/hardware/devicestate/DeviceStateInfo.aidl
similarity index 81%
copy from core/java/android/service/screenshot/ScreenshotHash.aidl
copy to core/java/android/hardware/devicestate/DeviceStateInfo.aidl
index a7c50db..e856792 100644
--- a/core/java/android/service/screenshot/ScreenshotHash.aidl
+++ b/core/java/android/hardware/devicestate/DeviceStateInfo.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.service.screenshot;
+package android.hardware.devicestate;
 
-parcelable ScreenshotHash;
+parcelable DeviceStateInfo;
diff --git a/core/java/android/hardware/devicestate/DeviceStateInfo.java b/core/java/android/hardware/devicestate/DeviceStateInfo.java
new file mode 100644
index 0000000..bc6af37
--- /dev/null
+++ b/core/java/android/hardware/devicestate/DeviceStateInfo.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.devicestate;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.concurrent.Executor;
+
+
+/**
+ * Information about the state of the device.
+ *
+ * @hide
+ */
+public final class DeviceStateInfo implements Parcelable {
+    /** Bit that indicates the {@link #supportedStates} field has changed. */
+    public static final int CHANGED_SUPPORTED_STATES = 1 << 0;
+
+    /** Bit that indicates the {@link #baseState} field has changed. */
+    public static final int CHANGED_BASE_STATE = 1 << 1;
+
+    /** Bit that indicates the {@link #currentState} field has changed. */
+    public static final int CHANGED_CURRENT_STATE = 1 << 2;
+
+    @IntDef(prefix = {"CHANGED_"}, flag = true, value = {
+            CHANGED_SUPPORTED_STATES,
+            CHANGED_BASE_STATE,
+            CHANGED_CURRENT_STATE,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ChangeFlags {}
+
+    /**
+     * The list of states supported by the device.
+     */
+    @NonNull
+    public final int[] supportedStates;
+
+    /**
+     * The base (non-override) state of the device. The base state is the state of the device
+     * ignoring any override requests made through a call to {@link DeviceStateManager#requestState(
+     * DeviceStateRequest, Executor, DeviceStateRequest.Callback)}.
+     */
+    public final int baseState;
+
+    /**
+     * The state of the device.
+     */
+    public final int currentState;
+
+    /**
+     * Creates a new instance of {@link DeviceStateInfo}.
+     * <p>
+     * NOTE: Unlike {@link #DeviceStateInfo(DeviceStateInfo)}, this constructor does not copy the
+     * supplied parameters.
+     */
+    public DeviceStateInfo(@NonNull int[] supportedStates, int baseState, int state) {
+        this.supportedStates = supportedStates;
+        this.baseState = baseState;
+        this.currentState = state;
+    }
+
+    /**
+     * Creates a new instance of {@link DeviceStateInfo} copying the fields of {@code info} into
+     * the fields of the returned instance.
+     */
+    public DeviceStateInfo(@NonNull DeviceStateInfo info) {
+        this(Arrays.copyOf(info.supportedStates, info.supportedStates.length),
+                info.baseState, info.currentState);
+    }
+
+    @Override
+    public boolean equals(@Nullable Object other) {
+        if (this == other) return true;
+        if (other == null || getClass() != other.getClass()) return false;
+        DeviceStateInfo that = (DeviceStateInfo) other;
+        return baseState == that.baseState
+                &&  currentState == that.currentState
+                && Arrays.equals(supportedStates, that.supportedStates);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = Objects.hash(baseState, currentState);
+        result = 31 * result + Arrays.hashCode(supportedStates);
+        return result;
+    }
+
+    /** Returns a bitmask of the differences between this instance and {@code other}. */
+    @ChangeFlags
+    public int diff(@NonNull DeviceStateInfo other) {
+        int diff = 0;
+        if (!Arrays.equals(supportedStates, other.supportedStates)) {
+            diff |= CHANGED_SUPPORTED_STATES;
+        }
+        if (baseState != other.baseState) {
+            diff |= CHANGED_BASE_STATE;
+        }
+        if (currentState != other.currentState) {
+            diff |= CHANGED_CURRENT_STATE;
+        }
+        return diff;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(supportedStates.length);
+        for (int i = 0; i < supportedStates.length; i++) {
+            dest.writeInt(supportedStates[i]);
+        }
+
+        dest.writeInt(baseState);
+        dest.writeInt(currentState);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final @NonNull Creator<DeviceStateInfo> CREATOR = new Creator<DeviceStateInfo>() {
+        @Override
+        public DeviceStateInfo createFromParcel(Parcel source) {
+            final int numberOfSupportedStates = source.readInt();
+            final int[] supportedStates = new int[numberOfSupportedStates];
+            for (int i = 0; i < numberOfSupportedStates; i++) {
+                supportedStates[i] = source.readInt();
+            }
+            final int baseState = source.readInt();
+            final int currentState = source.readInt();
+
+            return new DeviceStateInfo(supportedStates, baseState, currentState);
+        }
+
+        @Override
+        public DeviceStateInfo[] newArray(int size) {
+            return new DeviceStateInfo[size];
+        }
+    };
+}
diff --git a/core/java/android/hardware/devicestate/DeviceStateManager.java b/core/java/android/hardware/devicestate/DeviceStateManager.java
index 2d4b2cc..250145e 100644
--- a/core/java/android/hardware/devicestate/DeviceStateManager.java
+++ b/core/java/android/hardware/devicestate/DeviceStateManager.java
@@ -111,38 +111,63 @@
     }
 
     /**
-     * Registers a listener to receive notifications about changes in device state.
+     * Registers a callback to receive notifications about changes in device state.
      *
      * @param executor the executor to process notifications.
-     * @param listener the listener to register.
+     * @param callback the callback to register.
      *
-     * @see DeviceStateListener
+     * @see DeviceStateCallback
      */
-    public void addDeviceStateListener(@NonNull @CallbackExecutor Executor executor,
-            @NonNull DeviceStateListener listener) {
-        mGlobal.registerDeviceStateListener(listener, executor);
+    public void registerCallback(@NonNull @CallbackExecutor Executor executor,
+            @NonNull DeviceStateCallback callback) {
+        mGlobal.registerDeviceStateCallback(callback, executor);
     }
 
     /**
-     * Unregisters a listener previously registered with
-     * {@link #addDeviceStateListener(Executor, DeviceStateListener)}.
+     * Unregisters a callback previously registered with
+     * {@link #registerCallback(Executor, DeviceStateCallback)}.
      */
-    public void removeDeviceStateListener(@NonNull DeviceStateListener listener) {
-        mGlobal.unregisterDeviceStateListener(listener);
+    public void unregisterCallback(@NonNull DeviceStateCallback callback) {
+        mGlobal.unregisterDeviceStateCallback(callback);
     }
 
-    /**
-     * Listens for changes in device states.
-     */
-    public interface DeviceStateListener {
+    /** Callback to receive notifications about changes in device state. */
+    public interface DeviceStateCallback {
+        /**
+         * Called in response to a change in the states supported by the device.
+         * <p>
+         * Guaranteed to be called once on registration of the callback with the initial value and
+         * then on every subsequent change in the supported states.
+         *
+         * @param supportedStates the new supported states.
+         *
+         * @see DeviceStateManager#getSupportedStates()
+         */
+        default void onSupportedStatesChanged(@NonNull int[] supportedStates) {}
+
+        /**
+         * Called in response to a change in the base device state.
+         * <p>
+         * The base state is the state of the device without considering any requests made through
+         * calls to {@link #requestState(DeviceStateRequest, Executor, DeviceStateRequest.Callback)}
+         * from any client process. The base state is guaranteed to match the state provided with a
+         * call to {@link #onStateChanged(int)} when there are no active requests from any process.
+         * <p>
+         * Guaranteed to be called once on registration of the callback with the initial value and
+         * then on every subsequent change in the non-override state.
+         *
+         * @param state the new base device state.
+         */
+        default void onBaseStateChanged(int state) {}
+
         /**
          * Called in response to device state changes.
          * <p>
-         * Guaranteed to be called once on registration of the listener with the
-         * initial value and then on every subsequent change in device state.
+         * Guaranteed to be called once on registration of the callback with the initial value and
+         * then on every subsequent change in device state.
          *
-         * @param deviceState the new device state.
+         * @param state the new device state.
          */
-        void onDeviceStateChanged(int deviceState);
+        void onStateChanged(int state);
     }
 }
diff --git a/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java b/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
index b9ae88e..1b37fb9 100644
--- a/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
+++ b/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
@@ -19,7 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
-import android.hardware.devicestate.DeviceStateManager.DeviceStateListener;
+import android.hardware.devicestate.DeviceStateManager.DeviceStateCallback;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -31,12 +31,14 @@
 import com.android.internal.annotations.VisibleForTesting.Visibility;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.concurrent.Executor;
 
 /**
  * Provides communication with the device state system service on behalf of applications.
  *
  * @see DeviceStateManager
+ *
  * @hide
  */
 @VisibleForTesting(visibility = Visibility.PACKAGE)
@@ -68,13 +70,13 @@
     private DeviceStateManagerCallback mCallback;
 
     @GuardedBy("mLock")
-    private final ArrayList<DeviceStateListenerWrapper> mListeners = new ArrayList<>();
+    private final ArrayList<DeviceStateCallbackWrapper> mCallbacks = new ArrayList<>();
     @GuardedBy("mLock")
     private final ArrayMap<IBinder, DeviceStateRequestWrapper> mRequests = new ArrayMap<>();
 
     @Nullable
     @GuardedBy("mLock")
-    private Integer mLastReceivedState;
+    private DeviceStateInfo mLastReceivedInfo;
 
     @VisibleForTesting
     public DeviceStateManagerGlobal(@NonNull IDeviceStateManager deviceStateManager) {
@@ -87,18 +89,31 @@
      * @see DeviceStateManager#getSupportedStates()
      */
     public int[] getSupportedStates() {
-        try {
-            return mDeviceStateManager.getSupportedDeviceStates();
-        } catch (RemoteException ex) {
-            throw ex.rethrowFromSystemServer();
+        synchronized (mLock) {
+            final DeviceStateInfo currentInfo;
+            if (mLastReceivedInfo != null) {
+                // If we have mLastReceivedInfo a callback is registered for this instance and it
+                // is receiving the most recent info from the server. Use that info here.
+                currentInfo = mLastReceivedInfo;
+            } else {
+                // If mLastReceivedInfo is null there is no registered callback so we manually
+                // fetch the current info.
+                try {
+                    currentInfo = mDeviceStateManager.getDeviceStateInfo();
+                } catch (RemoteException ex) {
+                    throw ex.rethrowFromSystemServer();
+                }
+            }
+
+            return Arrays.copyOf(currentInfo.supportedStates, currentInfo.supportedStates.length);
         }
     }
 
     /**
      * Submits a {@link DeviceStateRequest request} to modify the device state.
      *
-     * @see DeviceStateManager#requestState(DeviceStateRequest,
-     * Executor, DeviceStateRequest.Callback)
+     * @see DeviceStateManager#requestState(DeviceStateRequest, Executor,
+     * DeviceStateRequest.Callback)
      * @see DeviceStateRequest
      */
     public void requestState(@NonNull DeviceStateRequest request,
@@ -157,49 +172,56 @@
     }
 
     /**
-     * Registers a listener to receive notifications about changes in device state.
+     * Registers a callback to receive notifications about changes in device state.
      *
-     * @see DeviceStateManager#addDeviceStateListener(Executor, DeviceStateListener)
+     * @see DeviceStateManager#registerCallback(Executor, DeviceStateCallback)
      */
     @VisibleForTesting(visibility = Visibility.PACKAGE)
-    public void registerDeviceStateListener(@NonNull DeviceStateListener listener,
+    public void registerDeviceStateCallback(@NonNull DeviceStateCallback callback,
             @NonNull Executor executor) {
-        Integer stateToReport;
-        DeviceStateListenerWrapper wrapper;
+        DeviceStateCallbackWrapper wrapper;
+        DeviceStateInfo currentInfo;
         synchronized (mLock) {
-            registerCallbackIfNeededLocked();
-
-            int index = findListenerLocked(listener);
+            int index = findCallbackLocked(callback);
             if (index != -1) {
-                // This listener is already registered.
+                // This callback is already registered.
                 return;
             }
 
-            wrapper = new DeviceStateListenerWrapper(listener, executor);
-            mListeners.add(wrapper);
-            stateToReport = mLastReceivedState;
+            registerCallbackIfNeededLocked();
+            if (mLastReceivedInfo == null) {
+                // Initialize the last received info with the current info if this is the first
+                // callback being registered.
+                try {
+                    mLastReceivedInfo = mDeviceStateManager.getDeviceStateInfo();
+                } catch (RemoteException ex) {
+                    throw ex.rethrowFromSystemServer();
+                }
+            }
+
+            currentInfo = new DeviceStateInfo(mLastReceivedInfo);
+
+            wrapper = new DeviceStateCallbackWrapper(callback, executor);
+            mCallbacks.add(wrapper);
         }
 
-        if (stateToReport != null) {
-            // Notify the listener with the most recent device state from the server. If the state
-            // to report is null this is likely the first listener added and we're still waiting
-            // from the callback from the server.
-            wrapper.notifyDeviceStateChanged(stateToReport);
-        }
+        wrapper.notifySupportedStatesChanged(currentInfo.supportedStates);
+        wrapper.notifyBaseStateChanged(currentInfo.baseState);
+        wrapper.notifyStateChanged(currentInfo.currentState);
     }
 
     /**
-     * Unregisters a listener previously registered with
-     * {@link #registerDeviceStateListener(DeviceStateListener, Executor)}.
+     * Unregisters a callback previously registered with
+     * {@link #registerDeviceStateCallback(DeviceStateCallback, Executor)}}.
      *
-     * @see DeviceStateManager#addDeviceStateListener(Executor, DeviceStateListener)
+     * @see DeviceStateManager#unregisterCallback(DeviceStateCallback)
      */
     @VisibleForTesting(visibility = Visibility.PACKAGE)
-    public void unregisterDeviceStateListener(DeviceStateListener listener) {
+    public void unregisterDeviceStateCallback(@NonNull DeviceStateCallback callback) {
         synchronized (mLock) {
-            int indexToRemove = findListenerLocked(listener);
+            int indexToRemove = findCallbackLocked(callback);
             if (indexToRemove != -1) {
-                mListeners.remove(indexToRemove);
+                mCallbacks.remove(indexToRemove);
             }
         }
     }
@@ -210,14 +232,15 @@
             try {
                 mDeviceStateManager.registerCallback(mCallback);
             } catch (RemoteException ex) {
+                mCallback = null;
                 throw ex.rethrowFromSystemServer();
             }
         }
     }
 
-    private int findListenerLocked(DeviceStateListener listener) {
-        for (int i = 0; i < mListeners.size(); i++) {
-            if (mListeners.get(i).mDeviceStateListener.equals(listener)) {
+    private int findCallbackLocked(DeviceStateCallback callback) {
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            if (mCallbacks.get(i).mDeviceStateCallback.equals(callback)) {
                 return i;
             }
         }
@@ -234,16 +257,34 @@
         return null;
     }
 
-    /** Handles a call from the server that the device state has changed. */
-    private void handleDeviceStateChanged(int newDeviceState) {
-        ArrayList<DeviceStateListenerWrapper> listeners;
+    /** Handles a call from the server that the device state info has changed. */
+    private void handleDeviceStateInfoChanged(@NonNull DeviceStateInfo info) {
+        ArrayList<DeviceStateCallbackWrapper> callbacks;
+        DeviceStateInfo oldInfo;
         synchronized (mLock) {
-            mLastReceivedState = newDeviceState;
-            listeners = new ArrayList<>(mListeners);
+            oldInfo = mLastReceivedInfo;
+            mLastReceivedInfo = info;
+            callbacks = new ArrayList<>(mCallbacks);
         }
 
-        for (int i = 0; i < listeners.size(); i++) {
-            listeners.get(i).notifyDeviceStateChanged(newDeviceState);
+        final int diff = oldInfo == null ? 1 : info.diff(oldInfo);
+        if ((diff & DeviceStateInfo.CHANGED_SUPPORTED_STATES) > 0) {
+            for (int i = 0; i < callbacks.size(); i++) {
+                // Copy the array to prevent callbacks from modifying the internal state.
+                final int[] supportedStates = Arrays.copyOf(info.supportedStates,
+                        info.supportedStates.length);
+                callbacks.get(i).notifySupportedStatesChanged(supportedStates);
+            }
+        }
+        if ((diff & DeviceStateInfo.CHANGED_BASE_STATE) > 0) {
+            for (int i = 0; i < callbacks.size(); i++) {
+                callbacks.get(i).notifyBaseStateChanged(info.baseState);
+            }
+        }
+        if ((diff & DeviceStateInfo.CHANGED_CURRENT_STATE) > 0) {
+            for (int i = 0; i < callbacks.size(); i++) {
+                callbacks.get(i).notifyStateChanged(info.currentState);
+            }
         }
     }
 
@@ -291,8 +332,8 @@
 
     private final class DeviceStateManagerCallback extends IDeviceStateManagerCallback.Stub {
         @Override
-        public void onDeviceStateChanged(int deviceState) {
-            handleDeviceStateChanged(deviceState);
+        public void onDeviceStateInfoChanged(DeviceStateInfo info) {
+            handleDeviceStateInfoChanged(info);
         }
 
         @Override
@@ -311,17 +352,29 @@
         }
     }
 
-    private static final class DeviceStateListenerWrapper {
-        private final DeviceStateListener mDeviceStateListener;
+    private static final class DeviceStateCallbackWrapper {
+        @NonNull
+        private final DeviceStateCallback mDeviceStateCallback;
+        @NonNull
         private final Executor mExecutor;
 
-        DeviceStateListenerWrapper(DeviceStateListener listener, Executor executor) {
-            mDeviceStateListener = listener;
+        DeviceStateCallbackWrapper(@NonNull DeviceStateCallback callback,
+                @NonNull Executor executor) {
+            mDeviceStateCallback = callback;
             mExecutor = executor;
         }
 
-        void notifyDeviceStateChanged(int newDeviceState) {
-            mExecutor.execute(() -> mDeviceStateListener.onDeviceStateChanged(newDeviceState));
+        void notifySupportedStatesChanged(int[] newSupportedStates) {
+            mExecutor.execute(() ->
+                    mDeviceStateCallback.onSupportedStatesChanged(newSupportedStates));
+        }
+
+        void notifyBaseStateChanged(int newBaseState) {
+            mExecutor.execute(() -> mDeviceStateCallback.onBaseStateChanged(newBaseState));
+        }
+
+        void notifyStateChanged(int newDeviceState) {
+            mExecutor.execute(() -> mDeviceStateCallback.onStateChanged(newDeviceState));
         }
     }
 
diff --git a/core/java/android/hardware/devicestate/DeviceStateRequest.java b/core/java/android/hardware/devicestate/DeviceStateRequest.java
index 70f7002..df488d2 100644
--- a/core/java/android/hardware/devicestate/DeviceStateRequest.java
+++ b/core/java/android/hardware/devicestate/DeviceStateRequest.java
@@ -116,7 +116,7 @@
          * requested state.
          * <p>
          * Guaranteed to be called after a call to
-         * {@link DeviceStateManager.DeviceStateListener#onDeviceStateChanged(int)} with a state
+         * {@link DeviceStateManager.DeviceStateCallback#onStateChanged(int)} with a state
          * matching the requested state.
          */
         default void onRequestActivated(@NonNull DeviceStateRequest request) {}
@@ -125,7 +125,7 @@
          * Called to indicate the request has been temporarily suspended.
          * <p>
          * Guaranteed to be called before a call to
-         * {@link DeviceStateManager.DeviceStateListener#onDeviceStateChanged(int)}.
+         * {@link DeviceStateManager.DeviceStateCallback#onStateChanged(int)}.
          */
         default void onRequestSuspended(@NonNull DeviceStateRequest request) {}
 
@@ -135,7 +135,7 @@
          * DeviceStateRequest.Callback)}.
          * <p>
          * Guaranteed to be called before a call to
-         * {@link DeviceStateManager.DeviceStateListener#onDeviceStateChanged(int)}.
+         * {@link DeviceStateManager.DeviceStateCallback#onStateChanged(int)}.
          * <p>
          * Note: A call to {@link #onRequestSuspended(DeviceStateRequest)} is not guaranteed to
          * occur before this method.
diff --git a/core/java/android/hardware/devicestate/IDeviceStateManager.aidl b/core/java/android/hardware/devicestate/IDeviceStateManager.aidl
index 323ad21..14ed03d 100644
--- a/core/java/android/hardware/devicestate/IDeviceStateManager.aidl
+++ b/core/java/android/hardware/devicestate/IDeviceStateManager.aidl
@@ -16,25 +16,26 @@
 
 package android.hardware.devicestate;
 
+import android.hardware.devicestate.DeviceStateInfo;
 import android.hardware.devicestate.IDeviceStateManagerCallback;
 
 /** @hide */
 interface IDeviceStateManager {
+    /** Returns the current device state info. */
+    DeviceStateInfo getDeviceStateInfo();
+
     /**
      * Registers a callback to receive notifications from the device state manager. Only one
      * callback can be registered per-process.
      * <p>
      * As the callback mechanism is used to alert the caller of changes to request status a callback
      * <b>MUST</b> be registered before calling {@link #requestState(IBinder, int, int)} or
-     * {@link #cancelRequest(IBinder)}. Otherwise an exception will be thrown.
+     * {@link #cancelRequest(IBinder)}, otherwise an exception will be thrown.
      *
      * @throws SecurityException if a callback is already registered for the calling process.
      */
     void registerCallback(in IDeviceStateManagerCallback callback);
 
-    /** Returns the array of supported device state identifiers. */
-    int[] getSupportedDeviceStates();
-
     /**
      * Requests that the device enter the supplied {@code state}. A callback <b>MUST</b> have been
      * previously registered with {@link #registerCallback(IDeviceStateManagerCallback)} before a
diff --git a/core/java/android/hardware/devicestate/IDeviceStateManagerCallback.aidl b/core/java/android/hardware/devicestate/IDeviceStateManagerCallback.aidl
index ee2a071..593be86 100644
--- a/core/java/android/hardware/devicestate/IDeviceStateManagerCallback.aidl
+++ b/core/java/android/hardware/devicestate/IDeviceStateManagerCallback.aidl
@@ -16,20 +16,23 @@
 
 package android.hardware.devicestate;
 
+import android.hardware.devicestate.DeviceStateInfo;
+
 /** @hide */
 interface IDeviceStateManagerCallback {
     /**
-     * Called in response to a change in device state. Guaranteed to be called once with the initial
-     * value on registration of the callback.
+     * Called in response to a change in {@link DeviceStateInfo}.
      *
-     * @param deviceState the new state of the device.
+     * @param info the new device state info.
+     *
+     * @see DeviceStateInfo
      */
-    oneway void onDeviceStateChanged(int deviceState);
+    oneway void onDeviceStateInfoChanged(in DeviceStateInfo info);
 
     /**
      * Called to notify the callback that a request has become active. Guaranteed to be called
-     * after a subsequent call to {@link #onDeviceStateChanged(int)} if the request becoming active
-     * resulted in a device state change.
+     * after a subsequent call to {@link #onDeviceStateInfoChanged(DeviceStateInfo)} if the request
+     * becoming active resulted in a change of device state info.
      *
      * @param token the request token previously registered with
      *        {@link IDeviceStateManager#requestState(IBinder, int, int)}
@@ -38,8 +41,8 @@
 
     /**
      * Called to notify the callback that a request has become suspended. Guaranteed to be called
-     * before a subsequent call to {@link #onDeviceStateChanged(int)} if the request becoming
-     * suspended resulted in a device state change.
+     * before a subsequent call to {@link #onDeviceStateInfoChanged(DeviceStateInfo)} if the request
+     * becoming suspended resulted in a change of device state info.
      *
      * @param token the request token previously registered with
      *        {@link IDeviceStateManager#requestState(IBinder, int, int)}
@@ -49,8 +52,8 @@
     /**
      * Called to notify the callback that a request has become canceled. No further callbacks will
      * be triggered for this request. Guaranteed to be called before a subsequent call to
-     * {@link #onDeviceStateChanged(int)} if the request becoming canceled resulted in a device
-     * state change.
+     * {@link #onDeviceStateInfoChanged(DeviceStateInfo)} if the request becoming canceled resulted
+     * in a change of device state info.
      *
      * @param token the request token previously registered with
      *        {@link IDeviceStateManager#requestState(IBinder, int, int)}
diff --git a/core/java/android/hardware/display/DeviceProductInfo.java b/core/java/android/hardware/display/DeviceProductInfo.java
index 41126b7..9457d8f1 100644
--- a/core/java/android/hardware/display/DeviceProductInfo.java
+++ b/core/java/android/hardware/display/DeviceProductInfo.java
@@ -16,40 +16,69 @@
 
 package android.hardware.display;
 
+import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import java.util.Arrays;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Objects;
 
 /**
  * Product-specific information about the display or the directly connected device on the
  * display chain. For example, if the display is transitively connected, this field may contain
  * product information about the intermediate device.
- * @hide
  */
 public final class DeviceProductInfo implements Parcelable {
+    /** @hide */
+    @IntDef(prefix = {"CONNECTION_TO_SINK_"}, value = {
+            CONNECTION_TO_SINK_UNKNOWN,
+            CONNECTION_TO_SINK_BUILT_IN,
+            CONNECTION_TO_SINK_DIRECT,
+            CONNECTION_TO_SINK_TRANSITIVE
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ConnectionToSinkType { }
+
+    /** The device connection to the display sink is unknown. */
+    public static final int CONNECTION_TO_SINK_UNKNOWN =
+            IDeviceProductInfoConstants.CONNECTION_TO_SINK_UNKNOWN;
+
+    /** The display sink is built-in to the device */
+    public static final int CONNECTION_TO_SINK_BUILT_IN =
+            IDeviceProductInfoConstants.CONNECTION_TO_SINK_BUILT_IN;
+
+    /** The device is directly connected to the display sink. */
+    public static final int CONNECTION_TO_SINK_DIRECT =
+            IDeviceProductInfoConstants.CONNECTION_TO_SINK_DIRECT;
+
+    /** The device is transitively connected to the display sink. */
+    public static final int CONNECTION_TO_SINK_TRANSITIVE =
+            IDeviceProductInfoConstants.CONNECTION_TO_SINK_TRANSITIVE;
+
     private final String mName;
     private final String mManufacturerPnpId;
     private final String mProductId;
     private final Integer mModelYear;
     private final ManufactureDate mManufactureDate;
-    private final int[] mRelativeAddress;
+    private final @ConnectionToSinkType int mConnectionToSinkType;
 
+    /** @hide */
     public DeviceProductInfo(
             String name,
             String manufacturerPnpId,
             String productId,
             Integer modelYear,
             ManufactureDate manufactureDate,
-            int[] relativeAddress) {
+            int connectionToSinkType) {
         this.mName = name;
         this.mManufacturerPnpId = manufacturerPnpId;
         this.mProductId = productId;
         this.mModelYear = modelYear;
         this.mManufactureDate = manufactureDate;
-        this.mRelativeAddress = relativeAddress;
+        this.mConnectionToSinkType = connectionToSinkType;
     }
 
     private DeviceProductInfo(Parcel in) {
@@ -58,12 +87,13 @@
         mProductId = (String) in.readValue(null);
         mModelYear = (Integer) in.readValue(null);
         mManufactureDate = (ManufactureDate) in.readValue(null);
-        mRelativeAddress = in.createIntArray();
+        mConnectionToSinkType = in.readInt();
     }
 
     /**
      * @return Display name.
      */
+    @Nullable
     public String getName() {
         return mName;
     }
@@ -71,6 +101,7 @@
     /**
      * @return Manufacturer Plug and Play ID.
      */
+    @NonNull
     public String getManufacturerPnpId() {
         return mManufacturerPnpId;
     }
@@ -78,32 +109,58 @@
     /**
      * @return Manufacturer product ID.
      */
+    @NonNull
     public String getProductId() {
         return mProductId;
     }
 
     /**
-     * @return Model year of the device. Typically exactly one of model year or
-     *      manufacture date will be present.
+     * @return Model year of the device. Return -1 if not available. Typically,
+     * one of model year or manufacture year is available.
      */
-    public Integer getModelYear() {
-        return mModelYear;
+    public int getModelYear()  {
+        return mModelYear != null ? mModelYear : -1;
+    }
+
+    /**
+     * @return The year of manufacture, or -1 it is not available. Typically,
+     * one of model year or manufacture year is available.
+     */
+    public int getManufactureYear()  {
+        if (mManufactureDate == null) {
+            return -1;
+        }
+        return mManufactureDate.mYear != null ? mManufactureDate.mYear : -1;
+    }
+
+    /**
+     * @return The week of manufacture, or -1 it is not available. Typically,
+     * not present if model year is available.
+     */
+    public int getManufactureWeek() {
+        if (mManufactureDate == null) {
+            return -1;
+        }
+        return mManufactureDate.mWeek != null ?  mManufactureDate.mWeek : -1;
     }
 
     /**
      * @return Manufacture date. Typically exactly one of model year or manufacture
      * date will be present.
+     *
+     * @hide
      */
     public ManufactureDate getManufactureDate() {
         return mManufactureDate;
     }
 
     /**
-     * @return Relative address in the display network. For example, for HDMI connected devices this
-     * can be its physical address. Each component of the address is in the range [0, 255].
+     * @return How the current device is connected to the display sink. For example, the display
+     * can be connected immediately to the device or there can be a receiver in between.
      */
-    public int[] getRelativeAddress() {
-        return mRelativeAddress;
+    @ConnectionToSinkType
+    public int getConnectionToSinkType() {
+        return mConnectionToSinkType;
     }
 
     @Override
@@ -119,8 +176,8 @@
                 + mModelYear
                 + ", manufactureDate="
                 + mManufactureDate
-                + ", relativeAddress="
-                + Arrays.toString(mRelativeAddress)
+                + ", connectionToSinkType="
+                + mConnectionToSinkType
                 + '}';
     }
 
@@ -134,16 +191,16 @@
                 && Objects.equals(mProductId, that.mProductId)
                 && Objects.equals(mModelYear, that.mModelYear)
                 && Objects.equals(mManufactureDate, that.mManufactureDate)
-                && Arrays.equals(mRelativeAddress, that.mRelativeAddress);
+                && mConnectionToSinkType == that.mConnectionToSinkType;
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(mName, mManufacturerPnpId, mProductId, mModelYear, mManufactureDate,
-            Arrays.hashCode(mRelativeAddress));
+                mConnectionToSinkType);
     }
 
-    public static final Creator<DeviceProductInfo> CREATOR =
+    @NonNull public static final Creator<DeviceProductInfo> CREATOR =
             new Creator<DeviceProductInfo>() {
                 @Override
                 public DeviceProductInfo createFromParcel(Parcel in) {
@@ -162,13 +219,13 @@
     }
 
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeString(mName);
         dest.writeString(mManufacturerPnpId);
         dest.writeValue(mProductId);
         dest.writeValue(mModelYear);
         dest.writeValue(mManufactureDate);
-        dest.writeIntArray(mRelativeAddress);
+        dest.writeInt(mConnectionToSinkType);
     }
 
     /**
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 48b05b7..2d58520 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -67,12 +67,6 @@
     public abstract boolean isProximitySensorAvailable();
 
     /**
-     * Returns the id of the {@link com.android.server.display.DisplayGroup} to which the provided
-     * display belongs.
-     */
-    public abstract int getDisplayGroupId(int displayId);
-
-    /**
      * Registers a display group listener which will be informed of the addition, removal, or change
      * of display groups.
      *
@@ -469,7 +463,7 @@
         void onStateChanged();
         void onProximityPositive();
         void onProximityNegative();
-        void onDisplayStateChange(int state); // one of the Display state constants
+        void onDisplayStateChange(boolean allInactive, boolean allOff);
 
         void acquireSuspendBlocker();
         void releaseSuspendBlocker();
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index a9bcdeff..0256b7b 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -831,6 +831,9 @@
             case BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED:
                 return context.getString(
                         com.android.internal.R.string.face_error_security_update_required);
+            case BIOMETRIC_ERROR_RE_ENROLL:
+                return context.getString(
+                        com.android.internal.R.string.face_recalibrate_notification_content);
             case FACE_ERROR_VENDOR: {
                 String[] msgArray = context.getResources().getStringArray(
                         com.android.internal.R.array.face_error_vendor);
@@ -1389,7 +1392,7 @@
             case FACE_ACQUIRED_PAN_TOO_EXTREME:
             case FACE_ACQUIRED_TILT_TOO_EXTREME:
             case FACE_ACQUIRED_ROLL_TOO_EXTREME:
-                return context.getString(R.string.face_acquired_not_detected);
+                return context.getString(R.string.face_acquired_poor_gaze);
 
             // Provide more detailed feedback for other soft errors.
             case FACE_ACQUIRED_INSUFFICIENT:
@@ -1445,13 +1448,17 @@
             case FACE_ACQUIRED_TOO_FAR:
                 return context.getString(R.string.face_acquired_too_far);
             case FACE_ACQUIRED_TOO_HIGH:
-                return context.getString(R.string.face_acquired_too_high);
-            case FACE_ACQUIRED_TOO_LOW:
+                // TODO(b/181269243): Change back once error codes are fixed.
                 return context.getString(R.string.face_acquired_too_low);
+            case FACE_ACQUIRED_TOO_LOW:
+                // TODO(b/181269243) Change back once error codes are fixed.
+                return context.getString(R.string.face_acquired_too_high);
             case FACE_ACQUIRED_TOO_RIGHT:
-                return context.getString(R.string.face_acquired_too_right);
-            case FACE_ACQUIRED_TOO_LEFT:
+                // TODO(b/181269243) Change back once error codes are fixed.
                 return context.getString(R.string.face_acquired_too_left);
+            case FACE_ACQUIRED_TOO_LEFT:
+                // TODO(b/181269243) Change back once error codes are fixed.
+                return context.getString(R.string.face_acquired_too_right);
             case FACE_ACQUIRED_POOR_GAZE:
                 return context.getString(R.string.face_acquired_poor_gaze);
             case FACE_ACQUIRED_NOT_DETECTED:
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 9d086cf..fc795d8 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -114,6 +114,21 @@
      */
     public static final int SENSOR_ID_ANY = -1;
 
+    private static class RemoveTracker {
+        static final int REMOVE_SINGLE = 1;
+        static final int REMOVE_ALL = 2;
+        @IntDef({REMOVE_SINGLE, REMOVE_ALL})
+        @interface RemoveRequest {}
+
+        final @RemoveRequest int mRemoveRequest;
+        @Nullable final Fingerprint mSingleFingerprint;
+
+        RemoveTracker(@RemoveRequest int request, @Nullable Fingerprint fingerprint) {
+            mRemoveRequest = request;
+            mSingleFingerprint = fingerprint;
+        }
+    }
+
     private IFingerprintService mService;
     private Context mContext;
     private IBinder mToken = new Binder();
@@ -123,10 +138,9 @@
     private RemovalCallback mRemovalCallback;
     private GenerateChallengeCallback mGenerateChallengeCallback;
     private CryptoObject mCryptoObject;
-    private Fingerprint mRemovalFingerprint;
+    @Nullable private RemoveTracker mRemoveTracker;
     private Handler mHandler;
 
-
     /**
      * Retrieves a list of properties for all fingerprint sensors on the device.
      * @hide
@@ -736,7 +750,7 @@
     public void remove(Fingerprint fp, int userId, RemovalCallback callback) {
         if (mService != null) try {
             mRemovalCallback = callback;
-            mRemovalFingerprint = fp;
+            mRemoveTracker = new RemoveTracker(RemoveTracker.REMOVE_SINGLE, fp);
             mService.remove(mToken, fp.getBiometricId(), userId, mServiceReceiver,
                     mContext.getOpPackageName());
         } catch (RemoteException e) {
@@ -753,6 +767,7 @@
         if (mService != null) {
             try {
                 mRemovalCallback = callback;
+                mRemoveTracker = new RemoveTracker(RemoveTracker.REMOVE_ALL, null /* fp */);
                 mService.removeAll(mToken, userId, mServiceReceiver, mContext.getOpPackageName());
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
@@ -1056,16 +1071,29 @@
         if (mRemovalCallback == null) {
             return;
         }
-        if (fingerprint == null) {
-            Slog.e(TAG, "Received MSG_REMOVED, but fingerprint is null");
+
+        if (mRemoveTracker == null) {
+            Slog.w(TAG, "Removal tracker is null");
             return;
         }
 
-        int fingerId = fingerprint.getBiometricId();
-        int reqFingerId = mRemovalFingerprint.getBiometricId();
-        if (reqFingerId != 0 && fingerId != 0 && fingerId != reqFingerId) {
-            Slog.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
-            return;
+        if (mRemoveTracker.mRemoveRequest == RemoveTracker.REMOVE_SINGLE) {
+            if (fingerprint == null) {
+                Slog.e(TAG, "Received MSG_REMOVED, but fingerprint is null");
+                return;
+            }
+
+            if (mRemoveTracker.mSingleFingerprint == null) {
+                Slog.e(TAG, "Missing fingerprint");
+                return;
+            }
+
+            final int fingerId = fingerprint.getBiometricId();
+            int reqFingerId = mRemoveTracker.mSingleFingerprint.getBiometricId();
+            if (reqFingerId != 0 && fingerId != 0 && fingerId != reqFingerId) {
+                Slog.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
+                return;
+            }
         }
 
         mRemovalCallback.onRemovalSucceeded(fingerprint, remaining);
@@ -1122,7 +1150,9 @@
             mAuthenticationCallback.onAuthenticationError(clientErrMsgId,
                     getErrorString(mContext, errMsgId, vendorCode));
         } else if (mRemovalCallback != null) {
-            mRemovalCallback.onRemovalError(mRemovalFingerprint, clientErrMsgId,
+            final Fingerprint fp = mRemoveTracker != null
+                    ? mRemoveTracker.mSingleFingerprint : null;
+            mRemovalCallback.onRemovalError(fp, clientErrMsgId,
                     getErrorString(mContext, errMsgId, vendorCode));
         }
     }
diff --git a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java
index 663a704..51addc9 100644
--- a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java
+++ b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java
@@ -85,8 +85,8 @@
             boolean resetLockoutRequiresHardwareAuthToken) {
         // TODO(b/179175438): Value should be provided from the HAL
         this(sensorId, strength, maxEnrollmentsPerUser, sensorType,
-                resetLockoutRequiresHardwareAuthToken, 0 /* sensorLocationX */,
-                0 /* sensorLocationY */, 0 /* sensorRadius */);
+                resetLockoutRequiresHardwareAuthToken, 540 /* sensorLocationX */,
+                1636 /* sensorLocationY */, 130 /* sensorRadius */);
     }
 
     /**
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index eaa38f3..4743fee 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -25,6 +25,8 @@
 import android.os.CombinedVibrationEffect;
 import android.hardware.input.IInputSensorEventListener;
 import android.hardware.input.InputSensorInfo;
+import android.hardware.lights.Light;
+import android.hardware.lights.LightState;
 import android.os.IBinder;
 import android.os.IVibratorStateListener;
 import android.os.VibrationEffect;
@@ -127,4 +129,14 @@
     void disableSensor(int deviceId, int sensorType);
 
     boolean flushSensor(int deviceId, int sensorType);
+
+    List<Light> getLights(int deviceId);
+
+    LightState getLightState(int deviceId, int lightId);
+
+    void setLightStates(int deviceId, in int[] lightIds, in LightState[] states, in IBinder token);
+
+    void openLightSession(int deviceId, String opPkg, in IBinder token);
+
+    void closeLightSession(int deviceId, in IBinder token);
 }
diff --git a/core/java/android/hardware/input/InputDeviceLightsManager.java b/core/java/android/hardware/input/InputDeviceLightsManager.java
new file mode 100644
index 0000000..a3b91a9
--- /dev/null
+++ b/core/java/android/hardware/input/InputDeviceLightsManager.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input;
+
+import android.annotation.NonNull;
+import android.app.ActivityThread;
+import android.hardware.lights.Light;
+import android.hardware.lights.LightState;
+import android.hardware.lights.LightsManager;
+import android.hardware.lights.LightsRequest;
+import android.util.CloseGuard;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.ref.Reference;
+import java.util.List;
+
+/**
+ * LightsManager manages an input device's lights {@link android.hardware.input.Light}.
+ */
+class InputDeviceLightsManager extends LightsManager {
+    private static final String TAG = "InputDeviceLightsManager";
+    private static final boolean DEBUG = false;
+
+    private final InputManager mInputManager;
+
+    // The input device ID.
+    private final int mDeviceId;
+    // Package name
+    private final String mPackageName;
+
+    InputDeviceLightsManager(InputManager inputManager, int deviceId) {
+        super(ActivityThread.currentActivityThread().getSystemContext());
+        mInputManager = inputManager;
+        mDeviceId = deviceId;
+        mPackageName = ActivityThread.currentPackageName();
+    }
+
+    /**
+     * Returns the lights available on the device.
+     *
+     * @return A list of available lights
+     */
+    @Override
+    public @NonNull List<Light> getLights() {
+        return mInputManager.getLights(mDeviceId);
+    }
+
+    /**
+     * Returns the state of a specified light.
+     *
+     * @hide
+     */
+    @Override
+    public @NonNull LightState getLightState(@NonNull Light light) {
+        Preconditions.checkNotNull(light);
+        return mInputManager.getLightState(mDeviceId, light);
+    }
+
+    /**
+     * Creates a new LightsSession that can be used to control the device lights.
+     */
+    @Override
+    public @NonNull LightsSession openSession() {
+        final LightsSession session = new InputDeviceLightsSession();
+        mInputManager.openLightSession(mDeviceId, mPackageName, session.getToken());
+        return session;
+    }
+
+    /**
+     * Encapsulates a session that can be used to control device lights and represents the lifetime
+     * of the requests.
+     */
+    public final class InputDeviceLightsSession extends LightsManager.LightsSession
+            implements AutoCloseable {
+
+        private final CloseGuard mCloseGuard = new CloseGuard();
+        private boolean mClosed = false;
+
+        /**
+         * Instantiated by {@link LightsManager#openSession()}.
+         */
+        private InputDeviceLightsSession() {
+            mCloseGuard.open("close");
+        }
+
+        /**
+         * Sends a request to modify the states of multiple lights.
+         *
+         * @param request the settings for lights that should change
+         */
+        @Override
+        public void requestLights(@NonNull LightsRequest request) {
+            Preconditions.checkNotNull(request);
+            Preconditions.checkArgument(!mClosed);
+
+            mInputManager.requestLights(mDeviceId, request, getToken());
+        }
+
+        /**
+         * Closes the session, reverting all changes made through it.
+         */
+        @Override
+        public void close() {
+            if (!mClosed) {
+                mInputManager.closeLightSession(mDeviceId, getToken());
+                mClosed = true;
+                mCloseGuard.close();
+            }
+            Reference.reachabilityFence(this);
+        }
+
+        /** @hide */
+        @Override
+        protected void finalize() throws Throwable {
+            try {
+                mCloseGuard.warnIfOpen();
+                close();
+            } finally {
+                super.finalize();
+            }
+        }
+    }
+
+}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 8a01c66..e15d629 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -30,6 +30,10 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.hardware.SensorManager;
+import android.hardware.lights.Light;
+import android.hardware.lights.LightState;
+import android.hardware.lights.LightsManager;
+import android.hardware.lights.LightsRequest;
 import android.os.BlockUntrustedTouchesMode;
 import android.os.Build;
 import android.os.CombinedVibrationEffect;
@@ -1409,7 +1413,7 @@
     }
 
     /**
-     * Gets a vibrator service associated with an input device, always create a new instance.
+     * Gets a vibrator service associated with an input device, always creates a new instance.
      * @return The vibrator, never null.
      * @hide
      */
@@ -1418,7 +1422,7 @@
     }
 
     /**
-     * Gets a vibrator manager service associated with an input device, always create a new
+     * Gets a vibrator manager service associated with an input device, always creates a new
      * instance.
      * @return The vibrator manager, never null.
      * @hide
@@ -1486,10 +1490,8 @@
 
     /**
      * Register input device vibrator state listener
-     *
-     * @hide
      */
-    public boolean registerVibratorStateListener(int deviceId, IVibratorStateListener listener) {
+    boolean registerVibratorStateListener(int deviceId, IVibratorStateListener listener) {
         try {
             return mIm.registerVibratorStateListener(deviceId, listener);
         } catch (RemoteException ex) {
@@ -1499,10 +1501,8 @@
 
     /**
      * Unregister input device vibrator state listener
-     *
-     * @hide
      */
-    public boolean unregisterVibratorStateListener(int deviceId, IVibratorStateListener listener) {
+    boolean unregisterVibratorStateListener(int deviceId, IVibratorStateListener listener) {
         try {
             return mIm.unregisterVibratorStateListener(deviceId, listener);
         } catch (RemoteException ex) {
@@ -1511,7 +1511,7 @@
     }
 
     /**
-     * Gets a sensor manager service associated with an input device, always create a new instance.
+     * Gets a sensor manager service associated with an input device, always creates a new instance.
      * @return The sensor manager, never null.
      * @hide
      */
@@ -1533,6 +1533,86 @@
     }
 
     /**
+     * Gets a lights manager associated with an input device, always creates a new instance.
+     * @return The lights manager, never null.
+     * @hide
+     */
+    @NonNull
+    public LightsManager getInputDeviceLightsManager(int deviceId) {
+        return new InputDeviceLightsManager(InputManager.this, deviceId);
+    }
+
+    /**
+     * Gets a list of light objects associated with an input device.
+     * @return The list of lights, never null.
+     */
+    @NonNull List<Light> getLights(int deviceId) {
+        try {
+            return mIm.getLights(deviceId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns the state of an input device light.
+     * @return the light state
+     */
+    @NonNull LightState getLightState(int deviceId, @NonNull Light light) {
+        try {
+            return mIm.getLightState(deviceId, light.getId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Request to modify the states of multiple lights.
+     *
+     * @param request the settings for lights that should change
+     */
+    void requestLights(int deviceId, @NonNull LightsRequest request, IBinder token) {
+        try {
+            List<Integer> lightIdList = request.getLights();
+            int[] lightIds = new int[lightIdList.size()];
+            for (int i = 0; i < lightIds.length; i++) {
+                lightIds[i] = lightIdList.get(i);
+            }
+            List<LightState> lightStateList = request.getLightStates();
+            mIm.setLightStates(deviceId, lightIds,
+                    lightStateList.toArray(new LightState[lightStateList.size()]),
+                    token);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Open light session for input device manager
+     *
+     * @param token The token for the light session
+     */
+    void openLightSession(int deviceId, String opPkg, @NonNull IBinder token) {
+        try {
+            mIm.openLightSession(deviceId, opPkg, token);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Close light session
+     *
+     */
+    void closeLightSession(int deviceId, @NonNull IBinder token) {
+        try {
+            mIm.closeLightSession(deviceId, token);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Listens for changes in input devices.
      */
     public interface InputDeviceListener {
diff --git a/core/java/android/hardware/input/OWNERS b/core/java/android/hardware/input/OWNERS
index 25e02e1..c390b33 100644
--- a/core/java/android/hardware/input/OWNERS
+++ b/core/java/android/hardware/input/OWNERS
@@ -1,6 +1,3 @@
 # Bug component: 136048
 
 include /services/core/java/com/android/server/input/OWNERS
-
-michaelwr@google.com
-svv@google.com
diff --git a/core/java/android/hardware/lights/Light.java b/core/java/android/hardware/lights/Light.java
index da27018..7bfff5d 100644
--- a/core/java/android/hardware/lights/Light.java
+++ b/core/java/android/hardware/lights/Light.java
@@ -16,22 +16,56 @@
 
 package android.hardware.lights;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Represents a logical light on the device.
  *
- * @hide
  */
-@SystemApi
 public final class Light implements Parcelable {
+    // These enum values copy the values from {@link com.android.server.lights.LightsManager}
+    // and the light HAL. Since 0-7 are lights reserved for system use, 8 for microphone light is
+    // defined in {@link android.hardware.lights.LightsManager}, following types are available
+    // through this API.
+    /** Type for lights that indicate microphone usage */
+    public static final int LIGHT_TYPE_MICROPHONE = 8;
+
+    /**
+     * Type for lights that indicate a monochrome color LED light.
+     */
+    public static final int LIGHT_TYPE_INPUT_SINGLE = 9;
+
+    /**
+     * Type for lights that indicate a group of LED lights representing player ID.
+     */
+    public static final int LIGHT_TYPE_INPUT_PLAYER_ID = 10;
+
+    /**
+     * Type for lights that indicate a color LED light.
+     */
+    public static final int LIGHT_TYPE_INPUT_RGB = 11;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"LIGHT_TYPE_"},
+        value = {
+            LIGHT_TYPE_INPUT_PLAYER_ID,
+            LIGHT_TYPE_INPUT_SINGLE,
+            LIGHT_TYPE_INPUT_RGB,
+        })
+    public @interface LightType {}
+
     private final int mId;
     private final int mOrdinal;
     private final int mType;
+    private final String mName;
 
     /**
      * Creates a new light with the given data.
@@ -39,15 +73,26 @@
      * @hide
      */
     public Light(int id, int ordinal, int type) {
+        this(id, ordinal, type, "Light");
+    }
+
+    /**
+     * Creates a new light with the given data.
+     *
+     * @hide
+     */
+    public Light(int id, int ordinal, int type, String name) {
         mId = id;
         mOrdinal = ordinal;
         mType = type;
+        mName = name;
     }
 
     private Light(@NonNull Parcel in) {
         mId = in.readInt();
         mOrdinal = in.readInt();
         mType = in.readInt();
+        mName = in.readString();
     }
 
     /** Implement the Parcelable interface */
@@ -56,6 +101,7 @@
         dest.writeInt(mId);
         dest.writeInt(mOrdinal);
         dest.writeInt(mType);
+        dest.writeString(mName);
     }
 
     /** Implement the Parcelable interface */
@@ -100,6 +146,14 @@
     }
 
     /**
+     * Returns the name of the light.
+     */
+    @NonNull
+    public String getName() {
+        return mName;
+    }
+
+    /**
      * Returns the ordinal of the light.
      *
      * <p>This is a sort key that represents the physical order of lights on the device with the
diff --git a/core/java/android/hardware/lights/LightState.java b/core/java/android/hardware/lights/LightState.java
index cd39e6d..650b383 100644
--- a/core/java/android/hardware/lights/LightState.java
+++ b/core/java/android/hardware/lights/LightState.java
@@ -32,36 +32,93 @@
  * will be converted to only a brightness value and that will be used for the light's single
  * channel.
  *
- * @hide
  */
-@SystemApi
 public final class LightState implements Parcelable {
     private final int mColor;
+    private final int mPlayerId;
 
     /**
-     * Creates a new LightState with the desired color and intensity.
+     * Creates a new LightState with the desired color and intensity, for a light type
+     * of RBG color or monochrome color.
      *
      * @param color the desired color and intensity in ARGB format.
+     * @deprecated this has been replaced with {@link android.hardware.lights.LightState#forColor }
+     * @hide
      */
+    @Deprecated
+    @SystemApi
     public LightState(@ColorInt int color) {
-        mColor = color;
-    }
-
-    private LightState(@NonNull Parcel in) {
-        mColor = in.readInt();
+        this(color, 0);
     }
 
     /**
-     * Return the color and intensity associated with this LightState.
-     * @return the color and intensity in ARGB format. The A channel is ignored.
+     * Creates a new LightState with the desired color and intensity, and the player Id.
+     * Player Id will only be applied on Light type
+     * {@link android.hardware.lights.Light#LIGHT_TYPE_INPUT_PLAYER_ID}
+     *
+     * @param color the desired color and intensity in ARGB format.
+     * @hide
+     */
+    public LightState(@ColorInt int color, int playerId) {
+        mColor = color;
+        mPlayerId = playerId;
+    }
+
+    /**
+     * Creates a new LightState with the desired color and intensity, for a light type
+     * of RBG color or single monochrome color.
+     *
+     * @param color the desired color and intensity in ARGB format.
+     * @return The LightState object contains the color.
+     */
+    @NonNull
+    public static LightState forColor(@ColorInt int color) {
+        return new LightState(color, 0);
+    }
+
+    /**
+     * Creates a new LightState with the desired player id, for a light of type
+     * {@link android.hardware.lights.Light#LIGHT_TYPE_INPUT_PLAYER_ID}.
+     *
+     * @param playerId the desired player id.
+     * @return The LightState object contains the player id.
+     */
+    @NonNull
+    public static LightState forPlayerId(int playerId) {
+        return new LightState(0, playerId);
+    }
+
+    /**
+     * Creates a new LightState from a parcel object.
+     */
+    private LightState(@NonNull Parcel in) {
+        mColor = in.readInt();
+        mPlayerId = in.readInt();
+    }
+
+    /**
+     * Returns the color and intensity associated with this LightState.
+     * @return the color and intensity in ARGB format. The A channel is ignored. return 0 when
+     * calling LightsManager.getLightState with LIGHT_TYPE_INPUT_PLAYER_ID.
      */
     public @ColorInt int getColor() {
         return mColor;
     }
 
+    /**
+     * Returns the player ID associated with this LightState for Light type
+     * {@link android.hardware.lights.Light#LIGHT_TYPE_INPUT_PLAYER_ID},
+     * or 0 for other types.
+     * @return the player ID.
+     */
+    public int getPlayerId() {
+        return mPlayerId;
+    }
+
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeInt(mColor);
+        dest.writeInt(mPlayerId);
     }
 
     @Override
@@ -69,6 +126,12 @@
         return 0;
     }
 
+    @Override
+    public String toString() {
+        return "LightState{Color=0x" + Integer.toHexString(mColor) + ", PlayerId="
+                + mPlayerId + "}";
+    }
+
     public static final @NonNull Parcelable.Creator<LightState> CREATOR =
             new Parcelable.Creator<LightState>() {
                 public LightState createFromParcel(Parcel in) {
diff --git a/core/java/android/hardware/lights/LightsManager.java b/core/java/android/hardware/lights/LightsManager.java
index 33e5fca..8fd56db 100644
--- a/core/java/android/hardware/lights/LightsManager.java
+++ b/core/java/android/hardware/lights/LightsManager.java
@@ -16,43 +16,38 @@
 
 package android.hardware.lights;
 
-import android.Manifest;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
-import android.annotation.TestApi;
 import android.content.Context;
 import android.os.Binder;
 import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.ServiceManager.ServiceNotFoundException;
-import android.util.CloseGuard;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.lang.ref.Reference;
 import java.util.List;
 
 /**
  * The LightsManager class allows control over device lights.
  *
- * @hide
  */
-@SystemApi
 @SystemService(Context.LIGHTS_SERVICE)
-public final class LightsManager {
+public abstract class LightsManager {
     private static final String TAG = "LightsManager";
 
+    @NonNull private final Context mContext;
     // These enum values copy the values from {@link com.android.server.lights.LightsManager}
     // and the light HAL. Since 0-7 are lights reserved for system use, only the microphone light
-    // is available through this API.
-    /** Type for lights that indicate microphone usage */
+    // and following types are available through this API.
+    /** Type for lights that indicate microphone usage
+     * @deprecated this has been moved to {@link android.hardware.lights.Light }
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
     public static final int LIGHT_TYPE_MICROPHONE = 8;
 
     /** @hide */
@@ -63,28 +58,11 @@
         })
     public @interface LightType {}
 
-    @NonNull private final Context mContext;
-    @NonNull private final ILightsManager mService;
-
     /**
-     * Creates a LightsManager.
-     *
-     * @hide
+     * @hide to prevent subclassing from outside of the framework
      */
-    public LightsManager(@NonNull Context context) throws ServiceNotFoundException {
-        this(context, ILightsManager.Stub.asInterface(
-            ServiceManager.getServiceOrThrow(Context.LIGHTS_SERVICE)));
-    }
-
-    /**
-     * Creates a LightsManager with a provided service implementation.
-     *
-     * @hide
-     */
-    @VisibleForTesting
-    public LightsManager(@NonNull Context context, @NonNull ILightsManager service) {
+    public LightsManager(Context context) {
         mContext = Preconditions.checkNotNull(context);
-        mService = Preconditions.checkNotNull(service);
     }
 
     /**
@@ -92,112 +70,44 @@
      *
      * @return A list of available lights
      */
-    @RequiresPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS)
-    public @NonNull List<Light> getLights() {
-        try {
-            return mService.getLights();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
+    public @NonNull abstract List<Light> getLights();
 
     /**
      * Returns the state of a specified light.
      *
-     * @hide
      */
-    @RequiresPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS)
-    @TestApi
-    public @NonNull LightState getLightState(@NonNull Light light) {
-        Preconditions.checkNotNull(light);
-        try {
-            return mService.getLightState(light.getId());
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
+    public abstract @NonNull LightState getLightState(@NonNull Light light);
 
     /**
      * Creates a new LightsSession that can be used to control the device lights.
      */
-    @RequiresPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS)
-    public @NonNull LightsSession openSession() {
-        try {
-            final LightsSession session = new LightsSession();
-            mService.openSession(session.mToken);
-            return session;
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
+    public abstract @NonNull LightsSession openSession();
 
     /**
      * Encapsulates a session that can be used to control device lights and represents the lifetime
      * of the requests.
      */
-    public final class LightsSession implements AutoCloseable {
-
+    public abstract static class LightsSession implements AutoCloseable {
         private final IBinder mToken = new Binder();
-
-        private final CloseGuard mCloseGuard = new CloseGuard();
-        private boolean mClosed = false;
-
-        /**
-         * Instantiated by {@link LightsManager#openSession()}.
-         */
-        @RequiresPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS)
-        private LightsSession() {
-            mCloseGuard.open("close");
-        }
-
         /**
          * Sends a request to modify the states of multiple lights.
          *
-         * <p>This method only controls lights that aren't overridden by higher-priority sessions.
-         * Additionally, lights not controlled by this session can be controlled by lower-priority
-         * sessions.
-         *
          * @param request the settings for lights that should change
          */
-        @RequiresPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS)
-        public void requestLights(@NonNull LightsRequest request) {
-            Preconditions.checkNotNull(request);
-            if (!mClosed) {
-                try {
-                    mService.setLightStates(mToken, request.mLightIds, request.mLightStates);
-                } catch (RemoteException e) {
-                    throw e.rethrowFromSystemServer();
-                }
-            }
-        }
+        public abstract void requestLights(@NonNull LightsRequest request);
+
+        @Override
+        public abstract void close();
 
         /**
-         * Closes the session, reverting all changes made through it.
+         * Get the token of a light session.
+         *
+         * @return Binder token of the light session.
+         * @hide
          */
-        @RequiresPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS)
-        @Override
-        public void close() {
-            if (!mClosed) {
-                try {
-                    mService.closeSession(mToken);
-                    mClosed = true;
-                    mCloseGuard.close();
-                } catch (RemoteException e) {
-                    throw e.rethrowFromSystemServer();
-                }
-            }
-            Reference.reachabilityFence(this);
-        }
-
-        /** @hide */
-        @Override
-        protected void finalize() throws Throwable {
-            try {
-                mCloseGuard.warnIfOpen();
-                close();
-            } finally {
-                super.finalize();
-            }
+        public @NonNull IBinder getToken() {
+            return mToken;
         }
     }
+
 }
diff --git a/core/java/android/hardware/lights/LightsRequest.java b/core/java/android/hardware/lights/LightsRequest.java
index a318992..2626a46 100644
--- a/core/java/android/hardware/lights/LightsRequest.java
+++ b/core/java/android/hardware/lights/LightsRequest.java
@@ -17,17 +17,17 @@
 package android.hardware.lights;
 
 import android.annotation.NonNull;
-import android.annotation.SystemApi;
 import android.util.SparseArray;
 
 import com.android.internal.util.Preconditions;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 /**
  * Encapsulates a request to modify the state of multiple lights.
  *
- * @hide
  */
-@SystemApi
 public final class LightsRequest {
 
     /** Visible to {@link LightsManager.Session}. */
@@ -50,6 +50,30 @@
     }
 
     /**
+     * Get a list of Light as ids.  The ids will returned in same order as the lights passed
+     * in Builder.
+     *
+     * @return List of light ids
+     */
+    public @NonNull List<Integer> getLights() {
+        List<Integer> lightList = new ArrayList<Integer>(mLightIds.length);
+        for (int i = 0; i < mLightIds.length; i++) {
+            lightList.add(mLightIds[i]);
+        }
+        return lightList;
+    }
+
+    /**
+     * Get a list of LightState.  The states will be returned in same order as the light states
+     * passed in Builder.
+     *
+     * @return List of light states
+     */
+    public @NonNull List<LightState> getLightStates() {
+        return Arrays.asList(mLightStates);
+    }
+
+    /**
      * Builder for creating device light change requests.
      */
     public static final class Builder {
@@ -62,7 +86,7 @@
          * @param light the light to modify
          * @param state the desired color and intensity of the light
          */
-        public @NonNull Builder setLight(@NonNull Light light, @NonNull LightState state) {
+        public @NonNull Builder addLight(@NonNull Light light, @NonNull LightState state) {
             Preconditions.checkNotNull(light);
             Preconditions.checkNotNull(state);
             mChanges.put(light.getId(), state);
diff --git a/core/java/android/hardware/lights/SystemLightsManager.java b/core/java/android/hardware/lights/SystemLightsManager.java
new file mode 100644
index 0000000..726a613
--- /dev/null
+++ b/core/java/android/hardware/lights/SystemLightsManager.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.lights;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.content.Context;
+import android.hardware.lights.LightsManager.LightsSession;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
+import android.util.CloseGuard;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
+
+import java.lang.ref.Reference;
+import java.util.List;
+
+/**
+ * The LightsManager class allows control over device lights.
+ *
+ * @hide
+ */
+public final class SystemLightsManager extends LightsManager {
+    private static final String TAG = "LightsManager";
+
+    @NonNull private final ILightsManager mService;
+
+    /**
+     * Creates a SystemLightsManager.
+     *
+     * @hide
+     */
+    public SystemLightsManager(@NonNull Context context) throws ServiceNotFoundException {
+        this(context, ILightsManager.Stub.asInterface(
+            ServiceManager.getServiceOrThrow(Context.LIGHTS_SERVICE)));
+    }
+
+    /**
+     * Creates a SystemLightsManager with a provided service implementation.
+     *
+     * @hide
+     */
+    @VisibleForTesting
+    public SystemLightsManager(@NonNull Context context, @NonNull ILightsManager service) {
+        super(context);
+        mService = Preconditions.checkNotNull(service);
+    }
+
+    /**
+     * Returns the lights available on the device.
+     *
+     * @return A list of available lights
+     */
+    @RequiresPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS)
+    @Override
+    public @NonNull List<Light> getLights() {
+        try {
+            return mService.getLights();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns the state of a specified light.
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS)
+    @Override
+    public @NonNull LightState getLightState(@NonNull Light light) {
+        Preconditions.checkNotNull(light);
+        try {
+            return mService.getLightState(light.getId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Creates a new LightsSession that can be used to control the device lights.
+     */
+    @RequiresPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS)
+    @Override
+    public @NonNull LightsSession openSession() {
+        try {
+            final LightsSession session = new SystemLightsSession();
+            mService.openSession(session.getToken());
+            return session;
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Encapsulates a session that can be used to control device lights and represents the lifetime
+     * of the requests.
+     */
+    public final class SystemLightsSession extends LightsManager.LightsSession
+            implements AutoCloseable {
+
+        private final CloseGuard mCloseGuard = new CloseGuard();
+        private boolean mClosed = false;
+
+        /**
+         * Instantiated by {@link LightsManager#openSession()}.
+         */
+        @RequiresPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS)
+        private SystemLightsSession() {
+            mCloseGuard.open("close");
+        }
+
+        /**
+         * Sends a request to modify the states of multiple lights.
+         *
+         * <p>This method only controls lights that aren't overridden by higher-priority sessions.
+         * Additionally, lights not controlled by this session can be controlled by lower-priority
+         * sessions.
+         *
+         * @param request the settings for lights that should change
+         */
+        @RequiresPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS)
+        @Override
+        public void requestLights(@NonNull LightsRequest request) {
+            Preconditions.checkNotNull(request);
+            if (!mClosed) {
+                try {
+                    mService.setLightStates(getToken(), request.mLightIds, request.mLightStates);
+                } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
+                }
+            }
+        }
+
+        /**
+         * Closes the session, reverting all changes made through it.
+         */
+        @RequiresPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS)
+        @Override
+        public void close() {
+            if (!mClosed) {
+                try {
+                    mService.closeSession(getToken());
+                    mClosed = true;
+                    mCloseGuard.close();
+                } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
+                }
+            }
+            Reference.reachabilityFence(this);
+        }
+
+        /** @hide */
+        @Override
+        protected void finalize() throws Throwable {
+            try {
+                mCloseGuard.warnIfOpen();
+                close();
+            } finally {
+                super.finalize();
+            }
+        }
+    }
+}
diff --git a/core/java/android/hardware/soundtrigger/OWNERS b/core/java/android/hardware/soundtrigger/OWNERS
index 816bc6b..e5d0370 100644
--- a/core/java/android/hardware/soundtrigger/OWNERS
+++ b/core/java/android/hardware/soundtrigger/OWNERS
@@ -1 +1,2 @@
-include /core/java/android/media/soundtrigger/OWNERS
+ytai@google.com
+elaurent@google.com
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index 32b19a4..303a407 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -18,6 +18,7 @@
 
 import static android.net.ConnectivityManager.TYPE_WIFI;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.net.wifi.WifiInfo;
@@ -41,6 +42,22 @@
 
     public static final int SUBTYPE_COMBINED = -1;
 
+    /**
+     * Network has no {@code NetworkCapabilities#NET_CAPABILITY_OEM_*}.
+     * @hide
+     */
+    public static final int OEM_NONE = 0x0;
+    /**
+     * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PAID}.
+     * @hide
+     */
+    public static final int OEM_PAID = 0x1;
+    /**
+     * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE}.
+     * @hide
+     */
+    public static final int OEM_PRIVATE = 0x2;
+
     final int mType;
     final int mSubType;
     final String mSubscriberId;
@@ -48,10 +65,11 @@
     final boolean mRoaming;
     final boolean mMetered;
     final boolean mDefaultNetwork;
+    final int mOemManaged;
 
     public NetworkIdentity(
             int type, int subType, String subscriberId, String networkId, boolean roaming,
-            boolean metered, boolean defaultNetwork) {
+            boolean metered, boolean defaultNetwork, int oemManaged) {
         mType = type;
         mSubType = subType;
         mSubscriberId = subscriberId;
@@ -59,12 +77,13 @@
         mRoaming = roaming;
         mMetered = metered;
         mDefaultNetwork = defaultNetwork;
+        mOemManaged = oemManaged;
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming, mMetered,
-                mDefaultNetwork);
+                mDefaultNetwork, mOemManaged);
     }
 
     @Override
@@ -75,7 +94,8 @@
                     && Objects.equals(mSubscriberId, ident.mSubscriberId)
                     && Objects.equals(mNetworkId, ident.mNetworkId)
                     && mMetered == ident.mMetered
-                    && mDefaultNetwork == ident.mDefaultNetwork;
+                    && mDefaultNetwork == ident.mDefaultNetwork
+                    && mOemManaged == ident.mOemManaged;
         }
         return false;
     }
@@ -102,6 +122,8 @@
         }
         builder.append(", metered=").append(mMetered);
         builder.append(", defaultNetwork=").append(mDefaultNetwork);
+        // TODO(180557699): Print a human readable string for OEM managed state.
+        builder.append(", oemManaged=").append(mOemManaged);
         return builder.append("}").toString();
     }
 
@@ -120,6 +142,7 @@
         proto.write(NetworkIdentityProto.ROAMING, mRoaming);
         proto.write(NetworkIdentityProto.METERED, mMetered);
         proto.write(NetworkIdentityProto.DEFAULT_NETWORK, mDefaultNetwork);
+        proto.write(NetworkIdentityProto.OEM_MANAGED_NETWORK, mOemManaged);
 
         proto.end(start);
     }
@@ -152,6 +175,10 @@
         return mDefaultNetwork;
     }
 
+    public int getOemManaged() {
+        return mOemManaged;
+    }
+
     /**
      * Build a {@link NetworkIdentity} from the given {@link NetworkState} and {@code subType},
      * assuming that any mobile networks are using the current IMSI. The subType if applicable,
@@ -171,6 +198,8 @@
 
         subscriberId = state.subscriberId;
 
+        final int oemManaged = getOemBitfield(state.networkCapabilities);
+
         if (legacyType == TYPE_WIFI) {
             if (state.networkCapabilities.getSsid() != null) {
                 networkId = state.networkCapabilities.getSsid();
@@ -185,7 +214,24 @@
         }
 
         return new NetworkIdentity(legacyType, subType, subscriberId, networkId, roaming, metered,
-                defaultNetwork);
+                defaultNetwork, oemManaged);
+    }
+
+    /**
+     * Builds a bitfield of {@code NetworkIdentity.OEM_*} based on {@link NetworkCapabilities}.
+     * @hide
+     */
+    public static int getOemBitfield(NetworkCapabilities nc) {
+        int oemManaged = OEM_NONE;
+
+        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID)) {
+            oemManaged |= OEM_PAID;
+        }
+        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE)) {
+            oemManaged |= OEM_PRIVATE;
+        }
+
+        return oemManaged;
     }
 
     @Override
@@ -209,6 +255,9 @@
         if (res == 0) {
             res = Boolean.compare(mDefaultNetwork, another.mDefaultNetwork);
         }
+        if (res == 0) {
+            res = Integer.compare(mOemManaged, another.mOemManaged);
+        }
         return res;
     }
 }
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 6353a25..6641206 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -16,14 +16,17 @@
 
 package android.net;
 
+import static android.app.ActivityManager.procStateToString;
 import static android.content.pm.PackageManager.GET_SIGNATURES;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.app.ActivityManager;
+import android.app.ActivityManager.ProcessCapability;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
@@ -617,8 +620,18 @@
      * to access network when the device is idle or in battery saver mode. Otherwise, false.
      * @hide
      */
-    public static boolean isProcStateAllowedWhileIdleOrPowerSaveMode(int procState) {
-        return procState <= FOREGROUND_THRESHOLD_STATE;
+    public static boolean isProcStateAllowedWhileIdleOrPowerSaveMode(@Nullable UidState uidState) {
+        if (uidState == null) {
+            return false;
+        }
+        return isProcStateAllowedWhileIdleOrPowerSaveMode(uidState.procState, uidState.capability);
+    }
+
+    /** @hide */
+    public static boolean isProcStateAllowedWhileIdleOrPowerSaveMode(
+            int procState, @ProcessCapability int capability) {
+        return procState <= FOREGROUND_THRESHOLD_STATE
+                || (capability & ActivityManager.PROCESS_CAPABILITY_NETWORK) != 0;
     }
 
     /**
@@ -626,11 +639,44 @@
      * to access network when the device is in data saver mode. Otherwise, false.
      * @hide
      */
+    public static boolean isProcStateAllowedWhileOnRestrictBackground(@Nullable UidState uidState) {
+        if (uidState == null) {
+            return false;
+        }
+        return isProcStateAllowedWhileOnRestrictBackground(uidState.procState);
+    }
+
+    /** @hide */
     public static boolean isProcStateAllowedWhileOnRestrictBackground(int procState) {
+        // Data saver and bg policy restrictions will only take procstate into account.
         return procState <= FOREGROUND_THRESHOLD_STATE;
     }
 
     /** @hide */
+    public static final class UidState {
+        public int uid;
+        public int procState;
+        public int capability;
+
+        public UidState(int uid, int procState, int capability) {
+            this.uid = uid;
+            this.procState = procState;
+            this.capability = capability;
+        }
+
+        @Override
+        public String toString() {
+            final StringBuilder sb = new StringBuilder();
+            sb.append("{procState=");
+            sb.append(procStateToString(procState));
+            sb.append(",cap=");
+            ActivityManager.printCapabilitiesSummary(sb, capability);
+            sb.append("}");
+            return sb.toString();
+        }
+    }
+
+    /** @hide */
     @TestApi
     @NonNull
     public static String resolveNetworkId(@NonNull WifiConfiguration config) {
diff --git a/core/java/android/net/NetworkStack.java b/core/java/android/net/NetworkStack.java
index 79f9e6e..dbb3127 100644
--- a/core/java/android/net/NetworkStack.java
+++ b/core/java/android/net/NetworkStack.java
@@ -15,9 +15,6 @@
  */
 package android.net;
 
-import static android.Manifest.permission.NETWORK_STACK;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
@@ -26,8 +23,7 @@
 import android.os.IBinder;
 import android.os.ServiceManager;
 
-import java.util.ArrayList;
-import java.util.Arrays;
+import com.android.net.module.util.PermissionUtils;
 /**
  * Constants and utilities for client code communicating with the network stack service.
  * @hide
@@ -79,9 +75,14 @@
      * @param context {@link android.content.Context} for the process.
      *
      * @hide
+     *
+     * @deprecated Use {@link PermissionUtils#enforceNetworkStackPermission} instead.
+     *
+     * TODO: remove this method and let the users call to PermissionUtils directly.
      */
+    @Deprecated
     public static void checkNetworkStackPermission(final @NonNull Context context) {
-        checkNetworkStackPermissionOr(context);
+        PermissionUtils.enforceNetworkStackPermission(context);
     }
 
     /**
@@ -92,31 +93,14 @@
      * @param otherPermissions The set of permissions that could be the candidate permissions , or
      *                         empty string if none of other permissions needed.
      * @hide
+     *
+     * @deprecated Use {@link PermissionUtils#enforceNetworkStackPermissionOr} instead.
+     *
+     * TODO: remove this method and let the users call to PermissionUtils directly.
      */
+    @Deprecated
     public static void checkNetworkStackPermissionOr(final @NonNull Context context,
             final @NonNull String... otherPermissions) {
-        ArrayList<String> permissions = new ArrayList<String>(Arrays.asList(otherPermissions));
-        permissions.add(NETWORK_STACK);
-        permissions.add(PERMISSION_MAINLINE_NETWORK_STACK);
-        enforceAnyPermissionOf(context, permissions.toArray(new String[0]));
+        PermissionUtils.enforceNetworkStackPermissionOr(context, otherPermissions);
     }
-
-    private static void enforceAnyPermissionOf(final @NonNull Context context,
-            final @NonNull String... permissions) {
-        if (!checkAnyPermissionOf(context, permissions)) {
-            throw new SecurityException("Requires one of the following permissions: "
-                + String.join(", ", permissions) + ".");
-        }
-    }
-
-    private static boolean checkAnyPermissionOf(final @NonNull Context context,
-            final @NonNull String... permissions) {
-        for (String permission : permissions) {
-            if (context.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) {
-                return true;
-            }
-        }
-        return false;
-    }
-
 }
diff --git a/core/java/android/net/NetworkState.java b/core/java/android/net/NetworkState.java
index e466d2e..813fde1 100644
--- a/core/java/android/net/NetworkState.java
+++ b/core/java/android/net/NetworkState.java
@@ -41,7 +41,6 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public final Network network;
     public final String subscriberId;
-    public final String networkId;
     public final int legacyNetworkType;
 
     private NetworkState() {
@@ -50,35 +49,33 @@
         networkCapabilities = null;
         network = null;
         subscriberId = null;
-        networkId = null;
         legacyNetworkType = 0;
     }
 
     public NetworkState(int legacyNetworkType, @NonNull LinkProperties linkProperties,
             @NonNull NetworkCapabilities networkCapabilities, @NonNull Network network,
-            @Nullable String subscriberId, @Nullable String networkId) {
+            @Nullable String subscriberId) {
         this(legacyNetworkType, new NetworkInfo(legacyNetworkType, 0, null, null), linkProperties,
-                networkCapabilities, network, subscriberId, networkId);
+                networkCapabilities, network, subscriberId);
     }
 
     // Constructor that used internally in ConnectivityService mainline module.
     public NetworkState(@NonNull NetworkInfo networkInfo, @NonNull LinkProperties linkProperties,
             @NonNull NetworkCapabilities networkCapabilities, @NonNull Network network,
-            String subscriberId, String networkId) {
+            @Nullable String subscriberId) {
         this(networkInfo.getType(), networkInfo, linkProperties,
-                networkCapabilities, network, subscriberId, networkId);
+                networkCapabilities, network, subscriberId);
     }
 
     public NetworkState(int legacyNetworkType, @NonNull NetworkInfo networkInfo,
             @NonNull LinkProperties linkProperties,
             @NonNull NetworkCapabilities networkCapabilities, @NonNull Network network,
-            String subscriberId, String networkId) {
+            @Nullable String subscriberId) {
         this.networkInfo = networkInfo;
         this.linkProperties = linkProperties;
         this.networkCapabilities = networkCapabilities;
         this.network = network;
         this.subscriberId = subscriberId;
-        this.networkId = networkId;
         this.legacyNetworkType = legacyNetworkType;
 
         // This object is an atomic view of a network, so the various components
@@ -99,7 +96,6 @@
         networkCapabilities = in.readParcelable(null);
         network = in.readParcelable(null);
         subscriberId = in.readString();
-        networkId = in.readString();
         legacyNetworkType = in.readInt();
     }
 
@@ -115,7 +111,6 @@
         out.writeParcelable(networkCapabilities, flags);
         out.writeParcelable(network, flags);
         out.writeString(subscriberId);
-        out.writeString(networkId);
         out.writeInt(legacyNetworkType);
     }
 
diff --git a/core/java/android/service/screenshot/ScreenshotHash.aidl b/core/java/android/net/NetworkStateSnapshot.aidl
similarity index 74%
copy from core/java/android/service/screenshot/ScreenshotHash.aidl
copy to core/java/android/net/NetworkStateSnapshot.aidl
index a7c50db..cb602d79 100644
--- a/core/java/android/service/screenshot/ScreenshotHash.aidl
+++ b/core/java/android/net/NetworkStateSnapshot.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
+/**
+ * Copyright (c) 2021, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.service.screenshot;
+package android.net;
 
-parcelable ScreenshotHash;
+parcelable NetworkStateSnapshot;
diff --git a/core/java/android/net/NetworkStateSnapshot.java b/core/java/android/net/NetworkStateSnapshot.java
new file mode 100644
index 0000000..881b373
--- /dev/null
+++ b/core/java/android/net/NetworkStateSnapshot.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Snapshot of network state.
+ *
+ * @hide
+ */
+public final class NetworkStateSnapshot implements Parcelable {
+    @NonNull
+    public final LinkProperties linkProperties;
+    @NonNull
+    public final NetworkCapabilities networkCapabilities;
+    @NonNull
+    public final Network network;
+    @Nullable
+    public final String subscriberId;
+    public final int legacyType;
+
+    public NetworkStateSnapshot(@NonNull LinkProperties linkProperties,
+            @NonNull NetworkCapabilities networkCapabilities, @NonNull Network network,
+            @Nullable String subscriberId, int legacyType) {
+        this.linkProperties = Objects.requireNonNull(linkProperties);
+        this.networkCapabilities = Objects.requireNonNull(networkCapabilities);
+        this.network = Objects.requireNonNull(network);
+        this.subscriberId = subscriberId;
+        this.legacyType = legacyType;
+    }
+
+    public NetworkStateSnapshot(@NonNull Parcel in) {
+        linkProperties = in.readParcelable(null);
+        networkCapabilities = in.readParcelable(null);
+        network = in.readParcelable(null);
+        subscriberId = in.readString();
+        legacyType = in.readInt();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel out, int flags) {
+        out.writeParcelable(linkProperties, flags);
+        out.writeParcelable(networkCapabilities, flags);
+        out.writeParcelable(network, flags);
+        out.writeString(subscriberId);
+        out.writeInt(legacyType);
+    }
+
+    @NonNull
+    public static final Creator<NetworkStateSnapshot> CREATOR =
+            new Creator<NetworkStateSnapshot>() {
+        @NonNull
+        @Override
+        public NetworkStateSnapshot createFromParcel(@NonNull Parcel in) {
+            return new NetworkStateSnapshot(in);
+        }
+
+        @NonNull
+        @Override
+        public NetworkStateSnapshot[] newArray(int size) {
+            return new NetworkStateSnapshot[size];
+        }
+    };
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof NetworkStateSnapshot)) return false;
+        NetworkStateSnapshot that = (NetworkStateSnapshot) o;
+        return legacyType == that.legacyType
+                && Objects.equals(linkProperties, that.linkProperties)
+                && Objects.equals(networkCapabilities, that.networkCapabilities)
+                && Objects.equals(network, that.network)
+                && Objects.equals(subscriberId, that.subscriberId);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(linkProperties, networkCapabilities, network, subscriberId, legacyType);
+    }
+}
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index aa61e03..c83dd99 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -23,6 +23,7 @@
 import static android.net.ConnectivityManager.TYPE_WIFI;
 import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
 import static android.net.ConnectivityManager.TYPE_WIMAX;
+import static android.net.NetworkIdentity.OEM_NONE;
 import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
 import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
 import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
@@ -99,6 +100,22 @@
      */
     public static final int NETWORK_TYPE_5G_NSA = -2;
 
+    /**
+     * Value to match both OEM managed and unmanaged networks (all networks).
+     * @hide
+     */
+    public static final int OEM_MANAGED_ALL = -1;
+    /**
+     * Value to match networks which are not OEM managed.
+     * @hide
+     */
+    public static final int OEM_MANAGED_NO = OEM_NONE;
+    /**
+     * Value to match any OEM managed network.
+     * @hide
+     */
+    public static final int OEM_MANAGED_YES = -2;
+
     private static boolean isKnownMatchRule(final int rule) {
         switch (rule) {
             case MATCH_MOBILE:
@@ -151,10 +168,10 @@
             @NetworkType int ratType) {
         if (TextUtils.isEmpty(subscriberId)) {
             return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null,
-                    METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType);
+                    METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL);
         }
         return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null,
-                METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType);
+                METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL);
     }
 
     /**
@@ -235,6 +252,9 @@
     private final int mDefaultNetwork;
     private final int mSubType;
 
+    // Bitfield containing OEM network properties{@code NetworkIdentity#OEM_*}.
+    private final int mOemManaged;
+
     @UnsupportedAppUsage
     public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
         this(matchRule, subscriberId, new String[] { subscriberId }, networkId);
@@ -243,11 +263,12 @@
     public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
             String networkId) {
         this(matchRule, subscriberId, matchSubscriberIds, networkId, METERED_ALL, ROAMING_ALL,
-                DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL);
+                DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL);
     }
 
     public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
-            String networkId, int metered, int roaming, int defaultNetwork, int subType) {
+            String networkId, int metered, int roaming, int defaultNetwork, int subType,
+            int oemManaged) {
         mMatchRule = matchRule;
         mSubscriberId = subscriberId;
         mMatchSubscriberIds = matchSubscriberIds;
@@ -256,6 +277,7 @@
         mRoaming = roaming;
         mDefaultNetwork = defaultNetwork;
         mSubType = subType;
+        mOemManaged = oemManaged;
 
         if (!isKnownMatchRule(matchRule)) {
             Log.e(TAG, "Unknown network template rule " + matchRule
@@ -272,6 +294,7 @@
         mRoaming = in.readInt();
         mDefaultNetwork = in.readInt();
         mSubType = in.readInt();
+        mOemManaged = in.readInt();
     }
 
     @Override
@@ -284,6 +307,7 @@
         dest.writeInt(mRoaming);
         dest.writeInt(mDefaultNetwork);
         dest.writeInt(mSubType);
+        dest.writeInt(mOemManaged);
     }
 
     @Override
@@ -319,13 +343,16 @@
         if (mSubType != NETWORK_TYPE_ALL) {
             builder.append(", subType=").append(mSubType);
         }
+        if (mOemManaged != OEM_MANAGED_ALL) {
+            builder.append(", oemManaged=").append(mOemManaged);
+        }
         return builder.toString();
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(mMatchRule, mSubscriberId, mNetworkId, mMetered, mRoaming,
-                mDefaultNetwork, mSubType);
+                mDefaultNetwork, mSubType, mOemManaged);
     }
 
     @Override
@@ -338,7 +365,8 @@
                     && mMetered == other.mMetered
                     && mRoaming == other.mRoaming
                     && mDefaultNetwork == other.mDefaultNetwork
-                    && mSubType == other.mSubType;
+                    && mSubType == other.mSubType
+                    && mOemManaged == other.mOemManaged;
         }
         return false;
     }
@@ -384,6 +412,7 @@
         if (!matchesMetered(ident)) return false;
         if (!matchesRoaming(ident)) return false;
         if (!matchesDefaultNetwork(ident)) return false;
+        if (!matchesOemNetwork(ident)) return false;
 
         switch (mMatchRule) {
             case MATCH_MOBILE:
@@ -425,6 +454,13 @@
             || (mDefaultNetwork == DEFAULT_NETWORK_NO && !ident.mDefaultNetwork);
     }
 
+    private boolean matchesOemNetwork(NetworkIdentity ident) {
+        return (mOemManaged == OEM_MANAGED_ALL)
+            || (mOemManaged == OEM_MANAGED_YES
+                    && ident.mOemManaged != OEM_NONE)
+            || (mOemManaged == ident.mOemManaged);
+    }
+
     private boolean matchesCollapsedRatType(NetworkIdentity ident) {
         return mSubType == NETWORK_TYPE_ALL
                 || getCollapsedRatType(mSubType) == getCollapsedRatType(ident.mSubType);
diff --git a/core/java/android/net/NetworkWatchlistManager.java b/core/java/android/net/NetworkWatchlistManager.java
index 49047d3..8f6510e 100644
--- a/core/java/android/net/NetworkWatchlistManager.java
+++ b/core/java/android/net/NetworkWatchlistManager.java
@@ -16,6 +16,8 @@
 
 package android.net;
 
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.content.Context;
 import android.os.RemoteException;
@@ -29,6 +31,7 @@
  * Class that manage network watchlist in system.
  * @hide
  */
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
 @SystemService(Context.NETWORK_WATCHLIST_SERVICE)
 public class NetworkWatchlistManager {
 
@@ -90,6 +93,7 @@
     /**
      * Get Network Watchlist config file hash.
      */
+    @Nullable
     public byte[] getWatchlistConfigHash() {
         try {
             return mNetworkWatchlistManager.getWatchlistConfigHash();
diff --git a/core/java/android/net/UidRange.java b/core/java/android/net/UidRange.java
index b172ccc..f0e7da7 100644
--- a/core/java/android/net/UidRange.java
+++ b/core/java/android/net/UidRange.java
@@ -42,10 +42,6 @@
         stop  = stopUid;
     }
 
-    public static UidRange createForUser(int userId) {
-        return new UidRange(userId * PER_USER_RANGE, (userId + 1) * PER_USER_RANGE - 1);
-    }
-
     /** Creates a UidRange for the specified user. */
     public static UidRange createForUser(UserHandle user) {
         final UserHandle nextUser = UserHandle.of(user.getIdentifier() + 1);
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index e43b0b6..f90fbaf 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -596,7 +596,8 @@
                     }
                 }
             }
-            mRoutes.add(new RouteInfo(new IpPrefix(address, prefixLength), null));
+            mRoutes.add(new RouteInfo(new IpPrefix(address, prefixLength), null, null,
+                RouteInfo.RTN_UNICAST));
             mConfig.updateAllowedFamilies(address);
             return this;
         }
diff --git a/core/java/android/net/vcn/IVcnStatusCallback.aidl b/core/java/android/net/vcn/IVcnStatusCallback.aidl
index a7386718..d91cef5 100644
--- a/core/java/android/net/vcn/IVcnStatusCallback.aidl
+++ b/core/java/android/net/vcn/IVcnStatusCallback.aidl
@@ -17,6 +17,12 @@
 package android.net.vcn;
 
 /** @hide */
-interface IVcnStatusCallback {
+oneway interface IVcnStatusCallback {
     void onEnteredSafeMode();
+    void onVcnStatusChanged(int statusCode);
+    void onGatewayConnectionError(
+            in int[] gatewayNetworkCapabilities,
+            int errorCode,
+            in String exceptionClass,
+            in String exceptionMessage);
 }
\ No newline at end of file
diff --git a/core/java/android/net/vcn/VcnControlPlaneConfig.java b/core/java/android/net/vcn/VcnControlPlaneConfig.java
index 0c6ccfe..92f6c44 100644
--- a/core/java/android/net/vcn/VcnControlPlaneConfig.java
+++ b/core/java/android/net/vcn/VcnControlPlaneConfig.java
@@ -35,8 +35,6 @@
  *
  * @see VcnManager
  * @see VcnGatewayConnectionConfig
- *
- * @hide
  */
 public abstract class VcnControlPlaneConfig {
     /** @hide */
diff --git a/core/java/android/net/vcn/VcnControlPlaneIkeConfig.java b/core/java/android/net/vcn/VcnControlPlaneIkeConfig.java
index 2f6e1f6..de086f6 100644
--- a/core/java/android/net/vcn/VcnControlPlaneIkeConfig.java
+++ b/core/java/android/net/vcn/VcnControlPlaneIkeConfig.java
@@ -34,8 +34,6 @@
  * configuration, authentication and authorization parameters.
  *
  * @see VcnControlPlaneConfig
- *
- * @hide
  */
 public final class VcnControlPlaneIkeConfig extends VcnControlPlaneConfig {
     private static final String TAG = VcnControlPlaneIkeConfig.class.getSimpleName();
diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
index 94dff91..9f83b21 100644
--- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
+++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
@@ -420,7 +420,6 @@
          *
          * @param ctrlPlaneConfig the control plane configuration
          * @see VcnControlPlaneConfig
-         * @hide
          */
         public Builder(@NonNull VcnControlPlaneConfig ctrlPlaneConfig) {
             Objects.requireNonNull(ctrlPlaneConfig, "ctrlPlaneConfig was null");
@@ -428,13 +427,6 @@
             mCtrlPlaneConfig = ctrlPlaneConfig;
         }
 
-        /** Construct a Builder object. */
-        // TODO: Remove this constructor when #Builder(ctrlPlaneConfig) is exposed as public API.
-        // This constructor is created to avoid changing API shape in this CL
-        public Builder() {
-            mCtrlPlaneConfig = null;
-        }
-
         /**
          * Add a capability that this VCN Gateway Connection will support.
          *
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
index aed64de..eb8c251 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -17,8 +17,11 @@
 
 import static java.util.Objects.requireNonNull;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.content.Context;
 import android.net.LinkProperties;
@@ -32,6 +35,8 @@
 import com.android.internal.annotations.VisibleForTesting.Visibility;
 
 import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Collections;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
@@ -68,8 +73,7 @@
 public class VcnManager {
     @NonNull private static final String TAG = VcnManager.class.getSimpleName();
 
-    private static final Map<
-                    VcnUnderlyingNetworkPolicyListener, VcnUnderlyingNetworkPolicyListenerBinder>
+    private static final Map<VcnNetworkPolicyListener, VcnUnderlyingNetworkPolicyListenerBinder>
             REGISTERED_POLICY_LISTENERS = new ConcurrentHashMap<>();
 
     @NonNull private final Context mContext;
@@ -89,13 +93,13 @@
     }
 
     /**
-     * Get all currently registered VcnUnderlyingNetworkPolicyListeners for testing purposes.
+     * Get all currently registered VcnNetworkPolicyListeners for testing purposes.
      *
      * @hide
      */
     @VisibleForTesting(visibility = Visibility.PRIVATE)
     @NonNull
-    public static Map<VcnUnderlyingNetworkPolicyListener, VcnUnderlyingNetworkPolicyListenerBinder>
+    public static Map<VcnNetworkPolicyListener, VcnUnderlyingNetworkPolicyListenerBinder>
             getAllPolicyListeners() {
         return Collections.unmodifiableMap(REGISTERED_POLICY_LISTENERS);
     }
@@ -157,22 +161,15 @@
         }
     }
 
-    // TODO: make VcnUnderlyingNetworkPolicyListener @SystemApi
+    // TODO(b/180537630): remove all VcnUnderlyingNetworkPolicyListener refs once Telephony is using
+    // the new VcnNetworkPolicyListener API
     /**
      * VcnUnderlyingNetworkPolicyListener is the interface through which internal system components
      * can register to receive updates for VCN-underlying Network policies from the System Server.
      *
      * @hide
      */
-    public interface VcnUnderlyingNetworkPolicyListener {
-        /**
-         * Notifies the implementation that the VCN's underlying Network policy has changed.
-         *
-         * <p>After receiving this callback, implementations MUST poll VcnManager for the updated
-         * VcnUnderlyingNetworkPolicy via VcnManager#getUnderlyingNetworkPolicy.
-         */
-        void onPolicyChanged();
-    }
+    public interface VcnUnderlyingNetworkPolicyListener extends VcnNetworkPolicyListener {}
 
     /**
      * Add a listener for VCN-underlying network policy updates.
@@ -181,29 +178,14 @@
      *     Listener
      * @param listener the VcnUnderlyingNetworkPolicyListener to be added
      * @throws SecurityException if the caller does not have permission NETWORK_FACTORY
-     * @throws IllegalArgumentException if the specified VcnUnderlyingNetworkPolicyListener is
-     *     already registered
+     * @throws IllegalStateException if the specified VcnUnderlyingNetworkPolicyListener is already
+     *     registered
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
     public void addVcnUnderlyingNetworkPolicyListener(
             @NonNull Executor executor, @NonNull VcnUnderlyingNetworkPolicyListener listener) {
-        requireNonNull(executor, "executor must not be null");
-        requireNonNull(listener, "listener must not be null");
-
-        VcnUnderlyingNetworkPolicyListenerBinder binder =
-                new VcnUnderlyingNetworkPolicyListenerBinder(executor, listener);
-        if (REGISTERED_POLICY_LISTENERS.putIfAbsent(listener, binder) != null) {
-            throw new IllegalArgumentException(
-                    "Attempting to add a listener that is already in use");
-        }
-
-        try {
-            mService.addVcnUnderlyingNetworkPolicyListener(binder);
-        } catch (RemoteException e) {
-            REGISTERED_POLICY_LISTENERS.remove(listener);
-            throw e.rethrowFromSystemServer();
-        }
+        addVcnNetworkPolicyListener(executor, listener);
     }
 
     /**
@@ -216,19 +198,7 @@
      */
     public void removeVcnUnderlyingNetworkPolicyListener(
             @NonNull VcnUnderlyingNetworkPolicyListener listener) {
-        requireNonNull(listener, "listener must not be null");
-
-        VcnUnderlyingNetworkPolicyListenerBinder binder =
-                REGISTERED_POLICY_LISTENERS.remove(listener);
-        if (binder == null) {
-            return;
-        }
-
-        try {
-            mService.removeVcnUnderlyingNetworkPolicyListener(binder);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        removeVcnNetworkPolicyListener(listener);
     }
 
     /**
@@ -262,6 +232,206 @@
         }
     }
 
+    /**
+     * VcnNetworkPolicyListener is the interface through which internal system components (e.g.
+     * Network Factories) can register to receive updates for VCN-underlying Network policies from
+     * the System Server.
+     *
+     * <p>Any Network Factory that brings up Networks capable of being VCN-underlying Networks
+     * should register a VcnNetworkPolicyListener. VcnManager will then use this listener to notify
+     * the registrant when VCN Network policies change. Upon receiving this signal, the listener
+     * must check {@link VcnManager} for the current Network policy result for each of its Networks
+     * via {@link #applyVcnNetworkPolicy(NetworkCapabilities, LinkProperties)}.
+     *
+     * @hide
+     */
+    @SystemApi
+    public interface VcnNetworkPolicyListener {
+        /**
+         * Notifies the implementation that the VCN's underlying Network policy has changed.
+         *
+         * <p>After receiving this callback, implementations should get the current {@link
+         * VcnNetworkPolicyResult} via {@link #applyVcnNetworkPolicy(NetworkCapabilities,
+         * LinkProperties)}.
+         */
+        void onPolicyChanged();
+    }
+
+    /**
+     * Add a listener for VCN-underlying Network policy updates.
+     *
+     * <p>A {@link VcnNetworkPolicyListener} is eligible to begin receiving callbacks once it is
+     * registered. No callbacks are guaranteed upon registration.
+     *
+     * @param executor the Executor that will be used for invoking all calls to the specified
+     *     Listener
+     * @param listener the VcnNetworkPolicyListener to be added
+     * @throws SecurityException if the caller does not have permission NETWORK_FACTORY
+     * @throws IllegalStateException if the specified VcnNetworkPolicyListener is already registered
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+    public void addVcnNetworkPolicyListener(
+            @NonNull Executor executor, @NonNull VcnNetworkPolicyListener listener) {
+        requireNonNull(executor, "executor must not be null");
+        requireNonNull(listener, "listener must not be null");
+
+        VcnUnderlyingNetworkPolicyListenerBinder binder =
+                new VcnUnderlyingNetworkPolicyListenerBinder(executor, listener);
+        if (REGISTERED_POLICY_LISTENERS.putIfAbsent(listener, binder) != null) {
+            throw new IllegalStateException("listener is already registered with VcnManager");
+        }
+
+        try {
+            mService.addVcnUnderlyingNetworkPolicyListener(binder);
+        } catch (RemoteException e) {
+            REGISTERED_POLICY_LISTENERS.remove(listener);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Remove the specified VcnNetworkPolicyListener from VcnManager.
+     *
+     * <p>If the specified listener is not currently registered, this is a no-op.
+     *
+     * @param listener the VcnNetworkPolicyListener that will be removed
+     * @hide
+     */
+    @SystemApi
+    public void removeVcnNetworkPolicyListener(@NonNull VcnNetworkPolicyListener listener) {
+        requireNonNull(listener, "listener must not be null");
+
+        VcnUnderlyingNetworkPolicyListenerBinder binder =
+                REGISTERED_POLICY_LISTENERS.remove(listener);
+        if (binder == null) {
+            return;
+        }
+
+        try {
+            mService.removeVcnUnderlyingNetworkPolicyListener(binder);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Applies the network policy for a {@link android.net.Network} with the given parameters.
+     *
+     * <p>Prior to a new NetworkAgent being registered, or upon notification that Carrier VCN policy
+     * may have changed via {@link VcnNetworkPolicyListener#onPolicyChanged()}, a Network Provider
+     * MUST poll for the updated Network policy based on that Network's capabilities and properties.
+     *
+     * @param networkCapabilities the NetworkCapabilities to be used in determining the Network
+     *     policy result for this Network.
+     * @param linkProperties the LinkProperties to be used in determining the Network policy result
+     *     for this Network.
+     * @throws SecurityException if the caller does not have permission NETWORK_FACTORY
+     * @return the {@link VcnNetworkPolicyResult} to be used for this Network.
+     * @hide
+     */
+    @NonNull
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+    public VcnNetworkPolicyResult applyVcnNetworkPolicy(
+            @NonNull NetworkCapabilities networkCapabilities,
+            @NonNull LinkProperties linkProperties) {
+        requireNonNull(networkCapabilities, "networkCapabilities must not be null");
+        requireNonNull(linkProperties, "linkProperties must not be null");
+
+        final VcnUnderlyingNetworkPolicy policy =
+                getUnderlyingNetworkPolicy(networkCapabilities, linkProperties);
+        return new VcnNetworkPolicyResult(
+                policy.isTeardownRequested(), policy.getMergedNetworkCapabilities());
+    }
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+        VCN_STATUS_CODE_NOT_CONFIGURED,
+        VCN_STATUS_CODE_INACTIVE,
+        VCN_STATUS_CODE_ACTIVE,
+        VCN_STATUS_CODE_SAFE_MODE
+    })
+    public @interface VcnStatusCode {}
+
+    /**
+     * Value indicating that the VCN for the subscription group is not configured, or that the
+     * callback is not privileged for the subscription group.
+     *
+     * @hide
+     */
+    public static final int VCN_STATUS_CODE_NOT_CONFIGURED = 0;
+
+    /**
+     * Value indicating that the VCN for the subscription group is inactive.
+     *
+     * <p>A VCN is inactive if a {@link VcnConfig} is present for the subscription group, but the
+     * provisioning package is not privileged.
+     *
+     * @hide
+     */
+    public static final int VCN_STATUS_CODE_INACTIVE = 1;
+
+    /**
+     * Value indicating that the VCN for the subscription group is active.
+     *
+     * <p>A VCN is active if a {@link VcnConfig} is present for the subscription, the provisioning
+     * package is privileged, and the VCN is not in Safe Mode. In other words, a VCN is considered
+     * active while it is connecting, fully connected, and disconnecting.
+     *
+     * @hide
+     */
+    public static final int VCN_STATUS_CODE_ACTIVE = 2;
+
+    /**
+     * Value indicating that the VCN for the subscription group is in Safe Mode.
+     *
+     * <p>A VCN will be put into Safe Mode if any of the gateway connections were unable to
+     * establish a connection within a system-determined timeout (while underlying networks were
+     * available).
+     *
+     * @hide
+     */
+    public static final int VCN_STATUS_CODE_SAFE_MODE = 3;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+        VCN_ERROR_CODE_INTERNAL_ERROR,
+        VCN_ERROR_CODE_CONFIG_ERROR,
+        VCN_ERROR_CODE_NETWORK_ERROR
+    })
+    public @interface VcnErrorCode {}
+
+    /**
+     * Value indicating that an internal failure occurred in this Gateway Connection.
+     *
+     * @hide
+     */
+    public static final int VCN_ERROR_CODE_INTERNAL_ERROR = 0;
+
+    /**
+     * Value indicating that an error with this Gateway Connection's configuration occurred.
+     *
+     * <p>For example, this error code will be returned after authentication failures.
+     *
+     * @hide
+     */
+    public static final int VCN_ERROR_CODE_CONFIG_ERROR = 1;
+
+    /**
+     * Value indicating that a Network error occurred with this Gateway Connection.
+     *
+     * <p>For example, this error code will be returned if an underlying {@link android.net.Network}
+     * for this Gateway Connection is lost, or if an error occurs while resolving the connection
+     * endpoint address.
+     *
+     * @hide
+     */
+    public static final int VCN_ERROR_CODE_NETWORK_ERROR = 2;
+
     // TODO: make VcnStatusCallback @SystemApi
     /**
      * VcnStatusCallback is the interface for Carrier apps to receive updates for their VCNs.
@@ -283,8 +453,36 @@
          *
          * <p>A VCN-configuring app may opt to exit safe mode by (re)setting the VCN configuration
          * via {@link #setVcnConfig(ParcelUuid, VcnConfig)}.
+         *
+         * @hide
          */
-        public abstract void onEnteredSafeMode();
+        public void onEnteredSafeMode() {}
+
+        /**
+         * Invoked when status of the VCN for this callback's subscription group changes.
+         *
+         * @param statusCode the code for the status change encountered by this {@link
+         *     VcnStatusCallback}'s subscription group.
+         */
+        public abstract void onVcnStatusChanged(@VcnStatusCode int statusCode);
+
+        /**
+         * Invoked when a VCN Gateway Connection corresponding to this callback's subscription
+         * encounters an error.
+         *
+         * @param networkCapabilities an array of underlying NetworkCapabilities for the Gateway
+         *     Connection that encountered the error for identification purposes. These will be a
+         *     sorted list with no duplicates, matching one of the {@link
+         *     VcnGatewayConnectionConfig}s set in the {@link VcnConfig} for this subscription
+         *     group.
+         * @param errorCode {@link VcnErrorCode} to indicate the error that occurred
+         * @param detail Throwable to provide additional information about the error, or {@code
+         *     null} if none
+         */
+        public abstract void onGatewayConnectionError(
+                @NonNull int[] networkCapabilities,
+                @VcnErrorCode int errorCode,
+                @Nullable Throwable detail);
     }
 
     /**
@@ -298,6 +496,11 @@
      * <p>A {@link VcnStatusCallback} will only be invoked if the registering package has carrier
      * privileges for the specified subscription at the time of invocation.
      *
+     * <p>{@link VcnStatusCallback#onVcnStatusChanged(int)} will be invoked on registration with the
+     * current status for the specified subscription group's VCN. If the registrant is not
+     * privileged for this subscription group, {@link #VCN_STATUS_CODE_NOT_CONFIGURED} will be
+     * returned.
+     *
      * @param subscriptionGroup The subscription group to match for callbacks
      * @param executor The {@link Executor} to be used for invoking callbacks
      * @param callback The VcnStatusCallback to be registered
@@ -357,18 +560,17 @@
     }
 
     /**
-     * Binder wrapper for added VcnUnderlyingNetworkPolicyListeners to receive signals from System
-     * Server.
+     * Binder wrapper for added VcnNetworkPolicyListeners to receive signals from System Server.
      *
      * @hide
      */
     private static class VcnUnderlyingNetworkPolicyListenerBinder
             extends IVcnUnderlyingNetworkPolicyListener.Stub {
         @NonNull private final Executor mExecutor;
-        @NonNull private final VcnUnderlyingNetworkPolicyListener mListener;
+        @NonNull private final VcnNetworkPolicyListener mListener;
 
         private VcnUnderlyingNetworkPolicyListenerBinder(
-                Executor executor, VcnUnderlyingNetworkPolicyListener listener) {
+                Executor executor, VcnNetworkPolicyListener listener) {
             mExecutor = executor;
             mListener = listener;
         }
@@ -385,11 +587,12 @@
      *
      * @hide
      */
-    private class VcnStatusCallbackBinder extends IVcnStatusCallback.Stub {
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    public static class VcnStatusCallbackBinder extends IVcnStatusCallback.Stub {
         @NonNull private final Executor mExecutor;
         @NonNull private final VcnStatusCallback mCallback;
 
-        private VcnStatusCallbackBinder(
+        public VcnStatusCallbackBinder(
                 @NonNull Executor executor, @NonNull VcnStatusCallback callback) {
             mExecutor = executor;
             mCallback = callback;
@@ -400,5 +603,42 @@
             Binder.withCleanCallingIdentity(
                     () -> mExecutor.execute(() -> mCallback.onEnteredSafeMode()));
         }
+
+        @Override
+        public void onVcnStatusChanged(@VcnStatusCode int statusCode) {
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> mCallback.onVcnStatusChanged(statusCode)));
+        }
+
+        // TODO(b/180521637): use ServiceSpecificException for safer Exception 'parceling'
+        @Override
+        public void onGatewayConnectionError(
+                @NonNull int[] networkCapabilities,
+                @VcnErrorCode int errorCode,
+                @Nullable String exceptionClass,
+                @Nullable String exceptionMessage) {
+            final Throwable cause = createThrowableByClassName(exceptionClass, exceptionMessage);
+
+            Binder.withCleanCallingIdentity(
+                    () ->
+                            mExecutor.execute(
+                                    () ->
+                                            mCallback.onGatewayConnectionError(
+                                                    networkCapabilities, errorCode, cause)));
+        }
+
+        private static Throwable createThrowableByClassName(
+                @Nullable String className, @Nullable String message) {
+            if (className == null) {
+                return null;
+            }
+
+            try {
+                Class<?> c = Class.forName(className);
+                return (Throwable) c.getConstructor(String.class).newInstance(message);
+            } catch (ReflectiveOperationException | ClassCastException e) {
+                return new RuntimeException(className + ": " + message);
+            }
+        }
     }
 }
diff --git a/core/java/android/service/screenshot/ScreenshotHash.aidl b/core/java/android/net/vcn/VcnNetworkPolicyResult.aidl
similarity index 81%
copy from core/java/android/service/screenshot/ScreenshotHash.aidl
copy to core/java/android/net/vcn/VcnNetworkPolicyResult.aidl
index a7c50db..3f13abe 100644
--- a/core/java/android/service/screenshot/ScreenshotHash.aidl
+++ b/core/java/android/net/vcn/VcnNetworkPolicyResult.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
-package android.service.screenshot;
+package android.net.vcn;
 
-parcelable ScreenshotHash;
+/** @hide */
+parcelable VcnNetworkPolicyResult;
diff --git a/core/java/android/net/vcn/VcnNetworkPolicyResult.java b/core/java/android/net/vcn/VcnNetworkPolicyResult.java
new file mode 100644
index 0000000..5e93820
--- /dev/null
+++ b/core/java/android/net/vcn/VcnNetworkPolicyResult.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.vcn;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.net.NetworkCapabilities;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * VcnNetworkPolicyResult represents the Network policy result for a Network transport applying its
+ * VCN policy via {@link VcnManager#applyVcnNetworkPolicy(NetworkCapabilities, LinkProperties)}.
+ *
+ * <p>Bearers that are bringing up networks capable of acting as a VCN's underlying network should
+ * query for Network policy results upon any capability changes (e.g. changing of TRUSTED bit), and
+ * when prompted by VcnManagementService via {@link VcnManager.VcnNetworkPolicyListener}.
+ *
+ * @hide
+ */
+@SystemApi
+public final class VcnNetworkPolicyResult implements Parcelable {
+    private final boolean mIsTearDownRequested;
+    private final NetworkCapabilities mNetworkCapabilities;
+
+    /**
+     * Constructs a VcnNetworkPolicyResult with the specified parameters.
+     *
+     * @hide
+     */
+    public VcnNetworkPolicyResult(
+            boolean isTearDownRequested, @NonNull NetworkCapabilities networkCapabilities) {
+        Objects.requireNonNull(networkCapabilities, "networkCapabilities must be non-null");
+
+        mIsTearDownRequested = isTearDownRequested;
+        mNetworkCapabilities = networkCapabilities;
+    }
+
+    /**
+     * Returns whether this VCN policy result requires that the underlying Network should be torn
+     * down.
+     *
+     * <p>Upon querying for the current Network policy result, the bearer must check this method,
+     * and MUST tear down the corresponding Network if it returns true.
+     */
+    public boolean isTeardownRequested() {
+        return mIsTearDownRequested;
+    }
+
+    /**
+     * Returns the NetworkCapabilities that the bearer should be using for the corresponding
+     * Network.
+     */
+    @NonNull
+    public NetworkCapabilities getNetworkCapabilities() {
+        return mNetworkCapabilities;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mIsTearDownRequested, mNetworkCapabilities);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof VcnNetworkPolicyResult)) return false;
+        final VcnNetworkPolicyResult that = (VcnNetworkPolicyResult) o;
+
+        return mIsTearDownRequested == that.mIsTearDownRequested
+                && mNetworkCapabilities.equals(that.mNetworkCapabilities);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeBoolean(mIsTearDownRequested);
+        dest.writeParcelable(mNetworkCapabilities, flags);
+    }
+
+    /** Implement the Parcelable interface */
+    public static final @NonNull Creator<VcnNetworkPolicyResult> CREATOR =
+            new Creator<VcnNetworkPolicyResult>() {
+                public VcnNetworkPolicyResult createFromParcel(Parcel in) {
+                    return new VcnNetworkPolicyResult(in.readBoolean(), in.readParcelable(null));
+                }
+
+                public VcnNetworkPolicyResult[] newArray(int size) {
+                    return new VcnNetworkPolicyResult[size];
+                }
+            };
+}
diff --git a/core/java/android/net/vcn/VcnUnderlyingNetworkPolicy.java b/core/java/android/net/vcn/VcnUnderlyingNetworkPolicy.java
index dd7c86d8..b47d564 100644
--- a/core/java/android/net/vcn/VcnUnderlyingNetworkPolicy.java
+++ b/core/java/android/net/vcn/VcnUnderlyingNetworkPolicy.java
@@ -33,8 +33,7 @@
  * @hide
  */
 public final class VcnUnderlyingNetworkPolicy implements Parcelable {
-    private final boolean mIsTearDownRequested;
-    private final NetworkCapabilities mMergedNetworkCapabilities;
+    private final VcnNetworkPolicyResult mVcnNetworkPolicyResult;
 
     /**
      * Constructs a VcnUnderlyingNetworkPolicy with the specified parameters.
@@ -46,8 +45,13 @@
         Objects.requireNonNull(
                 mergedNetworkCapabilities, "mergedNetworkCapabilities must be nonnull");
 
-        mIsTearDownRequested = isTearDownRequested;
-        mMergedNetworkCapabilities = mergedNetworkCapabilities;
+        mVcnNetworkPolicyResult =
+                new VcnNetworkPolicyResult(isTearDownRequested, mergedNetworkCapabilities);
+    }
+
+    private VcnUnderlyingNetworkPolicy(@NonNull VcnNetworkPolicyResult vcnNetworkPolicyResult) {
+        this.mVcnNetworkPolicyResult =
+                Objects.requireNonNull(vcnNetworkPolicyResult, "vcnNetworkPolicyResult");
     }
 
     /**
@@ -55,7 +59,7 @@
      * be torn down.
      */
     public boolean isTeardownRequested() {
-        return mIsTearDownRequested;
+        return mVcnNetworkPolicyResult.isTeardownRequested();
     }
 
     /**
@@ -64,12 +68,12 @@
      */
     @NonNull
     public NetworkCapabilities getMergedNetworkCapabilities() {
-        return mMergedNetworkCapabilities;
+        return mVcnNetworkPolicyResult.getNetworkCapabilities();
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mIsTearDownRequested, mMergedNetworkCapabilities);
+        return Objects.hash(mVcnNetworkPolicyResult);
     }
 
     @Override
@@ -78,8 +82,7 @@
         if (!(o instanceof VcnUnderlyingNetworkPolicy)) return false;
         final VcnUnderlyingNetworkPolicy that = (VcnUnderlyingNetworkPolicy) o;
 
-        return mIsTearDownRequested == that.mIsTearDownRequested
-                && mMergedNetworkCapabilities.equals(that.mMergedNetworkCapabilities);
+        return mVcnNetworkPolicyResult.equals(that.mVcnNetworkPolicyResult);
     }
 
     /** {@inheritDoc} */
@@ -91,16 +94,14 @@
     /** {@inheritDoc} */
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeBoolean(mIsTearDownRequested);
-        dest.writeParcelable(mMergedNetworkCapabilities, flags);
+        dest.writeParcelable(mVcnNetworkPolicyResult, flags);
     }
 
     /** Implement the Parcelable interface */
     public static final @NonNull Creator<VcnUnderlyingNetworkPolicy> CREATOR =
             new Creator<VcnUnderlyingNetworkPolicy>() {
                 public VcnUnderlyingNetworkPolicy createFromParcel(Parcel in) {
-                    return new VcnUnderlyingNetworkPolicy(
-                            in.readBoolean(), in.readParcelable(null));
+                    return new VcnUnderlyingNetworkPolicy(in.readParcelable(null));
                 }
 
                 public VcnUnderlyingNetworkPolicy[] newArray(int size) {
diff --git a/core/java/android/net/vcn/VcnUnderlyingNetworkSpecifier.java b/core/java/android/net/vcn/VcnUnderlyingNetworkSpecifier.java
new file mode 100644
index 0000000..a975637
--- /dev/null
+++ b/core/java/android/net/vcn/VcnUnderlyingNetworkSpecifier.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.vcn;
+
+import android.annotation.NonNull;
+import android.net.NetworkSpecifier;
+import android.net.TelephonyNetworkSpecifier;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.annotations.VisibleForTesting.Visibility;
+import com.android.internal.util.ArrayUtils;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * NetworkSpecifier object for VCN underlying network requests.
+ *
+ * <p>This matches any underlying network with the appropriate subIds.
+ *
+ * @hide
+ */
+public final class VcnUnderlyingNetworkSpecifier extends NetworkSpecifier implements Parcelable {
+    @NonNull private final int[] mSubIds;
+
+    /**
+     * Builds a new VcnUnderlyingNetworkSpecifier with the given list of subIds
+     *
+     * @hide
+     */
+    public VcnUnderlyingNetworkSpecifier(@NonNull int[] subIds) {
+        mSubIds = Objects.requireNonNull(subIds, "subIds were null");
+    }
+
+    /**
+     * Retrieves the list of subIds supported by this VcnUnderlyingNetworkSpecifier
+     *
+     * @hide
+     */
+    @NonNull
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    public int[] getSubIds() {
+        return mSubIds;
+    }
+
+    public static final @NonNull Creator<VcnUnderlyingNetworkSpecifier> CREATOR =
+            new Creator<VcnUnderlyingNetworkSpecifier>() {
+                @Override
+                public VcnUnderlyingNetworkSpecifier createFromParcel(Parcel in) {
+                    int[] subIds = in.createIntArray();
+                    return new VcnUnderlyingNetworkSpecifier(subIds);
+                }
+
+                @Override
+                public VcnUnderlyingNetworkSpecifier[] newArray(int size) {
+                    return new VcnUnderlyingNetworkSpecifier[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeIntArray(mSubIds);
+    }
+
+    @Override
+    public int hashCode() {
+        return Arrays.hashCode(mSubIds);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof VcnUnderlyingNetworkSpecifier)) {
+            return false;
+        }
+
+        VcnUnderlyingNetworkSpecifier lhs = (VcnUnderlyingNetworkSpecifier) obj;
+        return Arrays.equals(mSubIds, lhs.mSubIds);
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder()
+                .append("VcnUnderlyingNetworkSpecifier [")
+                .append("mSubIds = ").append(Arrays.toString(mSubIds))
+                .append("]")
+                .toString();
+    }
+
+    /** @hide */
+    @Override
+    public boolean canBeSatisfiedBy(NetworkSpecifier other) {
+        if (other instanceof TelephonyNetworkSpecifier) {
+            return ArrayUtils.contains(
+                    mSubIds, ((TelephonyNetworkSpecifier) other).getSubscriptionId());
+        }
+        // TODO(b/180140053): Allow matching against WifiNetworkAgentSpecifier
+
+        // MatchAllNetworkSpecifier matched in NetworkCapabilities.
+        return equals(other);
+    }
+}
diff --git a/core/java/android/net/vcn/persistablebundleutils/IkeTrafficSelectorUtils.java b/core/java/android/net/vcn/persistablebundleutils/IkeTrafficSelectorUtils.java
new file mode 100644
index 0000000..6bbc6b1
--- /dev/null
+++ b/core/java/android/net/vcn/persistablebundleutils/IkeTrafficSelectorUtils.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.vcn.persistablebundleutils;
+
+import static com.android.internal.annotations.VisibleForTesting.Visibility;
+
+import android.annotation.NonNull;
+import android.net.InetAddresses;
+import android.net.ipsec.ike.IkeTrafficSelector;
+import android.os.PersistableBundle;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.Objects;
+
+/**
+ * Provides utility methods to convert IkeTrafficSelector to/from PersistableBundle.
+ *
+ * @hide
+ */
+@VisibleForTesting(visibility = Visibility.PRIVATE)
+public final class IkeTrafficSelectorUtils {
+    private static final String START_PORT_KEY = "START_PORT_KEY";
+    private static final String END_PORT_KEY = "END_PORT_KEY";
+    private static final String START_ADDRESS_KEY = "START_ADDRESS_KEY";
+    private static final String END_ADDRESS_KEY = "END_ADDRESS_KEY";
+
+    /** Constructs an IkeTrafficSelector by deserializing a PersistableBundle. */
+    @NonNull
+    public static IkeTrafficSelector fromPersistableBundle(@NonNull PersistableBundle in) {
+        Objects.requireNonNull(in, "PersistableBundle was null");
+
+        final int startPort = in.getInt(START_PORT_KEY);
+        final int endPort = in.getInt(END_PORT_KEY);
+
+        final String startingAddress = in.getString(START_ADDRESS_KEY);
+        final String endingAddress = in.getString(END_ADDRESS_KEY);
+        Objects.requireNonNull(startingAddress, "startAddress was null");
+        Objects.requireNonNull(startingAddress, "endAddress was null");
+
+        return new IkeTrafficSelector(
+                startPort,
+                endPort,
+                InetAddresses.parseNumericAddress(startingAddress),
+                InetAddresses.parseNumericAddress(endingAddress));
+    }
+
+    /** Serializes an IkeTrafficSelector to a PersistableBundle. */
+    @NonNull
+    public static PersistableBundle toPersistableBundle(@NonNull IkeTrafficSelector ts) {
+        final PersistableBundle result = new PersistableBundle();
+
+        result.putInt(START_PORT_KEY, ts.startPort);
+        result.putInt(END_PORT_KEY, ts.endPort);
+        result.putString(START_ADDRESS_KEY, ts.startingAddress.getHostAddress());
+        result.putString(END_ADDRESS_KEY, ts.endingAddress.getHostAddress());
+
+        return result;
+    }
+}
diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java
index bf229e0..2b6f336 100644
--- a/core/java/android/os/BatteryConsumer.java
+++ b/core/java/android/os/BatteryConsumer.java
@@ -47,6 +47,7 @@
             POWER_COMPONENT_SYSTEM_SERVICES,
             POWER_COMPONENT_SENSORS,
             POWER_COMPONENT_GNSS,
+            POWER_COMPONENT_WIFI,
             POWER_COMPONENT_WAKELOCK,
             POWER_COMPONENT_SCREEN,
             POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS,
@@ -66,6 +67,7 @@
     public static final int POWER_COMPONENT_MOBILE_RADIO = 8;
     public static final int POWER_COMPONENT_SENSORS = 9;
     public static final int POWER_COMPONENT_GNSS = 10;
+    public static final int POWER_COMPONENT_WIFI = 11;
     public static final int POWER_COMPONENT_WAKELOCK = 12;
     public static final int POWER_COMPONENT_SCREEN = 13;
     // Power that is re-attributed to other battery consumers. For example, for System Server
@@ -94,6 +96,7 @@
             TIME_COMPONENT_MOBILE_RADIO,
             TIME_COMPONENT_SENSORS,
             TIME_COMPONENT_GNSS,
+            TIME_COMPONENT_WIFI,
             TIME_COMPONENT_WAKELOCK,
             TIME_COMPONENT_SCREEN,
     })
@@ -112,6 +115,7 @@
     public static final int TIME_COMPONENT_MOBILE_RADIO = 8;
     public static final int TIME_COMPONENT_SENSORS = 9;
     public static final int TIME_COMPONENT_GNSS = 10;
+    public static final int TIME_COMPONENT_WIFI = 11;
     public static final int TIME_COMPONENT_WAKELOCK = 12;
     public static final int TIME_COMPONENT_SCREEN = 13;
 
@@ -130,7 +134,7 @@
      * Total power consumed by this consumer, in mAh.
      */
     public double getConsumedPower() {
-        return mPowerComponents.getTotalPowerConsumed();
+        return mPowerComponents.getTotalConsumedPower();
     }
 
     /**
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 01a8901..6901df7 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1671,7 +1671,7 @@
         public char batteryVoltage;
 
         // The charge of the battery in micro-Ampere-hours.
-        public int batteryChargeUAh;
+        public int batteryChargeUah;
 
         public double modemRailChargeMah;
         public double wifiRailChargeMah;
@@ -1884,7 +1884,7 @@
             bat = (((int)batteryTemperature)&0xffff)
                     | ((((int)batteryVoltage)<<16)&0xffff0000);
             dest.writeInt(bat);
-            dest.writeInt(batteryChargeUAh);
+            dest.writeInt(batteryChargeUah);
             dest.writeDouble(modemRailChargeMah);
             dest.writeDouble(wifiRailChargeMah);
             dest.writeInt(states);
@@ -1916,7 +1916,7 @@
             int bat2 = src.readInt();
             batteryTemperature = (short)(bat2&0xffff);
             batteryVoltage = (char)((bat2>>16)&0xffff);
-            batteryChargeUAh = src.readInt();
+            batteryChargeUah = src.readInt();
             modemRailChargeMah = src.readDouble();
             wifiRailChargeMah = src.readDouble();
             states = src.readInt();
@@ -1959,7 +1959,7 @@
             batteryPlugType = 0;
             batteryTemperature = 0;
             batteryVoltage = 0;
-            batteryChargeUAh = 0;
+            batteryChargeUah = 0;
             modemRailChargeMah = 0;
             wifiRailChargeMah = 0;
             states = 0;
@@ -1991,7 +1991,7 @@
             batteryPlugType = o.batteryPlugType;
             batteryTemperature = o.batteryTemperature;
             batteryVoltage = o.batteryVoltage;
-            batteryChargeUAh = o.batteryChargeUAh;
+            batteryChargeUah = o.batteryChargeUah;
             modemRailChargeMah = o.modemRailChargeMah;
             wifiRailChargeMah = o.wifiRailChargeMah;
             states = o.states;
@@ -2025,7 +2025,7 @@
                     && batteryPlugType == o.batteryPlugType
                     && batteryTemperature == o.batteryTemperature
                     && batteryVoltage == o.batteryVoltage
-                    && batteryChargeUAh == o.batteryChargeUAh
+                    && batteryChargeUah == o.batteryChargeUah
                     && modemRailChargeMah == o.modemRailChargeMah
                     && wifiRailChargeMah == o.wifiRailChargeMah
                     && states == o.states
@@ -2179,12 +2179,6 @@
 
     public abstract void finishIteratingHistoryLocked();
 
-    public abstract boolean startIteratingOldHistoryLocked();
-
-    public abstract boolean getNextOldHistoryLocked(HistoryItem out);
-
-    public abstract void finishIteratingOldHistoryLocked();
-
     /**
      * Return the base time offset for the battery history.
      */
@@ -2859,6 +2853,11 @@
     public abstract boolean getIsOnBattery();
 
     /**
+     * Returns the timestamp of when battery stats collection started, in microseconds.
+     */
+    public abstract long getStatsStartRealtime();
+
+    /**
      * Returns a SparseArray containing the statistics for each uid.
      */
     @UnsupportedAppUsage
@@ -6520,7 +6519,7 @@
                     item.append(checkin ? ",Bv=" : " volt=");
                     item.append(oldVolt);
                 }
-                final int chargeMAh = rec.batteryChargeUAh / 1000;
+                final int chargeMAh = rec.batteryChargeUah / 1000;
                 if (oldChargeMAh != chargeMAh) {
                     oldChargeMAh = chargeMAh;
                     item.append(checkin ? ",Bcc=" : " charge=");
@@ -7056,24 +7055,6 @@
                     finishIteratingHistoryLocked();
                 }
             }
-
-            if (startIteratingOldHistoryLocked()) {
-                try {
-                    final HistoryItem rec = new HistoryItem();
-                    pw.println("Old battery History:");
-                    HistoryPrinter hprinter = new HistoryPrinter();
-                    long baseTime = -1;
-                    while (getNextOldHistoryLocked(rec)) {
-                        if (baseTime < 0) {
-                            baseTime = rec.time;
-                        }
-                        hprinter.printNextItem(pw, rec, baseTime, false, (flags&DUMP_VERBOSE) != 0);
-                    }
-                    pw.println();
-                } finally {
-                    finishIteratingOldHistoryLocked();
-                }
-            }
         }
 
         if (filtering && (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) {
diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java
index 305815f..de7b885 100644
--- a/core/java/android/os/BatteryUsageStats.java
+++ b/core/java/android/os/BatteryUsageStats.java
@@ -17,9 +17,12 @@
 package android.os;
 
 import android.annotation.NonNull;
-import android.annotation.SuppressLint;
+import android.util.Range;
 import android.util.SparseArray;
 
+import com.android.internal.os.BatteryStatsHistory;
+import com.android.internal.os.BatteryStatsHistoryIterator;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -31,35 +34,63 @@
 public final class BatteryUsageStats implements Parcelable {
     private final double mConsumedPower;
     private final int mDischargePercentage;
+    private final long mStatsStartRealtimeMs;
+    private final double mDischargedPowerLowerBound;
+    private final double mDischargedPowerUpperBound;
     private final ArrayList<UidBatteryConsumer> mUidBatteryConsumers;
     private final ArrayList<SystemBatteryConsumer> mSystemBatteryConsumers;
     private final ArrayList<UserBatteryConsumer> mUserBatteryConsumers;
+    private final Parcel mHistoryBuffer;
+    private final List<BatteryStats.HistoryTag> mHistoryTagPool;
 
     private BatteryUsageStats(@NonNull Builder builder) {
-        mConsumedPower = builder.mConsumedPower;
+        mStatsStartRealtimeMs = builder.mStatsStartRealtimeMs;
         mDischargePercentage = builder.mDischargePercentage;
+        mDischargedPowerLowerBound = builder.mDischargedPowerLowerBoundMah;
+        mDischargedPowerUpperBound = builder.mDischargedPowerUpperBoundMah;
+        mHistoryBuffer = builder.mHistoryBuffer;
+        mHistoryTagPool = builder.mHistoryTagPool;
 
-        int uidBatteryConsumerCount = builder.mUidBatteryConsumerBuilders.size();
+        double totalPower = 0;
+
+        final int uidBatteryConsumerCount = builder.mUidBatteryConsumerBuilders.size();
         mUidBatteryConsumers = new ArrayList<>(uidBatteryConsumerCount);
         for (int i = 0; i < uidBatteryConsumerCount; i++) {
-            UidBatteryConsumer.Builder uidBatteryConsumerBuilder =
+            final UidBatteryConsumer.Builder uidBatteryConsumerBuilder =
                     builder.mUidBatteryConsumerBuilders.valueAt(i);
             if (!uidBatteryConsumerBuilder.isExcludedFromBatteryUsageStats()) {
-                mUidBatteryConsumers.add(uidBatteryConsumerBuilder.build());
+                final UidBatteryConsumer consumer = uidBatteryConsumerBuilder.build();
+                totalPower += consumer.getConsumedPower();
+                mUidBatteryConsumers.add(consumer);
             }
         }
 
-        int systemBatteryConsumerCount = builder.mSystemBatteryConsumerBuilders.size();
+        final int systemBatteryConsumerCount = builder.mSystemBatteryConsumerBuilders.size();
         mSystemBatteryConsumers = new ArrayList<>(systemBatteryConsumerCount);
         for (int i = 0; i < systemBatteryConsumerCount; i++) {
-            mSystemBatteryConsumers.add(builder.mSystemBatteryConsumerBuilders.valueAt(i).build());
+            final SystemBatteryConsumer consumer =
+                    builder.mSystemBatteryConsumerBuilders.valueAt(i).build();
+            totalPower += consumer.getConsumedPower();
+            mSystemBatteryConsumers.add(consumer);
         }
 
-        int userBatteryConsumerCount = builder.mUserBatteryConsumerBuilders.size();
+        final int userBatteryConsumerCount = builder.mUserBatteryConsumerBuilders.size();
         mUserBatteryConsumers = new ArrayList<>(userBatteryConsumerCount);
         for (int i = 0; i < userBatteryConsumerCount; i++) {
-            mUserBatteryConsumers.add(builder.mUserBatteryConsumerBuilders.valueAt(i).build());
+            final UserBatteryConsumer consumer =
+                    builder.mUserBatteryConsumerBuilders.valueAt(i).build();
+            totalPower += consumer.getConsumedPower();
+            mUserBatteryConsumers.add(consumer);
         }
+
+        mConsumedPower = totalPower;
+    }
+
+    /**
+     * Timestamp of the latest battery stats reset, in milliseconds.
+     */
+    public long getStatsStartRealtime() {
+        return mStatsStartRealtimeMs;
     }
 
     /**
@@ -71,6 +102,14 @@
     }
 
     /**
+     * Returns the discharged power since BatteryStats were last reset, in mAh as an estimated
+     * range.
+     */
+    public Range<Double> getDischargedPowerRange() {
+        return Range.create(mDischargedPowerLowerBound, mDischargedPowerUpperBound);
+    }
+
+    /**
      * Total amount of battery charge drained since BatteryStats reset (e.g. due to being fully
      * charged), in mAh
      */
@@ -93,29 +132,88 @@
         return mUserBatteryConsumers;
     }
 
+    /**
+     * Returns an iterator for {@link android.os.BatteryStats.HistoryItem}'s.
+     */
+    @NonNull
+    public BatteryStatsHistoryIterator iterateBatteryStatsHistory() {
+        if (mHistoryBuffer == null) {
+            throw new IllegalStateException(
+                    "Battery history was not requested in the BatteryUsageStatsQuery");
+        }
+        return new BatteryStatsHistoryIterator(new BatteryStatsHistory(mHistoryBuffer),
+                mHistoryTagPool);
+    }
+
     @Override
     public int describeContents() {
         return 0;
     }
 
     private BatteryUsageStats(@NonNull Parcel source) {
+        mStatsStartRealtimeMs = source.readLong();
+        mConsumedPower = source.readDouble();
+        mDischargePercentage = source.readInt();
+        mDischargedPowerLowerBound = source.readDouble();
+        mDischargedPowerUpperBound = source.readDouble();
         mUidBatteryConsumers = new ArrayList<>();
         source.readParcelableList(mUidBatteryConsumers, getClass().getClassLoader());
         mSystemBatteryConsumers = new ArrayList<>();
         source.readParcelableList(mSystemBatteryConsumers, getClass().getClassLoader());
         mUserBatteryConsumers = new ArrayList<>();
         source.readParcelableList(mUserBatteryConsumers, getClass().getClassLoader());
-        mConsumedPower = source.readDouble();
-        mDischargePercentage = source.readInt();
+        if (source.readBoolean()) {
+            mHistoryBuffer = Parcel.obtain();
+            mHistoryBuffer.setDataSize(0);
+            mHistoryBuffer.setDataPosition(0);
+
+            int historyBufferSize = source.readInt();
+            int curPos = source.dataPosition();
+            mHistoryBuffer.appendFrom(source, curPos, historyBufferSize);
+            source.setDataPosition(curPos + historyBufferSize);
+
+            int historyTagCount = source.readInt();
+            mHistoryTagPool = new ArrayList<>(historyTagCount);
+            for (int i = 0; i < historyTagCount; i++) {
+                BatteryStats.HistoryTag tag = new BatteryStats.HistoryTag();
+                tag.string = source.readString();
+                tag.uid = source.readInt();
+                tag.poolIdx = source.readInt();
+                mHistoryTagPool.add(tag);
+            }
+        } else {
+            mHistoryBuffer = null;
+            mHistoryTagPool = null;
+        }
     }
 
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeLong(mStatsStartRealtimeMs);
+        dest.writeDouble(mConsumedPower);
+        dest.writeInt(mDischargePercentage);
+        dest.writeDouble(mDischargedPowerLowerBound);
+        dest.writeDouble(mDischargedPowerUpperBound);
         dest.writeParcelableList(mUidBatteryConsumers, flags);
         dest.writeParcelableList(mSystemBatteryConsumers, flags);
         dest.writeParcelableList(mUserBatteryConsumers, flags);
-        dest.writeDouble(mConsumedPower);
-        dest.writeInt(mDischargePercentage);
+        if (mHistoryBuffer != null) {
+            dest.writeBoolean(true);
+
+            final int historyBufferSize = mHistoryBuffer.dataSize();
+            dest.writeInt(historyBufferSize);
+            dest.appendFrom(mHistoryBuffer, 0, historyBufferSize);
+
+            dest.writeInt(mHistoryTagPool.size());
+            for (int i = mHistoryTagPool.size() - 1; i >= 0; i--) {
+                final BatteryStats.HistoryTag tag = mHistoryTagPool.get(i);
+                dest.writeString(tag.string);
+                dest.writeInt(tag.uid);
+                dest.writeInt(tag.poolIdx);
+            }
+        } else {
+            dest.writeBoolean(false);
+        }
     }
 
     @NonNull
@@ -135,14 +233,18 @@
     public static final class Builder {
         private final int mCustomPowerComponentCount;
         private final int mCustomTimeComponentCount;
-        private double mConsumedPower;
+        private long mStatsStartRealtimeMs;
         private int mDischargePercentage;
+        private double mDischargedPowerLowerBoundMah;
+        private double mDischargedPowerUpperBoundMah;
         private final SparseArray<UidBatteryConsumer.Builder> mUidBatteryConsumerBuilders =
                 new SparseArray<>();
         private final SparseArray<SystemBatteryConsumer.Builder> mSystemBatteryConsumerBuilders =
                 new SparseArray<>();
         private final SparseArray<UserBatteryConsumer.Builder> mUserBatteryConsumerBuilders =
                 new SparseArray<>();
+        private Parcel mHistoryBuffer;
+        private List<BatteryStats.HistoryTag> mHistoryTagPool;
 
         public Builder(int customPowerComponentCount, int customTimeComponentCount) {
             mCustomPowerComponentCount = customPowerComponentCount;
@@ -158,10 +260,17 @@
         }
 
         /**
+         * Sets the timestamp of the latest battery stats reset, in milliseconds.
+         */
+        public Builder setStatsStartRealtime(long statsStartRealtimeMs) {
+            mStatsStartRealtimeMs = statsStartRealtimeMs;
+            return this;
+        }
+
+        /**
          * Sets the battery discharge amount since BatteryStats reset as percentage of the full
          * charge.
          */
-        @SuppressLint("PercentageInt") // See b/174188159
         @NonNull
         public Builder setDischargePercentage(int dischargePercentage) {
             mDischargePercentage = dischargePercentage;
@@ -169,11 +278,24 @@
         }
 
         /**
-         * Sets the battery discharge amount since BatteryStats reset, in mAh.
+         * Sets the estimated battery discharge range.
          */
         @NonNull
-        public Builder setConsumedPower(double consumedPower) {
-            mConsumedPower = consumedPower;
+        public Builder setDischargedPowerRange(double dischargedPowerLowerBoundMah,
+                double dischargedPowerUpperBoundMah) {
+            mDischargedPowerLowerBoundMah = dischargedPowerLowerBoundMah;
+            mDischargedPowerUpperBoundMah = dischargedPowerUpperBoundMah;
+            return this;
+        }
+
+        /**
+         * Sets the parceled recent history.
+         */
+        @NonNull
+        public Builder setBatteryHistory(Parcel historyBuffer,
+                List<BatteryStats.HistoryTag> historyTagPool) {
+            mHistoryBuffer = historyBuffer;
+            mHistoryTagPool = historyTagPool;
             return this;
         }
 
diff --git a/core/java/android/os/BatteryUsageStatsQuery.java b/core/java/android/os/BatteryUsageStatsQuery.java
index 5b5fe1d..9518bf1 100644
--- a/core/java/android/os/BatteryUsageStatsQuery.java
+++ b/core/java/android/os/BatteryUsageStatsQuery.java
@@ -40,6 +40,7 @@
      */
     @IntDef(flag = true, prefix = { "FLAG_BATTERY_USAGE_STATS_" }, value = {
             FLAG_BATTERY_USAGE_STATS_POWER_PROFILE_MODEL,
+            FLAG_BATTERY_USAGE_STATS_INCLUDE_HISTORY,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface BatteryUsageStatsFlags {}
@@ -53,6 +54,12 @@
      */
     public static final int FLAG_BATTERY_USAGE_STATS_POWER_PROFILE_MODEL = 1;
 
+    /**
+     * Indicates that battery history should be included in the BatteryUsageStats.
+     * @hide
+     */
+    public static final int FLAG_BATTERY_USAGE_STATS_INCLUDE_HISTORY = 2;
+
     private final int mFlags;
     @NonNull
     private final int[] mUserIds;
@@ -79,6 +86,14 @@
         return mUserIds;
     }
 
+    /**
+     * Returns true if the power calculations must be based on the PowerProfile constants,
+     * even if measured energy data is available.
+     */
+    public boolean shouldForceUsePowerProfileModel() {
+        return (mFlags & FLAG_BATTERY_USAGE_STATS_POWER_PROFILE_MODEL) != 0;
+    }
+
     private BatteryUsageStatsQuery(Parcel in) {
         mFlags = in.readInt();
         mUserIds = new int[in.readInt()];
@@ -138,10 +153,10 @@
         }
 
         /**
-         * Sets flags to modify the behavior of {@link BatteryStatsManager#getBatteryUsageStats}.
+         * Requests that battery history be included in the BatteryUsageStats.
          */
-        public Builder setFlags(@BatteryUsageStatsFlags int flags) {
-            mFlags = flags;
+        public Builder includeBatteryHistory() {
+            mFlags |= BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_HISTORY;
             return this;
         }
 
diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java
index 305c686..73bb8d5 100644
--- a/core/java/android/os/BugreportManager.java
+++ b/core/java/android/os/BugreportManager.java
@@ -25,6 +25,7 @@
 import android.annotation.SuppressAutoDoc;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.WorkerThread;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.util.Log;
@@ -41,7 +42,15 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.concurrent.Executor;
 
-/** Class that provides a privileged API to capture and consume bugreports. */
+/**
+ * Class that provides a privileged API to capture and consume bugreports.
+ *
+ * <p>This class may only be used by apps that currently have carrier privileges (see {@link
+ * android.telephony.TelephonyManager#hasCarrierPrivileges}) on an active SIM or priv-apps
+ * explicitly allowed by the device manufacturer.
+ *
+ * <p>Only one bugreport can be generated by the system at a time.
+ */
 @SystemService(Context.BUGREPORT_SERVICE)
 public final class BugreportManager {
 
@@ -56,7 +65,15 @@
         mBinder = binder;
     }
 
-    /** An interface describing the callback for bugreport progress and status. */
+    /**
+     * An interface describing the callback for bugreport progress and status.
+     *
+     * <p>Callers will receive {@link #onProgress} calls as the bugreport progresses, followed by a
+     * terminal call to either {@link #onFinished} or {@link #onError}.
+     *
+     * <p>If an issue is encountered while starting the bugreport asynchronously, callers will
+     * receive an {@link #onError} call without any {@link #onProgress} callbacks.
+     */
     public abstract static class BugreportCallback {
         /**
          * Possible error codes taking a bugreport can encounter.
@@ -75,15 +92,18 @@
                 })
         public @interface BugreportErrorCode {}
 
-        /** The input options were invalid */
+        /**
+         * The input options were invalid. For example, the destination file the app provided could
+         * not be written by the system.
+         */
         public static final int BUGREPORT_ERROR_INVALID_INPUT =
                 IDumpstateListener.BUGREPORT_ERROR_INVALID_INPUT;
 
-        /** A runtime error occurred */
+        /** A runtime error occurred. */
         public static final int BUGREPORT_ERROR_RUNTIME =
                 IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR;
 
-        /** User denied consent to share the bugreport */
+        /** User denied consent to share the bugreport. */
         public static final int BUGREPORT_ERROR_USER_DENIED_CONSENT =
                 IDumpstateListener.BUGREPORT_ERROR_USER_DENIED_CONSENT;
 
@@ -149,6 +169,7 @@
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.DUMP)
+    @WorkerThread
     public void startBugreport(
             @NonNull ParcelFileDescriptor bugreportFd,
             @Nullable ParcelFileDescriptor screenshotFd,
@@ -222,6 +243,7 @@
      * @param callback callback for progress and status updates.
      */
     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+    @WorkerThread
     public void startConnectivityBugreport(
             @NonNull ParcelFileDescriptor bugreportFd,
             @NonNull @CallbackExecutor Executor executor,
@@ -247,6 +269,7 @@
      * @throws SecurityException if trying to cancel another app's bugreport in progress
      */
     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+    @WorkerThread
     public void cancelBugreport() {
         try {
             mBinder.cancelBugreport(-1 /* callingUid */, mContext.getOpPackageName());
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 33dedda..874add5 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -24,7 +24,6 @@
 import android.net.NetworkStats;
 import android.net.RouteInfo;
 import android.net.UidRange;
-import android.os.INetworkActivityListener;
 
 /**
  * @hide
@@ -294,25 +293,6 @@
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
     boolean isBandwidthControlEnabled();
 
-    /**
-     * Sets idletimer for an interface.
-     *
-     * This either initializes a new idletimer or increases its
-     * reference-counting if an idletimer already exists for given
-     * {@code iface}.
-     *
-     * {@code type} is the type of the interface, such as TYPE_MOBILE.
-     *
-     * Every {@code addIdleTimer} should be paired with a
-     * {@link removeIdleTimer} to cleanup when the network disconnects.
-     */
-    void addIdleTimer(String iface, int timeout, int type);
-
-    /**
-     * Removes idletimer for an interface.
-     */
-    void removeIdleTimer(String iface);
-
     void setFirewallEnabled(boolean enabled);
     boolean isFirewallEnabled();
     void setFirewallInterfaceRule(String iface, boolean allow);
@@ -320,21 +300,6 @@
     void setFirewallUidRules(int chain, in int[] uids, in int[] rules);
     void setFirewallChainEnabled(int chain, boolean enable);
 
-    /**
-     * Start listening for mobile activity state changes.
-     */
-    void registerNetworkActivityListener(INetworkActivityListener listener);
-
-    /**
-     * Stop listening for mobile activity state changes.
-     */
-    void unregisterNetworkActivityListener(INetworkActivityListener listener);
-
-    /**
-     * Check whether the mobile radio is currently active.
-     */
-    boolean isNetworkActive();
-
     void addLegacyRouteForNetId(int netId, in RouteInfo routeInfo, int uid);
 
     /**
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 7437e037..087568d 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -113,7 +113,7 @@
     boolean hasBadge(int userId);
     boolean isUserUnlocked(int userId);
     boolean isUserRunning(int userId);
-    boolean isUserForeground();
+    boolean isUserForeground(int userId);
     boolean isUserNameSet(int userId);
     boolean hasRestrictedProfiles();
     boolean requestQuietModeEnabled(String callingPackage, boolean enableQuietMode, int userId, in IntentSender target, int flags);
diff --git a/core/java/android/os/PowerComponents.java b/core/java/android/os/PowerComponents.java
index ac23285..d239b23 100644
--- a/core/java/android/os/PowerComponents.java
+++ b/core/java/android/os/PowerComponents.java
@@ -29,38 +29,38 @@
     public static final int CUSTOM_TIME_COMPONENT_OFFSET = BatteryConsumer.TIME_COMPONENT_COUNT
             - BatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID;
 
-    private final double mTotalPowerConsumed;
-    private final double[] mPowerComponents;
-    private final long[] mTimeComponents;
+    private final double mTotalConsumedPowerMah;
+    private final double[] mPowerComponentsMah;
+    private final long[] mTimeComponentsMs;
     private final int mCustomPowerComponentCount;
 
     PowerComponents(@NonNull Builder builder) {
         mCustomPowerComponentCount = builder.mCustomPowerComponentCount;
-        mPowerComponents = builder.mPowerComponents;
-        mTimeComponents = builder.mTimeComponents;
-        mTotalPowerConsumed = builder.getTotalPower();
+        mPowerComponentsMah = builder.mPowerComponentsMah;
+        mTimeComponentsMs = builder.mTimeComponentsMs;
+        mTotalConsumedPowerMah = builder.getTotalPower();
     }
 
     PowerComponents(@NonNull Parcel source) {
-        mTotalPowerConsumed = source.readDouble();
+        mTotalConsumedPowerMah = source.readDouble();
         mCustomPowerComponentCount = source.readInt();
-        mPowerComponents = source.createDoubleArray();
-        mTimeComponents = source.createLongArray();
+        mPowerComponentsMah = source.createDoubleArray();
+        mTimeComponentsMs = source.createLongArray();
     }
 
     /** Writes contents to Parcel */
     void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeDouble(mTotalPowerConsumed);
+        dest.writeDouble(mTotalConsumedPowerMah);
         dest.writeInt(mCustomPowerComponentCount);
-        dest.writeDoubleArray(mPowerComponents);
-        dest.writeLongArray(mTimeComponents);
+        dest.writeDoubleArray(mPowerComponentsMah);
+        dest.writeLongArray(mTimeComponentsMs);
     }
 
     /**
      * Total power consumed by this consumer, in mAh.
      */
-    public double getTotalPowerConsumed() {
-        return mTotalPowerConsumed;
+    public double getTotalConsumedPower() {
+        return mTotalConsumedPowerMah;
     }
 
     /**
@@ -76,7 +76,7 @@
                     "Unsupported power component ID: " + componentId);
         }
         try {
-            return mPowerComponents[componentId];
+            return mPowerComponentsMah[componentId];
         } catch (ArrayIndexOutOfBoundsException e) {
             throw new IllegalArgumentException("Unsupported power component ID: " + componentId);
         }
@@ -92,7 +92,7 @@
         if (componentId >= BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID
                 && componentId < BatteryConsumer.LAST_CUSTOM_POWER_COMPONENT_ID) {
             try {
-                return mPowerComponents[CUSTOM_POWER_COMPONENT_OFFSET + componentId];
+                return mPowerComponentsMah[CUSTOM_POWER_COMPONENT_OFFSET + componentId];
             } catch (ArrayIndexOutOfBoundsException e) {
                 throw new IllegalArgumentException(
                         "Unsupported custom power component ID: " + componentId);
@@ -116,7 +116,7 @@
                     "Unsupported time component ID: " + componentId);
         }
         try {
-            return mTimeComponents[componentId];
+            return mTimeComponentsMs[componentId];
         } catch (ArrayIndexOutOfBoundsException e) {
             throw new IllegalArgumentException("Unsupported power component ID: " + componentId);
         }
@@ -134,7 +134,7 @@
                     "Unsupported custom time component ID: " + componentId);
         }
         try {
-            return mTimeComponents[CUSTOM_TIME_COMPONENT_OFFSET + componentId];
+            return mTimeComponentsMs[CUSTOM_TIME_COMPONENT_OFFSET + componentId];
         } catch (ArrayIndexOutOfBoundsException e) {
             throw new IllegalArgumentException(
                     "Unsupported custom time component ID: " + componentId);
@@ -145,16 +145,16 @@
      * Builder for PowerComponents.
      */
     static final class Builder {
-        private final double[] mPowerComponents;
+        private final double[] mPowerComponentsMah;
         private final int mCustomPowerComponentCount;
-        private final long[] mTimeComponents;
+        private final long[] mTimeComponentsMs;
 
         Builder(int customPowerComponentCount, int customTimeComponentCount) {
             mCustomPowerComponentCount = customPowerComponentCount;
             int powerComponentCount =
                     BatteryConsumer.POWER_COMPONENT_COUNT + customPowerComponentCount;
-            mPowerComponents = new double[powerComponentCount];
-            mTimeComponents =
+            mPowerComponentsMah = new double[powerComponentCount];
+            mTimeComponentsMs =
                     new long[BatteryConsumer.TIME_COMPONENT_COUNT + customTimeComponentCount];
         }
 
@@ -173,7 +173,7 @@
                         "Unsupported power component ID: " + componentId);
             }
             try {
-                mPowerComponents[componentId] = componentPower;
+                mPowerComponentsMah[componentId] = componentPower;
             } catch (ArrayIndexOutOfBoundsException e) {
                 throw new IllegalArgumentException(
                         "Unsupported power component ID: " + componentId);
@@ -192,7 +192,8 @@
             if (componentId >= BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID
                     && componentId < BatteryConsumer.LAST_CUSTOM_POWER_COMPONENT_ID) {
                 try {
-                    mPowerComponents[CUSTOM_POWER_COMPONENT_OFFSET + componentId] = componentPower;
+                    mPowerComponentsMah[CUSTOM_POWER_COMPONENT_OFFSET + componentId] =
+                            componentPower;
                 } catch (ArrayIndexOutOfBoundsException e) {
                     throw new IllegalArgumentException(
                             "Unsupported custom power component ID: " + componentId);
@@ -219,7 +220,7 @@
                         "Unsupported time component ID: " + componentId);
             }
             try {
-                mTimeComponents[componentId] = componentUsageDurationMillis;
+                mTimeComponentsMs[componentId] = componentUsageDurationMillis;
             } catch (ArrayIndexOutOfBoundsException e) {
                 throw new IllegalArgumentException(
                         "Unsupported time component ID: " + componentId);
@@ -241,7 +242,7 @@
                         "Unsupported custom time component ID: " + componentId);
             }
             try {
-                mTimeComponents[CUSTOM_TIME_COMPONENT_OFFSET + componentId] =
+                mTimeComponentsMs[CUSTOM_TIME_COMPONENT_OFFSET + componentId] =
                         componentUsageDurationMillis;
             } catch (ArrayIndexOutOfBoundsException e) {
                 throw new IllegalArgumentException(
@@ -251,11 +252,11 @@
         }
 
         public void addPowerAndDuration(Builder other) {
-            for (int i = 0; i < mPowerComponents.length; i++) {
-                mPowerComponents[i] += other.mPowerComponents[i];
+            for (int i = 0; i < mPowerComponentsMah.length; i++) {
+                mPowerComponentsMah[i] += other.mPowerComponentsMah[i];
             }
-            for (int i = 0; i < mTimeComponents.length; i++) {
-                mTimeComponents[i] += other.mTimeComponents[i];
+            for (int i = 0; i < mTimeComponentsMs.length; i++) {
+                mTimeComponentsMs[i] += other.mTimeComponentsMs[i];
             }
         }
 
@@ -264,11 +265,11 @@
          * by the time the {@code build()} method is called.
          */
         public double getTotalPower() {
-            double totalPower = 0;
-            for (int i = mPowerComponents.length - 1; i >= 0; i--) {
-                totalPower += mPowerComponents[i];
+            double totalPowerMah = 0;
+            for (int i = mPowerComponentsMah.length - 1; i >= 0; i--) {
+                totalPowerMah += mPowerComponentsMah[i];
             }
-            return totalPower;
+            return totalPowerMah;
         }
 
         /**
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 3774fb5..e5163d8 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -1629,6 +1629,12 @@
      * <p>
      * Requires the {@link android.Manifest.permission#REBOOT} permission.
      * </p>
+     * <p>
+     * If the {@code reason} string contains ",quiescent", then the screen stays off during reboot
+     * and is not turned on again until the user triggers the device to wake up (for example,
+     * by pressing the power key).
+     * This behavior applies to Android TV devices launched on Android 11 (API level 30) or higher.
+     * </p>
      *
      * @param reason code to pass to the kernel (e.g., "recovery") to
      *               request special boot modes, or null.
@@ -1875,6 +1881,10 @@
      * Returns the current battery saver control mode. Values it may return are defined in
      * AutoPowerSaveModeTriggers. Note that this is a global device state, not a per user setting.
      *
+     * <p>Note: Prior to Android version {@link Build.VERSION_CODES#S}, any app calling this method
+     * was required to hold the {@link android.Manifest.permission#POWER_SAVER} permission. Starting
+     * from Android version {@link Build.VERSION_CODES#S}, that permission is no longer required.
+     *
      * @return The current value power saver mode for the system.
      *
      * @see AutoPowerSaveModeTriggers
@@ -1883,7 +1893,6 @@
      */
     @AutoPowerSaveModeTriggers
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.POWER_SAVER)
     public int getPowerSaveModeTrigger() {
         try {
             return mService.getPowerSaveModeTrigger();
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 54d2df8..136dc38 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -207,6 +207,12 @@
     public static final int SE_UID = 1068;
 
     /**
+     * Defines the UID/GID for the iorapd.
+     * @hide
+     */
+    public static final int IORAPD_UID = 1071;
+
+    /**
      * Defines the UID/GID for the NetworkStack app.
      * @hide
      */
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 93c1690..43184ea 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -26,6 +26,7 @@
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.app.KeyguardManager;
 import android.app.PendingIntent;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
@@ -631,10 +632,15 @@
     /**
      * Prepare to apply an unattended update by asking the user for their Lock Screen Knowledge
      * Factor (LSKF). If supplied, the {@code intentSender} will be called when the system is setup
-     * and ready to apply the OTA. This API is expected to handle requests from multiple clients
-     * simultaneously, e.g. from ota and mainline.
+     * and ready to apply the OTA. <p>
      *
-     * <p> The behavior of multi-client Resume on Reboot works as follows
+     * <p> If the device doesn't setup a lock screen, i.e. by checking
+     * {@link KeyguardManager#isKeyguardSecure()}, this API call will fail and throw an exception.
+     * Callers are expected to use {@link PowerManager#reboot(String)} directly without going
+     * through the RoR flow. <p>
+     *
+     * <p>  This API is expected to handle requests from multiple clients simultaneously, e.g.
+     * from ota and mainline. The behavior of multi-client Resume on Reboot works as follows
      * <li> Each client should call this function to prepare for Resume on Reboot before calling
      *      {@link #rebootAndApply(Context, String, boolean)} </li>
      * <li> One client cannot clear the Resume on Reboot preparation of another client. </li>
@@ -658,6 +664,13 @@
         if (updateToken == null) {
             throw new NullPointerException("updateToken == null");
         }
+
+        KeyguardManager keyguardManager = context.getSystemService(KeyguardManager.class);
+        if (keyguardManager == null || !keyguardManager.isDeviceSecure()) {
+            throw new IOException("Failed to request LSKF because the device doesn't have a"
+                    + " lock screen. ");
+        }
+
         RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
         if (!rs.requestLskf(context.getPackageName(), intentSender)) {
             throw new IOException("preparation for update failed");
diff --git a/core/java/android/os/SystemBatteryConsumer.java b/core/java/android/os/SystemBatteryConsumer.java
index fc4aa93..06cff90 100644
--- a/core/java/android/os/SystemBatteryConsumer.java
+++ b/core/java/android/os/SystemBatteryConsumer.java
@@ -45,12 +45,13 @@
             DRAIN_TYPE_FLASHLIGHT,
             DRAIN_TYPE_IDLE,
             DRAIN_TYPE_MEMORY,
-            DRAIN_TYPE_OVERCOUNTED,
+            // Reserved: OVERCOUNTED,
             DRAIN_TYPE_PHONE,
             DRAIN_TYPE_SCREEN,
-            DRAIN_TYPE_UNACCOUNTED,
+            // Reserved: UNACCOUNTED,
             // Reserved: USER,
             DRAIN_TYPE_WIFI,
+            DRAIN_TYPE_CUSTOM,
     })
     @Retention(RetentionPolicy.SOURCE)
     public static @interface DrainType {
@@ -63,11 +64,10 @@
     public static final int DRAIN_TYPE_FLASHLIGHT = 5;
     public static final int DRAIN_TYPE_IDLE = 6;
     public static final int DRAIN_TYPE_MEMORY = 7;
-    public static final int DRAIN_TYPE_OVERCOUNTED = 8;
     public static final int DRAIN_TYPE_PHONE = 9;
     public static final int DRAIN_TYPE_SCREEN = 10;
-    public static final int DRAIN_TYPE_UNACCOUNTED = 11;
     public static final int DRAIN_TYPE_WIFI = 13;
+    public static final int DRAIN_TYPE_CUSTOM = 14;
 
     @DrainType
     private final int mDrainType;
diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java
index e29d756..d8f6344 100644
--- a/core/java/android/os/SystemClock.java
+++ b/core/java/android/os/SystemClock.java
@@ -338,8 +338,7 @@
                 try {
                     time = mMgr.getGnssTimeMillis();
                 } catch (RemoteException e) {
-                    e.rethrowFromSystemServer();
-                    return 0;
+                    throw e.rethrowFromSystemServer();
                 }
                 if (time == null) {
                     throw new DateTimeException("Gnss based time is not available.");
diff --git a/core/java/android/os/TEST_MAPPING b/core/java/android/os/TEST_MAPPING
index 1bdc82a..97e03e9 100644
--- a/core/java/android/os/TEST_MAPPING
+++ b/core/java/android/os/TEST_MAPPING
@@ -38,6 +38,23 @@
           "include-filter": "com.android.server.pm.parsing.PackageInfoUserFieldsTest"
         }
       ]
+    },
+    {
+      "file_patterns": ["BatteryStats.java"],
+      "name": "FrameworksCoreTests",
+      "options": [
+        { "include-filter": "com.android.internal.os.BatteryStatsTests" },
+        { "exclude-annotation": "com.android.internal.os.SkipPresubmit" }
+      ]
+    },
+    {
+      "file_patterns": ["BatteryStats.java"],
+      "name": "FrameworksServicesTests",
+      "options": [
+        { "include-filter": "com.android.server.am.BatteryStatsServiceTest" },
+        { "include-filter": "com.android.server.am.MeasuredEnergySnapshotTest" },
+        { "include-filter": "com.android.server.am.BatteryExternalStatsWorkerTest" }
+      ]
     }
   ],
   "postsubmit": [
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index 9c9e499..c8cbc51 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -168,8 +168,10 @@
     }
 
     /**
-     * Set whether application tracing is allowed for this process.  This is intended to be set
-     * once at application start-up time based on whether the application is debuggable.
+     * From Android S, this is no-op.
+     *
+     * Before, set whether application tracing is allowed for this process.  This is intended to be
+     * set once at application start-up time based on whether the application is debuggable.
      *
      * @hide
      */
diff --git a/core/java/android/os/UidBatteryConsumer.java b/core/java/android/os/UidBatteryConsumer.java
index a828077..dfa0c39 100644
--- a/core/java/android/os/UidBatteryConsumer.java
+++ b/core/java/android/os/UidBatteryConsumer.java
@@ -16,9 +16,13 @@
 
 package android.os;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Contains power consumption data attributed to a specific UID.
  *
@@ -26,22 +30,40 @@
  */
 public final class UidBatteryConsumer extends BatteryConsumer implements Parcelable {
 
-    private final int mUid;
-    @Nullable
-    private final String mPackageWithHighestDrain;
-    private boolean mSystemComponent;
-
-    public int getUid() {
-        return mUid;
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            STATE_FOREGROUND,
+            STATE_BACKGROUND
+    })
+    public @interface State {
     }
 
     /**
-     * Returns true if this battery consumer is considered to be a part of the operating
-     * system itself. For example, the UidBatteryConsumer with the UID {@link Process#BLUETOOTH_UID}
-     * is a system component.
+     * The state of an application when it is either running a foreground (top) activity
+     * or a foreground service.
      */
-    public boolean isSystemComponent() {
-        return mSystemComponent;
+    public static final int STATE_FOREGROUND = 0;
+
+    /**
+     * The state of an application when it is running in the background, including the following
+     * states:
+     *
+     * {@link android.app.ActivityManager#PROCESS_STATE_IMPORTANT_BACKGROUND},
+     * {@link android.app.ActivityManager#PROCESS_STATE_TRANSIENT_BACKGROUND},
+     * {@link android.app.ActivityManager#PROCESS_STATE_BACKUP},
+     * {@link android.app.ActivityManager#PROCESS_STATE_SERVICE},
+     * {@link android.app.ActivityManager#PROCESS_STATE_RECEIVER}.
+     */
+    public static final int STATE_BACKGROUND = 1;
+
+    private final int mUid;
+    @Nullable
+    private final String mPackageWithHighestDrain;
+    private final long mTimeInForegroundMs;
+    private final long mTimeInBackgroundMs;
+
+    public int getUid() {
+        return mUid;
     }
 
     @Nullable
@@ -49,17 +71,33 @@
         return mPackageWithHighestDrain;
     }
 
+    /**
+     * Returns the amount of time in milliseconds this UID spent in the specified state.
+     */
+    public long getTimeInStateMs(@State int state) {
+        switch (state) {
+            case STATE_BACKGROUND:
+                return mTimeInBackgroundMs;
+            case STATE_FOREGROUND:
+                return mTimeInForegroundMs;
+        }
+        return 0;
+    }
+
     private UidBatteryConsumer(@NonNull Builder builder) {
         super(builder.mPowerComponentsBuilder.build());
         mUid = builder.mUid;
-        mSystemComponent = builder.mSystemComponent;
         mPackageWithHighestDrain = builder.mPackageWithHighestDrain;
+        mTimeInForegroundMs = builder.mTimeInForegroundMs;
+        mTimeInBackgroundMs = builder.mTimeInBackgroundMs;
     }
 
     private UidBatteryConsumer(@NonNull Parcel source) {
         super(new PowerComponents(source));
         mUid = source.readInt();
         mPackageWithHighestDrain = source.readString();
+        mTimeInForegroundMs = source.readLong();
+        mTimeInBackgroundMs = source.readLong();
     }
 
     /**
@@ -70,6 +108,8 @@
         super.writeToParcel(dest, flags);
         dest.writeInt(mUid);
         dest.writeString(mPackageWithHighestDrain);
+        dest.writeLong(mTimeInForegroundMs);
+        dest.writeLong(mTimeInBackgroundMs);
     }
 
     @NonNull
@@ -95,7 +135,8 @@
         private final BatteryStats.Uid mBatteryStatsUid;
         private final int mUid;
         private String mPackageWithHighestDrain;
-        private boolean mSystemComponent;
+        public long mTimeInForegroundMs;
+        public long mTimeInBackgroundMs;
         private boolean mExcludeFromBatteryUsageStats;
 
         public Builder(int customPowerComponentCount, int customTimeComponentCount,
@@ -125,6 +166,25 @@
         }
 
         /**
+         * Sets the duration, in milliseconds, that this UID was active in a particular state,
+         * such as foreground or background.
+         */
+        @NonNull
+        public Builder setTimeInStateMs(@State int state, long timeInStateMs) {
+            switch (state) {
+                case STATE_FOREGROUND:
+                    mTimeInForegroundMs = timeInStateMs;
+                    break;
+                case STATE_BACKGROUND:
+                    mTimeInBackgroundMs = timeInStateMs;
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unsupported state: " + state);
+            }
+            return this;
+        }
+
+        /**
          * Marks the UidBatteryConsumer for exclusion from the result set.
          */
         public Builder excludeFromBatteryUsageStats() {
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 8bdfd3d..5069e031 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1688,6 +1688,7 @@
      * @return Whether guest user is always ephemeral
      * @hide
      */
+    @TestApi
     public static boolean isGuestUserEphemeral() {
         return Resources.getSystem()
                 .getBoolean(com.android.internal.R.bool.config_guestUserEphemeral);
@@ -1802,6 +1803,20 @@
     }
 
     /**
+     * @return the user type of the context user.
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.CREATE_USERS
+    })
+    @UserHandleAware
+    public @NonNull String getUserType() {
+        UserInfo userInfo = getUserInfo(mUserId);
+        return userInfo == null ? "" : userInfo.userType;
+    }
+
+    /**
      * Returns the user name of the context user. This call is only available to applications on
      * the system image; it requires the {@code android.permission.MANAGE_USERS} or {@code
      * android.permission.GET_ACCOUNTS_PRIVILEGED} permissions.
@@ -1809,7 +1824,8 @@
      * @return the user name
      */
     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
-            android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED}, conditional = true)
+            android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED,
+            android.Manifest.permission.CREATE_USERS}, conditional = true)
     @UserHandleAware
     public @NonNull String getUserName() {
         if (UserHandle.myUserId() == mUserId) {
@@ -2300,13 +2316,14 @@
     }
 
     /**
-     * Checks if the calling user is running on foreground.
+     * Checks if the context user is running in the foreground.
      *
-     * @return whether the calling user is running on foreground.
+     * @return whether the context user is running in the foreground.
      */
+    @UserHandleAware
     public boolean isUserForeground() {
         try {
-            return mService.isUserForeground();
+            return mService.isUserForeground(mUserId);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
@@ -2792,6 +2809,7 @@
      */
     @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
             Manifest.permission.CREATE_USERS})
+    @TestApi
     public @Nullable UserInfo createUser(@Nullable String name, @NonNull String userType,
             @UserInfoFlag int flags) {
         try {
@@ -2828,6 +2846,7 @@
      * @throws UserOperationException if the user could not be created.
      * @hide
      */
+    @TestApi
     @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
             Manifest.permission.CREATE_USERS})
     public @NonNull UserInfo preCreateUser(@NonNull String userType)
@@ -2976,10 +2995,11 @@
      *
      * @hide
      */
+    @TestApi
     @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
             Manifest.permission.CREATE_USERS})
-    public UserInfo createProfileForUser(String name, @NonNull String userType,
-            @UserInfoFlag int flags, @UserIdInt int userId, String[] disallowedPackages) {
+    public @Nullable UserInfo createProfileForUser(@Nullable String name, @NonNull String userType,
+            @UserInfoFlag int flags, @UserIdInt int userId, @Nullable String[] disallowedPackages) {
         try {
             return mService.createProfileForUserWithThrow(name, userType, flags, userId,
                     disallowedPackages);
@@ -3022,9 +3042,10 @@
      *
      * @hide
      */
+    @TestApi
     @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
             Manifest.permission.CREATE_USERS})
-    public UserInfo createRestrictedProfile(String name) {
+    public @Nullable UserInfo createRestrictedProfile(@Nullable String name) {
         try {
             UserHandle parentUserHandle = Process.myUserHandle();
             UserInfo user = mService.createRestrictedProfileWithThrow(name,
@@ -3248,10 +3269,11 @@
 
     /**
      * Return the number of users currently created on the device.
-     * <p>This API is not for use by third-party apps. It requires the {@code MANAGE_USERS}
-     * permission.</p>
      */
-    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.CREATE_USERS
+    })
     public int getUserCount() {
         List<UserInfo> users = getUsers();
         return users != null ? users.size() : 1;
@@ -3274,7 +3296,10 @@
      * @hide
      */
     @UnsupportedAppUsage
-    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.CREATE_USERS
+    })
     public List<UserInfo> getUsers() {
         return getUsers(/*excludePartial= */ true, /* excludeDying= */ false,
                 /* excludePreCreated= */ true);
@@ -3292,7 +3317,10 @@
      * @return the list of users that were created.
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.CREATE_USERS
+    })
     public @NonNull List<UserInfo> getAliveUsers() {
         return getUsers(/*excludePartial= */ true, /* excludeDying= */ true,
                 /* excludePreCreated= */ true);
@@ -3306,7 +3334,10 @@
      */
     @Deprecated
     @UnsupportedAppUsage
-    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.CREATE_USERS
+    })
     public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
         return getUsers(/*excludePartial= */ true, excludeDying,
                 /* excludePreCreated= */ true);
@@ -3317,8 +3348,12 @@
      *
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
-    public List<UserInfo> getUsers(boolean excludePartial, boolean excludeDying,
+    @TestApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.CREATE_USERS
+    })
+    public @NonNull List<UserInfo> getUsers(boolean excludePartial, boolean excludeDying,
             boolean excludePreCreated) {
         try {
             return mService.getUsers(excludePartial, excludeDying, excludePreCreated);
@@ -3335,7 +3370,10 @@
      * @hide
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.CREATE_USERS
+    })
     public @NonNull List<UserHandle> getUserHandles(boolean excludeDying) {
         List<UserInfo> users = getUsers(/* excludePartial= */ true, excludeDying,
                 /* excludePreCreated= */ true);
@@ -3354,7 +3392,10 @@
      * @hide
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.CREATE_USERS
+    })
     public long[] getSerialNumbersOfUsers(boolean excludeDying) {
         List<UserInfo> users = getUsers(/* excludePartial= */ true, excludeDying,
                 /* excludePreCreated= */ true);
@@ -3678,7 +3719,10 @@
      * @hide
      */
     @UnsupportedAppUsage
-    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.INTERACT_ACROSS_USERS
+    })
     public UserInfo getProfileParent(@UserIdInt int userId) {
         try {
             return mService.getProfileParent(userId);
@@ -3697,7 +3741,10 @@
      * @hide
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.INTERACT_ACROSS_USERS
+    })
     public @Nullable UserHandle getProfileParent(@NonNull UserHandle user) {
         UserInfo info = getProfileParent(user.getIdentifier());
 
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index df3beb2..0587610 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -437,7 +437,11 @@
      * @hide
      */
     protected static int scale(int amplitude, float scaleFactor) {
-        return (int) (scale((float) amplitude / MAX_AMPLITUDE, scaleFactor) * MAX_AMPLITUDE);
+        if (amplitude == 0) {
+            return 0;
+        }
+        int scaled = (int) (scale((float) amplitude / MAX_AMPLITUDE, scaleFactor) * MAX_AMPLITUDE);
+        return MathUtils.constrain(scaled, 1, MAX_AMPLITUDE);
     }
 
     /**
@@ -473,7 +477,7 @@
         float a = (expMaxX + 1f) / (expMaxX - 1f);
         float fx = (expX - 1f) / (expX + 1f);
 
-        return a * fx;
+        return MathUtils.constrain(a * fx, 0f, 1f);
     }
 
     /** @hide */
@@ -536,9 +540,10 @@
         /** @hide */
         @Override
         public OneShot resolve(int defaultAmplitude) {
-            if (defaultAmplitude > MAX_AMPLITUDE || defaultAmplitude < 0) {
+            if (defaultAmplitude > MAX_AMPLITUDE || defaultAmplitude <= 0) {
                 throw new IllegalArgumentException(
-                        "Amplitude is negative or greater than MAX_AMPLITUDE");
+                        "amplitude must be between 1 and 255 inclusive (amplitude="
+                        + defaultAmplitude + ")");
             }
             if (mAmplitude == DEFAULT_AMPLITUDE) {
                 return new OneShot(mDuration, defaultAmplitude);
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index d6fa733..b003d23 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -186,7 +186,8 @@
     /**
      * Return the ID of this vibrator.
      *
-     * @return The id of the vibrator controlled by this service.
+     * @return A non-negative integer representing the id of the vibrator controlled by this
+     * service, or -1 this service is not attached to any physical vibrator.
      */
     public int getId() {
         return -1;
diff --git a/core/java/android/os/VibratorManager.java b/core/java/android/os/VibratorManager.java
index 5dd38b6..5a01814 100644
--- a/core/java/android/os/VibratorManager.java
+++ b/core/java/android/os/VibratorManager.java
@@ -91,10 +91,10 @@
      *
      * <p>
      * Pass in a {@link CombinedVibrationEffect} representing a combination of {@link
-     * VibrationEffect} to be played on one or more vibrators.
+     * VibrationEffect VibrationEffects} to be played on one or more vibrators.
      * </p>
      *
-     * @param effect an array of longs of times for which to turn the vibrator on or off.
+     * @param effect a combination of effects to be performed by one or more vibrators.
      */
     @RequiresPermission(android.Manifest.permission.VIBRATE)
     public final void vibrate(@NonNull CombinedVibrationEffect effect) {
@@ -109,7 +109,7 @@
      * VibrationEffect} to be played on one or more vibrators.
      * </p>
      *
-     * @param effect     an array of longs of times for which to turn the vibrator on or off.
+     * @param effect a combination of effects to be performed by one or more vibrators.
      * @param attributes {@link VibrationAttributes} corresponding to the vibration. For example,
      *                   specify {@link VibrationAttributes#USAGE_ALARM} for alarm vibrations or
      *                   {@link VibrationAttributes#USAGE_RINGTONE} for vibrations associated with
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 06203ff..9ffc5aa0 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -426,7 +426,7 @@
         // avoid writing a partial response to the zygote.
         for (String arg : args) {
             // Making two indexOf calls here is faster than running a manually fused loop due
-            // to the fact that indexOf is a optimized intrinsic.
+            // to the fact that indexOf is an optimized intrinsic.
             if (arg.indexOf('\n') >= 0) {
                 throw new ZygoteStartFailedEx("Embedded newlines not allowed");
             } else if (arg.indexOf('\r') >= 0) {
diff --git a/core/java/android/os/incremental/IncrementalFileStorages.java b/core/java/android/os/incremental/IncrementalFileStorages.java
index f2fe719..73520e0 100644
--- a/core/java/android/os/incremental/IncrementalFileStorages.java
+++ b/core/java/android/os/incremental/IncrementalFileStorages.java
@@ -36,6 +36,7 @@
 import android.content.Context;
 import android.content.pm.DataLoaderParams;
 import android.content.pm.IDataLoaderStatusListener;
+import android.content.pm.IPackageLoadingProgressCallback;
 import android.content.pm.InstallationFileParcel;
 
 import java.io.File;
@@ -58,7 +59,6 @@
     /**
      * Set up files and directories used in an installation session. Only used by Incremental.
      * All the files will be created in defaultStorage.
-     * TODO(b/133435829): code clean up
      *
      * @throws IllegalStateException the session is not an Incremental installation session.
      * @throws IOException if fails to setup files or directories.
@@ -71,12 +71,11 @@
             @Nullable StorageHealthCheckParams healthCheckParams,
             @Nullable IStorageHealthListener healthListener,
             @NonNull List<InstallationFileParcel> addedFiles,
-            @NonNull PerUidReadTimeouts[] perUidReadTimeouts) throws IOException {
-        // TODO(b/136132412): validity check if session should not be incremental
+            @NonNull PerUidReadTimeouts[] perUidReadTimeouts,
+            @Nullable IPackageLoadingProgressCallback progressCallback) throws IOException {
         IncrementalManager incrementalManager = (IncrementalManager) context.getSystemService(
                 Context.INCREMENTAL_SERVICE);
         if (incrementalManager == null) {
-            // TODO(b/146080380): add incremental-specific error code
             throw new IOException("Failed to obtain incrementalManager.");
         }
 
@@ -87,7 +86,6 @@
                 try {
                     result.addApkFile(file);
                 } catch (IOException e) {
-                    // TODO(b/146080380): add incremental-specific error code
                     throw new IOException(
                             "Failed to add file to IncFS: " + file.name + ", reason: ", e);
                 }
@@ -95,6 +93,11 @@
                 throw new IOException("Unknown file location: " + file.location);
             }
         }
+        // Register progress loading callback after files have been added
+        if (progressCallback != null) {
+            incrementalManager.registerLoadingProgressCallback(stageDir.getAbsolutePath(),
+                    progressCallback);
+        }
         result.startLoading(dataLoaderParams, statusListener, healthCheckParams, healthListener,
                 perUidReadTimeouts);
 
@@ -196,7 +199,6 @@
 
     /**
      * Resets the states and unbinds storage instances for an installation session.
-     * TODO(b/136132412): make sure unnecessary binds are removed but useful storages are kept
      */
     public void cleanUp() {
         if (mDefaultStorage == null) {
@@ -204,6 +206,7 @@
         }
 
         try {
+            mIncrementalManager.unregisterLoadingProgressCallbacks(mStageDir.getAbsolutePath());
             mDefaultStorage.unBind(mStageDir.getAbsolutePath());
         } catch (IOException ignored) {
         }
diff --git a/core/java/android/os/incremental/IncrementalManager.java b/core/java/android/os/incremental/IncrementalManager.java
index 0589994..592e98a 100644
--- a/core/java/android/os/incremental/IncrementalManager.java
+++ b/core/java/android/os/incremental/IncrementalManager.java
@@ -241,10 +241,12 @@
     }
 
     /**
-     * Checks if device supports V2 calls (e.g. PerUid).
+     * 0 - IncFs is disabled.
+     * 1 - IncFs v1, core features, no PerUid support. Optional in R.
+     * 2 - IncFs v2, PerUid support, fs-verity support. Required in S.
      */
-    public static boolean isV2Available() {
-        return nativeIsV2Available();
+    public static int getVersion() {
+        return nativeIsEnabled() ? nativeIsV2Available() ? 2 : 1 : 0;
     }
 
     /**
@@ -342,7 +344,6 @@
             storage.unregisterLoadingProgressListener();
         }
 
-        // TODO(b/165841827): handle reboot and app update
         public boolean registerCallback(@NonNull IncrementalStorage storage,
                 @NonNull IPackageLoadingProgressCallback callback) {
             final int storageId = storage.getId();
@@ -364,30 +365,6 @@
             return storage.registerLoadingProgressListener(this);
         }
 
-        public boolean unregisterCallback(@NonNull IncrementalStorage storage,
-                @NonNull IPackageLoadingProgressCallback callback) {
-            final int storageId = storage.getId();
-            final RemoteCallbackList<IPackageLoadingProgressCallback> callbacksForStorage;
-            synchronized (mCallbacks) {
-                callbacksForStorage = mCallbacks.get(storageId);
-                if (callbacksForStorage == null) {
-                    // no callback has ever been registered on this storage
-                    return false;
-                }
-                if (!callbacksForStorage.unregister(callback)) {
-                    // the callback was not registered
-                    return false;
-                }
-                if (callbacksForStorage.getRegisteredCallbackCount() > 0) {
-                    // other callbacks are still listening on this storage
-                    return true;
-                }
-                mCallbacks.delete(storageId);
-            }
-            // stop listening for this storage
-            return storage.unregisterLoadingProgressListener();
-        }
-
         @Override
         public void onStorageLoadingProgressChanged(int storageId, float progress) {
             final RemoteCallbackList<IPackageLoadingProgressCallback> callbacksForStorage;
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index 4669b20..0041699 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -196,4 +196,6 @@
     void clearUserKeyAuth(int userId, int serialNumber, in byte[] token, in byte[] secret) = 88;
     void fixupAppDir(in String path) = 89;
     void disableAppDataIsolation(in String pkgName, int pid, int userId) = 90;
-}
+    void notifyAppIoBlocked(in String volumeUuid, int uid, int tid, int reason) = 91;
+    void notifyAppIoResumed(in String volumeUuid, int uid, int tid, int reason) = 92;
+    }
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index a5d3c2a..7c8874c 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1536,6 +1536,7 @@
     }
 
     /** {@hide} */
+    @TestApi
     public static boolean isUserKeyUnlocked(int userId) {
         if (sStorageManager == null) {
             sStorageManager = IStorageManager.Stub
@@ -2698,6 +2699,80 @@
         }
     }
 
+    /**
+     * Reason to provide if app IO is blocked/resumed because of transcoding
+     *
+     * @hide
+     */
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    public static final int APP_IO_BLOCKED_REASON_TRANSCODING = 0;
+
+    /**
+     * Constants for use with
+     * {@link #notifyAppIoBlocked} and {@link notifyAppIoResumed}, to specify the reason an app's
+     * IO is blocked/resumed.
+     *
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "APP_IO_BLOCKED_REASON_" }, value = {
+            APP_IO_BLOCKED_REASON_TRANSCODING
+    })
+    public @interface AppIoBlockedReason {}
+
+    /**
+     * Notify the system that an app with {@code uid} and {@code tid} is blocked on an IO request on
+     * {@code volumeUuid} for {@code reason}.
+     *
+     * This blocked state can be used to modify the ANR behavior for the app while it's blocked.
+     * For example during transcoding.
+     *
+     * This can only be called by the {@link ExternalStorageService} holding the
+     * {@link android.Manifest.permission#WRITE_MEDIA_STORAGE} permission.
+     *
+     * @param volumeUuid the UUID of the storage volume that the app IO is blocked on
+     * @param uid the UID of the app blocked on IO
+     * @param tid the tid of the app blocked on IO
+     * @param reason the reason the app is blocked on IO
+     *
+     * @hide
+     */
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    public void notifyAppIoBlocked(@NonNull String volumeUuid, int uid, int tid,
+            @AppIoBlockedReason int reason) {
+        try {
+            mStorageManager.notifyAppIoBlocked(volumeUuid, uid, tid, reason);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Notify the system that an app with {@code uid} and {@code tid} has resmued a previously
+     * blocked IO request on {@code volumeUuid} for {@code reason}.
+     *
+     * All app IO will be automatically marked as unblocked if {@code volumeUuid} is unmounted.
+     *
+     * This can only be called by the {@link ExternalStorageService} holding the
+     * {@link android.Manifest.permission#WRITE_MEDIA_STORAGE} permission.
+     *
+     * @param volumeUuid the UUID of the storage volume that the app IO is resumed on
+     * @param uid the UID of the app resuming IO
+     * @param tid the tid of the app resuming IO
+     * @param reason the reason the app is resuming IO
+     *
+     * @hide
+     */
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    public void notifyAppIoResumed(@NonNull String volumeUuid, int uid, int tid,
+            @AppIoBlockedReason int reason) {
+        try {
+            mStorageManager.notifyAppIoResumed(volumeUuid, uid, tid, reason);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     private final Object mFuseAppLoopLock = new Object();
 
     @GuardedBy("mFuseAppLoopLock")
diff --git a/core/java/android/os/strictmode/IncorrectContextUseViolation.java b/core/java/android/os/strictmode/IncorrectContextUseViolation.java
index 11d26ca..d8c22fd 100644
--- a/core/java/android/os/strictmode/IncorrectContextUseViolation.java
+++ b/core/java/android/os/strictmode/IncorrectContextUseViolation.java
@@ -24,7 +24,7 @@
  * instance.
  *
  * @see Context#getSystemService(String)
- * @see Context#isUiContext(Context)
+ * @see Context#isUiContext
  * @see android.os.StrictMode.VmPolicy.Builder#detectIncorrectContextUse()
  */
 public final class IncorrectContextUseViolation extends Violation {
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index ff01011..bae36b29 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -485,10 +485,6 @@
      * One for cases where the installer of the package allowlists a permission. This list
      * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be
      * accessed by pre-installed holders of a dedicated permission or the installer on record.
-     * <li>
-     * One for cases where the system exempts the permission when granting a role. This list
-     * corresponds to the {@link PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE} flag. Can be
-     * accessed by pre-installed holders of a dedicated permission.
      * </ol>
      *
      * @param packageName the app for which to get allowlisted permissions
@@ -502,7 +498,6 @@
      * @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM
      * @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE
      * @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER
-     * @see PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE
      *
      * @hide Pending API
      */
@@ -549,10 +544,6 @@
      * One for cases where the installer of the package allowlists a permission. This list
      * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be
      * accessed by pre-installed holders of a dedicated permission or the installer on record.
-     * <li>
-     * One for cases where the system exempts the permission when granting a role. This list
-     * corresponds to the {@link PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE} flag. Can be
-     * accessed by pre-installed holders of a dedicated permission.
      * </ol>
      * <p>
      * You need to specify the allowlists for which to set the allowlisted permissions which will
@@ -570,7 +561,6 @@
      * @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM
      * @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE
      * @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER
-     * @see PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE
      *
      * @hide Pending API
      */
@@ -613,10 +603,6 @@
      * One for cases where the installer of the package allowlists a permission. This list
      * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be
      * accessed by pre-installed holders of a dedicated permission or the installer on record.
-     * <li>
-     * One for cases where the system exempts the permission when granting a role. This list
-     * corresponds to the {@link PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE} flag. Can be
-     * accessed by pre-installed holders of a dedicated permission.
      * </ol>
      * <p>
      * You need to specify the allowlists for which to set the allowlisted permissions which will
@@ -634,7 +620,6 @@
      * @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM
      * @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE
      * @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER
-     * @see PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE
      *
      * @hide Pending API
      */
diff --git a/core/java/android/permission/PermissionUsageHelper.java b/core/java/android/permission/PermissionUsageHelper.java
index 0e35ef9..4c9e77c 100644
--- a/core/java/android/permission/PermissionUsageHelper.java
+++ b/core/java/android/permission/PermissionUsageHelper.java
@@ -57,6 +57,8 @@
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
 
+import com.android.internal.R;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -186,6 +188,15 @@
                 == PackageManager.PERMISSION_GRANTED;
     }
 
+    private boolean isSpeechRecognizerUsage(String op, String packageName) {
+        if (!OPSTR_RECORD_AUDIO.equals(op)) {
+            return false;
+        }
+
+        return packageName.equals(
+                mContext.getString(R.string.config_systemSpeechRecognizer));
+    }
+
     /**
      * @see PermissionManager.getIndicatorAppOpUsageData
      */
@@ -317,7 +328,8 @@
                     if (packageName.equals(SYSTEM_PKG)
                             || (!isUserSensitive(packageName, user, op)
                             && !isLocationProvider(packageName, user)
-                            && !isAppPredictor(packageName, user))) {
+                            && !isAppPredictor(packageName, user))
+                            && !isSpeechRecognizerUsage(op, packageName)) {
                         continue;
                     }
 
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index e134c29..6e89faf 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -157,6 +157,14 @@
     public static final String NAMESPACE_BLUETOOTH = "bluetooth";
 
     /**
+     * Namespace for features relating to clipboard.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String NAMESPACE_CLIPBOARD = "clipboard";
+
+    /**
      * Namespace for all networking connectivity related features.
      *
      * @hide
@@ -275,6 +283,14 @@
     public static final String NAMESPACE_PROFCOLLECT_NATIVE_BOOT = "profcollect_native_boot";
 
     /**
+     * Namespace for features related to Reboot Readiness detection.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String NAMESPACE_REBOOT_READINESS = "reboot_readiness";
+
+    /**
      * Namespace for Rollback flags that are applied immediately.
      *
      * @hide
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e979e13..617220e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -417,6 +417,22 @@
             "android.settings.MANAGE_UNKNOWN_APP_SOURCES";
 
     /**
+     * Activity Action: Show settings to allow configuration of
+     * {@link Manifest.permission#SCHEDULE_EXACT_ALARM} permission
+     *
+     * Input: Optionally, the Intent's data URI can specify the application package name to
+     * directly invoke the management GUI specific to the package name. For example
+     * "package:com.my.app".
+     * <p>
+     * Output: When a package data uri is passed as input, the activity result is set to
+     * {@link android.app.Activity#RESULT_OK} if the permission was granted to the app. Otherwise,
+     * the result is set to {@link android.app.Activity#RESULT_CANCELED}.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_REQUEST_SCHEDULE_EXACT_ALARM =
+            "android.settings.REQUEST_SCHEDULE_EXACT_ALARM";
+
+    /**
      * Activity Action: Show settings to allow configuration of cross-profile access for apps
      *
      * Input: Optionally, the Intent's data URI can specify the application package name to
@@ -10496,18 +10512,6 @@
                 "force_desktop_mode_on_external_displays";
 
         /**
-         * Whether to allow non-resizable apps to be freeform.
-         *
-         * TODO(b/176061101) remove after update all usages
-         * @deprecated use {@link #DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW}
-         * @hide
-         */
-        @Deprecated
-        @Readable
-        public static final String DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM =
-                "enable_sizecompat_freeform";
-
-        /**
          * Whether to allow non-resizable apps to be shown in multi-window. The app will be
          * letterboxed if the request orientation is not met, and will be shown in size-compat
          * mode if the container size has changed.
@@ -10697,14 +10701,6 @@
                 "hdmi_cec_switch_enabled";
 
         /**
-         * HDMI CEC version to use. Defaults to v1.4b.
-         * @hide
-         */
-        @Readable
-        public static final String HDMI_CEC_VERSION =
-                "hdmi_cec_version";
-
-        /**
          * Whether TV will automatically turn on upon reception of the CEC command
          * &lt;Text View On&gt; or &lt;Image View On&gt;. (0 = false, 1 = true)
          *
@@ -14614,6 +14610,29 @@
         public static final String POWER_BUTTON_VERY_LONG_PRESS =
                 "power_button_very_long_press";
 
+
+        /**
+         * Keyguard should be on the left hand side of the screen, for wide screen layouts.
+         *
+         * @hide
+         */
+        public static final int ONE_HANDED_KEYGUARD_SIDE_LEFT = 0;
+
+        /**
+         * Keyguard should be on the right hand side of the screen, for wide screen layouts.
+         *
+         * @hide
+         */
+        public static final int ONE_HANDED_KEYGUARD_SIDE_RIGHT = 1;
+        /**
+         * In one handed mode, which side the keyguard should be on. Allowable values are one of
+         * the ONE_HANDED_KEYGUARD_SIDE_* constants.
+         *
+         * @hide
+         */
+        @Readable
+        public static final String ONE_HANDED_KEYGUARD_SIDE = "one_handed_keyguard_side";
+
         /**
          * Keys we no longer back up under the current schema, but want to continue to
          * process when restoring historical backup datasets.
diff --git a/core/java/android/provider/SimPhonebookContract.java b/core/java/android/provider/SimPhonebookContract.java
index 074d5f1..030b863 100644
--- a/core/java/android/provider/SimPhonebookContract.java
+++ b/core/java/android/provider/SimPhonebookContract.java
@@ -44,8 +44,11 @@
  * The contract between the provider of contact records on the device's SIM cards and applications.
  * Contains definitions of the supported URIs and columns.
  *
- * <p>This content provider does not support any of the QUERY_ARG_SQL* bundle arguments. An
- * IllegalArgumentException will be thrown if these are included.
+ * <h3>Permissions</h3>
+ * <p>
+ * Querying this provider requires {@link android.Manifest.permission#READ_CONTACTS} and writing
+ * to this provider requires {@link android.Manifest.permission#WRITE_CONTACTS}
+ * </p>
  */
 public final class SimPhonebookContract {
 
@@ -85,7 +88,73 @@
         }
     }
 
-    /** Constants for the contact records on a SIM card. */
+    /**
+     * Constants for the contact records on a SIM card.
+     *
+     * <h3 id="simrecords-data">Data</h3>
+     * <p>
+     * Data is stored in a specific elementary file on a specific SIM card and these are isolated
+     * from each other. SIM cards are identified by their subscription ID. SIM cards may not support
+     * all or even any of the elementary file types. A SIM will have constraints on
+     * the values of the data that can be stored in each elementary file. The available SIMs,
+     * their supported elementary file types and the constraints on the data can be discovered by
+     * querying {@link ElementaryFiles#CONTENT_URI}. Each elementary file has a fixed capacity
+     * for the number of records that may be stored. This can be determined from the value
+     * of the {@link ElementaryFiles#MAX_RECORDS} column.
+     * </p>
+     * <p>
+     * The {@link SimRecords#PHONE_NUMBER} column can only contain dialable characters and this
+     * applies regardless of the SIM that is being used. See
+     * {@link android.telephony.PhoneNumberUtils#isDialable(char)} for more details. Additionally
+     * the phone number can contain at most {@link ElementaryFiles#PHONE_NUMBER_MAX_LENGTH}
+     * characters. The {@link SimRecords#NAME} column can contain at most
+     * {@link ElementaryFiles#NAME_MAX_LENGTH} bytes when it is encoded for storage on the SIM.
+     * Encoding is done internally and so the name should be provided unencoded but the number of
+     * bytes required to encode it will vary depending on the characters it contains. This length
+     * can be determined by calling
+     * {@link SimRecords#getEncodedNameLength(ContentResolver, String)}.
+     * </p>
+     * <h3>Operations </h3>
+     * <dl>
+     * <dd><b>Insert</b></dd>
+     * <p>
+     * Only {@link ElementaryFiles#EF_ADN} supports inserts. {@link SimRecords#PHONE_NUMBER}
+     * is a required column. If the value provided for this column is missing, null, empty
+     * or violates the requirements discussed in the <a href="#simrecords-data">Data</a>
+     * section above an {@link IllegalArgumentException} will be thrown. The
+     * {@link SimRecords#NAME} column may be omitted but if provided and it violates any of
+     * the requirements discussed in the <a href="#simrecords-data">Data</a> section above
+     * an {@link IllegalArgumentException} will be thrown.
+     * </p>
+     * <p>
+     * If an insert is not possible because the elementary file is full then an
+     * {@link IllegalStateException} will be thrown.
+     * </p>
+     * <dd><b>Update</b></dd>
+     * <p>
+     * Updates can only be performed for individual records on {@link ElementaryFiles#EF_ADN}.
+     * A specific record is referenced via the Uri returned by
+     * {@link SimRecords#getItemUri(int, int, int)}. Updates have the same constraints and
+     * behavior for the {@link SimRecords#PHONE_NUMBER} and {@link SimRecords#NAME} as insert.
+     * However, in the case of update the {@link SimRecords#PHONE_NUMBER} may be omitted as
+     * the existing record will already have a valid value.
+     * </p>
+     * <dd><b>Delete</b></dd>
+     * <p>
+     * Delete may only be performed for individual records on {@link ElementaryFiles#EF_ADN}.
+     * Deleting records will free up space for use by future inserts.
+     * </p>
+     * <dd><b>Query</b></dd>
+     * <p>
+     * All the records stored on a specific elementary file can be read via a Uri returned by
+     * {@link SimRecords#getContentUri(int, int)}. This query always returns all records; there
+     * is no support for filtering via a selection. An individual record can be queried via a Uri
+     * returned by {@link SimRecords#getItemUri(int, int, int)}. Queries will throw an
+     * {@link IllegalArgumentException} when the SIM with the subscription ID or the elementary file
+     * type are invalid or unavailable.
+     * </p>
+     * </dl>
+     */
     public static final class SimRecords {
 
         /**
@@ -197,8 +266,8 @@
          * be discovered by querying {@link ElementaryFiles#CONTENT_URI}.
          *
          * <p>If a SIM with the provided subscription ID does not exist or the SIM with the provided
-         * subscription ID doesn't support the specified entity file then queries will return
-         * and empty cursor and inserts will throw an {@link IllegalArgumentException}
+         * subscription ID doesn't support the specified entity file then all operations will
+         * throw an {@link IllegalArgumentException}.
          *
          * @param subscriptionId the subscriptionId of the SIM card that this Uri will reference
          * @param efType         the elementary file on the SIM that this Uri will reference
@@ -233,6 +302,9 @@
          *                       must be greater than 0. If there is no record with this record
          *                       number in the specified entity file then it will be treated as a
          *                       non-existent record.
+         * @see ElementaryFiles#SUBSCRIPTION_ID
+         * @see ElementaryFiles#EF_TYPE
+         * @see #RECORD_NUMBER
          */
         @NonNull
         public static Uri getItemUri(
@@ -287,7 +359,28 @@
 
     }
 
-    /** Constants for metadata about the elementary files of the SIM cards in the phone. */
+    /**
+     * Constants for metadata about the elementary files of the SIM cards in the phone.
+     *
+     * <h3>Operations </h3>
+     * <dl>
+     * <dd><b>Insert</b></dd>
+     * <p>Insert is not supported for the Uris defined in this class.</p>
+     * <dd><b>Update</b></dd>
+     * <p>Update is not supported for the Uris defined in this class.</p>
+     * <dd><b>Delete</b></dd>
+     * <p>Delete is not supported for the Uris defined in this class.</p>
+     * <dd><b>Query</b></dd>
+     * <p>
+     * The elementary files for all the inserted SIMs can be read via
+     * {@link ElementaryFiles#CONTENT_URI}. Unsupported elementary files are omitted from the
+     * results. This Uri always returns all supported elementary files for all available SIMs; it
+     * does not support filtering via a selection. A specific elementary file can be queried
+     * via a Uri returned by {@link ElementaryFiles#getItemUri(int, int)}. If the elementary file
+     * referenced by this Uri is unsupported by the SIM then the query will return an empty cursor.
+     * </p>
+     * </dl>
+     */
     public static final class ElementaryFiles {
 
         /** {@link SubscriptionInfo#getSimSlotIndex()} of the SIM for this row. */
diff --git a/core/java/android/security/keystore/recovery/RecoveryController.java b/core/java/android/security/keystore/recovery/RecoveryController.java
index d859b1c..6788353 100644
--- a/core/java/android/security/keystore/recovery/RecoveryController.java
+++ b/core/java/android/security/keystore/recovery/RecoveryController.java
@@ -27,8 +27,11 @@
 import android.os.ServiceManager;
 import android.os.ServiceSpecificException;
 import android.security.KeyStore;
-import android.security.keystore.AndroidKeyStoreProvider;
+import android.security.KeyStore2;
 import android.security.keystore.KeyPermanentlyInvalidatedException;
+import android.security.keystore2.AndroidKeyStoreProvider;
+import android.system.keystore2.Domain;
+import android.system.keystore2.KeyDescriptor;
 
 import com.android.internal.widget.ILockSettings;
 
@@ -709,10 +712,34 @@
      */
     @NonNull Key getKeyFromGrant(@NonNull String grantAlias)
             throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
-        return AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore(
-                mKeyStore,
-                grantAlias,
-                KeyStore.UID_SELF);
+        if (grantAlias.startsWith(APPLICATION_KEY_GRANT_PREFIX)) {
+            return AndroidKeyStoreProvider
+                    .loadAndroidKeyStoreSecretKeyFromKeystore(
+                            KeyStore2.getInstance(),
+                            getGrantDescriptor(grantAlias));
+        }
+        // TODO(b/171305545): remove KeyStore1 logic.
+        return android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore(
+            mKeyStore,
+            grantAlias,
+            KeyStore.UID_SELF);
+
+    }
+
+    private static final String APPLICATION_KEY_GRANT_PREFIX = "recoverable_key:";
+
+    private static @Nullable KeyDescriptor getGrantDescriptor(String grantAlias) {
+        KeyDescriptor result = new KeyDescriptor();
+        result.domain = Domain.GRANT;
+        result.blob = null;
+        result.alias = null;
+        try {
+            result.nspace = Long.parseUnsignedLong(
+                    grantAlias.substring(APPLICATION_KEY_GRANT_PREFIX.length()), 16);
+        } catch (NumberFormatException e) {
+            return null;
+        }
+        return result;
     }
 
     /**
diff --git a/core/java/android/service/displayhash/DisplayHasherService.java b/core/java/android/service/displayhash/DisplayHasherService.java
new file mode 100644
index 0000000..331dbe9
--- /dev/null
+++ b/core/java/android/service/displayhash/DisplayHasherService.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.displayhash;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.Intent;
+import android.graphics.Rect;
+import android.hardware.HardwareBuffer;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteCallback;
+import android.view.displayhash.DisplayHash;
+import android.view.displayhash.DisplayHashResultCallback;
+import android.view.displayhash.VerifiedDisplayHash;
+
+/**
+ * A service that handles generating and verify {@link DisplayHash}.
+ *
+ * The service will generate a DisplayHash based on arguments passed in. Then later that
+ * same DisplayHash can be verified to determine that it was created by the system.
+ *
+ * @hide
+ */
+@SystemApi
+public abstract class DisplayHasherService extends Service {
+
+    /** @hide **/
+    public static final String EXTRA_VERIFIED_DISPLAY_HASH =
+            "android.service.displayhash.extra.VERIFIED_DISPLAY_HASH";
+
+    /**
+     * Manifest metadata key for the resource string array containing the names of all hashing
+     * algorithms provided by the service.
+     *
+     * @hide
+     */
+    public static final String SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS =
+            "android.displayhash.available_algorithms";
+
+    /**
+     * The {@link Intent} action that must be declared as handled by a service in its manifest
+     * for the system to recognize it as a DisplayHash providing service.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String SERVICE_INTERFACE =
+            "android.service.displayhash.DisplayHasherService";
+
+    private DisplayHasherServiceWrapper mWrapper;
+    private Handler mHandler;
+
+    public DisplayHasherService() {
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mWrapper = new DisplayHasherServiceWrapper();
+        mHandler = new Handler(Looper.getMainLooper(), null, true);
+    }
+
+    @NonNull
+    @Override
+    public final IBinder onBind(@NonNull Intent intent) {
+        return mWrapper;
+    }
+
+    /**
+     * Generates the DisplayHash that can be used to validate that the system generated the
+     * token.
+     *
+     * @param salt          The salt to use when generating the hmac. This should be unique to the
+     *                      caller so the token cannot be verified by any other process.
+     * @param buffer        The buffer for the content to generate the hash for.
+     * @param bounds        The size and position of the content in window space.
+     * @param hashAlgorithm The String for the hashing algorithm to use based values in
+     *                      {@link #SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS)}.
+     * @param callback      The callback to invoke
+     *                      {@link DisplayHashResultCallback#onDisplayHashResult(DisplayHash)}
+     *                      if successfully generated a DisplayHash or {@link
+     *                      DisplayHashResultCallback#onDisplayHashError(int)} if failed.
+     */
+    @Nullable
+    public abstract void onGenerateDisplayHash(@NonNull byte[] salt,
+            @NonNull HardwareBuffer buffer, @NonNull Rect bounds,
+            @NonNull String hashAlgorithm, @NonNull DisplayHashResultCallback callback);
+
+    /**
+     * Call to verify that the DisplayHash passed in was generated by the system.
+     *
+     * @param salt        The salt value to use when verifying the hmac. This should be the
+     *                    same value that was passed to
+     *                    {@link #onGenerateDisplayHash(byte[],
+     *                    HardwareBuffer, Rect, String, DisplayHashResultCallback)} to
+     *                    generate the token.
+     * @param displayHash The token to verify that it was generated by the system.
+     * @return a {@link VerifiedDisplayHash} if the token was generated by the system or null
+     * if the token cannot be verified.
+     */
+    @Nullable
+    public abstract VerifiedDisplayHash onVerifyDisplayHash(@NonNull byte[] salt,
+            @NonNull DisplayHash displayHash);
+
+    private void verifyDisplayHash(byte[] salt, DisplayHash displayHash,
+            RemoteCallback callback) {
+        VerifiedDisplayHash verifiedDisplayHash = onVerifyDisplayHash(salt,
+                displayHash);
+        final Bundle data = new Bundle();
+        data.putParcelable(EXTRA_VERIFIED_DISPLAY_HASH, verifiedDisplayHash);
+        callback.sendResult(data);
+    }
+
+    private final class DisplayHasherServiceWrapper extends IDisplayHasherService.Stub {
+        @Override
+        public void generateDisplayHash(byte[] salt, HardwareBuffer buffer, Rect bounds,
+                String hashAlgorithm, RemoteCallback callback) {
+            mHandler.sendMessage(
+                    obtainMessage(DisplayHasherService::onGenerateDisplayHash,
+                            DisplayHasherService.this, salt, buffer, bounds,
+                            hashAlgorithm, new DisplayHashResultCallback() {
+                                @Override
+                                public void onDisplayHashResult(
+                                        @NonNull DisplayHash displayHash) {
+                                    Bundle result = new Bundle();
+                                    result.putParcelable(EXTRA_DISPLAY_HASH, displayHash);
+                                    callback.sendResult(result);
+                                }
+
+                                @Override
+                                public void onDisplayHashError(int errorCode) {
+                                    Bundle result = new Bundle();
+                                    result.putInt(EXTRA_DISPLAY_HASH_ERROR_CODE, errorCode);
+                                    callback.sendResult(result);
+                                }
+                            }));
+        }
+
+        @Override
+        public void verifyDisplayHash(byte[] salt, DisplayHash displayHash,
+                RemoteCallback callback) {
+            mHandler.sendMessage(
+                    obtainMessage(DisplayHasherService::verifyDisplayHash,
+                            DisplayHasherService.this, salt, displayHash, callback));
+        }
+    }
+}
diff --git a/core/java/android/service/displayhash/IDisplayHasherService.aidl b/core/java/android/service/displayhash/IDisplayHasherService.aidl
new file mode 100644
index 0000000..236bc28
--- /dev/null
+++ b/core/java/android/service/displayhash/IDisplayHasherService.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.displayhash;
+
+import android.graphics.Rect;
+import android.hardware.HardwareBuffer;
+import android.os.RemoteCallback;
+import android.view.displayhash.DisplayHash;
+
+/**
+ * Service used to handle DisplayHash requests.
+ *
+ * @hide
+ */
+oneway interface IDisplayHasherService {
+    /**
+     * Generates the DisplayHash that can be used to validate that the system generated the token.
+     *
+     * @param salt The salt to use when generating the hmac. This should be unique to the caller so
+     *        the token cannot be verified by any other process.
+     * @param buffer The buffer to generate the hash for.
+     * @param bounds The size and position of the content being hashed in window space.
+     * @param hashAlgorithm The String for the hash algorithm to use based on values in
+     *        {@link #SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS}.
+     * @param Callback The callback invoked to send back the DisplayHash.
+     */
+    void generateDisplayHash(in byte[] salt, in HardwareBuffer buffer, in Rect bounds,
+                                 in String hashAlgorithm, in RemoteCallback callback);
+
+    /**
+     * Call to verify that the DisplayHash passed in was generated by the system. The result
+     * will be sent in the callback as a boolean with the key {@link #EXTRA_VERIFIED_DISPLAY_HASH}.
+     *
+     * @param salt The salt value to use when verifying the hmac. This should be the same value that
+     *        was passed to {@link generateDisplayHash()} to generate the DisplayHash.
+     * @param displayHash The hash to verify that it was generated by the system.
+     * @param callback The callback invoked to send back the VerifiedDisplayHash.
+     */
+    void verifyDisplayHash(in byte[] salt, in DisplayHash displayHash, in RemoteCallback callback);
+}
diff --git a/core/java/android/service/screenshot/OWNERS b/core/java/android/service/displayhash/OWNERS
similarity index 100%
rename from core/java/android/service/screenshot/OWNERS
rename to core/java/android/service/displayhash/OWNERS
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index 2b7cb1d..b384b66 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -20,6 +20,7 @@
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
 import android.content.pm.ParceledListSlice;
+import android.os.Bundle;
 import android.os.UserHandle;
 import android.service.notification.NotificationStats;
 import android.service.notification.IStatusBarNotificationHolder;
@@ -58,4 +59,5 @@
     void onActionClicked(String key, in Notification.Action action, int source);
     void onNotificationClicked(String key);
     void onAllowedAdjustmentsChanged();
+    void onNotificationFeedbackReceived(String key, in NotificationRankingUpdate update, in Bundle feedback);
 }
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index 1d49a72..4fd36e5 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -30,6 +30,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -90,6 +91,11 @@
             = "android.service.notification.NotificationAssistantService";
 
     /**
+     * Data type: int, the feedback rating score provided by user
+     */
+    public static final String FEEDBACK_RATING = "feedback.rating";
+
+    /**
      * @hide
      */
     protected Handler mHandler;
@@ -272,6 +278,17 @@
     }
 
     /**
+     * Implement this to know when user provides a feedback.
+     * @param key the notification key
+     * @param rankingMap The current ranking map that can be used to retrieve ranking information
+     *                   for active notifications.
+     * @param feedback the feedback detail
+     */
+    public void onNotificationFeedbackReceived(@NonNull String key, @NonNull RankingMap rankingMap,
+            @NonNull Bundle feedback) {
+    }
+
+    /**
      * Updates a notification.  N.B. this won’t cause
      * an existing notification to alert, but might allow a future update to
      * this notification to alert.
@@ -455,6 +472,18 @@
         public void onAllowedAdjustmentsChanged() {
             mHandler.obtainMessage(MyHandler.MSG_ON_ALLOWED_ADJUSTMENTS_CHANGED).sendToTarget();
         }
+
+        @Override
+        public void onNotificationFeedbackReceived(String key, NotificationRankingUpdate update,
+                Bundle feedback) {
+            applyUpdateLocked(update);
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = key;
+            args.arg2 = getCurrentRanking();
+            args.arg3 = feedback;
+            mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_FEEDBACK_RECEIVED,
+                    args).sendToTarget();
+        }
     }
 
     private void setAdjustmentIssuer(@Nullable Adjustment adjustment) {
@@ -476,6 +505,7 @@
         public static final int MSG_ON_PANEL_HIDDEN = 10;
         public static final int MSG_ON_NOTIFICATION_VISIBILITY_CHANGED = 11;
         public static final int MSG_ON_NOTIFICATION_CLICKED = 12;
+        public static final int MSG_ON_NOTIFICATION_FEEDBACK_RECEIVED = 13;
 
         public MyHandler(Looper looper) {
             super(looper, null, false);
@@ -589,6 +619,15 @@
                     onNotificationClicked(key);
                     break;
                 }
+                case MSG_ON_NOTIFICATION_FEEDBACK_RECEIVED: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    String key = (String) args.arg1;
+                    RankingMap ranking = (RankingMap) args.arg2;
+                    Bundle feedback = (Bundle) args.arg3;
+                    args.recycle();
+                    onNotificationFeedbackReceived(key, ranking, feedback);
+                    break;
+                }
             }
         }
     }
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index f66f85b..7aa5bbc9 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -43,6 +43,7 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.os.Build;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -84,6 +85,10 @@
  *               android:name="android.service.notification.default_filter_types"
  *               android:value="1,2">
  *           &lt;/meta-data>
+ *     &lt;meta-data
+ *               android:name="android.service.notification.disabled_filter_types"
+ *               android:value="2">
+ *           &lt;/meta-data>
  * &lt;/service></pre>
  *
  * <p>The service should wait for the {@link #onListenerConnected()} event
@@ -122,6 +127,19 @@
             = "android.service.notification.default_filter_types";
 
     /**
+     * The name of the {@code meta-data} tag containing a comma separated list of default
+     * integer notification types that this listener never wants to receive. See
+     * {@link #FLAG_FILTER_TYPE_ONGOING},
+     * {@link #FLAG_FILTER_TYPE_CONVERSATIONS}, {@link #FLAG_FILTER_TYPE_ALERTING),
+     * and {@link #FLAG_FILTER_TYPE_SILENT}.
+     * <p>Types provided in this list will appear as 'off' and 'disabled' in the user interface,
+     * so users don't enable a type that the listener will never bridge to their paired devices.</p>
+     *
+     */
+    public static final String META_DATA_DISABLED_FILTER_TYPES
+            = "android.service.notification.disabled_filter_types";
+
+    /**
      * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
      *     Normal interruption filter.
      */
@@ -1543,6 +1561,14 @@
             mHandler.obtainMessage(MyHandler.MSG_ON_STATUS_BAR_ICON_BEHAVIOR_CHANGED,
                     hideSilentStatusIcons).sendToTarget();
         }
+
+        @Override
+        public void onNotificationFeedbackReceived(String key, NotificationRankingUpdate update,
+                Bundle feedback) {
+            // no-op in the listener
+        }
+
+
     }
 
     /**
@@ -1628,6 +1654,7 @@
         private int mSuppressedVisualEffects;
         private @NotificationManager.Importance int mImportance;
         private CharSequence mImportanceExplanation;
+        private float mRankingScore;
         // System specified group key.
         private String mOverrideGroupKey;
         // Notification assistant channel override.
@@ -1668,6 +1695,7 @@
             out.writeInt(mSuppressedVisualEffects);
             out.writeInt(mImportance);
             out.writeCharSequence(mImportanceExplanation);
+            out.writeFloat(mRankingScore);
             out.writeString(mOverrideGroupKey);
             out.writeParcelable(mChannel, flags);
             out.writeStringList(mOverridePeople);
@@ -1705,6 +1733,7 @@
             mSuppressedVisualEffects = in.readInt();
             mImportance = in.readInt();
             mImportanceExplanation = in.readCharSequence(); // may be null
+            mRankingScore = in.readFloat();
             mOverrideGroupKey = in.readString(); // may be null
             mChannel = in.readParcelable(cl); // may be null
             mOverridePeople = in.createStringArrayList();
@@ -1802,6 +1831,17 @@
         }
 
         /**
+         * Returns the ranking score provided by the {@link NotificationAssistantService} to
+         * sort the notifications in the shade
+         *
+         * @return the ranking score of the notification, range from -1 to 1
+         * @hide
+         */
+        public float getRankingScore() {
+            return mRankingScore;
+        }
+
+        /**
          * If the system has overridden the group key, then this will be non-null, and this
          * key should be used to bundle notifications.
          */
diff --git a/core/java/android/service/screenshot/IScreenshotHasherService.aidl b/core/java/android/service/screenshot/IScreenshotHasherService.aidl
deleted file mode 100644
index d14d147..0000000
--- a/core/java/android/service/screenshot/IScreenshotHasherService.aidl
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.screenshot;
-
-import android.graphics.Rect;
-import android.hardware.HardwareBuffer;
-import android.os.RemoteCallback;
-import android.service.screenshot.ScreenshotHash;
-
-/**
- * Service used to handle ScreenshotHash requests.
- *
- * @hide
- */
-oneway interface IScreenshotHasherService {
-    /**
-     * Generates the ScreenshotHash token that can be used to validate that the system generated the
-     * token.
-     *
-     * @param salt The salt to use when generating the hmac. This should be unique to the caller so
-     *        the token cannot be verified by any other process.
-     * @param screenshot The screenshot to generate the hash and add to the token.
-     * @param bounds The size and position of the content being screenshot in the window.
-     * @param hashAlgorithm The String for the hashing algorithm to use based on values in
-     *        {@link #SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS}.
-     * @param Callback The callback invoked to send back the ScreenshotHash token.
-     */
-    void generateScreenshotHash(in byte[] salt, in HardwareBuffer screenshot, in Rect bounds,
-                                 in String hashAlgorithm, in RemoteCallback callback);
-
-    /**
-     * Call to verify that the ScreenshotHash passed in was generated by the system. The result
-     * will be sent in the callback as a boolean with the key {@link #EXTRA_VERIFICATION_STATUS}.
-     *
-     * @param salt The salt value to use when verifying the hmac. This should be the same value that
-     *        was passed to {@link generateScreenshotHash()} to generate the token.
-     * @param screenshotHash The hash to verify that it was generated by the system.
-     * @param callback The callback invoked to send back the verification status.
-     */
-    void verifyScreenshotHash(in byte[] salt, in ScreenshotHash screenshotHash,
-                               in RemoteCallback callback);
-}
diff --git a/core/java/android/service/screenshot/ScreenshotHash.java b/core/java/android/service/screenshot/ScreenshotHash.java
deleted file mode 100644
index 9ae4192..0000000
--- a/core/java/android/service/screenshot/ScreenshotHash.java
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.screenshot;
-
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.graphics.Rect;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.util.DataClass;
-
-/**
- * The screenshot hash used to validate information about what was present on screen.
- * @hide
- *
- * TODO: Remove hide and SystemAPI since this will be a public class
- */
-@SystemApi
-@DataClass(genToString = true, genAidl = true)
-public final class ScreenshotHash implements Parcelable {
-    /**
-     * The timestamp when the screenshot was generated.
-     */
-    private final long mScreenshotTimeMillis;
-
-    /**
-     * The bounds of the requested area to take the screenshot. This is in window space passed in
-     * by the client.
-     */
-    @NonNull
-    private final Rect mBoundsInWindow;
-
-    /**
-     * The selected hashing algorithm that generated the image hash.
-     */
-    @NonNull
-    private final String mHashingAlgorithm;
-
-    /**
-     * The image hash generated when creating the ScreenshotHash from the screenshot taken.
-     */
-    @NonNull
-    private final byte[] mImageHash;
-
-    /**
-     * The hmac generated by the system and used to verify whether this token was generated by
-     * the system. This should only be accessed by a system process.
-     */
-    @NonNull
-    private final byte[] mHmac;
-
-    /**
-     * The hmac generated by the system and used to verify whether this token was generated by
-     * the system. This should only be accessed by a system process.
-     *
-     * @hide
-     */
-    @SystemApi
-    @NonNull
-    public byte[] getHmac() {
-        return mHmac;
-    }
-
-
-
-    // Code below generated by codegen v1.0.22.
-    //
-    // DO NOT MODIFY!
-    // CHECKSTYLE:OFF Generated code
-    //
-    // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/screenshot
-    // /ScreenshotHash.java
-    //
-    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
-    //   Settings > Editor > Code Style > Formatter Control
-    //@formatter:off
-
-
-    /**
-     * Creates a new ScreenshotHash.
-     *
-     * @param screenshotTimeMillis
-     *   The timestamp when the screenshot was generated.
-     * @param boundsInWindow
-     *   The bounds of the requested area to take the screenshot. This is in window space passed in
-     *   by the client.
-     * @param hashingAlgorithm
-     *   The selected hashing algorithm that generated the image hash.
-     * @param imageHash
-     *   The image hash generated when creating the ScreenshotHash from the screenshot taken.
-     * @param hmac
-     *   The hmac generated by the system and used to verify whether this token was generated by
-     *   the system. This should only be accessed by a system process.
-     */
-    @DataClass.Generated.Member
-    public ScreenshotHash(
-            long screenshotTimeMillis,
-            @NonNull Rect boundsInWindow,
-            @NonNull String hashingAlgorithm,
-            @NonNull byte[] imageHash,
-            @NonNull byte[] hmac) {
-        this.mScreenshotTimeMillis = screenshotTimeMillis;
-        this.mBoundsInWindow = boundsInWindow;
-        com.android.internal.util.AnnotationValidations.validate(
-                NonNull.class, null, mBoundsInWindow);
-        this.mHashingAlgorithm = hashingAlgorithm;
-        com.android.internal.util.AnnotationValidations.validate(
-                NonNull.class, null, mHashingAlgorithm);
-        this.mImageHash = imageHash;
-        com.android.internal.util.AnnotationValidations.validate(
-                NonNull.class, null, mImageHash);
-        this.mHmac = hmac;
-        com.android.internal.util.AnnotationValidations.validate(
-                NonNull.class, null, mHmac);
-
-        // onConstructed(); // You can define this method to get a callback
-    }
-
-    /**
-     * The timestamp when the screenshot was generated.
-     */
-    @DataClass.Generated.Member
-    public long getScreenshotTimeMillis() {
-        return mScreenshotTimeMillis;
-    }
-
-    /**
-     * The bounds of the requested area to take the screenshot. This is in window space passed in
-     * by the client.
-     */
-    @DataClass.Generated.Member
-    public @NonNull Rect getBoundsInWindow() {
-        return mBoundsInWindow;
-    }
-
-    /**
-     * The selected hashing algorithm that generated the image hash.
-     */
-    @DataClass.Generated.Member
-    public @NonNull String getHashingAlgorithm() {
-        return mHashingAlgorithm;
-    }
-
-    /**
-     * The image hash generated when creating the ScreenshotHash from the screenshot taken.
-     */
-    @DataClass.Generated.Member
-    public @NonNull byte[] getImageHash() {
-        return mImageHash;
-    }
-
-    @Override
-    @DataClass.Generated.Member
-    public String toString() {
-        // You can override field toString logic by defining methods like:
-        // String fieldNameToString() { ... }
-
-        return "ScreenshotHash { " +
-                "screenshotTimeMillis = " + mScreenshotTimeMillis + ", " +
-                "boundsInWindow = " + mBoundsInWindow + ", " +
-                "hashingAlgorithm = " + mHashingAlgorithm + ", " +
-                "imageHash = " + java.util.Arrays.toString(mImageHash) + ", " +
-                "hmac = " + java.util.Arrays.toString(mHmac) +
-        " }";
-    }
-
-    @Override
-    @DataClass.Generated.Member
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        // You can override field parcelling by defining methods like:
-        // void parcelFieldName(Parcel dest, int flags) { ... }
-
-        dest.writeLong(mScreenshotTimeMillis);
-        dest.writeTypedObject(mBoundsInWindow, flags);
-        dest.writeString(mHashingAlgorithm);
-        dest.writeByteArray(mImageHash);
-        dest.writeByteArray(mHmac);
-    }
-
-    @Override
-    @DataClass.Generated.Member
-    public int describeContents() { return 0; }
-
-    /** @hide */
-    @SuppressWarnings({"unchecked", "RedundantCast"})
-    @DataClass.Generated.Member
-    /* package-private */ ScreenshotHash(@NonNull Parcel in) {
-        // You can override field unparcelling by defining methods like:
-        // static FieldType unparcelFieldName(Parcel in) { ... }
-
-        long screenshotTimeMillis = in.readLong();
-        Rect boundsInWindow = (Rect) in.readTypedObject(Rect.CREATOR);
-        String hashingAlgorithm = in.readString();
-        byte[] imageHash = in.createByteArray();
-        byte[] hmac = in.createByteArray();
-
-        this.mScreenshotTimeMillis = screenshotTimeMillis;
-        this.mBoundsInWindow = boundsInWindow;
-        com.android.internal.util.AnnotationValidations.validate(
-                NonNull.class, null, mBoundsInWindow);
-        this.mHashingAlgorithm = hashingAlgorithm;
-        com.android.internal.util.AnnotationValidations.validate(
-                NonNull.class, null, mHashingAlgorithm);
-        this.mImageHash = imageHash;
-        com.android.internal.util.AnnotationValidations.validate(
-                NonNull.class, null, mImageHash);
-        this.mHmac = hmac;
-        com.android.internal.util.AnnotationValidations.validate(
-                NonNull.class, null, mHmac);
-
-        // onConstructed(); // You can define this method to get a callback
-    }
-
-    @DataClass.Generated.Member
-    public static final @NonNull Parcelable.Creator<ScreenshotHash> CREATOR
-            = new Parcelable.Creator<ScreenshotHash>() {
-        @Override
-        public ScreenshotHash[] newArray(int size) {
-            return new ScreenshotHash[size];
-        }
-
-        @Override
-        public ScreenshotHash createFromParcel(@NonNull Parcel in) {
-            return new ScreenshotHash(in);
-        }
-    };
-
-    @DataClass.Generated(
-            time = 1612383172822L,
-            codegenVersion = "1.0.22",
-            sourceFile = "frameworks/base/core/java/android/service/screenshot/ScreenshotHash.java",
-            inputSignatures = "private final  long mScreenshotTimeMillis\nprivate final @android.annotation.NonNull android.graphics.Rect mBoundsInWindow\nprivate final @android.annotation.NonNull java.lang.String mHashingAlgorithm\nprivate final @android.annotation.NonNull byte[] mImageHash\nprivate final @android.annotation.NonNull byte[] mHmac\npublic @android.annotation.SystemApi @android.annotation.NonNull byte[] getHmac()\nclass ScreenshotHash extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genAidl=true)")
-    @Deprecated
-    private void __metadata() {}
-
-
-    //@formatter:on
-    // End of generated code
-
-}
diff --git a/core/java/android/service/screenshot/ScreenshotHasherService.java b/core/java/android/service/screenshot/ScreenshotHasherService.java
deleted file mode 100644
index d96cc7e..0000000
--- a/core/java/android/service/screenshot/ScreenshotHasherService.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.screenshot;
-
-import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.app.Service;
-import android.content.Intent;
-import android.graphics.Rect;
-import android.hardware.HardwareBuffer;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.RemoteCallback;
-
-/**
- * A service that handles generating and verify {@link ScreenshotHash}.
- *
- * The service will generate a ScreenshotHash based on arguments passed in. Then later that
- * same ScreenshotHash can be verified to determine that it was created by the system.
- *
- * @hide
- */
-@SystemApi
-public abstract class ScreenshotHasherService extends Service {
-    /** @hide **/
-    public static final String EXTRA_SCREENSHOT_HASH =
-            "android.service.screenshot.extra.SCREENSHOT_HASH";
-
-    /** @hide **/
-    public static final String EXTRA_VERIFICATION_STATUS =
-            "android.service.screenshot.extra.VERIFICATION_STATUS";
-
-    /**
-     * Manifest metadata key for the resource string array containing the names of all hashing
-     * algorithms provided by the service.
-     *
-     * @hide
-     */
-    public static final String SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS =
-            "android.screenshot.available_algorithms";
-
-    /**
-     * The {@link Intent} action that must be declared as handled by a service in its manifest
-     * for the system to recognize it as a ScreenshotHash providing service.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final String SERVICE_INTERFACE =
-            "android.service.screenshot.ScreenshotHasherService";
-
-    private ScreenshotHasherServiceWrapper mWrapper;
-    private Handler mHandler;
-
-    public ScreenshotHasherService() {
-    }
-
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        mWrapper = new ScreenshotHasherServiceWrapper();
-        mHandler = new Handler(Looper.getMainLooper(), null, true);
-    }
-
-    @NonNull
-    @Override
-    public final IBinder onBind(@NonNull Intent intent) {
-        return mWrapper;
-    }
-
-    /**
-     * Generates the ScreenshotHash that can be used to validate that the system generated the
-     * token.
-     *
-     * @param salt          The salt to use when generating the hmac. This should be unique to the
-     *                      caller so the token cannot be verified by any other process.
-     * @param screenshot    The screenshot buffer for the content.
-     * @param bounds        The size and position of the content being screenshot in the window.
-     * @param hashAlgorithm The String for the hashing algorithm to use based values in
-     *                      {@link #SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS)}.
-     * @return A ScreenshotHash that can be used to validate information about the content.
-     * Returns null when the arguments sent are invalid.
-     */
-    @Nullable
-    public abstract ScreenshotHash onGenerateScreenshotHash(@NonNull byte[] salt,
-            @NonNull HardwareBuffer screenshot, @NonNull Rect bounds,
-            @NonNull String hashAlgorithm);
-
-    /**
-     * Call to verify that the ScreenshotHash passed in was generated by the system.
-     *
-     * @param salt               The salt value to use when verifying the hmac. This should be the
-     *                           same value that was passed to
-     *                           {@link #onGenerateScreenshotHash(byte[],
-     *                           HardwareBuffer, Rect, String)} to
-     *                           generate the token.
-     * @param screenshotHash The token to verify that it was generated by the system.
-     * @return true if the token can be verified that it was generated by the system.
-     */
-    public abstract boolean onVerifyScreenshotHash(@NonNull byte[] salt,
-            @NonNull ScreenshotHash screenshotHash);
-
-    private void generateScreenshotHash(byte[] salt, HardwareBuffer screenshot, Rect bounds,
-            String hashAlgorithm, RemoteCallback callback) {
-        ScreenshotHash screenshotHash = onGenerateScreenshotHash(salt, screenshot,
-                bounds,
-                hashAlgorithm);
-        final Bundle data = new Bundle();
-        data.putParcelable(EXTRA_SCREENSHOT_HASH, screenshotHash);
-        callback.sendResult(data);
-    }
-
-    private void verifyScreenshotHash(byte[] salt, ScreenshotHash screenshotHash,
-            RemoteCallback callback) {
-        boolean verificationStatus = onVerifyScreenshotHash(salt, screenshotHash);
-        final Bundle data = new Bundle();
-        data.putBoolean(EXTRA_VERIFICATION_STATUS, verificationStatus);
-        callback.sendResult(data);
-    }
-
-    private final class ScreenshotHasherServiceWrapper extends
-            IScreenshotHasherService.Stub {
-        @Override
-        public void generateScreenshotHash(byte[] salt, HardwareBuffer screenshot, Rect bounds,
-                String hashAlgorithm, RemoteCallback callback) {
-            mHandler.sendMessage(
-                    obtainMessage(ScreenshotHasherService::generateScreenshotHash,
-                            ScreenshotHasherService.this, salt, screenshot, bounds,
-                            hashAlgorithm, callback));
-        }
-
-        @Override
-        public void verifyScreenshotHash(byte[] salt, ScreenshotHash screenshotHash,
-                RemoteCallback callback) {
-            mHandler.sendMessage(
-                    obtainMessage(ScreenshotHasherService::verifyScreenshotHash,
-                            ScreenshotHasherService.this, salt, screenshotHash,
-                            callback));
-        }
-    }
-}
diff --git a/core/java/android/service/storage/ExternalStorageService.java b/core/java/android/service/storage/ExternalStorageService.java
index 87add57..1e07a87 100644
--- a/core/java/android/service/storage/ExternalStorageService.java
+++ b/core/java/android/service/storage/ExternalStorageService.java
@@ -102,14 +102,6 @@
      */
     public static final String EXTRA_PACKAGE_NAME = "android.service.storage.extra.package_name";
 
-    /**
-     * {@link Bundle} key for a {@link Long} value.
-     *
-     * {@hide}
-     */
-    public static final String EXTRA_ANR_TIMEOUT_MS =
-            "android.service.storage.extra.anr_timeout_ms";
-
     /** @hide */
     @IntDef(flag = true, prefix = {"FLAG_SESSION_"},
         value = {FLAG_SESSION_TYPE_FUSE, FLAG_SESSION_ATTRIBUTE_INDEXABLE})
@@ -178,12 +170,12 @@
     }
 
     /**
-     * Called when {@code packageName} is about to ANR
+     * Called when {@code packageName} is about to ANR. The {@link ExternalStorageService} can
+     * show a progress dialog for the {@code reason}.
      *
-     * @return ANR dialog delay in milliseconds
      */
-    public long onGetAnrDelayMillis(@NonNull String packageName, int uid) {
-        throw new UnsupportedOperationException("onGetAnrDelayMillis not implemented");
+    public void onAnrDelayStarted(@NonNull String packageName, int uid, int tid, int reason) {
+        throw new UnsupportedOperationException("onAnrDelayStarted not implemented");
     }
 
     @Override
@@ -247,14 +239,14 @@
         }
 
         @Override
-        public void getAnrDelayMillis(String packageName, int uid, RemoteCallback callback)
-                throws RemoteException {
+        public void notifyAnrDelayStarted(String packageName, int uid, int tid, int reason,
+                RemoteCallback callback) throws RemoteException {
             mHandler.post(() -> {
                 try {
-                    long timeoutMs = onGetAnrDelayMillis(packageName, uid);
-                    sendTimeoutResult(packageName, timeoutMs, null /* throwable */, callback);
+                    onAnrDelayStarted(packageName, uid, tid, reason);
+                    sendResult(packageName, null /* throwable */, callback);
                 } catch (Throwable t) {
-                    sendTimeoutResult(packageName, 0 /* timeoutMs */, t, callback);
+                    sendResult(packageName, t, callback);
                 }
             });
         }
@@ -267,16 +259,5 @@
             }
             callback.sendResult(bundle);
         }
-
-        private void sendTimeoutResult(String packageName, long timeoutMs, Throwable throwable,
-                RemoteCallback callback) {
-            Bundle bundle = new Bundle();
-            bundle.putString(EXTRA_PACKAGE_NAME, packageName);
-            bundle.putLong(EXTRA_ANR_TIMEOUT_MS, timeoutMs);
-            if (throwable != null) {
-                bundle.putParcelable(EXTRA_ERROR, new ParcelableException(throwable));
-            }
-            callback.sendResult(bundle);
-        }
     }
 }
diff --git a/core/java/android/service/storage/IExternalStorageService.aidl b/core/java/android/service/storage/IExternalStorageService.aidl
index 2e0bd86..ba98efa 100644
--- a/core/java/android/service/storage/IExternalStorageService.aidl
+++ b/core/java/android/service/storage/IExternalStorageService.aidl
@@ -32,5 +32,6 @@
         in RemoteCallback callback);
     void freeCache(@utf8InCpp String sessionId, in String volumeUuid, long bytes,
         in RemoteCallback callback);
-    void getAnrDelayMillis(String packageName, int uid, in RemoteCallback callback);
+    void notifyAnrDelayStarted(String packageName, int uid, int tid, int reason,
+         in RemoteCallback callback);
 }
\ No newline at end of file
diff --git a/core/java/android/service/voice/HotwordDetectionService.java b/core/java/android/service/voice/HotwordDetectionService.java
index 3c35d2c..7f1c5ff 100644
--- a/core/java/android/service/voice/HotwordDetectionService.java
+++ b/core/java/android/service/voice/HotwordDetectionService.java
@@ -19,15 +19,18 @@
 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
 
 import android.annotation.CallSuper;
+import android.annotation.DurationMillisLong;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
 import android.app.Service;
 import android.content.Intent;
+import android.media.AudioFormat;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.util.Log;
 
@@ -57,14 +60,21 @@
 
     private final IHotwordDetectionService mInterface = new IHotwordDetectionService.Stub() {
         @Override
-        public void detectFromDspSource(int sessionId, IDspHotwordDetectionCallback callback)
+        public void detectFromDspSource(
+                ParcelFileDescriptor audioStream,
+                AudioFormat audioFormat,
+                long timeoutMillis,
+                IDspHotwordDetectionCallback callback)
                 throws RemoteException {
             if (DBG) {
                 Log.d(TAG, "#detectFromDspSource");
             }
             mHandler.sendMessage(obtainMessage(HotwordDetectionService::onDetectFromDspSource,
                     HotwordDetectionService.this,
-                    sessionId, new DspHotwordDetectionCallback(callback)));
+                    audioStream,
+                    audioFormat,
+                    timeoutMillis,
+                    new DspHotwordDetectionCallback(callback)));
         }
     };
 
@@ -89,15 +99,24 @@
     /**
      * Detect the audio data generated from Dsp.
      *
-     * @param sessionId The session to use when attempting to capture more audio from the DSP
-     *                  hardware.
+     * <p>Note: the clients are supposed to call {@code close} on the input stream when they are
+     * done with the operation in order to free up resources.
+     *
+     * @param audioStream Stream containing audio bytes returned from DSP
+     * @param audioFormat Format of the supplied audio
+     * @param timeoutMillis Timeout in milliseconds for the operation to invoke the callback. If
+     *                      the application fails to abide by the timeout, system will close the
+     *                      microphone and cancel the operation.
      * @param callback Use {@link HotwordDetectionService#DspHotwordDetectionCallback} to return
      * the detected result.
      *
      * @hide
      */
     @SystemApi
-    public void onDetectFromDspSource(int sessionId,
+    public void onDetectFromDspSource(
+            @NonNull ParcelFileDescriptor audioStream,
+            @NonNull AudioFormat audioFormat,
+            @DurationMillisLong long timeoutMillis,
             @NonNull DspHotwordDetectionCallback callback) {
     }
 
diff --git a/core/java/android/service/voice/IHotwordDetectionService.aidl b/core/java/android/service/voice/IHotwordDetectionService.aidl
index 990ad45..cbe76e4 100644
--- a/core/java/android/service/voice/IHotwordDetectionService.aidl
+++ b/core/java/android/service/voice/IHotwordDetectionService.aidl
@@ -16,6 +16,8 @@
 
 package android.service.voice;
 
+import android.media.AudioFormat;
+import android.os.ParcelFileDescriptor;
 import android.service.voice.IDspHotwordDetectionCallback;
 
 /**
@@ -24,5 +26,9 @@
  * @hide
  */
 oneway interface IHotwordDetectionService {
-    void detectFromDspSource(int sessionId, in IDspHotwordDetectionCallback callback);
+    void detectFromDspSource(
+    in ParcelFileDescriptor audioStream,
+    in AudioFormat audioFormat,
+    long timeoutMillis,
+    in IDspHotwordDetectionCallback callback);
 }
diff --git a/core/java/android/service/wallpaper/Android.bp b/core/java/android/service/wallpaper/Android.bp
index ffbdb03..a527d3d 100644
--- a/core/java/android/service/wallpaper/Android.bp
+++ b/core/java/android/service/wallpaper/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
 
     name: "WallpaperSharedLib",
diff --git a/core/java/android/service/wallpaper/EngineWindowPage.java b/core/java/android/service/wallpaper/EngineWindowPage.java
new file mode 100644
index 0000000..5ed0ad6
--- /dev/null
+++ b/core/java/android/service/wallpaper/EngineWindowPage.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.wallpaper;
+
+import android.app.WallpaperColors;
+import android.graphics.Bitmap;
+import android.graphics.RectF;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+
+/**
+ * This class represents a page of a launcher page used by the wallpaper
+ * @hide
+ */
+public class EngineWindowPage {
+    private Bitmap mScreenShot;
+    private volatile long  mLastUpdateTime = 0;
+    private Set<RectF> mCallbackAreas = new ArraySet<>();
+    private Map<RectF, WallpaperColors> mRectFColors = new ArrayMap<>();
+
+    /** should be locked extrnally */
+    public void addArea(RectF area) {
+        mCallbackAreas.add(area);
+    }
+
+    /** should be locked extrnally */
+    public void addWallpaperColors(RectF area, WallpaperColors colors) {
+        mCallbackAreas.add(area);
+        mRectFColors.put(area, colors);
+    }
+
+    /** get screenshot bitmap */
+    public Bitmap getBitmap() {
+        if (mScreenShot == null || mScreenShot.isRecycled()) return null;
+        return mScreenShot;
+    }
+
+    /** remove callbacks for an area */
+    public void removeArea(RectF area) {
+        mCallbackAreas.remove(area);
+        mRectFColors.remove(area);
+    }
+
+    /** set the last time the screenshot was updated */
+    public void setLastUpdateTime(long lastUpdateTime) {
+        mLastUpdateTime = lastUpdateTime;
+    }
+
+    /** get last screenshot time */
+    public long getLastUpdateTime() {
+        return mLastUpdateTime;
+    }
+
+    /** get colors for an area */
+    public WallpaperColors getColors(RectF rect) {
+        return mRectFColors.get(rect);
+    }
+
+    /** set the new bitmap version */
+    public void setBitmap(Bitmap screenShot) {
+        mScreenShot = screenShot;
+    }
+
+    /** get areas of interest */
+    public Set<RectF> getAreas() {
+        return mCallbackAreas;
+    }
+
+    /** run operations on this page */
+    public synchronized void execSync(Consumer<EngineWindowPage> run) {
+        run.accept(this);
+    }
+
+    /** nullify the area color */
+    public void removeColor(RectF colorArea) {
+        mRectFColors.remove(colorArea);
+    }
+}
diff --git a/core/java/android/service/wallpaper/IWallpaperConnection.aidl b/core/java/android/service/wallpaper/IWallpaperConnection.aidl
index f334d9d..f81ed34 100644
--- a/core/java/android/service/wallpaper/IWallpaperConnection.aidl
+++ b/core/java/android/service/wallpaper/IWallpaperConnection.aidl
@@ -16,6 +16,7 @@
 
 package android.service.wallpaper;
 
+import android.graphics.RectF;
 import android.os.ParcelFileDescriptor;
 import android.service.wallpaper.IWallpaperEngine;
 import android.app.WallpaperColors;
@@ -28,4 +29,5 @@
     void engineShown(IWallpaperEngine engine);
     ParcelFileDescriptor setWallpaper(String name);
     void onWallpaperColorsChanged(in WallpaperColors colors, int displayId);
+    void onLocalWallpaperColorsChanged(in RectF area, in WallpaperColors colors, int displayId);
 }
diff --git a/core/java/android/service/wallpaper/IWallpaperEngine.aidl b/core/java/android/service/wallpaper/IWallpaperEngine.aidl
index 90392e6..fbb449d 100644
--- a/core/java/android/service/wallpaper/IWallpaperEngine.aidl
+++ b/core/java/android/service/wallpaper/IWallpaperEngine.aidl
@@ -16,7 +16,10 @@
 
 package android.service.wallpaper;
 
+import android.app.ILocalWallpaperColorConsumer;
+import android.app.WallpaperColors;
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.view.MotionEvent;
 import android.os.Bundle;
 
@@ -39,4 +42,6 @@
     void destroy();
     void setZoomOut(float scale);
     void scalePreview(in Rect positionInWindow);
+    void removeLocalColorsAreas(in List<RectF> regions);
+    void addLocalColorsAreas(in List<RectF> regions);
 }
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 82e0b4a..920c6a7 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -23,6 +23,7 @@
 import static android.view.View.SYSTEM_UI_FLAG_VISIBLE;
 
 import android.annotation.FloatRange;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
@@ -42,6 +43,7 @@
 import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManager.DisplayListener;
@@ -53,6 +55,8 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.Trace;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.MergedConfiguration;
 import android.view.Display;
@@ -66,6 +70,8 @@
 import android.view.InsetsSourceControl;
 import android.view.InsetsState;
 import android.view.MotionEvent;
+import android.view.PixelCopy;
+import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.SurfaceHolder;
 import android.view.View;
@@ -83,6 +89,9 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Supplier;
 
@@ -116,6 +125,11 @@
 
     static final String TAG = "WallpaperService";
     static final boolean DEBUG = false;
+    static final float MIN_PAGE_ALLOWED_MARGIN = .05f;
+    private static final int MIN_BITMAP_SCREENSHOT_WIDTH = 64;
+    private static final long DEFAULT_UPDATE_SCREENSHOT_DURATION = 60 * 1000; //Once per minute
+    private static final @NonNull RectF LOCAL_COLOR_BOUNDS =
+            new RectF(0, 0, 1, 1);
 
     private static final int DO_ATTACH = 10;
     private static final int DO_DETACH = 20;
@@ -134,6 +148,8 @@
     private static final int MSG_REQUEST_WALLPAPER_COLORS = 10050;
     private static final int MSG_ZOOM = 10100;
     private static final int MSG_SCALE_PREVIEW = 10110;
+    private static final List<Float> PROHIBITED_STEPS = Arrays.asList(0f, Float.POSITIVE_INFINITY,
+            Float.NEGATIVE_INFINITY);
 
     private static final int NOTIFY_COLORS_RATE_LIMIT_MS = 1000;
 
@@ -158,6 +174,14 @@
      */
     public class Engine {
         IWallpaperEngineWrapper mIWallpaperEngine;
+        final ArraySet<RectF> mLocalColorAreas = new ArraySet<>(4);
+        final ArraySet<RectF> mLocalColorsToAdd = new ArraySet<>(4);
+
+        // 2D matrix [x][y] to represent a page of a portion of a window
+        EngineWindowPage[] mWindowPages = new EngineWindowPage[1];
+        Bitmap mLastScreenshot;
+        int mLastWindowPage = -1;
+        float mLastPageOffset = 0;
 
         // Copies from mIWallpaperEngine.
         HandlerCaller mCaller;
@@ -409,8 +433,8 @@
          */
         @VisibleForTesting
         public Engine(Supplier<Long> clockFunction, Handler handler) {
-           mClockFunction = clockFunction;
-           mHandler = handler;
+            mClockFunction = clockFunction;
+            mHandler = handler;
         }
 
         /**
@@ -448,6 +472,19 @@
         }
 
         /**
+         * Return whether the wallpaper is capable of extracting local colors in a rectangle area,
+         * Must implement without calling super:
+         * {@link #addLocalColorsAreas(List)}
+         * {@link #removeLocalColorsAreas(List)}
+         * When local colors change, call {@link #notifyLocalColorsChanged(List, List)}
+         * See {@link com.android.systemui.ImageWallpaper} for an example
+         * @hide
+         */
+        public boolean supportsLocalColorExtraction() {
+            return false;
+        }
+
+        /**
          * Returns true if this engine is running in preview mode -- that is,
          * it is being shown to the user before they select it as the actual
          * wallpaper.
@@ -691,6 +728,8 @@
                     Log.w(TAG, "Can't notify system because wallpaper connection "
                             + "was not established.");
                 }
+                resetWindowPages();
+                processLocalColors(mPendingXOffset, mPendingXOffsetStep);
             } catch (RemoteException e) {
                 Log.w(TAG, "Can't notify system because wallpaper connection was lost.", e);
             }
@@ -714,6 +753,28 @@
         }
 
         /**
+         * Send the changed local color areas for the connection
+         * @param regions
+         * @param colors
+         * @hide
+         */
+        public void notifyLocalColorsChanged(@NonNull List<RectF> regions,
+                @NonNull List<WallpaperColors> colors)
+                throws RuntimeException {
+            for (int i = 0; i < regions.size() && i < colors.size() && colors.get(i) != null; i++) {
+                try {
+                    mConnection.onLocalWallpaperColorsChanged(
+                            regions.get(i),
+                            colors.get(i),
+                            mDisplayContext.getDisplayId()
+                    );
+                } catch (RemoteException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+
+        /**
          * Sets internal engine state. Only for testing.
          * @param created {@code true} or {@code false}.
          * @hide
@@ -1068,7 +1129,9 @@
                         mIsCreating = false;
                         mSurfaceCreated = true;
                         if (redrawNeeded) {
+                            resetWindowPages();
                             mSession.finishDrawing(mWindow, null /* postDrawTransaction */);
+                            processLocalColors(mPendingXOffset, mPendingXOffsetStep);
                         }
                         reposition();
                         mIWallpaperEngine.reportShown();
@@ -1209,6 +1272,7 @@
             if (!mDestroyed) {
                 mVisible = visible;
                 reportVisibility();
+                if (visible) processLocalColors(mPendingXOffset, mPendingXOffsetStep);
             }
         }
 
@@ -1278,6 +1342,403 @@
                 } catch (RemoteException e) {
                 }
             }
+
+            // setup local color extraction data
+            processLocalColors(xOffset, xOffsetStep);
+        }
+
+        private void processLocalColors(float xOffset, float xOffsetStep) {
+            // implemented by the wallpaper
+            if (supportsLocalColorExtraction()) return;
+            if (DEBUG) {
+                Log.d(TAG, "processLocalColors " + xOffset + " of step "
+                        + xOffsetStep);
+            }
+            //below is the default implementation
+            if (xOffset % xOffsetStep > MIN_PAGE_ALLOWED_MARGIN) return;
+            int xPage;
+            int xPages;
+            if (!validStep(xOffsetStep)) {
+                if (DEBUG) {
+                    Log.w(TAG, "invalid offset step " + xOffsetStep);
+                }
+                xOffset = 0;
+                xOffsetStep = 1;
+                xPage = 0;
+                xPages = 1;
+            } else {
+                xPages = Math.round(1 / xOffsetStep) + 1;
+                xOffsetStep = (float) 1 / (float) xPages;
+                float shrink = (float) (xPages - 1) / (float) xPages;
+                xOffset *= shrink;
+                xPage = Math.round(xOffset / xOffsetStep);
+            }
+            if (DEBUG) {
+                Log.d(TAG, "xPages " + xPages + " xPage " + xPage);
+                Log.d(TAG, "xOffsetStep " + xOffsetStep + " xOffset " + xOffset);
+            }
+            EngineWindowPage current;
+            synchronized (mLock) {
+                if (mWindowPages.length == 0 || (mWindowPages.length != xPages)) {
+                    mWindowPages = new EngineWindowPage[xPages];
+                    initWindowPages(mWindowPages, xOffsetStep);
+                }
+                if (mLocalColorsToAdd.size() != 0) {
+                    for (RectF colorArea : mLocalColorsToAdd) {
+                        if (!isValid(colorArea)) continue;
+                        mLocalColorAreas.add(colorArea);
+                        int colorPage = getRectFPage(colorArea, xOffsetStep);
+                        EngineWindowPage currentPage = mWindowPages[colorPage];
+                        if (currentPage == null) {
+                            currentPage = new EngineWindowPage();
+                            currentPage.addArea(colorArea);
+                            mWindowPages[colorPage] = currentPage;
+                        } else {
+                            currentPage.setLastUpdateTime(0);
+                            currentPage.removeColor(colorArea);
+                        }
+                    }
+                    mLocalColorsToAdd.clear();
+                }
+                if (xPage >= mWindowPages.length) {
+                    if (DEBUG) {
+                        Log.e(TAG, "error xPage >= mWindowPages.length page: " + xPage);
+                        Log.e(TAG, "error on page " + xPage + " out of " + xPages);
+                        Log.e(TAG,
+                                "error on xOffsetStep " + xOffsetStep + " xOffset " + xOffset);
+                    }
+                    xPage = mWindowPages.length - 1;
+                }
+                current = mWindowPages[xPage];
+                if (current == null) {
+                    if (DEBUG) Log.d(TAG, "making page " + xPage + " out of " + xPages);
+                    if (DEBUG) {
+                        Log.d(TAG, "xOffsetStep " + xOffsetStep + " xOffset " + xOffset);
+                    }
+                    current = new EngineWindowPage();
+                    mWindowPages[xPage] = current;
+                }
+            }
+            updatePage(current, xPage, xPages, xOffsetStep);
+        }
+
+        private void initWindowPages(EngineWindowPage[] windowPages, float step) {
+            for (int i = 0; i < windowPages.length; i++) {
+                windowPages[i] = new EngineWindowPage();
+            }
+            mLocalColorAreas.addAll(mLocalColorsToAdd);
+            mLocalColorsToAdd.clear();
+            for (RectF area: mLocalColorAreas) {
+                if (!isValid(area)) {
+                    mLocalColorAreas.remove(area);
+                    continue;
+                }
+                int pageNum = getRectFPage(area, step);
+                windowPages[pageNum].addArea(area);
+            }
+        }
+
+        void updatePage(EngineWindowPage currentPage, int pageIndx, int numPages,
+                float xOffsetStep) {
+            // to save creating a runnable, check twice
+            long current = System.nanoTime() / 1_000_000;
+            long lapsed = current - currentPage.getLastUpdateTime();
+            if (lapsed < DEFAULT_UPDATE_SCREENSHOT_DURATION) {
+                return;
+            }
+            Surface surface = mSurfaceHolder.getSurface();
+            boolean widthIsLarger =
+                    mSurfaceControl.getWidth() > mSurfaceControl.getHeight();
+            int smaller = widthIsLarger ? mSurfaceControl.getWidth()
+                    : mSurfaceControl.getHeight();
+            float ratio = (float) MIN_BITMAP_SCREENSHOT_WIDTH / (float) smaller;
+            int width = (int) (ratio * mSurfaceControl.getWidth());
+            int height = (int) (ratio * mSurfaceControl.getHeight());
+            if (width <= 0 || height <= 0) {
+                Log.e(TAG, "wrong width and height values of bitmap " + width + " " + height);
+                return;
+            }
+            Bitmap screenShot = Bitmap.createBitmap(width, height,
+                    Bitmap.Config.ARGB_8888);
+            final Bitmap finalScreenShot = screenShot;
+            Trace.beginSection("WallpaperService#pixelCopy");
+            PixelCopy.request(surface, screenShot, (res) -> {
+                Trace.endSection();
+                if (DEBUG) Log.d(TAG, "result of pixel copy is " + res);
+                if (res != PixelCopy.SUCCESS) {
+                    Bitmap lastBitmap = currentPage.getBitmap();
+                    currentPage.execSync((p) -> {
+                        // assign the last bitmap taken for now
+                        p.setBitmap(mLastScreenshot);
+                    });
+                    Bitmap lastScreenshot = mLastScreenshot;
+                    if (lastScreenshot != null && !lastScreenshot.isRecycled()
+                            && !Objects.equals(lastBitmap, lastScreenshot)) {
+                        updatePageColors(currentPage, pageIndx, numPages, xOffsetStep);
+                    }
+                } else {
+                    mLastScreenshot = finalScreenShot;
+                    // going to hold this lock for a while
+                    currentPage.execSync((p) -> {
+                        p.setBitmap(finalScreenShot);
+                        p.setLastUpdateTime(current);
+                    });
+                    updatePageColors(currentPage, pageIndx, numPages, xOffsetStep);
+                }
+            }, mHandler);
+
+        }
+        // locked by the passed page
+        private void updatePageColors(EngineWindowPage page, int pageIndx, int numPages,
+                float xOffsetStep) {
+            if (page.getBitmap() == null) return;
+            if (DEBUG) {
+                Log.d(TAG, "updatePageColorsLocked for page " + pageIndx + " with areas "
+                        + page.getAreas().size() + " and bitmap size of "
+                        + page.getBitmap().getWidth() + " x " + page.getBitmap().getHeight());
+            }
+            for (RectF area: page.getAreas()) {
+                RectF subArea = generateSubRect(area, pageIndx, numPages);
+                Bitmap b = page.getBitmap();
+                int x = Math.round(b.getWidth() * subArea.left);
+                int y = Math.round(b.getHeight() * subArea.top);
+                int width = Math.round(b.getWidth() * subArea.width());
+                int height = Math.round(b.getHeight() * subArea.height());
+                Bitmap target;
+                try {
+                    target = Bitmap.createBitmap(page.getBitmap(), x, y, width, height);
+                } catch (Exception e) {
+                    Log.e(TAG, "Error creating page local color bitmap", e);
+                    continue;
+                }
+                WallpaperColors color = WallpaperColors.fromBitmap(target);
+                target.recycle();
+                WallpaperColors currentColor = page.getColors(area);
+
+                if (DEBUG) {
+                    Log.d(TAG, "getting local bitmap area x " + x + " y " + y
+                            + " width " + width + " height " + height + " for sub area " + subArea
+                            + " and with page " + pageIndx + " of " + numPages);
+
+                }
+                if (currentColor == null || !color.equals(currentColor)) {
+                    page.addWallpaperColors(area, color);
+                    if (DEBUG) {
+                        Log.d(TAG, "onLocalWallpaperColorsChanged"
+                                + " local color callback for area" + area + " for page " + pageIndx
+                                + " of " + numPages);
+                    }
+                    try {
+                        mConnection.onLocalWallpaperColorsChanged(area, color,
+                                mDisplayContext.getDisplayId());
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Error calling Connection.onLocalWallpaperColorsChanged", e);
+                    }
+                }
+            }
+        }
+
+        private RectF generateSubRect(RectF in, int pageInx, int numPages) {
+            float minLeft = (float) (pageInx) / (float) (numPages);
+            float maxRight = (float) (pageInx + 1) / (float) (numPages);
+            float left = in.left;
+            float right = in.right;
+
+            // bound rect
+            if (left < minLeft) left = minLeft;
+            if (right > maxRight) right = maxRight;
+
+            // scale up the sub area then trim
+            left = (left * (float) numPages) % 1f;
+            right = (right * (float) numPages) % 1f;
+            if (right == 0f) {
+                right = 1f;
+            }
+
+            return new RectF(left, in.top, right, in.bottom);
+        }
+
+        private void resetWindowPages() {
+            if (supportsLocalColorExtraction()) return;
+            mLastWindowPage = -1;
+            synchronized (mLock) {
+                for (int i = 0; i < mWindowPages.length; i++) {
+                    EngineWindowPage page = mWindowPages[i];
+                    if (page != null) {
+                        page.execSync((p) -> {
+                            p.setLastUpdateTime(0L);
+                        });
+                    }
+                }
+            }
+        }
+
+        private int getRectFPage(RectF area, float step) {
+            if (!isValid(area)) return 0;
+            if (!validStep(step)) return 0;
+            int pages = Math.round(1 / step);
+            int page = Math.round(area.centerX() * pages);
+            if (page == pages) return pages - 1;
+            if (page == mWindowPages.length) page = mWindowPages.length - 1;
+            return page;
+        }
+
+        /**
+         * Add local colors areas of interest
+         * @param regions list of areas
+         * @hide
+         */
+        public void addLocalColorsAreas(@NonNull List<RectF> regions) {
+            if (supportsLocalColorExtraction()) return;
+            if (DEBUG) {
+                Log.d(TAG, "addLocalColorsAreas adding local color areas " + regions);
+            }
+            float step = mPendingXOffsetStep;
+
+            List<WallpaperColors> colors = getLocalWallpaperColors(regions);
+            synchronized (mLock) {
+                if (!validStep(step)) {
+                    step = 0;
+                }
+                for (int i = 0; i < regions.size(); i++) {
+                    RectF area = regions.get(i);
+                    if (!isValid(area)) continue;
+                    int pageInx = getRectFPage(area, step);
+                    // no page should be null
+                    EngineWindowPage page = mWindowPages[pageInx];
+
+                    if (page != null) {
+                        mLocalColorAreas.add(area);
+                        page.addArea(area);
+                        WallpaperColors color = colors.get(i);
+                        if (color != null && !color.equals(page.getColors(area))) {
+                            page.execSync(p -> {
+                                p.addWallpaperColors(area, color);
+                            });
+                        }
+                    } else {
+                        mLocalColorsToAdd.add(area);
+                    }
+                }
+            }
+
+            for (int i = 0; i < colors.size() && colors.get(i) != null; i++) {
+                try {
+                    mConnection.onLocalWallpaperColorsChanged(regions.get(i), colors.get(i),
+                            mDisplayContext.getDisplayId());
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Error calling Connection.onLocalWallpaperColorsChanged", e);
+                    return;
+                }
+            }
+        }
+
+        /**
+         * Remove local colors areas of interest if they exist
+         * @param regions list of areas
+         * @hide
+         */
+        public void removeLocalColorsAreas(@NonNull List<RectF> regions) {
+            if (supportsLocalColorExtraction()) return;
+            synchronized (mLock) {
+                float step = mPendingXOffsetStep;
+                mLocalColorsToAdd.removeAll(regions);
+                mLocalColorAreas.removeAll(regions);
+                if (!validStep(step)) {
+                    return;
+                }
+                for (int i = 0; i < regions.size(); i++) {
+                    RectF area = regions.get(i);
+                    if (!isValid(area)) continue;
+                    int pageInx = getRectFPage(area, step);
+                    // no page should be null
+                    EngineWindowPage page = mWindowPages[pageInx];
+                    if (page != null) {
+                        page.execSync(p -> {
+                            p.removeArea(area);
+                        });
+                    }
+                }
+            }
+        }
+
+        private @NonNull List<WallpaperColors> getLocalWallpaperColors(@NonNull List<RectF> areas) {
+            ArrayList<WallpaperColors> colors = new ArrayList<>(areas.size());
+            float step = mPendingXOffsetStep;
+            if (!validStep(step)) {
+                if (DEBUG) Log.d(TAG, "invalid step size " + step);
+                step = 1.0f;
+            }
+            for (int i = 0; i < areas.size(); i++) {
+                RectF currentArea = areas.get(i);
+                EngineWindowPage page;
+                RectF area;
+                int pageIndx;
+                synchronized (mLock) {
+                    pageIndx = getRectFPage(currentArea, step);
+                    if (mWindowPages.length == 0 || pageIndx < 0
+                            || pageIndx > mWindowPages.length || !isValid(currentArea)) {
+                        colors.add(null);
+                        continue;
+                    }
+                    area = generateSubRect(currentArea, pageIndx, mWindowPages.length);
+                    page = mWindowPages[pageIndx];
+                }
+                if (page == null) {
+                    colors.add(null);
+                    continue;
+                }
+                float finalStep = step;
+                int finalPageIndx = pageIndx;
+                Bitmap screenShot = page.getBitmap();
+                if (screenShot == null || screenShot.isRecycled()) {
+                    if (DEBUG) {
+                        Log.d(TAG, "invalid bitmap " + screenShot
+                                + " for page " + finalPageIndx);
+                    }
+                    page.setLastUpdateTime(0);
+                    colors.add(null);
+                    continue;
+                }
+                Bitmap b = screenShot;
+                Rect subImage = new Rect(
+                        Math.round(area.left * b.getWidth() / finalStep),
+                        Math.round(area.top * b.getHeight()),
+                        Math.round(area.right * b.getWidth() / finalStep),
+                        Math.round(area.bottom * b.getHeight())
+                );
+                subImage = fixRect(b, subImage);
+                if (DEBUG) {
+                    Log.d(TAG, "getting subbitmap of " + subImage.toString()
+                            + " for RectF " + area.toString()
+                            + " screenshot width " + screenShot.getWidth() + " height "
+                            + screenShot.getHeight());
+                }
+                Bitmap colorImg = Bitmap.createBitmap(screenShot,
+                        subImage.left, subImage.top, subImage.width(), subImage.height());
+                if (DEBUG) {
+                    Log.d(TAG, "created bitmap " + colorImg.getWidth() + ", "
+                            + colorImg.getHeight());
+                }
+                WallpaperColors color = WallpaperColors.fromBitmap(colorImg);
+                colors.add(color);
+            }
+            return colors;
+        }
+
+        // fix the rect to be included within the bounds of the bitmap
+        private Rect fixRect(Bitmap b, Rect r) {
+            r.left =  r.left >= r.right || r.left >= b.getWidth() || r.left > 0
+                    ? 0
+                    : r.left;
+            r.right =  r.left >= r.right || r.right > b.getWidth()
+                    ? b.getWidth()
+                    : r.right;
+            return r;
+        }
+
+        private boolean validStep(float step) {
+            return !PROHIBITED_STEPS.contains(step) && step > 0. && step <= 1.;
         }
 
         void doCommand(WallpaperCommand cmd) {
@@ -1371,6 +1832,16 @@
         };
     }
 
+    private boolean isValid(RectF area) {
+        boolean valid = area.bottom > area.top && area.left < area.right
+                && LOCAL_COLOR_BOUNDS.contains(area);
+        return valid;
+    }
+
+    private boolean inRectFRange(float number) {
+        return number >= 0f && number <= 1f;
+    }
+
     class IWallpaperEngineWrapper extends IWallpaperEngine.Stub
             implements HandlerCaller.Callback {
         private final HandlerCaller mCaller;
@@ -1477,6 +1948,14 @@
             mCaller.sendMessage(msg);
         }
 
+        public void addLocalColorsAreas(List<RectF> regions) {
+            mEngine.addLocalColorsAreas(regions);
+        }
+
+        public void removeLocalColorsAreas(List<RectF> regions) {
+            mEngine.removeLocalColorsAreas(regions);
+        }
+
         public void destroy() {
             Message msg = mCaller.obtainMessage(DO_DETACH);
             mCaller.sendMessage(msg);
@@ -1516,14 +1995,15 @@
             }
             switch (message.what) {
                 case DO_ATTACH: {
+                    Engine engine = onCreateEngine();
+                    mEngine = engine;
                     try {
                         mConnection.attachEngine(this, mDisplayId);
                     } catch (RemoteException e) {
+                        engine.detach();
                         Log.w(TAG, "Wallpaper host disappeared", e);
                         return;
                     }
-                    Engine engine = onCreateEngine();
-                    mEngine = engine;
                     mActiveEngines.add(engine);
                     engine.attach(this);
                     return;
diff --git a/core/java/android/speech/IRecognitionService.aidl b/core/java/android/speech/IRecognitionService.aidl
index f91e122..cc1cded 100644
--- a/core/java/android/speech/IRecognitionService.aidl
+++ b/core/java/android/speech/IRecognitionService.aidl
@@ -43,7 +43,7 @@
      * @param featureId The feature in the package
      */
     void startListening(in Intent recognizerIntent, in IRecognitionListener listener,
-            String packageName, String featureId);
+            String packageName, String featureId, int callingUid);
 
     /**
      * Stops listening for speech. Speech captured so far will be recognized as
@@ -62,6 +62,7 @@
      * @param listener to receive callbacks, note that this must be non-null
      * @param packageName the package name calling this API
      * @param featureId The feature in the package
+     * @param isShutdown Whether the cancellation is caused by a client calling #shutdown
      */
-    void cancel(in IRecognitionListener listener, String packageName, String featureId);
+    void cancel(in IRecognitionListener listener, String packageName, String featureId, boolean isShutdown);
 }
diff --git a/core/java/android/speech/IRecognitionServiceManager.aidl b/core/java/android/speech/IRecognitionServiceManager.aidl
index 7158ba2..8e5292d 100644
--- a/core/java/android/speech/IRecognitionServiceManager.aidl
+++ b/core/java/android/speech/IRecognitionServiceManager.aidl
@@ -16,6 +16,8 @@
 
 package android.speech;
 
+import android.content.ComponentName;
+
 import android.speech.IRecognitionServiceManagerCallback;
 
 /**
@@ -23,6 +25,10 @@
  *
  * {@hide}
  */
-interface IRecognitionServiceManager {
-    void createSession(in IRecognitionServiceManagerCallback callback);
+oneway interface IRecognitionServiceManager {
+    void createSession(
+        in ComponentName componentName,
+        in IBinder clientToken,
+        boolean onDevice,
+        in IRecognitionServiceManagerCallback callback);
 }
diff --git a/core/java/android/speech/IRecognitionServiceManagerCallback.aidl b/core/java/android/speech/IRecognitionServiceManagerCallback.aidl
index d760810..26afdaa 100644
--- a/core/java/android/speech/IRecognitionServiceManagerCallback.aidl
+++ b/core/java/android/speech/IRecognitionServiceManagerCallback.aidl
@@ -25,5 +25,5 @@
  */
 oneway interface IRecognitionServiceManagerCallback {
     void onSuccess(in IRecognitionService service);
-    void onError();
+    void onError(int errorCode);
 }
diff --git a/core/java/android/speech/RecognitionService.java b/core/java/android/speech/RecognitionService.java
index c97dbfe..fd584f1 100644
--- a/core/java/android/speech/RecognitionService.java
+++ b/core/java/android/speech/RecognitionService.java
@@ -105,17 +105,6 @@
             int callingUid) {
         if (mCurrentCallback == null) {
             if (DBG) Log.d(TAG, "created new mCurrentCallback, listener = " + listener.asBinder());
-            try {
-                listener.asBinder().linkToDeath(new IBinder.DeathRecipient() {
-                    @Override
-                    public void binderDied() {
-                        mHandler.sendMessage(mHandler.obtainMessage(MSG_CANCEL, listener));
-                    }
-                }, 0);
-            } catch (RemoteException re) {
-                Log.e(TAG, "dead listener on startListening");
-                return;
-            }
             mCurrentCallback = new Callback(listener, callingUid);
             RecognitionService.this.onStartListening(intent, mCurrentCallback);
         } else {
@@ -352,7 +341,6 @@
          * Return the Linux uid assigned to the process that sent you the current transaction that
          * is being processed. This is obtained from {@link Binder#getCallingUid()}.
          */
-        // TODO(b/176578753): need to make sure this is fixed when proxied through system.
         public int getCallingUid() {
             return mCallingUid;
         }
@@ -368,7 +356,7 @@
 
         @Override
         public void startListening(Intent recognizerIntent, IRecognitionListener listener,
-                String packageName, String featureId) {
+                String packageName, String featureId, int callingUid) {
             Preconditions.checkNotNull(packageName);
 
             if (DBG) Log.d(TAG, "startListening called by:" + listener.asBinder());
@@ -377,7 +365,7 @@
                     packageName, featureId)) {
                 service.mHandler.sendMessage(Message.obtain(service.mHandler,
                         MSG_START_LISTENING, service.new StartListeningArgs(
-                                recognizerIntent, listener, Binder.getCallingUid())));
+                                recognizerIntent, listener, callingUid)));
             }
         }
 
@@ -397,7 +385,7 @@
 
         @Override
         public void cancel(IRecognitionListener listener, String packageName,
-                String featureId) {
+                String featureId, boolean isShutdown) {
             Preconditions.checkNotNull(packageName);
 
             if (DBG) Log.d(TAG, "cancel called by:" + listener.asBinder());
diff --git a/core/java/android/speech/SpeechRecognizer.java b/core/java/android/speech/SpeechRecognizer.java
index de879c6..850f997 100644
--- a/core/java/android/speech/SpeechRecognizer.java
+++ b/core/java/android/speech/SpeechRecognizer.java
@@ -20,8 +20,8 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.ServiceConnection;
 import android.content.pm.ResolveInfo;
+import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -32,10 +32,9 @@
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.Slog;
 
-import java.util.LinkedList;
 import java.util.List;
-import java.util.Queue;
 
 /**
  * This class provides access to the speech recognition service. This service allows access to the
@@ -107,6 +106,12 @@
     /** Insufficient permissions */
     public static final int ERROR_INSUFFICIENT_PERMISSIONS = 9;
 
+    /** Too many requests from the same client. */
+    public static final int ERROR_TOO_MANY_REQUESTS = 10;
+
+    /** Server has been disconnected, e.g. because the app has crashed. */
+    public static final int ERROR_SERVER_DISCONNECTED = 11;
+
     /** action codes */
     private final static int MSG_START = 1;
     private final static int MSG_STOP = 2;
@@ -116,9 +121,6 @@
     /** The actual RecognitionService endpoint */
     private IRecognitionService mService;
 
-    /** The connection to the actual service */
-    private Connection mConnection;
-
     /** Context with which the manager was created */
     private final Context mContext;
     
@@ -151,15 +153,11 @@
         }
     };
 
-    /**
-     * Temporary queue, saving the messages until the connection will be established, afterwards,
-     * only mHandler will receive the messages
-     */
-    private final Queue<Message> mPendingTasks = new LinkedList<Message>();
-
     /** The Listener that will receive all the callbacks */
     private final InternalListener mListener = new InternalListener();
 
+    private final IBinder mClientToken = new Binder();
+
     /**
      * The right way to create a {@code SpeechRecognizer} is by using
      * {@link #createSpeechRecognizer} static factory method
@@ -181,30 +179,6 @@
     }
 
     /**
-     * Basic ServiceConnection that records the mService variable. Additionally, on creation it
-     * invokes the {@link IRecognitionService#startListening(Intent, IRecognitionListener)}.
-     */
-    private class Connection implements ServiceConnection {
-
-        public void onServiceConnected(final ComponentName name, final IBinder service) {
-            // always done on the application main thread, so no need to send message to mHandler
-            mService = IRecognitionService.Stub.asInterface(service);
-            if (DBG) Log.d(TAG, "onServiceConnected - Success");
-            while (!mPendingTasks.isEmpty()) {
-                mHandler.sendMessage(mPendingTasks.poll());
-            }
-        }
-
-        public void onServiceDisconnected(final ComponentName name) {
-            // always done on the application main thread, so no need to send message to mHandler
-            mService = null;
-            mConnection = null;
-            mPendingTasks.clear();
-            if (DBG) Log.d(TAG, "onServiceDisconnected - Success");
-        }
-    }
-
-    /**
      * Checks whether a speech recognition service is available on the system. If this method
      * returns {@code false}, {@link SpeechRecognizer#createSpeechRecognizer(Context)} will
      * fail.
@@ -303,87 +277,52 @@
             throw new IllegalArgumentException("intent must not be null");
         }
         checkIsCalledFromMainThread();
-        if (mConnection == null) { // first time connection
-            // TODO(b/176578753): both flows should go through system service.
-            if (mOnDevice) {
-                connectToSystemService();
-            } else {
-                connectToService();
+
+        if (DBG) {
+            Slog.i(TAG, "#startListening called");
+            if (mService == null) {
+                Slog.i(TAG, "Connection is not established yet");
             }
         }
-        putMessage(Message.obtain(mHandler, MSG_START, recognizerIntent));
-    }
 
-    private void connectToSystemService() {
-        mManagerService = IRecognitionServiceManager.Stub.asInterface(
-                ServiceManager.getService(Context.SPEECH_RECOGNITION_SERVICE));
-
-        if (mManagerService == null) {
-            mListener.onError(ERROR_CLIENT);
-            return;
-        }
-
-        try {
-            // TODO(b/176578753): this has to supply information on whether to use on-device impl.
-            mManagerService.createSession(new IRecognitionServiceManagerCallback.Stub(){
-                @Override
-                public void onSuccess(IRecognitionService service) throws RemoteException {
-                    mService = service;
-                }
-
-                @Override
-                public void onError() throws RemoteException {
-                    Log.e(TAG, "Bind to system recognition service failed");
-                    mListener.onError(ERROR_CLIENT);
-                }
-            });
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-    }
-
-    private void connectToService() {
-        mConnection = new Connection();
-
-        Intent serviceIntent = new Intent(RecognitionService.SERVICE_INTERFACE);
-
-        if (mServiceComponent == null) {
-            String serviceComponent = Settings.Secure.getString(mContext.getContentResolver(),
-                    Settings.Secure.VOICE_RECOGNITION_SERVICE);
-
-            if (TextUtils.isEmpty(serviceComponent)) {
-                Log.e(TAG, "no selected voice recognition service");
-                mListener.onError(ERROR_CLIENT);
-                return;
-            }
-
-            serviceIntent.setComponent(
-                    ComponentName.unflattenFromString(serviceComponent));
+        if (mService == null) {
+            // First time connection: first establish a connection, then dispatch #startListening.
+            connectToSystemService(
+                    () -> putMessage(Message.obtain(mHandler, MSG_START, recognizerIntent)));
         } else {
-            serviceIntent.setComponent(mServiceComponent);
-        }
-        if (!mContext.bindService(serviceIntent, mConnection,
-                Context.BIND_AUTO_CREATE | Context.BIND_INCLUDE_CAPABILITIES)) {
-            Log.e(TAG, "bind to recognition service failed");
-            mConnection = null;
-            mService = null;
-            mListener.onError(ERROR_CLIENT);
-            return;
+            putMessage(Message.obtain(mHandler, MSG_START, recognizerIntent));
         }
     }
 
     /**
      * Stops listening for speech. Speech captured so far will be recognized as if the user had
-     * stopped speaking at this point. Note that in the default case, this does not need to be
-     * called, as the speech endpointer will automatically stop the recognizer listening when it
-     * determines speech has completed. However, you can manipulate endpointer parameters directly
-     * using the intent extras defined in {@link RecognizerIntent}, in which case you may sometimes
-     * want to manually call this method to stop listening sooner. Please note that
+     * stopped speaking at this point.
+     *
+     * <p>Note that in the default case, this does not need to be called, as the speech endpointer
+     * will automatically stop the recognizer listening when it determines speech has completed.
+     * However, you can manipulate endpointer parameters directly using the intent extras defined in
+     * {@link RecognizerIntent}, in which case you may sometimes want to manually call this method
+     * to stop listening sooner.
+     *
+     * <p>Upon invocation clients must wait until {@link RecognitionListener#onResults} or
+     * {@link RecognitionListener#onError} are invoked before calling
+     * {@link SpeechRecognizer#startListening} again. Otherwise such an attempt would be rejected by
+     * recognition service.
+     *
+     * <p>Please note that
      * {@link #setRecognitionListener(RecognitionListener)} should be called beforehand, otherwise
      * no notifications will be received.
      */
     public void stopListening() {
         checkIsCalledFromMainThread();
+
+        if (DBG) {
+            Slog.i(TAG, "#stopListening called");
+            if (mService == null) {
+                Slog.i(TAG, "Connection is not established yet");
+            }
+        }
+
         putMessage(Message.obtain(mHandler, MSG_STOP));
     }
 
@@ -405,11 +344,7 @@
     }
 
     private void putMessage(Message msg) {
-        if (mService == null) {
-            mPendingTasks.offer(msg);
-        } else {
-            mHandler.sendMessage(msg);
-        }
+        mHandler.sendMessage(msg);
     }
 
     /** sends the actual message to the service */
@@ -419,7 +354,7 @@
         }
         try {
             mService.startListening(recognizerIntent, mListener, mContext.getOpPackageName(),
-                    mContext.getAttributionTag());
+                    mContext.getAttributionTag(), android.os.Process.myUid());
             if (DBG) Log.d(TAG, "service start listening command succeded");
         } catch (final RemoteException e) {
             Log.e(TAG, "startListening() failed", e);
@@ -448,7 +383,11 @@
             return;
         }
         try {
-            mService.cancel(mListener, mContext.getOpPackageName(), mContext.getAttributionTag());
+            mService.cancel(
+                    mListener,
+                    mContext.getOpPackageName(),
+                    mContext.getAttributionTag(),
+                    false /* isShutdown */);
             if (DBG) Log.d(TAG, "service cancel command succeded");
         } catch (final RemoteException e) {
             Log.e(TAG, "cancel() failed", e);
@@ -471,28 +410,94 @@
         mListener.mInternalListener = listener;
     }
 
-    /**
-     * Destroys the {@code SpeechRecognizer} object.
-     */
+    /** Destroys the {@code SpeechRecognizer} object. */
     public void destroy() {
         if (mService != null) {
             try {
                 mService.cancel(mListener, mContext.getOpPackageName(),
-                        mContext.getAttributionTag());
+                        mContext.getAttributionTag(), true /* isShutdown */);
             } catch (final RemoteException e) {
                 // Not important
             }
         }
 
-        if (mConnection != null) {
-            mContext.unbindService(mConnection);
-        }
-        mPendingTasks.clear();
         mService = null;
-        mConnection = null;
         mListener.mInternalListener = null;
     }
 
+    /** Establishes a connection to system server proxy and initializes the session. */
+    private void connectToSystemService(Runnable onSuccess) {
+        mManagerService = IRecognitionServiceManager.Stub.asInterface(
+                ServiceManager.getService(Context.SPEECH_RECOGNITION_SERVICE));
+
+        if (mManagerService == null) {
+            mListener.onError(ERROR_CLIENT);
+            return;
+        }
+
+        ComponentName componentName = getSpeechRecognizerComponentName();
+
+        if (!mOnDevice && componentName == null) {
+            mListener.onError(ERROR_CLIENT);
+            return;
+        }
+
+        try {
+            mManagerService.createSession(
+                    componentName,
+                    mClientToken,
+                    mOnDevice,
+                    new IRecognitionServiceManagerCallback.Stub(){
+                        @Override
+                        public void onSuccess(IRecognitionService service) throws RemoteException {
+                            mService = service;
+                            onSuccess.run();
+                        }
+
+                        @Override
+                        public void onError(int errorCode) throws RemoteException {
+                            Log.e(TAG, "Bind to system recognition service failed");
+                            mListener.onError(errorCode);
+                        }
+                    });
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns the component name to be used for establishing a connection, based on the parameters
+     * used during initialization.
+     *
+     * <p>Note the 3 different scenarios:
+     * <ol>
+     *     <li>On-device speech recognizer which is determined by the manufacturer and not
+     *     changeable by the user
+     *     <li>Default user-selected speech recognizer as specified by
+     *     {@code Settings.Secure.VOICE_RECOGNITION_SERVICE}
+     *     <li>Custom speech recognizer supplied by the client.
+     */
+    private ComponentName getSpeechRecognizerComponentName() {
+        if (mOnDevice) {
+            return null;
+        }
+
+        if (mServiceComponent != null) {
+            return mServiceComponent;
+        }
+
+        String serviceComponent = Settings.Secure.getString(mContext.getContentResolver(),
+                Settings.Secure.VOICE_RECOGNITION_SERVICE);
+
+        if (TextUtils.isEmpty(serviceComponent)) {
+            Log.e(TAG, "no selected voice recognition service");
+            mListener.onError(ERROR_CLIENT);
+            return null;
+        }
+
+        return ComponentName.unflattenFromString(serviceComponent);
+    }
+
     /**
      * Internal wrapper of IRecognitionListener which will propagate the results to
      * RecognitionListener
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 5d66dc7..78e5eab 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -913,7 +913,7 @@
         // Special case, we are asked to shutdown connection that did finalize its connection.
         synchronized (mStartLock) {
             if (mConnectingServiceConnection != null) {
-                mContext.unbindService(mConnectingServiceConnection);
+                mConnectingServiceConnection.disconnect();
                 mConnectingServiceConnection = null;
                 return;
             }
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index ffb4a6e..3c355d4 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -270,13 +270,13 @@
     /**
      * Notify call state changed on certain subscription.
      *
-     * @param subId for which call state changed.
      * @param slotIndex for which call state changed. Can be derived from subId except when subId is
      * invalid.
+     * @param subId for which call state changed.
      * @param state latest call state. e.g, offhook, ringing
      * @param incomingNumber incoming phone number.
      */
-    public void notifyCallStateChanged(int subId, int slotIndex, @CallState int state,
+    public void notifyCallStateChanged(int slotIndex, int subId, @CallState int state,
             @Nullable String incomingNumber) {
         try {
             sRegistry.notifyCallState(slotIndex, subId, state, incomingNumber);
@@ -329,12 +329,12 @@
     /**
      * Notify {@link ServiceState} update on certain subscription.
      *
-     * @param subId for which the service state changed.
      * @param slotIndex for which the service state changed. Can be derived from subId except
      * subId is invalid.
+     * @param subId for which the service state changed.
      * @param state service state e.g, in service, out of service or roaming status.
      */
-    public void notifyServiceStateChanged(int subId, int slotIndex, @NonNull ServiceState state) {
+    public void notifyServiceStateChanged(int slotIndex, int subId, @NonNull ServiceState state) {
         try {
             sRegistry.notifyServiceStateForPhoneId(slotIndex, subId, state);
         } catch (RemoteException ex) {
@@ -345,12 +345,12 @@
     /**
      * Notify {@link SignalStrength} update on certain subscription.
      *
-     * @param subId for which the signalstrength changed.
      * @param slotIndex for which the signalstrength changed. Can be derived from subId except when
      * subId is invalid.
+     * @param subId for which the signalstrength changed.
      * @param signalStrength e.g, signalstrength level {@see SignalStrength#getLevel()}
      */
-    public void notifySignalStrengthChanged(int subId, int slotIndex,
+    public void notifySignalStrengthChanged(int slotIndex, int subId,
             @NonNull SignalStrength signalStrength) {
         try {
             sRegistry.notifySignalStrengthForPhoneId(slotIndex, subId, signalStrength);
@@ -363,13 +363,13 @@
      * Notify changes to the message-waiting indicator on certain subscription. e.g, The status bar
      * uses message waiting indicator to determine when to display the voicemail icon.
      *
-     * @param subId for which message waiting indicator changed.
      * @param slotIndex for which message waiting indicator changed. Can be derived from subId
      * except when subId is invalid.
+     * @param subId for which message waiting indicator changed.
      * @param msgWaitingInd {@code true} indicates there is message-waiting indicator, {@code false}
      * otherwise.
      */
-    public void notifyMessageWaitingChanged(int subId, int slotIndex, boolean msgWaitingInd) {
+    public void notifyMessageWaitingChanged(int slotIndex, int subId, boolean msgWaitingInd) {
         try {
             sRegistry.notifyMessageWaitingChangedForPhoneId(slotIndex, subId, msgWaitingInd);
         } catch (RemoteException ex) {
@@ -410,9 +410,9 @@
     /**
      * Notify changes to default (Internet) data connection state on certain subscription.
      *
-     * @param subId for which data connection state changed.
      * @param slotIndex for which data connections state changed. Can be derived from subId except
      * when subId is invalid.
+     * @param subId for which data connection state changed.
      * @param preciseState the PreciseDataConnectionState
      *
      * @see PreciseDataConnectionState
@@ -431,13 +431,13 @@
     /**
      * Notify {@link CallQuality} change on certain subscription.
      *
-     * @param subId for which call quality state changed.
      * @param slotIndex for which call quality state changed. Can be derived from subId except when
      * subId is invalid.
+     * @param subId for which call quality state changed.
      * @param callQuality Information about call quality e.g, call quality level
      * @param networkType associated with this data connection. e.g, LTE
      */
-    public void notifyCallQualityChanged(int subId, int slotIndex, @NonNull CallQuality callQuality,
+    public void notifyCallQualityChanged(int slotIndex, int subId, @NonNull CallQuality callQuality,
         @NetworkType int networkType) {
         try {
             sRegistry.notifyCallQualityChanged(callQuality, slotIndex, subId, networkType);
@@ -449,11 +449,11 @@
     /**
      * Notify emergency number list changed on certain subscription.
      *
-     * @param subId for which emergency number list changed.
      * @param slotIndex for which emergency number list changed. Can be derived from subId except
      * when subId is invalid.
+     * @param subId for which emergency number list changed.
      */
-    public void notifyEmergencyNumberList(int subId, int slotIndex) {
+    public void notifyEmergencyNumberList( int slotIndex, int subId) {
         try {
             sRegistry.notifyEmergencyNumberList(slotIndex, subId);
         } catch (RemoteException ex) {
@@ -494,13 +494,13 @@
     /**
      * Notify radio power state changed on certain subscription.
      *
-     * @param subId for which radio power state changed.
      * @param slotIndex for which radio power state changed. Can be derived from subId except when
      * subId is invalid.
+     * @param subId for which radio power state changed.
      * @param radioPowerState the current modem radio state.
      */
-    public void notifyRadioPowerStateChanged(int subId, int slotIndex,
-        @RadioPowerState int radioPowerState) {
+    public void notifyRadioPowerStateChanged(int slotIndex, int subId,
+            @RadioPowerState int radioPowerState) {
         try {
             sRegistry.notifyRadioPowerStateChanged(slotIndex, subId, radioPowerState);
         } catch (RemoteException ex) {
@@ -538,13 +538,13 @@
      * Notify data activation state changed on certain subscription.
      * @see TelephonyManager#getDataActivationState()
      *
-     * @param subId for which data activation state changed.
      * @param slotIndex for which data activation state changed. Can be derived from subId except
      * when subId is invalid.
+     * @param subId for which data activation state changed.
      * @param activationState sim activation state e.g, activated.
      */
-    public void notifyDataActivationStateChanged(int subId, int slotIndex,
-        @SimActivationState int activationState) {
+    public void notifyDataActivationStateChanged(int slotIndex, int subId,
+            @SimActivationState int activationState) {
         try {
             sRegistry.notifySimActivationStateChangedForPhoneId(slotIndex, subId,
                     SIM_ACTIVATION_TYPE_DATA, activationState);
@@ -557,13 +557,13 @@
      * Notify voice activation state changed on certain subscription.
      * @see TelephonyManager#getVoiceActivationState()
      *
-     * @param subId for which voice activation state changed.
      * @param slotIndex for which voice activation state changed. Can be derived from subId except
      * subId is invalid.
+     * @param subId for which voice activation state changed.
      * @param activationState sim activation state e.g, activated.
      */
-    public void notifyVoiceActivationStateChanged(int subId, int slotIndex,
-        @SimActivationState int activationState) {
+    public void notifyVoiceActivationStateChanged(int slotIndex, int subId,
+            @SimActivationState int activationState) {
         try {
             sRegistry.notifySimActivationStateChangedForPhoneId(slotIndex, subId,
                     SIM_ACTIVATION_TYPE_VOICE, activationState);
@@ -576,9 +576,9 @@
      * Notify User mobile data state changed on certain subscription. e.g, mobile data is enabled
      * or disabled.
      *
-     * @param subId for which mobile data state has changed.
      * @param slotIndex for which mobile data state has changed. Can be derived from subId except
      * when subId is invalid.
+     * @param subId for which mobile data state has changed.
      * @param state {@code true} indicates mobile data is enabled/on. {@code false} otherwise.
      */
     public void notifyUserMobileDataStateChanged(int slotIndex, int subId, boolean state) {
@@ -599,7 +599,7 @@
      * @param telephonyDisplayInfo The display info.
      */
     public void notifyDisplayInfoChanged(int slotIndex, int subscriptionId,
-                                         @NonNull TelephonyDisplayInfo telephonyDisplayInfo) {
+            @NonNull TelephonyDisplayInfo telephonyDisplayInfo) {
         try {
             sRegistry.notifyDisplayInfoChanged(slotIndex, subscriptionId, telephonyDisplayInfo);
         } catch (RemoteException ex) {
@@ -640,14 +640,14 @@
      * Notify precise call state changed on certain subscription, including foreground, background
      * and ringcall states.
      *
-     * @param subId for which precise call state changed.
      * @param slotIndex for which precise call state changed. Can be derived from subId except when
      * subId is invalid.
+     * @param subId for which precise call state changed.
      * @param ringCallPreciseState ringCall state.
      * @param foregroundCallPreciseState foreground call state.
      * @param backgroundCallPreciseState background call state.
      */
-    public void notifyPreciseCallState(int subId, int slotIndex,
+    public void notifyPreciseCallState(int slotIndex, int subId,
             @PreciseCallStates int ringCallPreciseState,
             @PreciseCallStates int foregroundCallPreciseState,
             @PreciseCallStates int backgroundCallPreciseState) {
@@ -790,9 +790,10 @@
      * @param reason Reason for data enabled/disabled. See {@code REASON_*} in
      * {@link TelephonyManager}.
      */
-    public void notifyDataEnabled(boolean enabled, @TelephonyManager.DataEnabledReason int reason) {
+    public void notifyDataEnabled(int slotIndex, int subId, boolean enabled,
+            @TelephonyManager.DataEnabledReason int reason) {
         try {
-            sRegistry.notifyDataEnabled(enabled, reason);
+            sRegistry.notifyDataEnabled(slotIndex, subId, enabled, reason);
         } catch (RemoteException ex) {
             // system server crash
         }
@@ -801,11 +802,11 @@
     /**
      * Notify emergency number list changed on certain subscription.
      *
-     * @param subId for which emergency number list changed.
      * @param slotIndex for which emergency number list changed. Can be derived from subId except
      * when subId is invalid.
+     * @param subId for which emergency number list changed.
      */
-    public void notifyAllowedNetworkTypesChanged(int subId, int slotIndex,
+    public void notifyAllowedNetworkTypesChanged(int slotIndex, int subId,
             Map<Integer, Long> allowedNetworkTypeList) {
         try {
             sRegistry.notifyAllowedNetworkTypesChanged(slotIndex, subId, allowedNetworkTypeList);
diff --git a/core/java/android/text/FontConfig.java b/core/java/android/text/FontConfig.java
index aef185c..33b7c75 100644
--- a/core/java/android/text/FontConfig.java
+++ b/core/java/android/text/FontConfig.java
@@ -18,6 +18,7 @@
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
+import android.annotation.CurrentTimeMillisLong;
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
@@ -101,7 +102,7 @@
      *
      * If there is no update, this return 0.
      */
-    public long getLastModifiedTimeMillis() {
+    public @CurrentTimeMillisLong long getLastModifiedTimeMillis() {
         return mLastModifiedTimeMillis;
     }
 
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index b229212..2b577d0 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -46,6 +46,9 @@
             "settings_do_not_restore_preserved";
     /** @hide */
     public static final String SETTINGS_PROVIDER_MODEL = "settings_provider_model";
+    /** @hide */
+    public static final String SETTINGS_USE_NEW_BACKUP_ELIGIBILITY_RULES
+            = "settings_use_new_backup_eligibility_rules";
 
     private static final Map<String, String> DEFAULT_FLAGS;
 
@@ -68,6 +71,7 @@
         DEFAULT_FLAGS.put("settings_silky_home", "false");
         DEFAULT_FLAGS.put("settings_contextual_home", "false");
         DEFAULT_FLAGS.put(SETTINGS_PROVIDER_MODEL, "false");
+        DEFAULT_FLAGS.put(SETTINGS_USE_NEW_BACKUP_ELIGIBILITY_RULES, "false");
     }
 
     private static final Set<String> PERSISTENT_FLAGS;
diff --git a/core/java/android/util/MergedConfiguration.java b/core/java/android/util/MergedConfiguration.java
index 3ac44aa..4328e08 100644
--- a/core/java/android/util/MergedConfiguration.java
+++ b/core/java/android/util/MergedConfiguration.java
@@ -33,9 +33,9 @@
  */
 public class MergedConfiguration implements Parcelable {
 
-    private Configuration mGlobalConfig = new Configuration();
-    private Configuration mOverrideConfig = new Configuration();
-    private Configuration mMergedConfig = new Configuration();
+    private final Configuration mGlobalConfig = new Configuration();
+    private final Configuration mOverrideConfig = new Configuration();
+    private final Configuration mMergedConfig = new Configuration();
 
     public MergedConfiguration() {
     }
@@ -59,15 +59,15 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeParcelable(mGlobalConfig, flags);
-        dest.writeParcelable(mOverrideConfig, flags);
-        dest.writeParcelable(mMergedConfig, flags);
+        mGlobalConfig.writeToParcel(dest, flags);
+        mOverrideConfig.writeToParcel(dest, flags);
+        mMergedConfig.writeToParcel(dest, flags);
     }
 
     public void readFromParcel(Parcel source) {
-        mGlobalConfig = source.readParcelable(Configuration.class.getClassLoader());
-        mOverrideConfig = source.readParcelable(Configuration.class.getClassLoader());
-        mMergedConfig = source.readParcelable(Configuration.class.getClassLoader());
+        mGlobalConfig.readFromParcel(source);
+        mOverrideConfig.readFromParcel(source);
+        mMergedConfig.readFromParcel(source);
     }
 
     @Override
diff --git a/core/java/android/util/RotationUtils.java b/core/java/android/util/RotationUtils.java
index 698cb77..0ac2c9c 100644
--- a/core/java/android/util/RotationUtils.java
+++ b/core/java/android/util/RotationUtils.java
@@ -24,6 +24,7 @@
 import android.annotation.Dimension;
 import android.graphics.Insets;
 import android.graphics.Matrix;
+import android.graphics.Rect;
 import android.view.Surface.Rotation;
 
 /**
@@ -73,6 +74,60 @@
     }
 
     /**
+     * Rotates bounds as if parentBounds and bounds are a group. The group is rotated from
+     * oldRotation to newRotation. This assumes that parentBounds is at 0,0 and remains at 0,0 after
+     * rotation. The bounds will be at the same physical position in parentBounds.
+     *
+     * Only 'inOutBounds' is mutated.
+     */
+    public static void rotateBounds(Rect inOutBounds, Rect parentBounds, @Rotation int oldRotation,
+            @Rotation int newRotation) {
+        rotateBounds(inOutBounds, parentBounds, deltaRotation(oldRotation, newRotation));
+    }
+
+    /**
+     * Rotates bounds as if parentBounds and bounds are a group. The group is rotated by `delta`
+     * 90-degree counter-clockwise increments. This assumes that parentBounds is at 0,0 and
+     * remains at 0,0 after rotation. The bounds will be at the same physical position in
+     * parentBounds.
+     *
+     * Only 'inOutBounds' is mutated.
+     */
+    public static void rotateBounds(Rect inOutBounds, Rect parentBounds, @Rotation int rotation) {
+        final int origLeft = inOutBounds.left;
+        final int origTop = inOutBounds.top;
+        switch (rotation) {
+            case ROTATION_0:
+                return;
+            case ROTATION_90:
+                inOutBounds.left = inOutBounds.top;
+                inOutBounds.top = parentBounds.right - inOutBounds.right;
+                inOutBounds.right = inOutBounds.bottom;
+                inOutBounds.bottom = parentBounds.right - origLeft;
+                return;
+            case ROTATION_180:
+                inOutBounds.left = parentBounds.right - inOutBounds.right;
+                inOutBounds.right = parentBounds.right - origLeft;
+                inOutBounds.top = parentBounds.bottom - inOutBounds.bottom;
+                inOutBounds.bottom = parentBounds.bottom - origTop;
+                return;
+            case ROTATION_270:
+                inOutBounds.left = parentBounds.bottom - inOutBounds.bottom;
+                inOutBounds.bottom = inOutBounds.right;
+                inOutBounds.right = parentBounds.bottom - inOutBounds.top;
+                inOutBounds.top = origLeft;
+        }
+    }
+
+    /** @return the rotation needed to rotate from oldRotation to newRotation. */
+    @Rotation
+    public static int deltaRotation(int oldRotation, int newRotation) {
+        int delta = newRotation - oldRotation;
+        if (delta < 0) delta += 4;
+        return delta;
+    }
+
+    /**
      * Sets a matrix such that given a rotation, it transforms physical display
      * coordinates to that rotation's logical coordinates.
      *
diff --git a/core/java/android/uwb/AngleOfArrivalSupport.aidl b/core/java/android/uwb/AngleOfArrivalSupport.aidl
deleted file mode 100644
index 57666ff..0000000
--- a/core/java/android/uwb/AngleOfArrivalSupport.aidl
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-/**
- * @hide
- */
-@Backing(type="int")
-enum AngleOfArrivalSupport {
-  /**
-   * The device does not support angle of arrival
-   */
-  NONE,
-
-  /**
-   * The device supports planar angle of arrival
-   */
-  TWO_DIMENSIONAL,
-
-  /**
-   * The device does supports three dimensional angle of arrival with hemispherical azimuth angles
-   */
-  THREE_DIMENSIONAL_HEMISPHERICAL,
-
-  /**
-   * The device does supports three dimensional angle of arrival with full azimuth angles
-   */
-  THREE_DIMENSIONAL_SPHERICAL,
-}
-
diff --git a/core/java/android/uwb/IUwbAdapter.aidl b/core/java/android/uwb/IUwbAdapter.aidl
index b9c5508..468a69c 100644
--- a/core/java/android/uwb/IUwbAdapter.aidl
+++ b/core/java/android/uwb/IUwbAdapter.aidl
@@ -17,7 +17,6 @@
 package android.uwb;
 
 import android.os.PersistableBundle;
-import android.uwb.AngleOfArrivalSupport;
 import android.uwb.IUwbAdapterStateCallbacks;
 import android.uwb.IUwbRangingCallbacks;
 import android.uwb.SessionHandle;
@@ -47,43 +46,6 @@
   void unregisterAdapterStateCallbacks(in IUwbAdapterStateCallbacks callbacks);
 
   /**
-   * Returns true if ranging is supported, false otherwise
-   */
-  boolean isRangingSupported();
-
-  /**
-   * Get the angle of arrival supported by this device
-   *
-   * @return the angle of arrival type supported
-   */
-  AngleOfArrivalSupport getAngleOfArrivalSupport();
-
-  /**
-   * Generates a list of the supported 802.15.4z channels
-   *
-   * The list must be prioritized in the order of preferred channel usage.
-   *
-   * The list must only contain channels that are permitted to be used in the
-   * device's current location.
-   *
-   * @return an array of support channels on the device for the current location.
-   */
-  int[] getSupportedChannels();
-
-  /**
-   * Generates a list of the supported 802.15.4z preamble codes
-   *
-   * The list must be prioritized in the order of preferred preamble usage.
-   *
-   * The list must only contain preambles that are permitted to be used in the
-   * device's current location.
-   *
-   * @return an array of supported preambles on the device for the current
-   *         location.
-   */
-  int[] getSupportedPreambleCodes();
-
-  /**
    * Get the accuracy of the ranging timestamps
    *
    * @return accuracy of the ranging timestamps in nanoseconds
@@ -91,27 +53,6 @@
   long getTimestampResolutionNanos();
 
   /**
-   * Get the supported number of simultaneous ranging sessions
-   *
-   * @return the supported number of simultaneous ranging sessions
-   */
-  int getMaxSimultaneousSessions();
-
-  /**
-   * Get the maximum number of remote devices per session when local device is initiator
-   *
-   * @return the maximum number of remote devices supported in a single session
-   */
-  int getMaxRemoteDevicesPerInitiatorSession();
-
-  /**
-   * Get the maximum number of remote devices per session when local device is responder
-   *
-   * @return the maximum number of remote devices supported in a single session
-   */
-  int getMaxRemoteDevicesPerResponderSession();
-
-  /**
    * Provides the capabilities and features of the device
    *
    * @return specification specific capabilities and features of the device
diff --git a/core/java/android/uwb/OWNERS b/core/java/android/uwb/OWNERS
index ea41c39..17936ae 100644
--- a/core/java/android/uwb/OWNERS
+++ b/core/java/android/uwb/OWNERS
@@ -1,5 +1,6 @@
 bstack@google.com
 eliptus@google.com
 jsolnit@google.com
+matbev@google.com
 siyuanh@google.com
 zachoverflow@google.com
diff --git a/core/java/android/uwb/TEST_MAPPING b/core/java/android/uwb/TEST_MAPPING
index 9e50bd6..08ed2c7 100644
--- a/core/java/android/uwb/TEST_MAPPING
+++ b/core/java/android/uwb/TEST_MAPPING
@@ -2,6 +2,9 @@
   "presubmit": [
     {
       "name": "UwbManagerTests"
+    },
+    {
+      "name": "CtsUwbTestCases"
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/core/java/android/uwb/UwbManager.java b/core/java/android/uwb/UwbManager.java
index 2dc0ba0..63a6d05 100644
--- a/core/java/android/uwb/UwbManager.java
+++ b/core/java/android/uwb/UwbManager.java
@@ -32,10 +32,6 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
 import java.util.concurrent.Executor;
 
 /**
@@ -195,133 +191,6 @@
     }
 
     /**
-     * Check if ranging is supported, regardless of ranging method
-     *
-     * @return true if ranging is supported
-     */
-    @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
-    public boolean isRangingSupported() {
-        try {
-            return mUwbAdapter.isRangingSupported();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * @hide
-     */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(value = {
-            ANGLE_OF_ARRIVAL_SUPPORT_TYPE_NONE,
-            ANGLE_OF_ARRIVAL_SUPPORT_TYPE_2D,
-            ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_HEMISPHERICAL,
-            ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_SPHERICAL})
-    public @interface AngleOfArrivalSupportType {}
-
-    /**
-     * Indicate absence of support for angle of arrival measurement
-     */
-    public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_NONE = 1;
-
-    /**
-     * Indicate support for planar angle of arrival measurement, due to antenna
-     * limitation. Typically requires at least two antennas.
-     */
-    public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_2D = 2;
-
-    /**
-     * Indicate support for three dimensional angle of arrival measurement.
-     * Typically requires at least three antennas. However, due to antenna
-     * arrangement, a platform may only support hemi-spherical azimuth angles
-     * ranging from -pi/2 to pi/2
-     */
-    public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_HEMISPHERICAL = 3;
-
-    /**
-     * Indicate support for three dimensional angle of arrival measurement.
-     * Typically requires at least three antennas. This mode supports full
-     * azimuth angles ranging from -pi to pi.
-     */
-    public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_SPHERICAL = 4;
-
-    /**
-     * Gets the {@link AngleOfArrivalSupportType} supported on this platform
-     * <p>Possible return values are
-     * {@link #ANGLE_OF_ARRIVAL_SUPPORT_TYPE_NONE},
-     * {@link #ANGLE_OF_ARRIVAL_SUPPORT_TYPE_2D},
-     * {@link #ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_HEMISPHERICAL},
-     * {@link #ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_SPHERICAL}.
-     *
-     * @return angle of arrival type supported
-     */
-    @AngleOfArrivalSupportType
-    @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
-    public int getAngleOfArrivalSupport() {
-        try {
-            switch (mUwbAdapter.getAngleOfArrivalSupport()) {
-                case AngleOfArrivalSupport.TWO_DIMENSIONAL:
-                    return ANGLE_OF_ARRIVAL_SUPPORT_TYPE_2D;
-
-                case AngleOfArrivalSupport.THREE_DIMENSIONAL_HEMISPHERICAL:
-                    return ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_HEMISPHERICAL;
-
-                case AngleOfArrivalSupport.THREE_DIMENSIONAL_SPHERICAL:
-                    return ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_SPHERICAL;
-
-                case AngleOfArrivalSupport.NONE:
-                default:
-                    return ANGLE_OF_ARRIVAL_SUPPORT_TYPE_NONE;
-            }
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Get a {@link List} of supported channel numbers based on the device's current location
-     * <p>The returned values are ordered by the system's desired ordered of use, with the first
-     * entry being the most preferred.
-     *
-     * <p>Channel numbers are defined based on the IEEE 802.15.4z standard for UWB.
-     *
-     * @return {@link List} of supported channel numbers ordered by preference
-     */
-    @NonNull
-    @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
-    public List<Integer> getSupportedChannelNumbers() {
-        List<Integer> channels = new ArrayList<>();
-        try {
-            for (int channel : mUwbAdapter.getSupportedChannels()) {
-                channels.add(channel);
-            }
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-        return channels;
-    }
-
-    /**
-     * Get a {@link List} of supported preamble code indices
-     * <p> Preamble code indices are defined based on the IEEE 802.15.4z standard for UWB.
-     *
-     * @return {@link List} of supported preamble code indices
-     */
-    @NonNull
-    @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
-    public Set<Integer> getSupportedPreambleCodeIndices() {
-        Set<Integer> preambles = new HashSet<>();
-        try {
-            for (int preamble : mUwbAdapter.getSupportedPreambleCodes()) {
-                preambles.add(preamble);
-            }
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-        return preambles;
-    }
-
-    /**
      * Get the timestamp resolution for events in nanoseconds
      * <p>This value defines the maximum error of all timestamps for events reported to
      * {@link RangingSession.Callback}.
@@ -339,50 +208,6 @@
     }
 
     /**
-     * Get the number of simultaneous sessions allowed in the system
-     *
-     * @return the maximum allowed number of simultaneously open {@link RangingSession} instances.
-     */
-    @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
-    public int getMaxSimultaneousSessions() {
-        try {
-            return mUwbAdapter.getMaxSimultaneousSessions();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Get the maximum number of remote devices in a {@link RangingSession} when the local device
-     * is the initiator.
-     *
-     * @return the maximum number of remote devices per {@link RangingSession}
-     */
-    @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
-    public int getMaxRemoteDevicesPerInitiatorSession() {
-        try {
-            return mUwbAdapter.getMaxRemoteDevicesPerInitiatorSession();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Get the maximum number of remote devices in a {@link RangingSession} when the local device
-     * is a responder.
-     *
-     * @return the maximum number of remote devices per {@link RangingSession}
-     */
-    @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
-    public int getMaxRemoteDevicesPerResponderSession() {
-        try {
-            return mUwbAdapter.getMaxRemoteDevicesPerResponderSession();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Open a {@link RangingSession} with the given parameters
      * <p>The {@link RangingSession.Callback#onOpened(RangingSession)} function is called with a
      * {@link RangingSession} object used to control ranging when the session is successfully
diff --git a/core/java/android/view/CrossWindowBlurListeners.java b/core/java/android/view/CrossWindowBlurListeners.java
new file mode 100644
index 0000000..5a1b850
--- /dev/null
+++ b/core/java/android/view/CrossWindowBlurListeners.java
@@ -0,0 +1,137 @@
+/**
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.SystemProperties;
+import android.util.ArraySet;
+import android.util.Log;
+
+import java.util.function.Consumer;
+
+/**
+ * Class that holds all registered {@link CrossWindowBlurEnabledListener}s. It listens
+ * for updates from the WindowManagerService and updates all registered listeners.
+ * @hide
+ */
+public final class CrossWindowBlurListeners {
+    private static final String TAG = "CrossWindowBlurListeners";
+
+    // property for background blur support in surface flinger
+    private static final String BLUR_PROPERTY = "ro.surface_flinger.supports_background_blur";
+    public static final boolean CROSS_WINDOW_BLUR_SUPPORTED =
+            SystemProperties.get(BLUR_PROPERTY, "default").equals("1");
+
+    private static volatile CrossWindowBlurListeners sInstance;
+    private static final Object sLock = new Object();
+
+    private final BlurEnabledListenerInternal mListenerInternal = new BlurEnabledListenerInternal();
+    private final ArraySet<Consumer<Boolean>> mListeners = new ArraySet();
+    private final Handler mMainHandler = new Handler(Looper.getMainLooper());
+    private boolean mInternalListenerAttached = false;
+    private boolean mCrossWindowBlurEnabled;
+
+    private CrossWindowBlurListeners() {}
+
+    /**
+     * Returns a CrossWindowBlurListeners instance
+     */
+    public static CrossWindowBlurListeners getInstance() {
+        CrossWindowBlurListeners instance = sInstance;
+        if (instance == null) {
+
+            synchronized (sLock) {
+                instance = sInstance;
+                if (instance == null) {
+                    instance = new CrossWindowBlurListeners();
+                    sInstance = instance;
+                }
+            }
+        }
+        return instance;
+    }
+
+    boolean isCrossWindowBlurEnabled() {
+        synchronized (sLock) {
+            attachInternalListenerIfNeededLocked();
+            return mCrossWindowBlurEnabled;
+        }
+    }
+
+    void addListener(Consumer<Boolean> listener) {
+        if (listener == null) return;
+
+        synchronized (sLock) {
+            attachInternalListenerIfNeededLocked();
+
+            mListeners.add(listener);
+            notifyListenerOnMain(listener, mCrossWindowBlurEnabled);
+        }
+    }
+
+
+    void removeListener(Consumer<Boolean> listener) {
+        if (listener == null) return;
+
+        synchronized (sLock) {
+            mListeners.remove(listener);
+
+            if (mInternalListenerAttached && mListeners.size() == 0) {
+                try {
+                    WindowManagerGlobal.getWindowManagerService()
+                            .unregisterCrossWindowBlurEnabledListener(mListenerInternal);
+                    mInternalListenerAttached = false;
+                } catch (RemoteException e) {
+                    Log.d(TAG, "Could not unregister ICrossWindowBlurEnabledListener");
+                }
+            }
+        }
+    }
+
+    private void attachInternalListenerIfNeededLocked() {
+        if (!mInternalListenerAttached) {
+            try {
+                mCrossWindowBlurEnabled = WindowManagerGlobal.getWindowManagerService()
+                        .registerCrossWindowBlurEnabledListener(mListenerInternal);
+                mInternalListenerAttached = true;
+            } catch (RemoteException e) {
+                Log.d(TAG, "Could not register ICrossWindowBlurEnabledListener");
+            }
+        }
+    }
+
+    private void notifyListenerOnMain(Consumer<Boolean> listener, boolean enabled) {
+        mMainHandler.post(() -> {
+            listener.accept(enabled);
+        });
+    }
+
+    private final class BlurEnabledListenerInternal extends ICrossWindowBlurEnabledListener.Stub {
+        @Override
+        public void onCrossWindowBlurEnabledChanged(boolean enabled) {
+            synchronized (sLock) {
+                mCrossWindowBlurEnabled = enabled;
+
+                for (int i = 0; i < mListeners.size(); i++) {
+                    notifyListenerOnMain(mListeners.valueAt(i), enabled);
+                }
+            }
+        }
+    }
+}
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 0ba1dfe..8117c96 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -34,6 +34,7 @@
 import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.hardware.display.DeviceProductInfo;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManagerGlobal;
 import android.os.Build;
@@ -1181,6 +1182,18 @@
     }
 
     /**
+     * Returns the product-specific information about the display or the directly connected
+     * device on the display chain.
+     * For example, if the display is transitively connected, this field may contain product
+     * information about the intermediate device.
+     * Returns {@code null} if product information is not available.
+     */
+    @Nullable
+    public DeviceProductInfo getDeviceProductInfo() {
+        return mDisplayInfo.deviceProductInfo;
+    }
+
+    /**
      * Gets display metrics that describe the size and density of this display.
      * The size returned by this method does not necessarily represent the
      * actual raw size (native resolution) of the display.
diff --git a/core/java/android/view/FrameMetrics.java b/core/java/android/view/FrameMetrics.java
index 6543de1..eb49e52 100644
--- a/core/java/android/view/FrameMetrics.java
+++ b/core/java/android/view/FrameMetrics.java
@@ -213,8 +213,7 @@
             Index.FRAME_TIMELINE_VSYNC_ID,
             Index.INTENDED_VSYNC,
             Index.VSYNC,
-            Index.OLDEST_INPUT_EVENT,
-            Index.NEWEST_INPUT_EVENT,
+            Index.INPUT_EVENT_ID,
             Index.HANDLE_INPUT_START,
             Index.ANIMATION_START,
             Index.PERFORM_TRAVERSALS_START,
@@ -225,8 +224,11 @@
             Index.ISSUE_DRAW_COMMANDS_START,
             Index.SWAP_BUFFERS,
             Index.FRAME_COMPLETED,
+            Index.DEQUEUE_BUFFER_DURATION,
+            Index.QUEUE_BUFFER_DURATION,
             Index.GPU_COMPLETED,
-            Index.SWAP_BUFFERS_COMPLETED
+            Index.SWAP_BUFFERS_COMPLETED,
+            Index.DISPLAY_PRESENT_TIME,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface Index {
@@ -234,20 +236,22 @@
         int FRAME_TIMELINE_VSYNC_ID = 1;
         int INTENDED_VSYNC = 2;
         int VSYNC = 3;
-        int OLDEST_INPUT_EVENT = 4;
-        int NEWEST_INPUT_EVENT = 5;
-        int HANDLE_INPUT_START = 6;
-        int ANIMATION_START = 7;
-        int PERFORM_TRAVERSALS_START = 8;
-        int DRAW_START = 9;
-        int FRAME_DEADLINE = 10;
-        int SYNC_QUEUED = 11;
-        int SYNC_START = 12;
-        int ISSUE_DRAW_COMMANDS_START = 13;
-        int SWAP_BUFFERS = 14;
-        int FRAME_COMPLETED = 15;
-        int GPU_COMPLETED = 18;
-        int SWAP_BUFFERS_COMPLETED = 19;
+        int INPUT_EVENT_ID = 4;
+        int HANDLE_INPUT_START = 5;
+        int ANIMATION_START = 6;
+        int PERFORM_TRAVERSALS_START = 7;
+        int DRAW_START = 8;
+        int FRAME_DEADLINE = 9;
+        int SYNC_QUEUED = 10;
+        int SYNC_START = 11;
+        int ISSUE_DRAW_COMMANDS_START = 12;
+        int SWAP_BUFFERS = 13;
+        int FRAME_COMPLETED = 14;
+        int DEQUEUE_BUFFER_DURATION = 15;
+        int QUEUE_BUFFER_DURATION = 16;
+        int GPU_COMPLETED = 17;
+        int SWAP_BUFFERS_COMPLETED = 18;
+        int DISPLAY_PRESENT_TIME = 19;
 
         int FRAME_STATS_COUNT = 20; // must always be last and in sync with
                                     // FrameInfoIndex::NumIndexes in libs/hwui/FrameInfo.h
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockModule.java b/core/java/android/view/ICrossWindowBlurEnabledListener.aidl
similarity index 61%
rename from packages/SystemUI/src/com/android/keyguard/clock/ClockModule.java
rename to core/java/android/view/ICrossWindowBlurEnabledListener.aidl
index c4be1ba535..69286e2 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockModule.java
+++ b/core/java/android/view/ICrossWindowBlurEnabledListener.aidl
@@ -14,20 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.keyguard.clock;
+package android.view;
 
-import java.util.List;
-
-import dagger.Module;
-import dagger.Provides;
-
-/** Dagger Module for clock package. */
-@Module
-public abstract class ClockModule {
-
-    /** */
-    @Provides
-    public static List<ClockInfo> provideClockInfoList(ClockManager clockManager) {
-        return clockManager.getClockInfos();
-    }
+/**
+ * Listener to be invoked when cross-window blur is enabled or disabled.
+ * {@hide}
+ */
+oneway interface ICrossWindowBlurEnabledListener {
+    /**
+     * Method that will be invoked when cross-window blur is enabled or disabled.
+     * @param enabled True if cross-window blur is enabled.
+     */
+    void onCrossWindowBlurEnabledChanged(boolean enabled);
 }
diff --git a/core/java/android/view/IPinnedStackListener.aidl b/core/java/android/view/IPinnedTaskListener.aidl
similarity index 95%
rename from core/java/android/view/IPinnedStackListener.aidl
rename to core/java/android/view/IPinnedTaskListener.aidl
index 29c9c15..c31e67e 100644
--- a/core/java/android/view/IPinnedStackListener.aidl
+++ b/core/java/android/view/IPinnedTaskListener.aidl
@@ -23,11 +23,11 @@
 import android.view.DisplayInfo;
 
 /**
- * Listener for changes to the pinned stack made by the WindowManager.
+ * Listener for changes to the pinned task made by the WindowManager.
  *
  * @hide
  */
-oneway interface IPinnedStackListener {
+oneway interface IPinnedTaskListener {
 
     /**
      * Called when the window manager has detected a change that would cause the movement bounds
diff --git a/core/java/android/view/IScrollCaptureCallbacks.aidl b/core/java/android/view/IScrollCaptureCallbacks.aidl
index d97e3c6..26eaac0 100644
--- a/core/java/android/view/IScrollCaptureCallbacks.aidl
+++ b/core/java/android/view/IScrollCaptureCallbacks.aidl
@@ -16,12 +16,10 @@
 
 package android.view;
 
-import android.graphics.Point;
 import android.graphics.Rect;
+import android.view.ScrollCaptureResponse;
 import android.view.Surface;
 
-import android.view.IScrollCaptureConnection;
-
 /**
  * Asynchronous callback channel for responses to scroll capture requests.
  *
@@ -29,34 +27,30 @@
  */
 interface IScrollCaptureCallbacks {
     /**
-     * Scroll capture is available, and a connection has been provided.
+     * Provides the result of WindowManagerService#requestScrollCapture
      *
-     * @param connection a connection to a window process and scrollable content
-     * @param scrollAreaInWindow the location of scrolling in global (window) coordinate space
+     * @param response the response which describes the result
      */
-    oneway void onConnected(in IScrollCaptureConnection connection, in Rect scrollBounds,
-            in Point positionInWindow);
+    oneway void onScrollCaptureResponse(in ScrollCaptureResponse response);
 
     /**
-     * The window does not support scroll capture.
-     */
-    oneway void onUnavailable();
-
-    /**
-     * Called when the remote end has confirmed the request and is ready to begin providing image
-     * requests.
+     * Called in reply to IScrollCaptureConnection#startCapture, when the remote end has confirmed
+     * the request and is ready to begin capturing images.
      */
     oneway void onCaptureStarted();
 
     /**
-     * Received a response from a capture request.
+     * Received a response from a capture request. The provided rectangle indicates the portion
+     * of the requested rectangle which was captured. An empty rectangle indicates that the request
+     * could not be satisfied (most commonly due to the available scrolling range).
+     *
+     * @param flags flags describing additional status of the result
+     * @param capturedArea the actual area of the image captured
      */
-    oneway void onCaptureBufferSent(long frameNumber, in Rect capturedArea);
+    oneway void onImageRequestCompleted(int flags, in Rect capturedArea);
 
     /**
-     * Signals that the capture session has completed and the target window may be returned to
-     * normal interactive use. This may be due to normal shutdown, or after a timeout or other
-     * unrecoverable state change such as activity lifecycle, window visibility or focus.
+     * Signals that the capture session has completed and the target window is ready for normal use.
      */
-    oneway void onConnectionClosed();
+    oneway void onCaptureEnded();
 }
diff --git a/core/java/android/view/IScrollCaptureConnection.aidl b/core/java/android/view/IScrollCaptureConnection.aidl
index 63a4f48..c55e888 100644
--- a/core/java/android/view/IScrollCaptureConnection.aidl
+++ b/core/java/android/view/IScrollCaptureConnection.aidl
@@ -17,33 +17,45 @@
 package android.view;
 
 import android.graphics.Rect;
+import android.os.ICancellationSignal;
 import android.view.Surface;
 
 
  /**
-   * Interface implemented by a client of the Scroll Capture framework to receive requests
-   * to start, capture images and end the session.
+   * A remote connection to a scroll capture target.
    *
    * {@hide}
    */
 interface IScrollCaptureConnection {
 
     /**
-     * Informs the client that it has been selected for scroll capture and should prepare to
-     * to begin handling capture requests.
-     */
-    oneway void startCapture(in Surface surface);
-
-    /**
-     * Request the client capture an image within the provided rectangle.
+     * Informs the target that it has been selected for scroll capture.
      *
-     * @see android.view.ScrollCaptureCallback#onScrollCaptureRequest
+     * @param surface a return channel for image buffers
+     *
+     * @return a cancallation signal which is used cancel the request
      */
-    oneway void requestImage(in Rect captureArea);
+    ICancellationSignal startCapture(in Surface surface);
 
     /**
-     * Inform the client that capture has ended. The client should shut down and release all
-     * local resources in use and prepare for return to normal interactive usage.
+     * Request the target capture an image within the provided rectangle.
+     *
+     * @param surface a return channel for image buffers
+     * @param signal a cancallation signal which can interrupt the request
+     *
+     * @return a cancallation signal which is used cancel the request
      */
-    oneway void endCapture();
+    ICancellationSignal requestImage(in Rect captureArea);
+
+    /**
+     * Inform the target that capture has ended.
+     *
+     * @return a cancallation signal which is used cancel the request
+     */
+    ICancellationSignal endCapture();
+
+    /**
+     * Closes the connection.
+     */
+    oneway void close();
 }
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 62f4b86..5477800 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -32,17 +32,16 @@
 import android.os.Bundle;
 import android.os.IRemoteCallback;
 import android.os.ParcelFileDescriptor;
-import android.service.screenshot.ScreenshotHash;
 import android.view.DisplayCutout;
 import android.view.IApplicationToken;
 import android.view.IAppTransitionAnimationSpecsFuture;
-import android.view.IDockedStackListener;
+import android.view.ICrossWindowBlurEnabledListener;
 import android.view.IDisplayWindowInsetsController;
 import android.view.IDisplayWindowListener;
 import android.view.IDisplayFoldListener;
 import android.view.IDisplayWindowRotationController;
 import android.view.IOnKeyguardExitResult;
-import android.view.IPinnedStackListener;
+import android.view.IPinnedTaskListener;
 import android.view.IScrollCaptureCallbacks;
 import android.view.RemoteAnimationAdapter;
 import android.view.IRotationWatcher;
@@ -63,6 +62,8 @@
 import android.view.WindowContentFrameStats;
 import android.view.WindowManager;
 import android.view.SurfaceControl;
+import android.view.displayhash.DisplayHash;
+import android.view.displayhash.VerifiedDisplayHash;
 
 /**
  * System private interface to the window manager.
@@ -445,12 +446,12 @@
      * Sets the region the user can touch the divider. This region will be excluded from the region
      * which is used to cause a focus switch when dispatching touch.
      */
-    void setDockedStackDividerTouchRegion(in Rect touchableRegion);
+    void setDockedTaskDividerTouchRegion(in Rect touchableRegion);
 
     /**
-     * Registers a listener that will be called when the pinned stack state changes.
+     * Registers a listener that will be called when the pinned task state changes.
      */
-    void registerPinnedStackListener(int displayId, IPinnedStackListener listener);
+    void registerPinnedTaskListener(int displayId, IPinnedTaskListener listener);
 
     /**
      * Requests Keyboard Shortcuts from the displayed window.
@@ -730,7 +731,7 @@
     void showGlobalActions();
 
     /**
-     * Sets layer tracing flags for SurfaceFlingerTrace. 
+     * Sets layer tracing flags for SurfaceFlingerTrace.
      *
      * @param flags see definition in SurfaceTracing.cpp
      */
@@ -757,23 +758,23 @@
     void holdLock(in IBinder token, in int durationMs);
 
     /**
-     * Gets an array of support hashing algorithms that can be used to generate the hash of the
-     * screenshot. The String value of one algorithm should be used when requesting to generate
-     * the ScreenshotHash.
+     * Gets an array of support hash algorithms that can be used to generate a DisplayHash. The
+     * String value of one algorithm should be used when requesting to generate
+     * the DisplayHash.
      *
-     * @return a String array of supported hashing algorithms.
+     * @return a String array of supported hash algorithms.
      */
-    String[] getSupportedScreenshotHashingAlgorithms();
+    String[] getSupportedDisplayHashAlgorithms();
 
     /**
-     * Validate the ScreenshotHash was generated by the system. The ScreenshotHash passed in
-     * should be the token generated when calling {@link IWindowSession#generateScreenshotHash}
+     * Validate the DisplayHash was generated by the system. The DisplayHash passed in should be
+     * the object generated when calling {@link IWindowSession#generateDisplayHash}
      *
-     * @param ScreenshotHash The token to verify that it was generated by the system.
-     * @return true if the token was generated by the system or false if the token cannot be
-     *         verified.
+     * @param DisplayHash The hash to verify that it was generated by the system.
+     * @return a {@link VerifiedDisplayHash} if the hash was generated by the system or null
+     * if the token cannot be verified.
      */
-    boolean verifyScreenshotHash(in ScreenshotHash screenshotHash);
+    VerifiedDisplayHash verifyDisplayHash(in DisplayHash displayHash);
 
     /**
      * Registers a listener for a {@link android.app.WindowContext} to handle configuration changes
@@ -799,4 +800,20 @@
      * @param clientToken the window context's token
      */
     void unregisterWindowContextListener(IBinder clientToken);
+
+    /**
+     * Registers a listener, which is to be called whenever cross-window blur is enabled/disabled.
+     *
+     * @param listener the listener to be registered
+     * @return true if cross-window blur is currently enabled; false otherwise
+     */
+    boolean registerCrossWindowBlurEnabledListener(ICrossWindowBlurEnabledListener listener);
+
+    /**
+     * Unregisters a listener which was registered with
+     * {@link #registerCrossWindowBlurEnabledListener()}.
+     *
+     * @param listener the listener to be unregistered
+     */
+    void unregisterCrossWindowBlurEnabledListener(ICrossWindowBlurEnabledListener listener);
 }
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index dad932c..ce649cc 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -22,7 +22,7 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.os.Bundle;
-import android.service.screenshot.ScreenshotHash;
+import android.os.RemoteCallback;
 import android.util.MergedConfiguration;
 import android.view.DisplayCutout;
 import android.view.InputChannel;
@@ -337,14 +337,15 @@
     void grantEmbeddedWindowFocus(IWindow window, in IBinder inputToken, boolean grantFocus);
 
     /**
-     * Generates an ScreenshotHash that can be used to validate whether specific content was on
+     * Generates an DisplayHash that can be used to validate whether specific content was on
      * screen.
      *
-     * @param window The token for the window where the view to screenshot is shown.
-     * @param boundsInWindow The size and position of the ads view in the window
-     * @param hashAlgorithm The String for the hashing algorithm to use based on values returned
-     *                      from {@link IWindowManager#getSupportedHashingAlgorithms()}
+     * @param window The token for the window to generate the hash of.
+     * @param boundsInWindow The size and position in the window of where to generate the hash.
+     * @param hashAlgorithm The String for the hash algorithm to use based on values returned
+     *                      from {@link IWindowManager#getSupportedDisplayHashAlgorithms()}
+     * @param callback The callback invoked to get the results of generateDisplayHash
      */
-    ScreenshotHash generateScreenshotHash(IWindow window, in Rect boundsInWindow,
-            in String hashAlgorithm);
+    oneway void generateDisplayHash(IWindow window, in Rect boundsInWindow,
+            in String hashAlgorithm, in RemoteCallback callback);
 }
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 59e4931..fafb885 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -26,6 +26,7 @@
 import android.hardware.SensorManager;
 import android.hardware.input.InputDeviceIdentifier;
 import android.hardware.input.InputManager;
+import android.hardware.lights.LightsManager;
 import android.os.Build;
 import android.os.NullVibrator;
 import android.os.Parcel;
@@ -89,6 +90,9 @@
     @GuardedBy("mMotionRanges")
     private Battery mBattery;
 
+    @GuardedBy("mMotionRanges")
+    private LightsManager mLightsManager;
+
     /**
      * A mask for input source classes.
      *
@@ -859,6 +863,21 @@
     }
 
     /**
+     * Gets the lights manager associated with the device, if there is one.
+     * Even if the device does not have lights, the result is never null.
+     * Use {@link LightsManager#getLights} to determine whether any lights is
+     * present.
+     *
+     * @return The lights manager associated with the device, never null.
+     */
+    public @NonNull LightsManager getLightsManager() {
+        if (mLightsManager == null) {
+            mLightsManager = InputManager.getInstance().getInputDeviceLightsManager(mId);
+        }
+        return mLightsManager;
+    }
+
+    /**
      * Gets the sensor manager service associated with the input device.
      * Even if the device does not have a sensor, the result is never null.
      * Use {@link SensorManager#getSensorList} to get a full list of all supported sensors.
diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java
index 2f40bdbf..e6cf683 100644
--- a/core/java/android/view/InsetsSource.java
+++ b/core/java/android/view/InsetsSource.java
@@ -140,7 +140,11 @@
         if (getType() == ITYPE_CAPTION_BAR) {
             return Insets.of(0, frame.height(), 0, 0);
         }
-        if (!getIntersection(frame, relativeFrame, mTmpFrame)) {
+        // Checks for whether there is shared edge with insets for 0-width/height window.
+        final boolean hasIntersection = relativeFrame.isEmpty()
+                ? getIntersection(frame, relativeFrame, mTmpFrame)
+                : mTmpFrame.setIntersect(frame, relativeFrame);
+        if (!hasIntersection) {
             return Insets.NONE;
         }
 
@@ -257,11 +261,7 @@
 
     public InsetsSource(Parcel in) {
         mType = in.readInt();
-        if (in.readInt() != 0) {
-            mFrame = Rect.CREATOR.createFromParcel(in);
-        } else {
-            mFrame = null;
-        }
+        mFrame = Rect.CREATOR.createFromParcel(in);
         if (in.readInt() != 0) {
             mVisibleFrame = Rect.CREATOR.createFromParcel(in);
         } else {
@@ -278,12 +278,7 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(mType);
-        if (mFrame != null) {
-            dest.writeInt(1);
-            mFrame.writeToParcel(dest, 0);
-        } else {
-            dest.writeInt(0);
-        }
+        mFrame.writeToParcel(dest, 0);
         if (mVisibleFrame != null) {
             dest.writeInt(1);
             mVisibleFrame.writeToParcel(dest, 0);
diff --git a/core/java/android/view/InsetsSourceControl.java b/core/java/android/view/InsetsSourceControl.java
index c717c2a..1d4b411 100644
--- a/core/java/android/view/InsetsSourceControl.java
+++ b/core/java/android/view/InsetsSourceControl.java
@@ -77,8 +77,8 @@
 
     public InsetsSourceControl(Parcel in) {
         mType = in.readInt();
-        mLeash = in.readParcelable(null /* loader */);
-        mSurfacePosition = in.readParcelable(null /* loader */);
+        mLeash = in.readTypedObject(SurfaceControl.CREATOR);
+        mSurfacePosition = in.readTypedObject(Point.CREATOR);
         mSkipAnimationOnce = in.readBoolean();
     }
 
@@ -119,8 +119,8 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(mType);
-        dest.writeParcelable(mLeash, 0 /* flags*/);
-        dest.writeParcelable(mSurfacePosition, 0 /* flags*/);
+        dest.writeTypedObject(mLeash, 0 /* parcelableFlags */);
+        dest.writeTypedObject(mSurfacePosition, 0 /* parcelableFlags */);
         dest.writeBoolean(mSkipAnimationOnce);
     }
 
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 219190f..fce1952 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -20,8 +20,6 @@
 import static android.view.InsetsStateProto.DISPLAY_FRAME;
 import static android.view.InsetsStateProto.SOURCES;
 import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
-import static android.view.WindowInsets.Type.MANDATORY_SYSTEM_GESTURES;
-import static android.view.WindowInsets.Type.SYSTEM_GESTURES;
 import static android.view.WindowInsets.Type.displayCutout;
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.indexOf;
@@ -106,14 +104,11 @@
     public static final int ITYPE_NAVIGATION_BAR = 1;
     public static final int ITYPE_CAPTION_BAR = 2;
 
-    // The always visible types are visible to all windows regardless of the z-order.
-    public static final int FIRST_ALWAYS_VISIBLE_TYPE = 3;
-    public static final int ITYPE_TOP_GESTURES = FIRST_ALWAYS_VISIBLE_TYPE;
+    public static final int ITYPE_TOP_GESTURES = 3;
     public static final int ITYPE_BOTTOM_GESTURES = 4;
     public static final int ITYPE_LEFT_GESTURES = 5;
     public static final int ITYPE_RIGHT_GESTURES = 6;
 
-    /** Additional gesture inset types that map into {@link Type.MANDATORY_SYSTEM_GESTURES}. */
     public static final int ITYPE_TOP_MANDATORY_GESTURES = 7;
     public static final int ITYPE_BOTTOM_MANDATORY_GESTURES = 8;
     public static final int ITYPE_LEFT_MANDATORY_GESTURES = 9;
@@ -123,7 +118,6 @@
     public static final int ITYPE_TOP_DISPLAY_CUTOUT = 12;
     public static final int ITYPE_RIGHT_DISPLAY_CUTOUT = 13;
     public static final int ITYPE_BOTTOM_DISPLAY_CUTOUT = 14;
-    public static final int LAST_ALWAYS_VISIBLE_TYPE = ITYPE_BOTTOM_DISPLAY_CUTOUT;
 
     public static final int ITYPE_LEFT_TAPPABLE_ELEMENT = 15;
     public static final int ITYPE_TOP_TAPPABLE_ELEMENT = 16;
@@ -162,7 +156,7 @@
     static final int ISIDE_FLOATING = 4;
     static final int ISIDE_UNKNOWN = 5;
 
-    private InsetsSource[] mSources = new InsetsSource[SIZE];
+    private final InsetsSource[] mSources = new InsetsSource[SIZE];
 
     /**
      * The frame of the display these sources are relative to.
@@ -188,18 +182,6 @@
     }
 
     /**
-     * Mirror the always visible sources from the other state. They will share the same object for
-     * the always visible types.
-     *
-     * @param other the state to mirror the mirrored sources from.
-     */
-    public void mirrorAlwaysVisibleInsetsSources(InsetsState other) {
-        for (int type = FIRST_ALWAYS_VISIBLE_TYPE; type <= LAST_ALWAYS_VISIBLE_TYPE; type++) {
-            mSources[type] = other.mSources[type];
-        }
-    }
-
-    /**
      * Calculates {@link WindowInsets} based on the current source configuration.
      *
      * @param frame The frame to calculate the insets relative to.
@@ -380,14 +362,14 @@
         processSourceAsPublicType(source, typeInsetsMap, typeSideMap, typeVisibilityMap,
                 insets, type);
 
-        if (type == MANDATORY_SYSTEM_GESTURES) {
+        if (type == Type.MANDATORY_SYSTEM_GESTURES) {
             // Mandatory system gestures are also system gestures.
             // TODO: find a way to express this more generally. One option would be to define
             //       Type.systemGestureInsets() as NORMAL | MANDATORY, but then we lose the
             //       ability to set systemGestureInsets() independently from
             //       mandatorySystemGestureInsets() in the Builder.
             processSourceAsPublicType(source, typeInsetsMap, typeSideMap, typeVisibilityMap,
-                    insets, SYSTEM_GESTURES);
+                    insets, Type.SYSTEM_GESTURES);
         }
     }
 
@@ -493,9 +475,14 @@
      * to the client.
      *
      * @param type The {@link InternalInsetsType} of the source to remove
+     * @return {@code true} if this InsetsState was modified; {@code false} otherwise.
      */
-    public void removeSource(@InternalInsetsType int type) {
+    public boolean removeSource(@InternalInsetsType int type) {
+        if (mSources[type] == null) {
+            return false;
+        }
         mSources[type] = null;
+        return true;
     }
 
     /**
@@ -552,6 +539,24 @@
         }
     }
 
+    /**
+     * Sets the values from the other InsetsState. But for sources, only specific types of source
+     * would be set.
+     *
+     * @param other the other InsetsState.
+     * @param types the only types of sources would be set.
+     */
+    public void set(InsetsState other, @InsetsType int types) {
+        mDisplayFrame.set(other.mDisplayFrame);
+        mDisplayCutout.set(other.mDisplayCutout);
+        mRoundedCorners = other.getRoundedCorners();
+        final ArraySet<Integer> t = toInternalType(types);
+        for (int i = t.size() - 1; i >= 0; i--) {
+            final int type = t.valueAt(i);
+            mSources[type] = other.mSources[type];
+        }
+    }
+
     public void addSource(InsetsSource source) {
         mSources[source.getType()] = source;
     }
@@ -575,6 +580,18 @@
         if ((types & Type.CAPTION_BAR) != 0) {
             result.add(ITYPE_CAPTION_BAR);
         }
+        if ((types & Type.SYSTEM_GESTURES) != 0) {
+            result.add(ITYPE_LEFT_GESTURES);
+            result.add(ITYPE_TOP_GESTURES);
+            result.add(ITYPE_RIGHT_GESTURES);
+            result.add(ITYPE_BOTTOM_GESTURES);
+        }
+        if ((types & Type.MANDATORY_SYSTEM_GESTURES) != 0) {
+            result.add(ITYPE_LEFT_MANDATORY_GESTURES);
+            result.add(ITYPE_TOP_MANDATORY_GESTURES);
+            result.add(ITYPE_RIGHT_MANDATORY_GESTURES);
+            result.add(ITYPE_BOTTOM_MANDATORY_GESTURES);
+        }
         if ((types & Type.DISPLAY_CUTOUT) != 0) {
             result.add(ITYPE_LEFT_DISPLAY_CUTOUT);
             result.add(ITYPE_TOP_DISPLAY_CUTOUT);
@@ -787,7 +804,7 @@
     public void writeToParcel(Parcel dest, int flags) {
         mDisplayFrame.writeToParcel(dest, flags);
         mDisplayCutout.writeToParcel(dest, flags);
-        dest.writeParcelableArray(mSources, 0);
+        dest.writeTypedArray(mSources, 0 /* parcelableFlags */);
         dest.writeTypedObject(mRoundedCorners, flags);
     }
 
@@ -803,9 +820,9 @@
     };
 
     public void readFromParcel(Parcel in) {
-        mDisplayFrame.set(Rect.CREATOR.createFromParcel(in));
-        mDisplayCutout.set(DisplayCutout.ParcelableWrapper.CREATOR.createFromParcel(in));
-        mSources = in.readParcelableArray(null, InsetsSource.class);
+        mDisplayFrame.readFromParcel(in);
+        mDisplayCutout.readFromParcel(in);
+        in.readTypedArray(mSources, InsetsSource.CREATOR);
         mRoundedCorners = in.readTypedObject(RoundedCorners.CREATOR);
     }
 
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 52b7cff..d67439c 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -3768,6 +3768,41 @@
         return (getButtonState() & button) == button;
     }
 
+    /**
+     * Gets a rotation matrix that (when applied to a motionevent) will rotate that motion event
+     * such that the result coordinates end up in the same physical location on a display whose
+     * coordinates are rotated by `rotation`.
+     *
+     * For example, rotating 0,0 by 90 degrees will move a point from the physical top-left to
+     * the bottom-left of the 90-degree-rotated display.
+     *
+     * @hide
+     */
+    public static Matrix createRotateMatrix(
+            @Surface.Rotation int rotation, int displayW, int displayH) {
+        if (rotation == Surface.ROTATION_0) {
+            return new Matrix(Matrix.IDENTITY_MATRIX);
+        }
+        // values is row-major
+        float[] values = null;
+        if (rotation == Surface.ROTATION_90) {
+            values = new float[]{0, 1, 0,
+                    -1, 0, displayH,
+                    0, 0, 1};
+        } else if (rotation == Surface.ROTATION_180) {
+            values = new float[]{-1, 0, displayW,
+                    0, -1, displayH,
+                    0, 0, 1};
+        } else if (rotation == Surface.ROTATION_270) {
+            values = new float[]{0, -1, displayW,
+                    1, 0, 0,
+                    0, 0, 1};
+        }
+        Matrix toOrient = new Matrix();
+        toOrient.setValues(values);
+        return toOrient;
+    }
+
     public static final @android.annotation.NonNull Parcelable.Creator<MotionEvent> CREATOR
             = new Parcelable.Creator<MotionEvent>() {
         public MotionEvent createFromParcel(Parcel in) {
diff --git a/core/java/android/view/RoundedCorners.java b/core/java/android/view/RoundedCorners.java
index 015e804..569c287 100644
--- a/core/java/android/view/RoundedCorners.java
+++ b/core/java/android/view/RoundedCorners.java
@@ -335,7 +335,7 @@
         }
         if (o instanceof RoundedCorners) {
             RoundedCorners r = (RoundedCorners) o;
-            return Arrays.deepEquals(mRoundedCorners, ((RoundedCorners) o).mRoundedCorners);
+            return Arrays.deepEquals(mRoundedCorners, r.mRoundedCorners);
         }
         return false;
     }
diff --git a/core/java/android/view/ScrollCaptureCallback.java b/core/java/android/view/ScrollCaptureCallback.java
index d3aad2c..1688616 100644
--- a/core/java/android/view/ScrollCaptureCallback.java
+++ b/core/java/android/view/ScrollCaptureCallback.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.UiThread;
 import android.graphics.Rect;
+import android.os.CancellationSignal;
 
 import java.util.function.Consumer;
 
@@ -58,8 +59,6 @@
  * @see View#setScrollCaptureHint(int)
  * @see View#setScrollCaptureCallback(ScrollCaptureCallback)
  * @see Window#registerScrollCaptureCallback(ScrollCaptureCallback)
- *
- * @hide
  */
 @UiThread
 public interface ScrollCaptureCallback {
@@ -68,80 +67,84 @@
      * The system is searching for the appropriate scrolling container to capture and would like to
      * know the size and position of scrolling content handled by this callback.
      * <p>
-     * Implementations should inset {@code containingViewBounds} to cover only the area within the
-     * containing view where scrolling content may be positioned. This should cover only the content
-     * which tracks with scrolling movement.
+     * To determine scroll bounds, an implementation should inset the visible bounds of the
+     * containing view to cover only the area where scrolling content may be positioned. This
+     * should cover only the content which tracks with scrolling movement.
      * <p>
-     * Return the updated rectangle to {@code resultConsumer}. If for any reason the scrolling
-     * content is not available to capture, a {@code null} rectangle may be returned, and this view
-     * will be excluded as the target for this request.
+     * Return the updated rectangle to {@link Consumer#accept onReady.accept}. If for any reason the
+     * scrolling content is not available to capture, a empty rectangle may be returned which will
+     * exclude this view from consideration.
      * <p>
-     * Responses received after XXXms will be discarded.
-     * <p>
-     * TODO: finalize timeout
+     * This request may be cancelled via the provided {@link CancellationSignal}. When this happens,
+     * any future call to {@link Consumer#accept onReady.accept} will have no effect and this
+     * content will be omitted from the search results.
      *
-     * @param onReady              consumer for the updated rectangle
+     * @param signal  signal to cancel the operation in progress
+     * @param onReady consumer for the updated rectangle
      */
-    void onScrollCaptureSearch(@NonNull Consumer<Rect> onReady);
+    void onScrollCaptureSearch(@NonNull CancellationSignal signal, @NonNull Consumer<Rect> onReady);
 
     /**
      * Scroll Capture has selected this callback to provide the scrolling image content.
      * <p>
-     * The onReady signal should be called when ready to begin handling image requests.
+     * {@link Runnable#run onReady.run} should be called when ready to begin handling image
+     * requests.
+     * <p>
+     * This request may be cancelled via the provided {@link CancellationSignal}. When this happens,
+     * any future call to {@link Runnable#run onReady.run} will have no effect and provided session
+     * will not be activated.
+     *
+     * @param session the current session, resources provided by it are valid for use until the
+     *                {@link #onScrollCaptureEnd(Runnable) session ends}
+     * @param signal  signal to cancel the operation in progress
+     * @param onReady signal used to report completion of the request
      */
-    void onScrollCaptureStart(@NonNull ScrollCaptureSession session, @NonNull Runnable onReady);
+    void onScrollCaptureStart(@NonNull ScrollCaptureSession session,
+            @NonNull CancellationSignal signal, @NonNull Runnable onReady);
 
     /**
      * An image capture has been requested from the scrolling content.
      * <p>
-     * <code>captureArea</code> contains the bounds of the image requested, relative to the
-     * rectangle provided by {@link ScrollCaptureCallback#onScrollCaptureSearch}, referred to as
-     * {@code scrollBounds}.
-     * here.
+     * The requested rectangle describes an area inside the target view, relative to
+     * <code>scrollBounds</code>. The content may be offscreen, above or below the current visible
+     * portion of the target view. To handle the request, render the available portion of this
+     * rectangle to a buffer and return it via the Surface available from {@link
+     * ScrollCaptureSession#getSurface()}.
      * <p>
-     * A series of requests will step by a constant vertical amount relative to {@code
-     * scrollBounds}, moving through the scrolling range of content, above and below the current
-     * visible area. The rectangle's vertical position will not account for any scrolling movement
-     * since capture started. Implementations therefore must track any scroll position changes and
-     * subtract this distance from requests.
+     * Note: Implementations are only required to render the requested content, and may do so into
+     * off-screen buffers without scrolling if they are able.
      * <p>
-     * To handle a request, the content should be scrolled to maximize the visible area of the
-     * requested rectangle. Offset {@code captureArea} again to account for any further scrolling.
+     * The resulting available portion of the request must be computed as a portion of {@code
+     * captureArea}, and sent to signal the operation is complete, using  {@link Consumer#accept
+     * onComplete.accept}. If the requested rectangle is  partially or fully out of bounds the
+     * resulting portion should be returned. If no portion is available (outside of available
+     * content), then skip sending any buffer and report an empty Rect as result.
      * <p>
-     * Finally, clip this rectangle against scrollBounds to determine what portion, if any is
-     * visible content to capture. If the rectangle is completely clipped, set it to {@link
-     * Rect#setEmpty() empty} and skip the next step.
-     * <p>
-     * Make a copy of {@code captureArea}, transform to window coordinates and draw the window,
-     * clipped to this rectangle, into the {@link ScrollCaptureSession#getSurface() surface} at
-     * offset (0,0).
-     * <p>
-     * Finally, return the resulting {@code captureArea} using
-     * {@link ScrollCaptureSession#notifyBufferSent}.
-     * <p>
-     * If the response is not supplied within XXXms, the session will end with a call to {@link
-     * #onScrollCaptureEnd}, after which {@code session} is invalid and should be discarded.
-     * <p>
-     * TODO: finalize timeout
-     * <p>
+     * This request may be cancelled via the provided {@link CancellationSignal}. When this happens,
+     * any future call to {@link Consumer#accept onComplete.accept} will be ignored until the next
+     * request.
      *
+     * @param session the current session, resources provided by it are valid for use until the
+     *                {@link #onScrollCaptureEnd(Runnable) session ends}
+     * @param signal      signal to cancel the operation in progress
      * @param captureArea the area to capture, a rectangle within {@code scrollBounds}
+     * @param onComplete  a consumer for the captured area
      */
-    void onScrollCaptureImageRequest(
-            @NonNull ScrollCaptureSession session, @NonNull Rect captureArea);
+    void onScrollCaptureImageRequest(@NonNull ScrollCaptureSession session,
+            @NonNull CancellationSignal signal, @NonNull Rect captureArea,
+            @NonNull Consumer<Rect> onComplete);
 
     /**
      * Signals that capture has ended. Implementations should release any temporary resources or
      * references to objects in use during the capture. Any resources obtained from the session are
      * now invalid and attempts to use them after this point may throw an exception.
      * <p>
-     * The window should be returned as much as possible to its original state when capture started.
-     * At a minimum, the content should be scrolled to its original position.
+     * The window should be returned to its original state when capture started. At a minimum, the
+     * content should be scrolled to its original position.
      * <p>
-     * <code>onReady</code> should be called when the window should be made visible and
-     * interactive. The system will wait up to XXXms for this call before proceeding.
-     * <p>
-     * TODO: finalize timeout
+     * {@link Runnable#run onReady.run} should be called as soon as possible after the window is
+     * ready for normal interactive use. After the callback (or after a timeout, if not called) the
+     * screenshot tool will be dismissed and the window may become visible to the user at any time.
      *
      * @param onReady a callback to inform the system that the application has completed any
      *                cleanup and is ready to become visible
diff --git a/core/java/android/view/ScrollCaptureConnection.java b/core/java/android/view/ScrollCaptureConnection.java
index 0e6cdd1d..3456e01 100644
--- a/core/java/android/view/ScrollCaptureConnection.java
+++ b/core/java/android/view/ScrollCaptureConnection.java
@@ -18,18 +18,23 @@
 
 import static java.util.Objects.requireNonNull;
 
+import android.annotation.BinderThread;
 import android.annotation.NonNull;
 import android.annotation.UiThread;
-import android.annotation.WorkerThread;
 import android.graphics.Point;
 import android.graphics.Rect;
-import android.os.Handler;
+import android.os.CancellationSignal;
+import android.os.ICancellationSignal;
 import android.os.RemoteException;
+import android.os.Trace;
 import android.util.CloseGuard;
+import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 
-import java.util.concurrent.atomic.AtomicBoolean;
+import java.lang.ref.WeakReference;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
 
 /**
  * Mediator between a selected scroll capture target view and a remote process.
@@ -41,270 +46,276 @@
 public class ScrollCaptureConnection extends IScrollCaptureConnection.Stub {
 
     private static final String TAG = "ScrollCaptureConnection";
-    private static final int DEFAULT_TIMEOUT = 1000;
 
-    private final Handler mHandler;
-    private ScrollCaptureTarget mSelectedTarget;
-    private int mTimeoutMillis = DEFAULT_TIMEOUT;
-
-    protected Surface mSurface;
-    private IScrollCaptureCallbacks mCallbacks;
-
+    private final Object mLock = new Object();
     private final Rect mScrollBounds;
     private final Point mPositionInWindow;
     private final CloseGuard mCloseGuard;
+    private final Executor mUiThread;
 
-    // The current session instance in use by the callback.
+    private ScrollCaptureCallback mLocal;
+    private IScrollCaptureCallbacks mRemote;
+
     private ScrollCaptureSession mSession;
 
-    // Helps manage timeout callbacks registered to handler and aids testing.
-    private DelayedAction mTimeoutAction;
+    private CancellationSignal mCancellation;
+
+    private volatile boolean mStarted;
+    private volatile boolean mConnected;
 
     /**
      * Constructs a ScrollCaptureConnection.
      *
      * @param selectedTarget  the target the client is controlling
-     * @param callbacks the callbacks to reply to system requests
+     * @param remote the callbacks to reply to system requests
      *
      * @hide
      */
     public ScrollCaptureConnection(
+            @NonNull Executor uiThread,
             @NonNull ScrollCaptureTarget selectedTarget,
-            @NonNull IScrollCaptureCallbacks callbacks) {
+            @NonNull IScrollCaptureCallbacks remote) {
+        mUiThread = requireNonNull(uiThread, "<uiThread> must non-null");
         requireNonNull(selectedTarget, "<selectedTarget> must non-null");
-        requireNonNull(callbacks, "<callbacks> must non-null");
-        final Rect scrollBounds = requireNonNull(selectedTarget.getScrollBounds(),
+        mRemote = requireNonNull(remote, "<callbacks> must non-null");
+        mScrollBounds = requireNonNull(Rect.copyOrNull(selectedTarget.getScrollBounds()),
                 "target.getScrollBounds() must be non-null to construct a client");
 
-        mSelectedTarget = selectedTarget;
-        mHandler = selectedTarget.getContainingView().getHandler();
-        mScrollBounds = new Rect(scrollBounds);
+        mLocal = selectedTarget.getCallback();
         mPositionInWindow = new Point(selectedTarget.getPositionInWindow());
 
-        mCallbacks = callbacks;
         mCloseGuard = new CloseGuard();
         mCloseGuard.open("close");
-
-        selectedTarget.getContainingView().addOnAttachStateChangeListener(
-                new View.OnAttachStateChangeListener() {
-                    @Override
-                    public void onViewAttachedToWindow(View v) {
-
-                    }
-
-                    @Override
-                    public void onViewDetachedFromWindow(View v) {
-                        selectedTarget.getContainingView().removeOnAttachStateChangeListener(this);
-                        endCapture();
-                    }
-                });
+        mConnected = true;
     }
 
-    @VisibleForTesting
-    public void setTimeoutMillis(int timeoutMillis) {
-        mTimeoutMillis = timeoutMillis;
-    }
-
-    @VisibleForTesting
-    public DelayedAction getTimeoutAction() {
-        return mTimeoutAction;
-    }
-
-    private void checkConnected() {
-        if (mSelectedTarget == null || mCallbacks == null) {
-            throw new IllegalStateException("This client has been disconnected.");
-        }
-    }
-
-    private void checkStarted() {
-        if (mSession == null) {
-            throw new IllegalStateException("Capture session has not been started!");
-        }
-    }
-
-    @WorkerThread // IScrollCaptureConnection
+    @BinderThread
     @Override
-    public void startCapture(Surface surface) throws RemoteException {
+    public ICancellationSignal startCapture(Surface surface) throws RemoteException {
         checkConnected();
-        mSurface = surface;
-        scheduleTimeout(mTimeoutMillis, this::onStartCaptureTimeout);
-        mSession = new ScrollCaptureSession(mSurface, mScrollBounds, mPositionInWindow, this);
-        mHandler.post(() -> mSelectedTarget.getCallback().onScrollCaptureStart(mSession,
-                this::onStartCaptureCompleted));
+        if (!surface.isValid()) {
+            throw new RemoteException(new IllegalArgumentException("surface must be valid"));
+        }
+
+        ICancellationSignal cancellation = CancellationSignal.createTransport();
+        mCancellation = CancellationSignal.fromTransport(cancellation);
+        mSession = new ScrollCaptureSession(surface, mScrollBounds, mPositionInWindow);
+
+        Runnable listener =
+                SafeCallback.create(mCancellation, mUiThread, this::onStartCaptureCompleted);
+        // -> UiThread
+        mUiThread.execute(() -> mLocal.onScrollCaptureStart(mSession, mCancellation, listener));
+        return cancellation;
     }
 
     @UiThread
     private void onStartCaptureCompleted() {
-        if (cancelTimeout()) {
-            mHandler.post(() -> {
-                try {
-                    mCallbacks.onCaptureStarted();
-                } catch (RemoteException e) {
-                    doShutdown();
-                }
-            });
+        mStarted = true;
+        try {
+            mRemote.onCaptureStarted();
+        } catch (RemoteException e) {
+            Log.w(TAG, "Shutting down due to error: ", e);
+            close();
         }
     }
 
-    @UiThread
-    private void onStartCaptureTimeout() {
-        endCapture();
-    }
 
-    @WorkerThread // IScrollCaptureConnection
+    @BinderThread
     @Override
-    public void requestImage(Rect requestRect) {
+    public ICancellationSignal requestImage(Rect requestRect) throws RemoteException {
+        Trace.beginSection("requestImage");
         checkConnected();
         checkStarted();
-        scheduleTimeout(mTimeoutMillis, this::onRequestImageTimeout);
-        // Response is dispatched via ScrollCaptureSession, to onRequestImageCompleted
-        mHandler.post(() -> mSelectedTarget.getCallback().onScrollCaptureImageRequest(
-                mSession, new Rect(requestRect)));
+
+        ICancellationSignal cancellation = CancellationSignal.createTransport();
+        mCancellation = CancellationSignal.fromTransport(cancellation);
+
+        Consumer<Rect> listener =
+                SafeCallback.create(mCancellation, mUiThread, this::onImageRequestCompleted);
+        // -> UiThread
+        mUiThread.execute(() -> mLocal.onScrollCaptureImageRequest(
+                mSession, mCancellation, new Rect(requestRect), listener));
+        Trace.endSection();
+        return cancellation;
     }
 
     @UiThread
-    void onRequestImageCompleted(long frameNumber, Rect capturedArea) {
-        final Rect finalCapturedArea = new Rect(capturedArea);
-        if (cancelTimeout()) {
-            mHandler.post(() -> {
-                try {
-                    mCallbacks.onCaptureBufferSent(frameNumber, finalCapturedArea);
-                } catch (RemoteException e) {
-                    doShutdown();
-                }
-            });
-        }
-    }
-
-    @UiThread
-    private void onRequestImageTimeout() {
-        endCapture();
-    }
-
-    @WorkerThread // IScrollCaptureConnection
-    @Override
-    public void endCapture() {
-        if (isStarted()) {
-            scheduleTimeout(mTimeoutMillis, this::onEndCaptureTimeout);
-            mHandler.post(() ->
-                    mSelectedTarget.getCallback().onScrollCaptureEnd(this::onEndCaptureCompleted));
-        } else {
-            disconnect();
-        }
-    }
-
-    private boolean isStarted() {
-        return mCallbacks != null && mSelectedTarget != null;
-    }
-
-    @UiThread
-    private void onEndCaptureCompleted() { // onEndCaptureCompleted
-        if (cancelTimeout()) {
-            doShutdown();
-        }
-    }
-
-    @UiThread
-    private void onEndCaptureTimeout() {
-        doShutdown();
-    }
-
-
-    private void doShutdown() {
+    void onImageRequestCompleted(Rect capturedArea) {
         try {
-            if (mCallbacks != null) {
-                mCallbacks.onConnectionClosed();
-            }
+            mRemote.onImageRequestCompleted(0, capturedArea);
         } catch (RemoteException e) {
-            // Ignore
-        } finally {
-            disconnect();
+            Log.w(TAG, "Shutting down due to error: ", e);
+            close();
         }
     }
 
+    @BinderThread
+    @Override
+    public ICancellationSignal endCapture() throws RemoteException {
+        checkConnected();
+        checkStarted();
+
+        ICancellationSignal cancellation = CancellationSignal.createTransport();
+        mCancellation = CancellationSignal.fromTransport(cancellation);
+
+        Runnable listener =
+                SafeCallback.create(mCancellation, mUiThread, this::onEndCaptureCompleted);
+        // -> UiThread
+        mUiThread.execute(() -> mLocal.onScrollCaptureEnd(listener));
+        return cancellation;
+    }
+
+    @UiThread
+    private void onEndCaptureCompleted() {
+        synchronized (mLock) {
+            mStarted = false;
+            try {
+                mRemote.onCaptureEnded();
+            } catch (RemoteException e) {
+                Log.w(TAG, "Shutting down due to error: ", e);
+                close();
+            }
+        }
+    }
+
+    @BinderThread
+    @Override
+    public void close() {
+        if (mStarted) {
+            Log.w(TAG, "close(): capture is still started?! Ending now.");
+
+            // -> UiThread
+            mUiThread.execute(() -> mLocal.onScrollCaptureEnd(() -> { /* ignore */ }));
+            mStarted = false;
+        }
+        disconnect();
+    }
+
     /**
      * Shuts down this client and releases references to dependent objects. No attempt is made
      * to notify the controller, use with caution!
      */
-    public void disconnect() {
-        if (mSession != null) {
-            mSession.disconnect();
+    private void disconnect() {
+        synchronized (mLock) {
             mSession = null;
+            mConnected = false;
+            mStarted = false;
+            mRemote = null;
+            mLocal = null;
+            mCloseGuard.close();
         }
+    }
 
-        mSelectedTarget = null;
-        mCallbacks = null;
+    public boolean isConnected() {
+        return mConnected;
+    }
+
+    public boolean isStarted() {
+        return mStarted;
+    }
+
+    private synchronized void checkConnected() throws RemoteException {
+        synchronized (mLock) {
+            if (!mConnected) {
+                throw new RemoteException(new IllegalStateException("Not connected"));
+            }
+        }
+    }
+
+    private void checkStarted() throws RemoteException {
+        synchronized (mLock) {
+            if (!mStarted) {
+                throw new RemoteException(new IllegalStateException("Not started!"));
+            }
+        }
     }
 
     /** @return a string representation of the state of this client */
     public String toString() {
         return "ScrollCaptureConnection{"
+                + "connected=" + mConnected
+                + ", started=" + mStarted
                 + ", session=" + mSession
-                + ", selectedTarget=" + mSelectedTarget
-                + ", clientCallbacks=" + mCallbacks
+                + ", remote=" + mRemote
+                + ", local=" + mLocal
                 + "}";
     }
 
-    private boolean cancelTimeout() {
-        if (mTimeoutAction != null) {
-            return mTimeoutAction.cancel();
-        }
-        return false;
-    }
-
-    private void scheduleTimeout(long timeoutMillis, Runnable action) {
-        if (mTimeoutAction != null) {
-            mTimeoutAction.cancel();
-        }
-        mTimeoutAction = new DelayedAction(mHandler, timeoutMillis, action);
-    }
-
-    /** @hide */
     @VisibleForTesting
-    public static class DelayedAction {
-        private final AtomicBoolean mCompleted = new AtomicBoolean();
-        private final Object mToken = new Object();
-        private final Handler mHandler;
-        private final Runnable mAction;
+    public CancellationSignal getCancellation() {
+        return mCancellation;
+    }
 
-        @VisibleForTesting
-        public DelayedAction(Handler handler, long timeoutMillis, Runnable action) {
-            mHandler = handler;
-            mAction = action;
-            mHandler.postDelayed(this::onTimeout, mToken, timeoutMillis);
-        }
-
-        private boolean onTimeout() {
-            if (mCompleted.compareAndSet(false, true)) {
-                mAction.run();
-                return true;
+    protected void finalize() throws Throwable {
+        try {
+            if (mCloseGuard != null) {
+                mCloseGuard.warnIfOpen();
             }
-            return false;
+            close();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    private static class SafeCallback<T> {
+        private final CancellationSignal mSignal;
+        private final WeakReference<T> mTargetRef;
+        private final Executor mExecutor;
+        private boolean mExecuted;
+
+        protected SafeCallback(CancellationSignal signal, Executor executor, T target) {
+            mSignal = signal;
+            mTargetRef = new WeakReference<>(target);
+            mExecutor = executor;
         }
 
-        /**
-         * Cause the timeout action to run immediately and mark as timed out.
-         *
-         * @return true if the timeout was run, false if the timeout had already been canceled
-         */
-        @VisibleForTesting
-        public boolean timeoutNow() {
-            return onTimeout();
-        }
-
-        /**
-         * Attempt to cancel the timeout action (such as after a callback is made)
-         *
-         * @return true if the timeout was canceled and will not run, false if time has expired and
-         * the timeout action has or will run momentarily
-         */
-        public boolean cancel() {
-            if (!mCompleted.compareAndSet(false, true)) {
-                // Whoops, too late!
-                return false;
+        // Provide the target to the consumer to invoke, forward on handler thread ONCE,
+        // and only if noy cancelled, and the target is still available (not collected)
+        protected final void maybeAccept(Consumer<T> targetConsumer) {
+            if (mExecuted) {
+                return;
             }
-            mHandler.removeCallbacksAndMessages(mToken);
-            return true;
+            mExecuted = true;
+            if (mSignal.isCanceled()) {
+                return;
+            }
+            T target = mTargetRef.get();
+            if (target == null) {
+                return;
+            }
+            mExecutor.execute(() -> targetConsumer.accept(target));
+        }
+
+        static Runnable create(CancellationSignal signal, Executor executor, Runnable target) {
+            return new RunnableCallback(signal, executor, target);
+        }
+
+        static <T> Consumer<T> create(CancellationSignal signal, Executor executor,
+                Consumer<T> target) {
+            return new ConsumerCallback<T>(signal, executor, target);
+        }
+    }
+
+    private static final class RunnableCallback extends SafeCallback<Runnable> implements Runnable {
+        RunnableCallback(CancellationSignal signal, Executor executor, Runnable target) {
+            super(signal, executor, target);
+        }
+
+        @Override
+        public void run() {
+            maybeAccept(Runnable::run);
+        }
+    }
+
+    private static final class ConsumerCallback<T> extends SafeCallback<Consumer<T>>
+            implements Consumer<T> {
+        ConsumerCallback(CancellationSignal signal, Executor executor, Consumer<T> target) {
+            super(signal, executor, target);
+        }
+
+        @Override
+        public void accept(T value) {
+            maybeAccept((target) -> target.accept(value));
         }
     }
 }
diff --git a/core/java/android/service/screenshot/ScreenshotHash.aidl b/core/java/android/view/ScrollCaptureResponse.aidl
similarity index 82%
copy from core/java/android/service/screenshot/ScreenshotHash.aidl
copy to core/java/android/view/ScrollCaptureResponse.aidl
index a7c50db..3de2b80 100644
--- a/core/java/android/service/screenshot/ScreenshotHash.aidl
+++ b/core/java/android/view/ScrollCaptureResponse.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.service.screenshot;
+package android.view;
 
-parcelable ScreenshotHash;
+parcelable ScrollCaptureResponse;
diff --git a/core/java/android/view/ScrollCaptureResponse.java b/core/java/android/view/ScrollCaptureResponse.java
new file mode 100644
index 0000000..564113e
--- /dev/null
+++ b/core/java/android/view/ScrollCaptureResponse.java
@@ -0,0 +1,381 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.Rect;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+import java.util.ArrayList;
+
+/** @hide */
+@DataClass(genToString = true, genGetters = true)
+public class ScrollCaptureResponse implements Parcelable {
+
+    /** Developer-facing human readable description of the result. */
+    @NonNull
+    private String mDescription = "";
+
+    // Remaining fields are non-null when isConnected() == true
+
+    /** The active connection for a successful result. */
+    @Nullable
+    @DataClass.MaySetToNull
+    private IScrollCaptureConnection mConnection = null;
+
+    /** The bounds of the window within the display */
+    @Nullable
+    private Rect mWindowBounds = null;
+
+    /** The bounds of the scrolling content, in window space. */
+    @Nullable
+    private Rect mBoundsInWindow = null;
+
+    /** The current window title. */
+    @Nullable
+    private String mWindowTitle = null;
+
+    /** Carries additional logging and debugging information when enabled. */
+    @NonNull
+    @DataClass.PluralOf("message")
+    private ArrayList<String> mMessages = new ArrayList<>();
+
+    /** Whether a connection has been returned. */
+    public boolean isConnected() {
+        return mConnection != null;
+    }
+
+
+
+
+    // Code below generated by codegen v1.0.22.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/ScrollCaptureResponse.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    @DataClass.Generated.Member
+    /* package-private */ ScrollCaptureResponse(
+            @NonNull String description,
+            @Nullable IScrollCaptureConnection connection,
+            @Nullable Rect windowBounds,
+            @Nullable Rect boundsInWindow,
+            @Nullable String windowTitle,
+            @NonNull ArrayList<String> messages) {
+        this.mDescription = description;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mDescription);
+        this.mConnection = connection;
+        this.mWindowBounds = windowBounds;
+        this.mBoundsInWindow = boundsInWindow;
+        this.mWindowTitle = windowTitle;
+        this.mMessages = messages;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mMessages);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    /**
+     * Developer-facing human readable description of the result.
+     */
+    @DataClass.Generated.Member
+    public @NonNull String getDescription() {
+        return mDescription;
+    }
+
+    /**
+     * The active connection for a successful result.
+     */
+    @DataClass.Generated.Member
+    public @Nullable IScrollCaptureConnection getConnection() {
+        return mConnection;
+    }
+
+    /**
+     * The bounds of the window within the display
+     */
+    @DataClass.Generated.Member
+    public @Nullable Rect getWindowBounds() {
+        return mWindowBounds;
+    }
+
+    /**
+     * The bounds of the scrolling content, in window space.
+     */
+    @DataClass.Generated.Member
+    public @Nullable Rect getBoundsInWindow() {
+        return mBoundsInWindow;
+    }
+
+    /**
+     * The current window title.
+     */
+    @DataClass.Generated.Member
+    public @Nullable String getWindowTitle() {
+        return mWindowTitle;
+    }
+
+    /**
+     * Carries additional logging and debugging information when enabled.
+     */
+    @DataClass.Generated.Member
+    public @NonNull ArrayList<String> getMessages() {
+        return mMessages;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "ScrollCaptureResponse { " +
+                "description = " + mDescription + ", " +
+                "connection = " + mConnection + ", " +
+                "windowBounds = " + mWindowBounds + ", " +
+                "boundsInWindow = " + mBoundsInWindow + ", " +
+                "windowTitle = " + mWindowTitle + ", " +
+                "messages = " + mMessages +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        byte flg = 0;
+        if (mConnection != null) flg |= 0x2;
+        if (mWindowBounds != null) flg |= 0x4;
+        if (mBoundsInWindow != null) flg |= 0x8;
+        if (mWindowTitle != null) flg |= 0x10;
+        dest.writeByte(flg);
+        dest.writeString(mDescription);
+        if (mConnection != null) dest.writeStrongInterface(mConnection);
+        if (mWindowBounds != null) dest.writeTypedObject(mWindowBounds, flags);
+        if (mBoundsInWindow != null) dest.writeTypedObject(mBoundsInWindow, flags);
+        if (mWindowTitle != null) dest.writeString(mWindowTitle);
+        dest.writeStringList(mMessages);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    protected ScrollCaptureResponse(@NonNull android.os.Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        byte flg = in.readByte();
+        String description = in.readString();
+        IScrollCaptureConnection connection = (flg & 0x2) == 0 ? null : IScrollCaptureConnection.Stub.asInterface(in.readStrongBinder());
+        Rect windowBounds = (flg & 0x4) == 0 ? null : (Rect) in.readTypedObject(Rect.CREATOR);
+        Rect boundsInWindow = (flg & 0x8) == 0 ? null : (Rect) in.readTypedObject(Rect.CREATOR);
+        String windowTitle = (flg & 0x10) == 0 ? null : in.readString();
+        ArrayList<String> messages = new ArrayList<>();
+        in.readStringList(messages);
+
+        this.mDescription = description;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mDescription);
+        this.mConnection = connection;
+        this.mWindowBounds = windowBounds;
+        this.mBoundsInWindow = boundsInWindow;
+        this.mWindowTitle = windowTitle;
+        this.mMessages = messages;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mMessages);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<ScrollCaptureResponse> CREATOR
+            = new Parcelable.Creator<ScrollCaptureResponse>() {
+        @Override
+        public ScrollCaptureResponse[] newArray(int size) {
+            return new ScrollCaptureResponse[size];
+        }
+
+        @Override
+        public ScrollCaptureResponse createFromParcel(@NonNull android.os.Parcel in) {
+            return new ScrollCaptureResponse(in);
+        }
+    };
+
+    /**
+     * A builder for {@link ScrollCaptureResponse}
+     */
+    @SuppressWarnings("WeakerAccess")
+    @DataClass.Generated.Member
+    public static class Builder {
+
+        private @NonNull String mDescription;
+        private @Nullable IScrollCaptureConnection mConnection;
+        private @Nullable Rect mWindowBounds;
+        private @Nullable Rect mBoundsInWindow;
+        private @Nullable String mWindowTitle;
+        private @NonNull ArrayList<String> mMessages;
+
+        private long mBuilderFieldsSet = 0L;
+
+        public Builder() {
+        }
+
+        /**
+         * Developer-facing human readable description of the result.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setDescription(@NonNull String value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x1;
+            mDescription = value;
+            return this;
+        }
+
+        /**
+         * The active connection for a successful result.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setConnection(@Nullable IScrollCaptureConnection value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x2;
+            mConnection = value;
+            return this;
+        }
+
+        /**
+         * The bounds of the window within the display
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setWindowBounds(@NonNull Rect value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x4;
+            mWindowBounds = value;
+            return this;
+        }
+
+        /**
+         * The bounds of the scrolling content, in window space.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setBoundsInWindow(@NonNull Rect value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x8;
+            mBoundsInWindow = value;
+            return this;
+        }
+
+        /**
+         * The current window title.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setWindowTitle(@NonNull String value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x10;
+            mWindowTitle = value;
+            return this;
+        }
+
+        /**
+         * Carries additional logging and debugging information when enabled.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setMessages(@NonNull ArrayList<String> value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x20;
+            mMessages = value;
+            return this;
+        }
+
+        /** @see #setMessages */
+        @DataClass.Generated.Member
+        public @NonNull Builder addMessage(@NonNull String value) {
+            if (mMessages == null) setMessages(new ArrayList<>());
+            mMessages.add(value);
+            return this;
+        }
+
+        /** Builds the instance. This builder should not be touched after calling this! */
+        public @NonNull ScrollCaptureResponse build() {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x40; // Mark builder used
+
+            if ((mBuilderFieldsSet & 0x1) == 0) {
+                mDescription = "";
+            }
+            if ((mBuilderFieldsSet & 0x2) == 0) {
+                mConnection = null;
+            }
+            if ((mBuilderFieldsSet & 0x4) == 0) {
+                mWindowBounds = null;
+            }
+            if ((mBuilderFieldsSet & 0x8) == 0) {
+                mBoundsInWindow = null;
+            }
+            if ((mBuilderFieldsSet & 0x10) == 0) {
+                mWindowTitle = null;
+            }
+            if ((mBuilderFieldsSet & 0x20) == 0) {
+                mMessages = new ArrayList<>();
+            }
+            ScrollCaptureResponse o = new ScrollCaptureResponse(
+                    mDescription,
+                    mConnection,
+                    mWindowBounds,
+                    mBoundsInWindow,
+                    mWindowTitle,
+                    mMessages);
+            return o;
+        }
+
+        private void checkNotUsed() {
+            if ((mBuilderFieldsSet & 0x40) != 0) {
+                throw new IllegalStateException(
+                        "This Builder should not be reused. Use a new Builder instance instead");
+            }
+        }
+    }
+
+    @DataClass.Generated(
+            time = 1612282689462L,
+            codegenVersion = "1.0.22",
+            sourceFile = "frameworks/base/core/java/android/view/ScrollCaptureResponse.java",
+            inputSignatures = "private @android.annotation.NonNull java.lang.String mDescription\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.MaySetToNull android.view.IScrollCaptureConnection mConnection\nprivate @android.annotation.Nullable android.graphics.Rect mWindowBounds\nprivate @android.annotation.Nullable android.graphics.Rect mBoundsInWindow\nprivate @android.annotation.Nullable java.lang.String mWindowTitle\nprivate @android.annotation.NonNull @com.android.internal.util.DataClass.PluralOf(\"message\") java.util.ArrayList<java.lang.String> mMessages\npublic  boolean isConnected()\nclass ScrollCaptureResponse extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genGetters=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/view/ScrollCaptureSearchResults.java b/core/java/android/view/ScrollCaptureSearchResults.java
new file mode 100644
index 0000000..3469b9d
--- /dev/null
+++ b/core/java/android/view/ScrollCaptureSearchResults.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.NonNull;
+import android.annotation.UiThread;
+import android.graphics.Rect;
+import android.os.CancellationSignal;
+import android.util.IndentingPrintWriter;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+/**
+ * Collects nodes in the view hierarchy which have been identified as scrollable content.
+ *
+ * @hide
+ */
+@UiThread
+public final class ScrollCaptureSearchResults {
+    private final Executor mExecutor;
+    private final List<ScrollCaptureTarget> mTargets;
+    private final CancellationSignal mCancel;
+
+    private Runnable mOnCompleteListener;
+    private int mCompleted;
+    private boolean mComplete = true;
+
+    public ScrollCaptureSearchResults(Executor executor) {
+        mExecutor = executor;
+        mTargets = new ArrayList<>();
+        mCancel = new CancellationSignal();
+    }
+
+    // Public
+
+    /**
+     * Add the given target to the results.
+     *
+     * @param target the target to consider
+     */
+    public void addTarget(@NonNull ScrollCaptureTarget target) {
+        requireNonNull(target);
+
+        mTargets.add(target);
+        mComplete = false;
+        final ScrollCaptureCallback callback = target.getCallback();
+        final Consumer<Rect> consumer = new SearchRequest(target);
+
+        // Defer so the view hierarchy scan completes first
+        mExecutor.execute(
+                () -> callback.onScrollCaptureSearch(mCancel, consumer));
+    }
+
+    public boolean isComplete() {
+        return mComplete;
+    }
+
+    /**
+     * Provides a callback to be invoked as soon as all responses have been received from all
+     * targets to this point.
+     *
+     * @param onComplete listener to add
+     */
+    public void setOnCompleteListener(Runnable onComplete) {
+        if (mComplete) {
+            onComplete.run();
+        } else {
+            mOnCompleteListener = onComplete;
+        }
+    }
+
+    /**
+     * Indicates whether the search results are empty.
+     *
+     * @return true if no targets have been added
+     */
+    public boolean isEmpty() {
+        return mTargets.isEmpty();
+    }
+
+    /**
+     * Force the results to complete now, cancelling any pending requests and calling a complete
+     * listener if provided.
+     */
+    public void finish() {
+        if (!mComplete) {
+            mCancel.cancel();
+            signalComplete();
+        }
+    }
+
+    private void signalComplete() {
+        mComplete = true;
+        mTargets.sort(PRIORITY_ORDER);
+        if (mOnCompleteListener != null) {
+            mOnCompleteListener.run();
+            mOnCompleteListener = null;
+        }
+    }
+
+    @VisibleForTesting
+    public List<ScrollCaptureTarget> getTargets() {
+        return new ArrayList<>(mTargets);
+    }
+
+    /**
+     * Get the top ranked result out of all completed requests.
+     *
+     * @return the top ranked result
+     */
+    public ScrollCaptureTarget getTopResult() {
+        ScrollCaptureTarget target = mTargets.isEmpty() ? null : mTargets.get(0);
+        return target != null && target.getScrollBounds() != null ? target : null;
+    }
+
+    private class SearchRequest implements Consumer<Rect> {
+        private ScrollCaptureTarget mTarget;
+
+        SearchRequest(ScrollCaptureTarget target) {
+            mTarget = target;
+        }
+
+        @Override
+        public void accept(Rect scrollBounds) {
+            if (mTarget == null || mCancel.isCanceled()) {
+                return;
+            }
+            mExecutor.execute(() -> consume(scrollBounds));
+        }
+
+        private void consume(Rect scrollBounds) {
+            if (mTarget == null || mCancel.isCanceled()) {
+                return;
+            }
+            if (!nullOrEmpty(scrollBounds)) {
+                mTarget.setScrollBounds(scrollBounds);
+                mTarget.updatePositionInWindow();
+            }
+            mCompleted++;
+            mTarget = null;
+
+            // All done?
+            if (mCompleted == mTargets.size()) {
+                signalComplete();
+            }
+        }
+    }
+
+    private static final int AFTER = 1;
+    private static final int BEFORE = -1;
+    private static final int EQUAL = 0;
+
+    static final Comparator<ScrollCaptureTarget> PRIORITY_ORDER = (a, b) -> {
+        if (a == null && b == null) {
+            return 0;
+        } else if (a == null || b == null) {
+            return (a == null) ? 1 : -1;
+        }
+
+        boolean emptyScrollBoundsA = nullOrEmpty(a.getScrollBounds());
+        boolean emptyScrollBoundsB = nullOrEmpty(b.getScrollBounds());
+        if (emptyScrollBoundsA || emptyScrollBoundsB) {
+            if (emptyScrollBoundsA && emptyScrollBoundsB) {
+                return EQUAL;
+            }
+            // Prefer the one with a non-empty scroll bounds
+            if (emptyScrollBoundsA) {
+                return AFTER;
+            }
+            return BEFORE;
+        }
+
+        final View viewA = a.getContainingView();
+        final View viewB = b.getContainingView();
+
+        // Prefer any view with scrollCaptureHint="INCLUDE", over one without
+        // This is an escape hatch for the next rule (descendants first)
+        boolean hintIncludeA = hasIncludeHint(viewA);
+        boolean hintIncludeB = hasIncludeHint(viewB);
+        if (hintIncludeA != hintIncludeB) {
+            return (hintIncludeA) ? BEFORE : AFTER;
+        }
+        // If the views are relatives, prefer the descendant. This allows implementations to
+        // leverage nested scrolling APIs by interacting with the innermost scrollable view (as
+        // would happen with touch input).
+        if (isDescendant(viewA, viewB)) {
+            return BEFORE;
+        }
+        if (isDescendant(viewB, viewA)) {
+            return AFTER;
+        }
+
+        // finally, prefer one with larger scroll bounds
+        int scrollAreaA = area(a.getScrollBounds());
+        int scrollAreaB = area(b.getScrollBounds());
+        return (scrollAreaA >= scrollAreaB) ? BEFORE : AFTER;
+    };
+
+    private static int area(Rect r) {
+        return r.width() * r.height();
+    }
+
+    private static boolean nullOrEmpty(Rect r) {
+        return r == null || r.isEmpty();
+    }
+
+    private static boolean hasIncludeHint(View view) {
+        return (view.getScrollCaptureHint() & View.SCROLL_CAPTURE_HINT_INCLUDE) != 0;
+    }
+
+    /**
+     * Determines if {@code otherView} is a descendant of {@code view}.
+     *
+     * @param view      a view
+     * @param otherView another view
+     * @return true if {@code view} is an ancestor of {@code otherView}
+     */
+    private static boolean isDescendant(@NonNull View view, @NonNull View otherView) {
+        if (view == otherView) {
+            return false;
+        }
+        ViewParent otherParent = otherView.getParent();
+        while (otherParent != view && otherParent != null) {
+            otherParent = otherParent.getParent();
+        }
+        return otherParent == view;
+    }
+
+    void dump(IndentingPrintWriter writer) {
+        writer.println("results:");
+        writer.increaseIndent();
+        writer.println("complete: " + isComplete());
+        writer.println("cancelled: " + mCancel.isCanceled());
+        writer.println("targets:");
+        writer.increaseIndent();
+        if (isEmpty()) {
+            writer.println("None");
+        } else {
+            for (int i = 0; i < mTargets.size(); i++) {
+                writer.println("[" + i + "]");
+                writer.increaseIndent();
+                mTargets.get(i).dump(writer);
+                writer.decreaseIndent();
+            }
+            writer.decreaseIndent();
+        }
+        writer.decreaseIndent();
+    }
+}
diff --git a/core/java/android/view/ScrollCaptureSession.java b/core/java/android/view/ScrollCaptureSession.java
index 92617a3..748e7ea 100644
--- a/core/java/android/view/ScrollCaptureSession.java
+++ b/core/java/android/view/ScrollCaptureSession.java
@@ -16,18 +16,15 @@
 
 package android.view;
 
+import static java.util.Objects.requireNonNull;
+
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.graphics.Point;
 import android.graphics.Rect;
 
 /**
  * A session represents the scope of interaction between a {@link ScrollCaptureCallback} and the
- * system during an active scroll capture operation. During the scope of a session, a callback
- * will receive a series of requests for image data. Resources provided here are valid for use
- * until {@link ScrollCaptureCallback#onScrollCaptureEnd(Runnable)}.
- *
- * @hide
+ * system during an active scroll capture operation.
  */
 public class ScrollCaptureSession {
 
@@ -35,22 +32,27 @@
     private final Rect mScrollBounds;
     private final Point mPositionInWindow;
 
-    @Nullable
-    private ScrollCaptureConnection mConnection;
-
-    /** @hide */
-    public ScrollCaptureSession(Surface surface, Rect scrollBounds, Point positionInWindow,
-            ScrollCaptureConnection connection) {
-        mSurface = surface;
-        mScrollBounds = scrollBounds;
-        mPositionInWindow = positionInWindow;
-        mConnection = connection;
+    /**
+     * Constructs a new session instance.
+     *
+     * @param surface the surface to consume generated images
+     * @param scrollBounds the bounds of the capture area within the containing view
+     * @param positionInWindow the offset of scrollBounds within the window
+     */
+    public ScrollCaptureSession(@NonNull Surface surface, @NonNull Rect scrollBounds,
+            @NonNull Point positionInWindow) {
+        mSurface = requireNonNull(surface);
+        mScrollBounds = requireNonNull(scrollBounds);
+        mPositionInWindow = requireNonNull(positionInWindow);
     }
 
     /**
      * Returns a
      * <a href="https://source.android.com/devices/graphics/arch-bq-gralloc">BufferQueue</a> in the
      * form of a {@link Surface} for transfer of image buffers.
+     * <p>
+     * The surface is guaranteed to remain {@link Surface#isValid() valid} until the session
+     * {@link ScrollCaptureCallback#onScrollCaptureEnd(Runnable) ends}.
      *
      * @return the surface for transferring image buffers
      * @throws IllegalStateException if the session has been closed
@@ -80,26 +82,4 @@
     public Point getPositionInWindow() {
         return mPositionInWindow;
     }
-
-    /**
-     * Notify the system that an a buffer has been posted via the getSurface() channel.
-     *
-     * @param frameNumber  the frame number of the queued buffer
-     * @param capturedArea the area captured, relative to scroll bounds
-     */
-    public void notifyBufferSent(long frameNumber, @NonNull Rect capturedArea) {
-        if (mConnection != null) {
-            mConnection.onRequestImageCompleted(frameNumber, capturedArea);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void disconnect() {
-        mConnection = null;
-        if (mSurface.isValid()) {
-            mSurface.release();
-        }
-    }
 }
diff --git a/core/java/android/view/ScrollCaptureTarget.java b/core/java/android/view/ScrollCaptureTarget.java
index f3fcabb..4fd4889 100644
--- a/core/java/android/view/ScrollCaptureTarget.java
+++ b/core/java/android/view/ScrollCaptureTarget.java
@@ -22,14 +22,16 @@
 import android.graphics.Matrix;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.os.CancellationSignal;
 
 import com.android.internal.util.FastMath;
 
+import java.io.PrintWriter;
+import java.util.function.Consumer;
+
 /**
  * A target collects the set of contextual information for a ScrollCaptureHandler discovered during
  * a {@link View#dispatchScrollCaptureSearch scroll capture search}.
- *
- * @hide
  */
 public final class ScrollCaptureTarget {
     private final View mContainingView;
@@ -41,7 +43,6 @@
 
     private final float[] mTmpFloatArr = new float[2];
     private final Matrix mMatrixViewLocalToWindow = new Matrix();
-    private final Rect mTmpRect = new Rect();
 
     public ScrollCaptureTarget(@NonNull View scrollTarget, @NonNull Rect localVisibleRect,
             @NonNull Point positionInWindow, @NonNull ScrollCaptureCallback callback) {
@@ -52,7 +53,10 @@
         mPositionInWindow = positionInWindow;
     }
 
-    /** @return the hint that the {@code containing view} had during the scroll capture search */
+    /**
+     * @return the hint that the {@code containing view} had during the scroll capture search
+     * @see View#getScrollCaptureHint()
+     */
     @View.ScrollCaptureHint
     public int getHint() {
         return mHint;
@@ -71,8 +75,7 @@
     }
 
     /**
-     * Returns the un-clipped, visible bounds of the containing view during the scroll capture
-     * search. This is used to determine on-screen area to assist in selecting the primary target.
+     * Returns the visible bounds of the containing view.
      *
      * @return the visible bounds of the {@code containing view} in view-local coordinates
      */
@@ -81,13 +84,17 @@
         return mLocalVisibleRect;
     }
 
-    /** @return the position of the {@code containing view} within the window */
+    /** @return the position of the visible bounds of the containing view within the window */
     @NonNull
     public Point getPositionInWindow() {
         return mPositionInWindow;
     }
 
-    /** @return the {@code scroll bounds} for this {@link ScrollCaptureCallback callback} */
+    /**
+     * @return the {@code scroll bounds} for this {@link ScrollCaptureCallback callback}
+     *
+     * @see ScrollCaptureCallback#onScrollCaptureSearch(CancellationSignal, Consumer)
+     */
     @Nullable
     public Rect getScrollBounds() {
         return mScrollBounds;
@@ -119,8 +126,8 @@
     }
 
     /**
-     * Refresh the value of {@link #mLocalVisibleRect} and {@link #mPositionInWindow} based on the
-     * current state of the {@code containing view}.
+     * Refresh the local visible bounds and it's offset within the window, based on the current
+     * state of the {@code containing view}.
      */
     @UiThread
     public void updatePositionInWindow() {
@@ -132,4 +139,27 @@
         roundIntoPoint(mPositionInWindow, mTmpFloatArr);
     }
 
+    public String toString() {
+        return "ScrollCaptureTarget{" + "view=" + mContainingView
+                + ", callback=" + mCallback
+                + ", scrollBounds=" + mScrollBounds
+                + ", localVisibleRect=" + mLocalVisibleRect
+                + ", positionInWindow=" + mPositionInWindow
+                + "}";
+    }
+
+    void dump(@NonNull PrintWriter writer) {
+        View view = getContainingView();
+        writer.println("view: " + view);
+        writer.println("hint: " + mHint);
+        writer.println("callback: " + mCallback);
+        writer.println("scrollBounds: "
+                + (mScrollBounds == null ? "null" : mScrollBounds.toShortString()));
+        Point inWindow = getPositionInWindow();
+        writer.println("positionInWindow: "
+                + ((inWindow == null) ? "null" : "[" + inWindow.x + "," + inWindow.y + "]"));
+        Rect localVisible = getLocalVisibleRect();
+        writer.println("localVisibleRect: "
+                + (localVisible == null ? "null" : localVisible.toShortString()));
+    }
 }
diff --git a/core/java/android/view/ScrollCaptureTargetResolver.java b/core/java/android/view/ScrollCaptureTargetResolver.java
deleted file mode 100644
index e4316bb..0000000
--- a/core/java/android/view/ScrollCaptureTargetResolver.java
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.annotation.AnyThread;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.UiThread;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.SystemClock;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-
-import java.util.Queue;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Consumer;
-
-/**
- * Queries additional state from a list of {@link ScrollCaptureTarget targets} via asynchronous
- * callbacks, then aggregates and reduces the target list to a single target, or null if no target
- * is suitable.
- * <p>
- * The rules for selection are (in order):
- * <ul>
- * <li>prefer getScrollBounds(): non-empty
- * <li>prefer View.getScrollCaptureHint == SCROLL_CAPTURE_HINT_INCLUDE
- * <li>prefer descendants before parents
- * <li>prefer larger area for getScrollBounds() (clipped to view bounds)
- * </ul>
- *
- * <p>
- * All calls to {@link ScrollCaptureCallback#onScrollCaptureSearch} are made on the main thread,
- * with results are queued and consumed to the main thread as well.
- *
- * @see #start(Handler, long, Consumer)
- *
- * @hide
- */
-@UiThread
-public class ScrollCaptureTargetResolver {
-    private static final String TAG = "ScrollCaptureTargetRes";
-
-    private final Object mLock = new Object();
-
-    private final Queue<ScrollCaptureTarget> mTargets;
-    private Handler mHandler;
-    private long mTimeLimitMillis;
-
-    private Consumer<ScrollCaptureTarget> mWhenComplete;
-    private int mPendingBoundsRequests;
-    private long mDeadlineMillis;
-
-    private ScrollCaptureTarget mResult;
-    private boolean mFinished;
-
-    private boolean mStarted;
-
-    private static int area(Rect r) {
-        return r.width() * r.height();
-    }
-
-    private static boolean nullOrEmpty(Rect r) {
-        return r == null || r.isEmpty();
-    }
-
-    /**
-     * Binary operator which selects the best {@link ScrollCaptureTarget}.
-     */
-    private static ScrollCaptureTarget chooseTarget(ScrollCaptureTarget a, ScrollCaptureTarget b) {
-        if (a == null && b == null) {
-            return null;
-        } else if (a == null || b == null) {
-            ScrollCaptureTarget c = (a == null) ? b : a;
-            return c;
-        }
-
-        boolean emptyScrollBoundsA = nullOrEmpty(a.getScrollBounds());
-        boolean emptyScrollBoundsB = nullOrEmpty(b.getScrollBounds());
-        if (emptyScrollBoundsA || emptyScrollBoundsB) {
-            if (emptyScrollBoundsA && emptyScrollBoundsB) {
-                // Both have an empty or null scrollBounds
-                Log.d(TAG, "chooseTarget: (both have empty or null bounds) return " + null);
-                return null;
-            }
-            // Prefer the one with a non-empty scroll bounds
-            if (emptyScrollBoundsA) {
-                Log.d(TAG, "chooseTarget: (a has empty or null bounds) return " + b);
-                return b;
-            }
-            Log.d(TAG, "chooseTarget: (b has empty or null bounds) return " + a);
-            return a;
-        }
-
-        final View viewA = a.getContainingView();
-        final View viewB = b.getContainingView();
-
-        // Prefer any view with scrollCaptureHint="INCLUDE", over one without
-        // This is an escape hatch for the next rule (descendants first)
-        boolean hintIncludeA = hasIncludeHint(viewA);
-        boolean hintIncludeB = hasIncludeHint(viewB);
-        if (hintIncludeA != hintIncludeB) {
-            ScrollCaptureTarget c = (hintIncludeA) ? a : b;
-            Log.d(TAG, "chooseTarget: (has hint=INCLUDE) return " + c);
-            return c;
-        }
-
-        // If the views are relatives, prefer the descendant. This allows implementations to
-        // leverage nested scrolling APIs by interacting with the innermost scrollable view (as
-        // would happen with touch input).
-        if (isDescendant(viewA, viewB)) {
-            Log.d(TAG, "chooseTarget: (b is descendant of a) return " + b);
-            return b;
-        }
-        if (isDescendant(viewB, viewA)) {
-            Log.d(TAG, "chooseTarget: (a is descendant of b) return " + a);
-            return a;
-        }
-
-        // finally, prefer one with larger scroll bounds
-        int scrollAreaA = area(a.getScrollBounds());
-        int scrollAreaB = area(b.getScrollBounds());
-        ScrollCaptureTarget c = (scrollAreaA >= scrollAreaB) ? a : b;
-        Log.d(TAG, "chooseTarget: return " + c);
-        return c;
-    }
-
-    /**
-     * Creates an instance to query and filter {@code target}.
-     *
-     * @param targets   a list of {@link ScrollCaptureTarget} as collected by {@link
-     *                  View#dispatchScrollCaptureSearch}.
-     * @see #start(Handler, long, Consumer)
-     */
-    public ScrollCaptureTargetResolver(Queue<ScrollCaptureTarget> targets) {
-        mTargets = targets;
-    }
-
-    void checkThread() {
-        if (mHandler.getLooper() != Looper.myLooper()) {
-            throw new IllegalStateException("Called from wrong thread! ("
-                    + Thread.currentThread().getName() + ")");
-        }
-    }
-
-    /**
-     * Blocks until a result is returned (after completion or timeout).
-     * <p>
-     * For testing only. Normal usage should receive a callback after calling {@link #start}.
-     */
-    @VisibleForTesting
-    public ScrollCaptureTarget waitForResult() throws InterruptedException {
-        synchronized (mLock) {
-            while (!mFinished) {
-                mLock.wait();
-            }
-        }
-        return mResult;
-    }
-
-    private void supplyResult(ScrollCaptureTarget target) {
-        checkThread();
-        if (mFinished) {
-            return;
-        }
-        mResult = chooseTarget(mResult, target);
-        boolean finish = mPendingBoundsRequests == 0
-                || SystemClock.uptimeMillis() >= mDeadlineMillis;
-        if (finish) {
-            mPendingBoundsRequests = 0;
-            mWhenComplete.accept(mResult);
-            synchronized (mLock) {
-                mFinished = true;
-                mLock.notify();
-            }
-            mWhenComplete = null;
-        }
-    }
-
-    /**
-     * Asks all targets for {@link ScrollCaptureCallback#onScrollCaptureSearch(Consumer)
-     * scrollBounds}, and selects the primary target according to the {@link
-     * #chooseTarget} function.
-     *
-     * @param timeLimitMillis the amount of time to wait for all responses before delivering the top
-     *                        result
-     * @param resultConsumer  the consumer to receive the primary target
-     */
-    @AnyThread
-    public void start(Handler uiHandler, long timeLimitMillis,
-            Consumer<ScrollCaptureTarget> resultConsumer) {
-        synchronized (mLock) {
-            if (mStarted) {
-                throw new IllegalStateException("already started!");
-            }
-            if (timeLimitMillis < 0) {
-                throw new IllegalArgumentException("Time limit must be positive");
-            }
-            mHandler = uiHandler;
-            mTimeLimitMillis = timeLimitMillis;
-            mWhenComplete = resultConsumer;
-            if (mTargets.isEmpty()) {
-                mHandler.post(() -> supplyResult(null));
-                return;
-            }
-            mStarted = true;
-            uiHandler.post(this::run);
-        }
-    }
-
-    private void run() {
-        checkThread();
-
-        mPendingBoundsRequests = mTargets.size();
-        for (ScrollCaptureTarget target : mTargets) {
-            queryTarget(target);
-        }
-        mDeadlineMillis = SystemClock.uptimeMillis() + mTimeLimitMillis;
-        mHandler.postAtTime(mTimeoutRunnable, mDeadlineMillis);
-    }
-
-    private final Runnable mTimeoutRunnable = () -> {
-        checkThread();
-        supplyResult(null);
-    };
-
-    /**
-     * Adds a target to the list and requests {@link ScrollCaptureCallback#onScrollCaptureSearch}
-     * scrollBounds} from it. Results are returned by a call to {@link #onScrollBoundsProvided}.
-     *
-     * @param target the target to add
-     */
-    @UiThread
-    private void queryTarget(@NonNull ScrollCaptureTarget target) {
-        checkThread();
-        final ScrollCaptureCallback callback = target.getCallback();
-        // from the UI thread, request scroll bounds
-        callback.onScrollCaptureSearch(
-                // allow only one callback to onReady.accept():
-                new SingletonConsumer<Rect>(
-                        // Queue and consume on the UI thread
-                        ((scrollBounds) -> mHandler.post(
-                                () -> onScrollBoundsProvided(target, scrollBounds)))));
-    }
-
-    @UiThread
-    private void onScrollBoundsProvided(ScrollCaptureTarget target, @Nullable Rect scrollBounds) {
-        checkThread();
-        if (mFinished) {
-            return;
-        }
-
-        // Record progress.
-        mPendingBoundsRequests--;
-
-        // Remove the timeout.
-        mHandler.removeCallbacks(mTimeoutRunnable);
-
-        boolean doneOrTimedOut = mPendingBoundsRequests == 0
-                || SystemClock.uptimeMillis() >= mDeadlineMillis;
-
-        final View containingView = target.getContainingView();
-        if (!nullOrEmpty(scrollBounds) && containingView.isAggregatedVisible()) {
-            target.updatePositionInWindow();
-            target.setScrollBounds(scrollBounds);
-            supplyResult(target);
-        }
-
-        if (!mFinished) {
-            // Reschedule the timeout.
-            mHandler.postAtTime(mTimeoutRunnable, mDeadlineMillis);
-        }
-    }
-
-    private static boolean hasIncludeHint(View view) {
-        return (view.getScrollCaptureHint() & View.SCROLL_CAPTURE_HINT_INCLUDE) != 0;
-    }
-
-    /**
-     * Determines if {@code otherView} is a descendant of {@code view}.
-     *
-     * @param view      a view
-     * @param otherView another view
-     * @return true if {@code view} is an ancestor of {@code otherView}
-     */
-    private static boolean isDescendant(@NonNull View view, @NonNull View otherView) {
-        if (view == otherView) {
-            return false;
-        }
-        ViewParent otherParent = otherView.getParent();
-        while (otherParent != view && otherParent != null) {
-            otherParent = otherParent.getParent();
-        }
-        return otherParent == view;
-    }
-
-    /**
-     * A safe wrapper for a consumer callbacks intended to accept a single value. It ensures
-     * that the receiver of the consumer does not retain a reference to {@code target} after use nor
-     * cause race conditions by invoking {@link Consumer#accept accept} more than once.
-     */
-    static class SingletonConsumer<T> implements Consumer<T> {
-        final AtomicReference<Consumer<T>> mAtomicRef;
-
-        /**
-         * @param target the target consumer
-         **/
-        SingletonConsumer(Consumer<T> target) {
-            mAtomicRef = new AtomicReference<>(target);
-        }
-
-        @Override
-        public void accept(T t) {
-            final Consumer<T> consumer = mAtomicRef.getAndSet(null);
-            if (consumer != null) {
-                consumer.accept(t);
-            }
-        }
-    }
-}
diff --git a/core/java/android/view/SoundEffectConstants.java b/core/java/android/view/SoundEffectConstants.java
index 8d891bb..f177451 100644
--- a/core/java/android/view/SoundEffectConstants.java
+++ b/core/java/android/view/SoundEffectConstants.java
@@ -16,12 +16,21 @@
 
 package android.view;
 
+import android.media.AudioManager;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.annotations.VisibleForTesting.Visibility;
+
+import java.util.Random;
+
 /**
- * Constants to be used to play sound effects via {@link View#playSoundEffect(int)} 
+ * Constants to be used to play sound effects via {@link View#playSoundEffect(int)}
  */
 public class SoundEffectConstants {
 
     private SoundEffectConstants() {}
+    private static final Random NAVIGATION_REPEAT_RANDOMIZER = new Random();
+    private static int sLastNavigationRepeatSoundEffectId = -1;
 
     public static final int CLICK = 0;
 
@@ -29,6 +38,14 @@
     public static final int NAVIGATION_UP = 2;
     public static final int NAVIGATION_RIGHT = 3;
     public static final int NAVIGATION_DOWN = 4;
+    /** Sound effect for a repeatedly triggered navigation, e.g. due to long pressing a button */
+    public static final int NAVIGATION_REPEAT_LEFT = 5;
+    /** @see #NAVIGATION_REPEAT_LEFT */
+    public static final int NAVIGATION_REPEAT_UP = 6;
+    /** @see #NAVIGATION_REPEAT_LEFT */
+    public static final int NAVIGATION_REPEAT_RIGHT = 7;
+    /** @see #NAVIGATION_REPEAT_LEFT */
+    public static final int NAVIGATION_REPEAT_DOWN = 8;
 
     /**
      * Get the sonification constant for the focus directions.
@@ -40,7 +57,7 @@
      * @throws {@link IllegalArgumentException} when the passed direction is not one of the
      *     documented values.
      */
-    public static int getContantForFocusDirection(int direction) {
+    public static int getContantForFocusDirection(@View.FocusDirection int direction) {
         switch (direction) {
             case View.FOCUS_RIGHT:
                 return SoundEffectConstants.NAVIGATION_RIGHT;
@@ -56,4 +73,65 @@
         throw new IllegalArgumentException("direction must be one of "
                 + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD, FOCUS_BACKWARD}.");
     }
+
+    /**
+     * Get the sonification constant for the focus directions
+     * @param direction One of {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
+     *     {@link View#FOCUS_LEFT}, {@link View#FOCUS_RIGHT}, {@link View#FOCUS_FORWARD}
+     *     or {@link View#FOCUS_BACKWARD}
+     * @param repeating True if the user long-presses a direction
+     * @return The appropriate sonification constant
+     * @throws IllegalArgumentException when the passed direction is not one of the
+     *      documented values.
+     */
+    public static int getConstantForFocusDirection(@View.FocusDirection int direction,
+            boolean repeating) {
+        if (repeating) {
+            switch (direction) {
+                case View.FOCUS_RIGHT:
+                    return SoundEffectConstants.NAVIGATION_REPEAT_RIGHT;
+                case View.FOCUS_FORWARD:
+                case View.FOCUS_DOWN:
+                    return SoundEffectConstants.NAVIGATION_REPEAT_DOWN;
+                case View.FOCUS_LEFT:
+                    return SoundEffectConstants.NAVIGATION_REPEAT_LEFT;
+                case View.FOCUS_BACKWARD:
+                case View.FOCUS_UP:
+                    return SoundEffectConstants.NAVIGATION_REPEAT_UP;
+            }
+            throw new IllegalArgumentException("direction must be one of {FOCUS_UP, FOCUS_DOWN, "
+                    + "FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD, FOCUS_BACKWARD}.");
+        } else {
+            return getContantForFocusDirection(direction);
+        }
+    }
+
+    /**
+     * @param effectId any of the effect ids defined in {@link SoundEffectConstants}
+     * @return true if the given effect id is a navigation repeat one
+     * @hide
+     */
+    @VisibleForTesting(visibility = Visibility.PACKAGE)
+    public static boolean isNavigationRepeat(int effectId) {
+        return effectId == SoundEffectConstants.NAVIGATION_REPEAT_DOWN
+                || effectId == SoundEffectConstants.NAVIGATION_REPEAT_LEFT
+                || effectId == SoundEffectConstants.NAVIGATION_REPEAT_RIGHT
+                || effectId == SoundEffectConstants.NAVIGATION_REPEAT_UP;
+    }
+
+    /**
+     * @return The next navigation repeat sound effect id, chosen at random in a non-repeating
+     * fashion
+     * @hide
+     */
+    @VisibleForTesting(visibility = Visibility.PACKAGE)
+    public static int nextNavigationRepeatSoundEffectId() {
+        int next = NAVIGATION_REPEAT_RANDOMIZER.nextInt(
+                AudioManager.NUM_NAVIGATION_REPEAT_SOUND_EFFECTS - 1);
+        if (next >= sLastNavigationRepeatSoundEffectId) {
+            next++;
+        }
+        sLastNavigationRepeatSoundEffectId = next;
+        return AudioManager.getNthNavigationRepeatSoundEffect(next);
+    }
 }
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 66b9617..03dd100 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -68,6 +68,7 @@
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Objects;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -141,6 +142,9 @@
             int layerStack);
     private static native void nativeSetBlurRegions(long transactionObj, long nativeObj,
             float[][] regions, int length);
+    private static native void nativeSetStretchEffect(long transactionObj, long nativeObj,
+            float left, float top, float right, float bottom, float vecX, float vecY,
+            float maxStretchAmount);
 
     private static native boolean nativeClearContentFrameStats(long nativeObject);
     private static native boolean nativeGetContentFrameStats(long nativeObject, WindowContentFrameStats outStats);
@@ -161,25 +165,21 @@
             int L, int T, int R, int B);
     private static native void nativeSetDisplaySize(long transactionObj, IBinder displayToken,
             int width, int height);
-    private static native DisplayInfo nativeGetDisplayInfo(IBinder displayToken);
-    private static native DisplayMode[] nativeGetDisplayModes(
-            IBinder displayToken);
+    private static native StaticDisplayInfo nativeGetStaticDisplayInfo(IBinder displayToken);
+    private static native DynamicDisplayInfo nativeGetDynamicDisplayInfo(IBinder displayToken);
     private static native DisplayedContentSamplingAttributes
             nativeGetDisplayedContentSamplingAttributes(IBinder displayToken);
     private static native boolean nativeSetDisplayedContentSamplingEnabled(IBinder displayToken,
             boolean enable, int componentMask, int maxFrames);
     private static native DisplayedContentSample nativeGetDisplayedContentSample(
             IBinder displayToken, long numFrames, long timestamp);
-    private static native int nativeGetActiveDisplayMode(IBinder displayToken);
     private static native boolean nativeSetDesiredDisplayModeSpecs(IBinder displayToken,
             DesiredDisplayModeSpecs desiredDisplayModeSpecs);
     private static native DesiredDisplayModeSpecs
             nativeGetDesiredDisplayModeSpecs(IBinder displayToken);
-    private static native int[] nativeGetDisplayColorModes(IBinder displayToken);
     private static native DisplayPrimaries nativeGetDisplayNativePrimaries(
             IBinder displayToken);
     private static native int[] nativeGetCompositionDataspaces();
-    private static native int nativeGetActiveColorMode(IBinder displayToken);
     private static native boolean nativeSetActiveColorMode(IBinder displayToken,
             int colorMode);
     private static native void nativeSetAutoLowLatencyMode(IBinder displayToken, boolean on);
@@ -191,11 +191,6 @@
     private static native void nativeReparent(long transactionObj, long nativeObject,
             long newParentNativeObject);
 
-    private static native Display.HdrCapabilities nativeGetHdrCapabilities(IBinder displayToken);
-
-    private static native boolean nativeGetAutoLowLatencyModeSupport(IBinder displayToken);
-    private static native boolean nativeGetGameContentTypeSupport(IBinder displayToken);
-
     private static native void nativeSetInputWindowInfo(long transactionObj, long nativeObject,
             InputWindowHandle handle);
 
@@ -1707,7 +1702,7 @@
      *
      * @hide
      */
-    public static final class DisplayInfo {
+    public static final class StaticDisplayInfo {
         public boolean isInternal;
         public float density;
         public boolean secure;
@@ -1715,7 +1710,7 @@
 
         @Override
         public String toString() {
-            return "DisplayInfo{isInternal=" + isInternal
+            return "StaticDisplayInfo{isInternal=" + isInternal
                     + ", density=" + density
                     + ", secure=" + secure
                     + ", deviceProductInfo=" + deviceProductInfo + "}";
@@ -1725,7 +1720,7 @@
         public boolean equals(@Nullable Object o) {
             if (this == o) return true;
             if (o == null || getClass() != o.getClass()) return false;
-            DisplayInfo that = (DisplayInfo) o;
+            StaticDisplayInfo that = (StaticDisplayInfo) o;
             return isInternal == that.isInternal
                     && density == that.density
                     && secure == that.secure
@@ -1739,6 +1734,54 @@
     }
 
     /**
+     * Dynamic information about physical display.
+     *
+     * @hide
+     */
+    public static final class DynamicDisplayInfo {
+        public DisplayMode[] supportedDisplayModes;
+        public int activeDisplayModeId;
+
+        public int[] supportedColorModes;
+        public int activeColorMode;
+
+        public Display.HdrCapabilities hdrCapabilities;
+
+        public boolean autoLowLatencyModeSupported;
+        public boolean gameContentTypeSupported;
+
+        @Override
+        public String toString() {
+            return "DynamicDisplayInfo{"
+                    + "supportedDisplayModes=" + Arrays.toString(supportedDisplayModes)
+                    + ", activeDisplayModeId=" + activeDisplayModeId
+                    + ", supportedColorModes=" + Arrays.toString(supportedColorModes)
+                    + ", activeColorMode=" + activeColorMode
+                    + ", hdrCapabilities=" + hdrCapabilities
+                    + ", autoLowLatencyModeSupported=" + autoLowLatencyModeSupported
+                    + ", gameContentTypeSupported" + gameContentTypeSupported + "}";
+        }
+
+        @Override
+        public boolean equals(@Nullable Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            DynamicDisplayInfo that = (DynamicDisplayInfo) o;
+            return Arrays.equals(supportedDisplayModes, that.supportedDisplayModes)
+                && activeDisplayModeId == that.activeDisplayModeId
+                && Arrays.equals(supportedColorModes, that.supportedColorModes)
+                && activeColorMode == that.activeColorMode
+                && Objects.equals(hdrCapabilities, that.hdrCapabilities);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(supportedDisplayModes, activeDisplayModeId, activeDisplayModeId,
+                    activeColorMode, hdrCapabilities);
+        }
+    }
+
+    /**
      * Configuration supported by physical display.
      *
      * @hide
@@ -1749,6 +1792,7 @@
          */
         public static final int INVALID_DISPLAY_MODE_ID = -1;
 
+        public int id;
         public int width;
         public int height;
         public float xDpi;
@@ -1768,7 +1812,8 @@
 
         @Override
         public String toString() {
-            return "DisplayConfig{width=" + width
+            return "DisplayMode{id=" + id
+                    + ", width=" + width
                     + ", height=" + height
                     + ", xDpi=" + xDpi
                     + ", yDpi=" + yDpi
@@ -1777,6 +1822,28 @@
                     + ", presentationDeadlineNanos=" + presentationDeadlineNanos
                     + ", group=" + group + "}";
         }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            DisplayMode that = (DisplayMode) o;
+            return id == that.id
+                    && width == that.width
+                    && height == that.height
+                    && Float.compare(that.xDpi, xDpi) == 0
+                    && Float.compare(that.yDpi, yDpi) == 0
+                    && Float.compare(that.refreshRate, refreshRate) == 0
+                    && appVsyncOffsetNanos == that.appVsyncOffsetNanos
+                    && presentationDeadlineNanos == that.presentationDeadlineNanos
+                    && group == that.group;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(id, width, height, xDpi, yDpi, refreshRate, appVsyncOffsetNanos,
+                    presentationDeadlineNanos, group);
+        }
     }
 
     /**
@@ -1792,31 +1859,21 @@
     /**
      * @hide
      */
-    public static SurfaceControl.DisplayInfo getDisplayInfo(IBinder displayToken) {
+    public static StaticDisplayInfo getStaticDisplayInfo(IBinder displayToken) {
         if (displayToken == null) {
             throw new IllegalArgumentException("displayToken must not be null");
         }
-        return nativeGetDisplayInfo(displayToken);
+        return nativeGetStaticDisplayInfo(displayToken);
     }
 
     /**
      * @hide
      */
-    public static DisplayMode[] getDisplayModes(IBinder displayToken) {
+    public static DynamicDisplayInfo getDynamicDisplayInfo(IBinder displayToken) {
         if (displayToken == null) {
             throw new IllegalArgumentException("displayToken must not be null");
         }
-        return nativeGetDisplayModes(displayToken);
-    }
-
-    /**
-     * @hide
-     */
-    public static int getActiveDisplayMode(IBinder displayToken) {
-        if (displayToken == null) {
-            throw new IllegalArgumentException("displayToken must not be null");
-        }
-        return nativeGetActiveDisplayMode(displayToken);
+        return nativeGetDynamicDisplayInfo(displayToken);
     }
 
     /**
@@ -1978,16 +2035,6 @@
     }
 
     /**
-     * @hide
-     */
-    public static int[] getDisplayColorModes(IBinder displayToken) {
-        if (displayToken == null) {
-            throw new IllegalArgumentException("displayToken must not be null");
-        }
-        return nativeGetDisplayColorModes(displayToken);
-    }
-
-    /**
      * Color coordinates in CIE1931 XYZ color space
      *
      * @hide
@@ -2057,16 +2104,6 @@
     /**
      * @hide
      */
-    public static int getActiveColorMode(IBinder displayToken) {
-        if (displayToken == null) {
-            throw new IllegalArgumentException("displayToken must not be null");
-        }
-        return nativeGetActiveColorMode(displayToken);
-    }
-
-    /**
-     * @hide
-     */
     public static boolean setActiveColorMode(IBinder displayToken, int colorMode) {
         if (displayToken == null) {
             throw new IllegalArgumentException("displayToken must not be null");
@@ -2169,38 +2206,6 @@
     /**
      * @hide
      */
-    public static Display.HdrCapabilities getHdrCapabilities(IBinder displayToken) {
-        if (displayToken == null) {
-            throw new IllegalArgumentException("displayToken must not be null");
-        }
-        return nativeGetHdrCapabilities(displayToken);
-    }
-
-    /**
-     * @hide
-     */
-    public static boolean getAutoLowLatencyModeSupport(IBinder displayToken) {
-        if (displayToken == null) {
-            throw new IllegalArgumentException("displayToken must not be null");
-        }
-
-        return nativeGetAutoLowLatencyModeSupport(displayToken);
-    }
-
-    /**
-     * @hide
-     */
-    public static boolean getGameContentTypeSupport(IBinder displayToken) {
-        if (displayToken == null) {
-            throw new IllegalArgumentException("displayToken must not be null");
-        }
-
-        return nativeGetGameContentTypeSupport(displayToken);
-    }
-
-    /**
-     * @hide
-     */
     @UnsupportedAppUsage
     public static IBinder createDisplay(String name, boolean secure) {
         if (name == null) {
@@ -2951,6 +2956,17 @@
         /**
          * @hide
          */
+        public Transaction setStretchEffect(SurfaceControl sc, float left, float top, float right,
+                float bottom, float vecX, float vecY, float maxStretchAmount) {
+            checkPreconditions(sc);
+            nativeSetStretchEffect(mNativeObject, sc.mNativeObject, left, top, right, bottom,
+                    vecX, vecY, maxStretchAmount);
+            return this;
+        }
+
+        /**
+         * @hide
+         */
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.O)
         public Transaction setLayerStack(SurfaceControl sc, int layerStack) {
             checkPreconditions(sc);
@@ -3488,64 +3504,4 @@
     public static Transaction getGlobalTransaction() {
         return sGlobalTransaction;
     }
-
-    /**
-     * Wrapper for sending blur data to SurfaceFlinger.
-     * @hide
-     */
-    public static final class BlurRegion {
-        public int blurRadius;
-        public float cornerRadiusTL;
-        public float cornerRadiusTR;
-        public float cornerRadiusBL;
-        public float cornerRadiusBR;
-        public float alpha = 1;
-        public boolean visible = true;
-        public final Rect rect = new Rect();
-
-        private final float[] mFloatArray = new float[10];
-
-        public BlurRegion() {
-        }
-
-        public BlurRegion(BlurRegion other) {
-            rect.set(other.rect);
-            blurRadius = other.blurRadius;
-            alpha = other.alpha;
-            cornerRadiusTL = other.cornerRadiusTL;
-            cornerRadiusTR = other.cornerRadiusTR;
-            cornerRadiusBL = other.cornerRadiusBL;
-            cornerRadiusBR = other.cornerRadiusBR;
-        }
-
-        /**
-         * Serializes this class into a float array that's more JNI friendly.
-         */
-        public float[] toFloatArray() {
-            mFloatArray[0] = blurRadius;
-            mFloatArray[1] = alpha;
-            mFloatArray[2] = rect.left;
-            mFloatArray[3] = rect.top;
-            mFloatArray[4] = rect.right;
-            mFloatArray[5] = rect.bottom;
-            mFloatArray[6] = cornerRadiusTL;
-            mFloatArray[7] = cornerRadiusTR;
-            mFloatArray[8] = cornerRadiusBL;
-            mFloatArray[9] = cornerRadiusBR;
-            return mFloatArray;
-        }
-
-        @Override
-        public String toString() {
-            return "BlurRegion{"
-                    + "blurRadius=" + blurRadius
-                    + ", corners={" + cornerRadiusTL
-                    + "," + cornerRadiusTR
-                    + "," + cornerRadiusBL
-                    + "," + cornerRadiusBR
-                    + "}, alpha=" + alpha
-                    + ", rect=" + rect
-                    + "}";
-        }
-    }
 }
diff --git a/core/java/android/view/SurfaceControlFpsListener.java b/core/java/android/view/SurfaceControlFpsListener.java
new file mode 100644
index 0000000..517b0fb
--- /dev/null
+++ b/core/java/android/view/SurfaceControlFpsListener.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.annotation.NonNull;
+
+/**
+ * Listener for sampling the frames per second for a SurfaceControl and its children.
+ * This should only be used by a system component that needs to listen to a SurfaceControl's
+ * tree's FPS when it is not actively submitting transactions for that SurfaceControl.
+ * Otherwise, ASurfaceTransaction_OnComplete callbacks should be used.
+ *
+ * @hide
+ */
+public abstract class SurfaceControlFpsListener {
+    private long mNativeListener;
+
+    public SurfaceControlFpsListener() {
+        mNativeListener = nativeCreate(this);
+    }
+
+    protected void destroy() {
+        if (mNativeListener == 0) {
+            return;
+        }
+        unregister();
+        nativeDestroy(mNativeListener);
+        mNativeListener = 0;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            destroy();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    /**
+     * Reports the fps from the registered SurfaceControl
+     */
+    public abstract void onFpsReported(float fps);
+
+    /**
+     * Registers the sampling listener.
+     */
+    public void register(@NonNull SurfaceControl layer) {
+        if (mNativeListener == 0) {
+            return;
+        }
+
+        nativeRegister(mNativeListener, layer.mNativeObject);
+    }
+
+    /**
+     * Unregisters the sampling listener.
+     */
+    public void unregister() {
+        if (mNativeListener == 0) {
+            return;
+        }
+        nativeUnregister(mNativeListener);
+    }
+
+    /**
+     * Dispatch the collected sample.
+     *
+     * Called from native code on a binder thread.
+     */
+    private static void dispatchOnFpsReported(SurfaceControlFpsListener listener, float fps) {
+        listener.onFpsReported(fps);
+    }
+
+    private static native long nativeCreate(SurfaceControlFpsListener thiz);
+    private static native void nativeDestroy(long ptr);
+    private static native void nativeRegister(long ptr, long layerObject);
+    private static native void nativeUnregister(long ptr);
+}
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index 18029af..870fd8c 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -218,16 +218,6 @@
     }
 
     /**
-     * @hide
-     */
-    @TestApi
-    public void setView(@NonNull View view, @NonNull WindowManager.LayoutParams attrs) {
-        Objects.requireNonNull(view);
-        view.setLayoutParams(attrs);
-        mViewRoot.setView(view, attrs, null);
-    }
-
-    /**
      * Set the root view of the SurfaceControlViewHost. This view will render in to
      * the SurfaceControl, and receive input based on the SurfaceControls positioning on
      * screen. It will be laid as if it were in a window of the passed in width and height.
@@ -240,11 +230,21 @@
         final WindowManager.LayoutParams lp =
                 new WindowManager.LayoutParams(width, height,
                         WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.TRANSPARENT);
-        lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
         setView(view, lp);
     }
 
     /**
+     * @hide
+     */
+    @TestApi
+    public void setView(@NonNull View view, @NonNull WindowManager.LayoutParams attrs) {
+        Objects.requireNonNull(view);
+        attrs.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+        view.setLayoutParams(attrs);
+        mViewRoot.setView(view, attrs, null);
+    }
+
+    /**
      * @return The view passed to setView, or null if none has been passed.
      */
     public @Nullable View getView() {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 6eba83f..9688c67 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -544,6 +544,7 @@
         // recreate this Surface, so only release it when we are fully
         // detached.
         if (mSurfacePackage != null) {
+            mTmpTransaction.reparent(mSurfacePackage.getSurfaceControl(), null).apply();
             mSurfacePackage.release();
             mSurfacePackage = null;
         }
@@ -1444,6 +1445,14 @@
         }
 
         @Override
+        public void applyStretch(long frameNumber, float left, float top, float right,
+                float bottom, float vecX, float vecY, float maxStretch) {
+            mRtTransaction.setStretchEffect(mSurfaceControl, left, top, right, bottom, vecX, vecY,
+                    maxStretch);
+            applyRtTransaction(frameNumber);
+        }
+
+        @Override
         public void positionLost(long frameNumber) {
             if (DEBUG) {
                 Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d",
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 44d4d6b..ebef464 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -18,6 +18,12 @@
 
 import static android.content.res.Resources.ID_NULL;
 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
+import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_INVALID_BOUNDS;
+import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW;
+import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN;
+import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_UNKNOWN;
+import static android.view.displayhash.DisplayHashResultCallback.EXTRA_DISPLAY_HASH;
+import static android.view.displayhash.DisplayHashResultCallback.EXTRA_DISPLAY_HASH_ERROR_CODE;
 
 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS;
 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS;
@@ -89,6 +95,7 @@
 import android.os.Message;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.Trace;
@@ -135,6 +142,9 @@
 import android.view.contentcapture.ContentCaptureContext;
 import android.view.contentcapture.ContentCaptureManager;
 import android.view.contentcapture.ContentCaptureSession;
+import android.view.displayhash.DisplayHash;
+import android.view.displayhash.DisplayHashManager;
+import android.view.displayhash.DisplayHashResultCallback;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.view.inspector.InspectableProperty;
@@ -174,9 +184,10 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-import java.util.Queue;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
 import java.util.function.Predicate;
 
 /**
@@ -1473,7 +1484,6 @@
      *
      * @see #getScrollCaptureHint()
      * @see #setScrollCaptureHint(int)
-     * @hide
      */
     public static final int SCROLL_CAPTURE_HINT_AUTO = 0;
 
@@ -1484,7 +1494,6 @@
      *
      * @see #getScrollCaptureHint()
      * @see #setScrollCaptureHint(int)
-     * @hide
      */
     public static final int SCROLL_CAPTURE_HINT_EXCLUDE = 0x1;
 
@@ -1495,7 +1504,6 @@
      *
      * @see #getScrollCaptureHint()
      * @see #setScrollCaptureHint(int)
-     * @hide
      */
     public static final int SCROLL_CAPTURE_HINT_INCLUDE = 0x2;
 
@@ -1506,7 +1514,6 @@
      *
      * @see #getScrollCaptureHint()
      * @see #setScrollCaptureHint(int)
-     * @hide
      */
     public static final int SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS = 0x4;
 
@@ -6985,6 +6992,7 @@
      * @see #getScrollIndicators()
      * @attr ref android.R.styleable#View_scrollIndicators
      */
+    @RemotableViewMethod
     public void setScrollIndicators(@ScrollIndicators int indicators) {
         setScrollIndicators(indicators,
                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
@@ -11870,6 +11878,7 @@
      * @see #setFocusable(int)
      * @attr ref android.R.styleable#View_focusable
      */
+    @RemotableViewMethod
     public void setFocusable(boolean focusable) {
         setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
     }
@@ -11888,6 +11897,7 @@
      * @see #setFocusableInTouchMode(boolean)
      * @attr ref android.R.styleable#View_focusable
      */
+    @RemotableViewMethod
     public void setFocusable(@Focusable int focusable) {
         if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
@@ -11906,6 +11916,7 @@
      * @see #setFocusable(boolean)
      * @attr ref android.R.styleable#View_focusableInTouchMode
      */
+    @RemotableViewMethod
     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
         // Focusable in touch mode should always be set before the focusable flag
         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
@@ -12860,6 +12871,7 @@
      *
      * @attr ref android.R.styleable#View_focusedByDefault
      */
+    @RemotableViewMethod
     public void setFocusedByDefault(boolean isFocusedByDefault) {
         if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
             return;
@@ -16839,6 +16851,7 @@
      *
      * @attr ref android.R.styleable#View_rotation
      */
+    @RemotableViewMethod
     public void setRotation(float rotation) {
         if (rotation != getRotation()) {
             // Double-invalidation is necessary to capture view's old and new areas
@@ -16885,6 +16898,7 @@
      *
      * @attr ref android.R.styleable#View_rotationY
      */
+    @RemotableViewMethod
     public void setRotationY(float rotationY) {
         if (rotationY != getRotationY()) {
             invalidateViewProperty(true, false);
@@ -16930,6 +16944,7 @@
      *
      * @attr ref android.R.styleable#View_rotationX
      */
+    @RemotableViewMethod
     public void setRotationX(float rotationX) {
         if (rotationX != getRotationX()) {
             invalidateViewProperty(true, false);
@@ -16967,6 +16982,7 @@
      *
      * @attr ref android.R.styleable#View_scaleX
      */
+    @RemotableViewMethod
     public void setScaleX(float scaleX) {
         if (scaleX != getScaleX()) {
             scaleX = sanitizeFloatPropertyValue(scaleX, "scaleX");
@@ -17005,6 +17021,7 @@
      *
      * @attr ref android.R.styleable#View_scaleY
      */
+    @RemotableViewMethod
     public void setScaleY(float scaleY) {
         if (scaleY != getScaleY()) {
             scaleY = sanitizeFloatPropertyValue(scaleY, "scaleY");
@@ -17050,6 +17067,7 @@
      *
      * @attr ref android.R.styleable#View_transformPivotX
      */
+    @RemotableViewMethod
     public void setPivotX(float pivotX) {
         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
             invalidateViewProperty(true, false);
@@ -17092,6 +17110,7 @@
      *
      * @attr ref android.R.styleable#View_transformPivotY
      */
+    @RemotableViewMethod
     public void setPivotY(float pivotY) {
         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
             invalidateViewProperty(true, false);
@@ -17232,6 +17251,7 @@
      *
      * @attr ref android.R.styleable#View_alpha
      */
+    @RemotableViewMethod
     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
         ensureTransformationInfo();
         if (mTransformationInfo.mAlpha != alpha) {
@@ -17721,6 +17741,7 @@
      *
      * @attr ref android.R.styleable#View_elevation
      */
+    @RemotableViewMethod
     public void setElevation(float elevation) {
         if (elevation != getElevation()) {
             elevation = sanitizeFloatPropertyValue(elevation, "elevation");
@@ -17755,6 +17776,7 @@
      *
      * @attr ref android.R.styleable#View_translationX
      */
+    @RemotableViewMethod
     public void setTranslationX(float translationX) {
         if (translationX != getTranslationX()) {
             invalidateViewProperty(true, false);
@@ -17790,6 +17812,7 @@
      *
      * @attr ref android.R.styleable#View_translationY
      */
+    @RemotableViewMethod
     public void setTranslationY(float translationY) {
         if (translationY != getTranslationY()) {
             invalidateViewProperty(true, false);
@@ -17817,6 +17840,7 @@
      *
      * @attr ref android.R.styleable#View_translationZ
      */
+    @RemotableViewMethod
     public void setTranslationZ(float translationZ) {
         if (translationZ != getTranslationZ()) {
             translationZ = sanitizeFloatPropertyValue(translationZ, "translationZ");
@@ -23978,6 +24002,7 @@
      * @see #getBackgroundTintList()
      * @see Drawable#setTintList(ColorStateList)
      */
+    @RemotableViewMethod
     public void setBackgroundTintList(@Nullable ColorStateList tint) {
         if (mBackgroundTint == null) {
             mBackgroundTint = new TintInfo();
@@ -24237,6 +24262,7 @@
      * @see #getForegroundTintList()
      * @see Drawable#setTintList(ColorStateList)
      */
+    @RemotableViewMethod
     public void setForegroundTintList(@Nullable ColorStateList tint) {
         if (mForegroundInfo == null) {
             mForegroundInfo = new ForegroundInfo();
@@ -30023,8 +30049,6 @@
      * Returns the current scroll capture hint for this view.
      *
      * @return the current scroll capture hint
-     *
-     * @hide
      */
     @ScrollCaptureHint
     public int getScrollCaptureHint() {
@@ -30037,8 +30061,6 @@
      * scroll capture targets.
      *
      * @param hint the scrollCaptureHint flags value to set
-     *
-     * @hide
      */
     public void setScrollCaptureHint(@ScrollCaptureHint int hint) {
         mPrivateFlags4 &= ~PFLAG4_SCROLL_CAPTURE_HINT_MASK;
@@ -30058,10 +30080,8 @@
      * setting a custom callback to help ensure it is selected as the target.
      *
      * @param callback the new callback to assign
-     *
-     * @hide
      */
-    public void setScrollCaptureCallback(@Nullable ScrollCaptureCallback callback) {
+    public final void setScrollCaptureCallback(@Nullable ScrollCaptureCallback callback) {
         getListenerInfo().mScrollCaptureCallback = callback;
     }
 
@@ -30080,29 +30100,54 @@
     }
 
     /**
+     * Dispatch a scroll capture search request down the view hierarchy.
+     *
+     * @param localVisibleRect the visible area of this ViewGroup in local coordinates, according to
+     *                         the parent
+     * @param windowOffset     the offset of this view within the window
+     * @param targets          accepts potential scroll capture targets; {@link Consumer#accept
+     *                         results.accept} may be called zero or more times on the calling
+     *                         thread before onScrollCaptureSearch returns
+     */
+    public void dispatchScrollCaptureSearch(
+            @NonNull Rect localVisibleRect, @NonNull Point windowOffset,
+            @NonNull Consumer<ScrollCaptureTarget> targets) {
+        onScrollCaptureSearch(localVisibleRect, windowOffset, targets);
+    }
+
+    /**
      * Called when scroll capture is requested, to search for appropriate content to scroll. If
      * applicable, this view adds itself to the provided list for consideration, subject to the
      * flags set by {@link #setScrollCaptureHint}.
      *
      * @param localVisibleRect the local visible rect of this view
      * @param windowOffset     the offset of localVisibleRect within the window
-     * @param targets          a queue which collects potential targets
-     *
+     * @param targets          accepts potential scroll capture targets; {@link Consumer#accept
+     *                         results.accept} may be called zero or more times on the calling
+     *                         thread before onScrollCaptureSearch returns
      * @throws IllegalStateException if this view is not attached to a window
-     * @hide
      */
-    public void dispatchScrollCaptureSearch(@NonNull Rect localVisibleRect,
-            @NonNull Point windowOffset, @NonNull Queue<ScrollCaptureTarget> targets) {
+    public void onScrollCaptureSearch(@NonNull Rect localVisibleRect,
+            @NonNull Point windowOffset, @NonNull Consumer<ScrollCaptureTarget> targets) {
         int hint = getScrollCaptureHint();
         if ((hint & SCROLL_CAPTURE_HINT_EXCLUDE) != 0) {
             return;
         }
+        boolean rectIsVisible = true;
+
+        // Apply clipBounds if present.
+        if (mClipBounds != null) {
+            rectIsVisible = localVisibleRect.intersect(mClipBounds);
+        }
+        if (!rectIsVisible) {
+            return;
+        }
 
         // Get a callback provided by the framework, library or application.
         ScrollCaptureCallback callback =
                 (mListenerInfo == null) ? null : mListenerInfo.mScrollCaptureCallback;
 
-        // Try internal support for standard scrolling containers.
+        // Try framework support for standard scrolling containers.
         if (callback == null) {
             callback = createScrollCaptureCallbackInternal(localVisibleRect, windowOffset);
         }
@@ -30112,7 +30157,7 @@
             // Add to the list for consideration
             Point offset = new Point(windowOffset.x, windowOffset.y);
             Rect rect = new Rect(localVisibleRect);
-            targets.add(new ScrollCaptureTarget(this, rect, offset, callback));
+            targets.accept(new ScrollCaptureTarget(this, rect, offset, callback));
         }
     }
 
@@ -30707,4 +30752,71 @@
     public void onTranslationComplete(@NonNull TranslationRequest request) {
         // no-op
     }
+
+    /**
+     * Called to generate a {@link DisplayHash} for this view.
+     *
+     * @param hashAlgorithm The hash algorithm to use when hashing the display. Must be one of
+     *                      the values returned from
+     *                      {@link DisplayHashManager#getSupportedHashAlgorithms()}
+     * @param bounds The bounds for the content within the View to generate the hash for. If
+     *               bounds are null, the entire View's bounds will be used. If empty, it will
+     *               invoke the callback
+     *               {@link DisplayHashResultCallback#onDisplayHashError} with error
+     *               {@link DisplayHashResultCallback#DISPLAY_HASH_ERROR_INVALID_BOUNDS}
+     * @param executor The executor that the callback should be invoked on.
+     * @param callback The callback to handle the results of generating the display hash
+     */
+    @Nullable
+    public void generateDisplayHash(@NonNull String hashAlgorithm,
+            @Nullable Rect bounds, @NonNull Executor executor,
+            @NonNull DisplayHashResultCallback callback) {
+        IWindowSession session = getWindowSession();
+        if (session == null) {
+            callback.onDisplayHashError(DISPLAY_HASH_ERROR_MISSING_WINDOW);
+            return;
+        }
+        IWindow window = getWindow();
+        if (window == null) {
+            callback.onDisplayHashError(DISPLAY_HASH_ERROR_MISSING_WINDOW);
+            return;
+        }
+
+        Rect visibleBounds = new Rect();
+        getGlobalVisibleRect(visibleBounds);
+
+        if (bounds != null && bounds.isEmpty()) {
+            callback.onDisplayHashError(DISPLAY_HASH_ERROR_INVALID_BOUNDS);
+            return;
+        }
+
+        if (bounds != null) {
+            bounds.offset(visibleBounds.left, visibleBounds.top);
+            visibleBounds.intersectUnchecked(bounds);
+        }
+
+        if (visibleBounds.isEmpty()) {
+            callback.onDisplayHashError(DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN);
+            return;
+        }
+
+        RemoteCallback remoteCallback = new RemoteCallback(result ->
+                executor.execute(() -> {
+                    DisplayHash displayHash = result.getParcelable(EXTRA_DISPLAY_HASH);
+                    int errorCode = result.getInt(EXTRA_DISPLAY_HASH_ERROR_CODE,
+                            DISPLAY_HASH_ERROR_UNKNOWN);
+                    if (displayHash != null) {
+                        callback.onDisplayHashResult(displayHash);
+                    } else {
+                        callback.onDisplayHashError(errorCode);
+                    }
+                }));
+
+        try {
+            session.generateDisplayHash(window, visibleBounds, hashAlgorithm, remoteCallback);
+        } catch (RemoteException e) {
+            Log.e(VIEW_LOG_TAG, "Failed to call generateDisplayHash");
+            callback.onDisplayHashError(DISPLAY_HASH_ERROR_UNKNOWN);
+        }
+    }
 }
diff --git a/core/java/android/view/ViewFrameInfo.java b/core/java/android/view/ViewFrameInfo.java
index 890d071..d4aaa61 100644
--- a/core/java/android/view/ViewFrameInfo.java
+++ b/core/java/android/view/ViewFrameInfo.java
@@ -58,8 +58,8 @@
     public void populateFrameInfo(FrameInfo frameInfo) {
         frameInfo.frameInfo[FrameInfo.FLAGS] |= flags;
         frameInfo.frameInfo[FrameInfo.DRAW_START] = drawStart;
-        frameInfo.frameInfo[FrameInfo.OLDEST_INPUT_EVENT] = oldestInputEventTime;
-        frameInfo.frameInfo[FrameInfo.NEWEST_INPUT_EVENT] = newestInputEventTime;
+        // TODO(b/169866723): Use InputEventAssigner
+        frameInfo.frameInfo[FrameInfo.INPUT_EVENT_ID] = newestInputEventTime;
     }
 
     /**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 37bea58..38a5937 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -77,7 +77,7 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Queue;
+import java.util.function.Consumer;
 import java.util.function.Predicate;
 
 /**
@@ -7463,92 +7463,73 @@
     }
 
     /**
-     * Offsets the given rectangle in parent's local coordinates into child's coordinate space
-     * and clips the result to the child View's bounds, padding and clipRect if appropriate. If the
-     * resulting rectangle is not empty, the request is forwarded to the child.
-     * <p>
-     * Note: This method does not account for any static View transformations which may be
-     * applied to the child view.
-     *
-     * @param child            the child to dispatch to
-     * @param localVisibleRect the visible (clipped) area of this ViewGroup, in local coordinates
-     * @param windowOffset     the offset of localVisibleRect within the window
-     * @param targets          a queue to collect located targets
-     */
-    private void dispatchTransformedScrollCaptureSearch(View child, Rect localVisibleRect,
-            Point windowOffset, Queue<ScrollCaptureTarget> targets) {
-
-        // copy local visible rect for modification and dispatch
-        final Rect childVisibleRect = getTempRect();
-        childVisibleRect.set(localVisibleRect);
-
-        // transform to child coords
-        final Point childWindowOffset = getTempPoint();
-        childWindowOffset.set(windowOffset.x, windowOffset.y);
-
-        final int dx = child.mLeft - mScrollX;
-        final int dy = child.mTop - mScrollY;
-
-        childVisibleRect.offset(-dx, -dy);
-        childWindowOffset.offset(dx, dy);
-
-        boolean rectIsVisible = true;
-        final int width = mRight - mLeft;
-        final int height = mBottom - mTop;
-
-        // Clip to child bounds
-        if (getClipChildren()) {
-            rectIsVisible = childVisibleRect.intersect(0, 0, child.getWidth(), child.getHeight());
-        }
-
-        // Clip to child padding.
-        if (rectIsVisible && (child instanceof ViewGroup)
-                && ((ViewGroup) child).getClipToPadding()) {
-            rectIsVisible = childVisibleRect.intersect(
-                    child.mPaddingLeft, child.mPaddingTop,
-                    child.getWidth() - child.mPaddingRight,
-                    child.getHeight() - child.mPaddingBottom);
-        }
-        // Clip to child clipBounds.
-        if (rectIsVisible && child.mClipBounds != null) {
-            rectIsVisible = childVisibleRect.intersect(child.mClipBounds);
-        }
-        if (rectIsVisible) {
-            child.dispatchScrollCaptureSearch(childVisibleRect, childWindowOffset, targets);
-        }
-    }
-
-    /**
      * Handle the scroll capture search request by checking this view if applicable, then to each
      * child view.
      *
      * @param localVisibleRect the visible area of this ViewGroup in local coordinates, according to
      *                         the parent
      * @param windowOffset     the offset of this view within the window
-     * @param targets          the collected list of scroll capture targets
-     *
-     * @hide
+     * @param targets          accepts potential scroll capture targets; {@link Consumer#accept
+     *                         results.accept} may be called zero or more times on the calling
+     *                         thread before onScrollCaptureSearch returns
      */
     @Override
     public void dispatchScrollCaptureSearch(
             @NonNull Rect localVisibleRect, @NonNull Point windowOffset,
-            @NonNull Queue<ScrollCaptureTarget> targets) {
+            @NonNull Consumer<ScrollCaptureTarget> targets) {
+
+        // copy local visible rect for modification and dispatch
+        final Rect rect = getTempRect();
+        rect.set(localVisibleRect);
+
+        if (getClipToPadding()) {
+            rect.inset(mPaddingLeft, mPaddingTop, mPaddingRight, mPaddingBottom);
+        }
 
         // Dispatch to self first.
         super.dispatchScrollCaptureSearch(localVisibleRect, windowOffset, targets);
 
-        // Then dispatch to children, if not excluding descendants.
-        if ((getScrollCaptureHint() & SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS) == 0) {
-            final int childCount = getChildCount();
-            for (int i = 0; i < childCount; i++) {
-                View child = getChildAt(i);
-                // Only visible views can be captured.
-                if (child.getVisibility() != View.VISIBLE) {
-                    continue;
-                }
-                // Transform to child coords and dispatch
-                dispatchTransformedScrollCaptureSearch(child, localVisibleRect, windowOffset,
-                        targets);
+        // Skip children if descendants excluded.
+        if ((getScrollCaptureHint() & SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS) != 0) {
+            return;
+        }
+
+        final int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            // Only visible views can be captured.
+            if (child.getVisibility() != View.VISIBLE) {
+                continue;
+            }
+            // Offset the given rectangle (in parent's local coordinates) into child's coordinate
+            // space and clip the result to the child View's bounds, padding and clipRect as needed.
+            // If the resulting rectangle is not empty, the request is forwarded to the child.
+
+            // copy local visible rect for modification and dispatch
+            final Rect childVisibleRect = getTempRect();
+            childVisibleRect.set(localVisibleRect);
+
+            // transform to child coords
+            final Point childWindowOffset = getTempPoint();
+            childWindowOffset.set(windowOffset.x, windowOffset.y);
+
+            final int dx = child.mLeft - mScrollX;
+            final int dy = child.mTop - mScrollY;
+
+            childVisibleRect.offset(-dx, -dy);
+            childWindowOffset.offset(dx, dy);
+
+            boolean rectIsVisible = true;
+
+            // Clip to child bounds
+            if (getClipChildren()) {
+                rectIsVisible = childVisibleRect.intersect(0, 0, child.getWidth(),
+                        child.getHeight());
+            }
+
+            // Clip to child padding.
+            if (rectIsVisible) {
+                child.dispatchScrollCaptureSearch(childVisibleRect, childWindowOffset, targets);
             }
         }
     }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f1f6786..f8e65bd 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -141,6 +141,7 @@
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
+import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.util.LongArray;
 import android.util.MergedConfiguration;
@@ -202,6 +203,7 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -274,6 +276,11 @@
      */
     private static final int CONTENT_CAPTURE_ENABLED_FALSE = 2;
 
+    /**
+     * Maximum time to wait for {@link View#dispatchScrollCaptureSearch} to complete.
+     */
+    private static final int SCROLL_CAPTURE_REQUEST_TIMEOUT_MILLIS = 2500;
+
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     static final ThreadLocal<HandlerActionQueue> sRunQueues = new ThreadLocal<HandlerActionQueue>();
 
@@ -323,6 +330,8 @@
     private boolean mForceDisableBLAST;
     private boolean mEnableTripleBuffering;
 
+    private boolean mFastScrollSoundEffectsEnabled;
+
     /**
      * Signals that compatibility booleans have been initialized according to
      * target SDK versions.
@@ -666,8 +675,6 @@
     private final InsetsController mInsetsController;
     private final ImeFocusController mImeFocusController;
 
-    private ScrollCaptureConnection mScrollCaptureConnection;
-
     private boolean mIsSurfaceOpaque;
 
     private final BackgroundBlurDrawable.Aggregator mBlurRegionAggregator =
@@ -681,12 +688,6 @@
         return mImeFocusController;
     }
 
-    /** @return The current {@link ScrollCaptureConnection} for this instance, if any is active. */
-    @Nullable
-    public ScrollCaptureConnection getScrollCaptureConnection() {
-        return mScrollCaptureConnection;
-    }
-
     private final GestureExclusionTracker mGestureExclusionTracker = new GestureExclusionTracker();
 
     private IAccessibilityEmbeddedConnection mAccessibilityEmbeddedConnection;
@@ -728,6 +729,8 @@
 
     private HashSet<ScrollCaptureCallback> mRootScrollCaptureCallbacks;
 
+    private long mScrollCaptureRequestTimeout = SCROLL_CAPTURE_REQUEST_TIMEOUT_MILLIS;
+
     /**
      * Increment this value when the surface has been replaced.
      */
@@ -813,6 +816,10 @@
 
         loadSystemProperties();
         mImeFocusController = new ImeFocusController(this);
+        AudioManager audioManager = mContext.getSystemService(AudioManager.class);
+        mFastScrollSoundEffectsEnabled = audioManager.areNavigationRepeatSoundEffectsEnabled();
+
+        mScrollCaptureRequestTimeout = SCROLL_CAPTURE_REQUEST_TIMEOUT_MILLIS;
     }
 
     public static void addFirstDrawHandler(Runnable callback) {
@@ -1677,7 +1684,8 @@
 
         // See comment for View.sForceLayoutWhenInsetsChanged
         if (View.sForceLayoutWhenInsetsChanged && mView != null
-                && mWindowAttributes.softInputMode == SOFT_INPUT_ADJUST_RESIZE) {
+                && (mWindowAttributes.softInputMode & SOFT_INPUT_MASK_ADJUST)
+                        == SOFT_INPUT_ADJUST_RESIZE) {
             forceLayout(mView);
         }
 
@@ -3961,11 +3969,12 @@
     }
 
     private void addFrameCallbackIfNeeded() {
-        boolean nextDrawUseBlastSync = mNextDrawUseBlastSync;
-        boolean hasBlur = mBlurRegionAggregator.hasRegions();
-        boolean reportNextDraw = mReportNextDraw;
+        final boolean nextDrawUseBlastSync = mNextDrawUseBlastSync;
+        final boolean reportNextDraw = mReportNextDraw;
+        final boolean hasBlurUpdates = mBlurRegionAggregator.hasUpdates();
+        final boolean needsCallbackForBlur = hasBlurUpdates || mBlurRegionAggregator.hasRegions();
 
-        if (!nextDrawUseBlastSync && !reportNextDraw && !hasBlur) {
+        if (!nextDrawUseBlastSync && !reportNextDraw && !needsCallbackForBlur) {
             return;
         }
 
@@ -3973,18 +3982,22 @@
             Log.d(mTag, "Creating frameDrawingCallback"
                     + " nextDrawUseBlastSync=" + nextDrawUseBlastSync
                     + " reportNextDraw=" + reportNextDraw
-                    + " hasBlur=" + hasBlur);
+                    + " hasBlurUpdates=" + hasBlurUpdates);
         }
 
-        // The callback will run on a worker thread pool from the render thread.
+        final BackgroundBlurDrawable.BlurRegion[] blurRegionsForFrame =
+                needsCallbackForBlur ?  mBlurRegionAggregator.getBlurRegionsCopyForRT() : null;
+
+        // The callback will run on the render thread.
         HardwareRenderer.FrameDrawingCallback frameDrawingCallback = frame -> {
             if (DEBUG_BLAST) {
                 Log.d(mTag, "Received frameDrawingCallback frameNum=" + frame + "."
                         + " Creating transactionCompleteCallback=" + nextDrawUseBlastSync);
             }
 
-            if (hasBlur) {
-                mBlurRegionAggregator.dispatchBlurTransactionIfNeeded(frame);
+            if (needsCallbackForBlur) {
+                mBlurRegionAggregator
+                    .dispatchBlurTransactionIfNeeded(frame, blurRegionsForFrame, hasBlurUpdates);
             }
 
             if (mBlastBufferQueue == null) {
@@ -6080,8 +6093,10 @@
                                     v, mTempRect);
                         }
                         if (v.requestFocus(direction, mTempRect)) {
-                            playSoundEffect(SoundEffectConstants
-                                    .getContantForFocusDirection(direction));
+                            boolean isFastScrolling = event.getRepeatCount() > 0;
+                            playSoundEffect(
+                                    SoundEffectConstants.getConstantForFocusDirection(direction,
+                                            isFastScrolling));
                             return true;
                         }
                     }
@@ -7742,20 +7757,31 @@
         try {
             final AudioManager audioManager = getAudioManager();
 
+            if (mFastScrollSoundEffectsEnabled
+                    && SoundEffectConstants.isNavigationRepeat(effectId)) {
+                audioManager.playSoundEffect(
+                        SoundEffectConstants.nextNavigationRepeatSoundEffectId());
+                return;
+            }
+
             switch (effectId) {
                 case SoundEffectConstants.CLICK:
                     audioManager.playSoundEffect(AudioManager.FX_KEY_CLICK);
                     return;
                 case SoundEffectConstants.NAVIGATION_DOWN:
+                case SoundEffectConstants.NAVIGATION_REPEAT_DOWN:
                     audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN);
                     return;
                 case SoundEffectConstants.NAVIGATION_LEFT:
+                case SoundEffectConstants.NAVIGATION_REPEAT_LEFT:
                     audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT);
                     return;
                 case SoundEffectConstants.NAVIGATION_RIGHT:
+                case SoundEffectConstants.NAVIGATION_REPEAT_RIGHT:
                     audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT);
                     return;
                 case SoundEffectConstants.NAVIGATION_UP:
+                case SoundEffectConstants.NAVIGATION_REPEAT_UP:
                     audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP);
                     return;
                 default:
@@ -9205,9 +9231,9 @@
      * Collect and include any ScrollCaptureCallback instances registered with the window.
      *
      * @see #addScrollCaptureCallback(ScrollCaptureCallback)
-     * @param targets the search queue for targets
+     * @param results an object to collect the results of the search
      */
-    private void collectRootScrollCaptureTargets(Queue<ScrollCaptureTarget> targets) {
+    private void collectRootScrollCaptureTargets(ScrollCaptureSearchResults results) {
         if (mRootScrollCaptureCallbacks == null) {
             return;
         }
@@ -9215,26 +9241,45 @@
             // Add to the list for consideration
             Point offset = new Point(mView.getLeft(), mView.getTop());
             Rect rect = new Rect(0, 0, mView.getWidth(), mView.getHeight());
-            targets.add(new ScrollCaptureTarget(mView, rect, offset, cb));
+            results.addTarget(new ScrollCaptureTarget(mView, rect, offset, cb));
         }
     }
 
     /**
-     * Handles an inbound request for scroll capture from the system. If a client is not already
-     * active, a search will be dispatched through the view tree to locate scrolling content.
+     * Update the timeout for scroll capture requests. Only affects this view root.
+     * The default value is {@link #SCROLL_CAPTURE_REQUEST_TIMEOUT_MILLIS}.
+     *
+     * @param timeMillis the new timeout in milliseconds
+     */
+    public void setScrollCaptureRequestTimeout(int timeMillis) {
+        mScrollCaptureRequestTimeout = timeMillis;
+    }
+
+    /**
+     * Get the current timeout for scroll capture requests.
+     *
+     * @return the timeout in milliseconds
+     */
+    public long getScrollCaptureRequestTimeout() {
+        return mScrollCaptureRequestTimeout;
+    }
+
+    /**
+     * Handles an inbound request for scroll capture from the system. A search will be
+     * dispatched through the view tree to locate scrolling content.
      * <p>
-     * Either {@link IScrollCaptureCallbacks#onConnected(IScrollCaptureConnection, Rect,
-     * Point)} or {@link IScrollCaptureCallbacks#onUnavailable()} will be returned
-     * depending on the results of the search.
+     * A call to {@link IScrollCaptureCallbacks#onScrollCaptureResponse(ScrollCaptureResponse)}
+     * will follow.
      *
      * @param callbacks to receive responses
-     * @see ScrollCaptureTargetResolver
+     * @see ScrollCaptureTargetSelector
      */
     public void handleScrollCaptureRequest(@NonNull IScrollCaptureCallbacks callbacks) {
-        LinkedList<ScrollCaptureTarget> targetList = new LinkedList<>();
+        ScrollCaptureSearchResults results =
+                new ScrollCaptureSearchResults(mContext.getMainExecutor());
 
         // Window (root) level callbacks
-        collectRootScrollCaptureTargets(targetList);
+        collectRootScrollCaptureTargets(results);
 
         // Search through View-tree
         View rootView = getView();
@@ -9242,58 +9287,70 @@
             Point point = new Point();
             Rect rect = new Rect(0, 0, rootView.getWidth(), rootView.getHeight());
             getChildVisibleRect(rootView, rect, point);
-            rootView.dispatchScrollCaptureSearch(rect, point, targetList);
+            rootView.dispatchScrollCaptureSearch(rect, point, results::addTarget);
         }
-
-        // No-op path. Scroll capture not offered for this window.
-        if (targetList.isEmpty()) {
-            dispatchScrollCaptureSearchResult(callbacks, null);
-            return;
+        Runnable onComplete = () -> dispatchScrollCaptureSearchResult(callbacks, results);
+        results.setOnCompleteListener(onComplete);
+        if (!results.isComplete()) {
+            mHandler.postDelayed(results::finish, getScrollCaptureRequestTimeout());
         }
-
-        // Request scrollBounds from each of the targets.
-        // Continues with the consumer once all responses are consumed, or the timeout expires.
-        ScrollCaptureTargetResolver resolver = new ScrollCaptureTargetResolver(targetList);
-        resolver.start(mHandler, 1000,
-                (selected) -> dispatchScrollCaptureSearchResult(callbacks, selected));
     }
 
     /** Called by {@link #handleScrollCaptureRequest} when a result is returned */
     private void dispatchScrollCaptureSearchResult(
             @NonNull IScrollCaptureCallbacks callbacks,
-            @Nullable ScrollCaptureTarget selectedTarget) {
+            @NonNull ScrollCaptureSearchResults results) {
 
-        // If timeout or no eligible targets found.
+        ScrollCaptureTarget selectedTarget = results.getTopResult();
+
+        ScrollCaptureResponse.Builder response = new ScrollCaptureResponse.Builder();
+        response.setWindowTitle(getTitle().toString());
+
+        StringWriter writer =  new StringWriter();
+        IndentingPrintWriter pw = new IndentingPrintWriter(writer);
+        results.dump(pw);
+        pw.flush();
+        response.addMessage(writer.toString());
+
         if (selectedTarget == null) {
+            response.setDescription("No scrollable targets found in window");
             try {
-                if (DEBUG_SCROLL_CAPTURE) {
-                    Log.d(TAG, "scrollCaptureSearch returned no targets available.");
-                }
-                callbacks.onUnavailable();
+                callbacks.onScrollCaptureResponse(response.build());
             } catch (RemoteException e) {
-                if (DEBUG_SCROLL_CAPTURE) {
-                    Log.w(TAG, "Failed to send scroll capture search result.", e);
-                }
+                Log.e(TAG, "Failed to send scroll capture search result", e);
             }
             return;
         }
 
-        // Create a client instance and return it to the caller
-        mScrollCaptureConnection = new ScrollCaptureConnection(selectedTarget, callbacks);
+        response.setDescription("Connected");
+
+        // Compute area covered by scrolling content within window
+        Rect boundsInWindow = new Rect();
+        View containingView = selectedTarget.getContainingView();
+        containingView.getLocationInWindow(mAttachInfo.mTmpLocation);
+        boundsInWindow.set(selectedTarget.getScrollBounds());
+        boundsInWindow.offset(mAttachInfo.mTmpLocation[0], mAttachInfo.mTmpLocation[1]);
+        response.setBoundsInWindow(boundsInWindow);
+
+        // Compute the area on screen covered by the window
+        Rect boundsOnScreen = new Rect();
+        mView.getLocationOnScreen(mAttachInfo.mTmpLocation);
+        boundsOnScreen.set(0, 0, mView.getWidth(), mView.getHeight());
+        boundsOnScreen.offset(mAttachInfo.mTmpLocation[0], mAttachInfo.mTmpLocation[1]);
+        response.setWindowBounds(boundsOnScreen);
+
+        // Create a connection and return it to the caller
+        ScrollCaptureConnection connection = new ScrollCaptureConnection(
+                mView.getContext().getMainExecutor(), selectedTarget, callbacks);
+        response.setConnection(connection);
+
         try {
-            if (DEBUG_SCROLL_CAPTURE) {
-                Log.d(TAG, "scrollCaptureSearch returning client: " + getScrollCaptureConnection());
-            }
-            callbacks.onConnected(
-                    mScrollCaptureConnection,
-                    selectedTarget.getScrollBounds(),
-                    selectedTarget.getPositionInWindow());
+            callbacks.onScrollCaptureResponse(response.build());
         } catch (RemoteException e) {
             if (DEBUG_SCROLL_CAPTURE) {
-                Log.w(TAG, "Failed to send scroll capture search result.", e);
+                Log.w(TAG, "Failed to send scroll capture search response.", e);
             }
-            mScrollCaptureConnection.disconnect();
-            mScrollCaptureConnection = null;
+            connection.close();
         }
     }
 
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 4ecdd78..cf5ec8d 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1716,13 +1716,22 @@
      * For the blur region to be visible, the window has to be translucent. See
      * {@link android.R.styleable#Window_windowIsTranslucent}.
      *
-     * Note the difference with {@link android.view.WindowManager.LayoutParams#blurBehindRadius},
+     * Note the difference with {@link WindowManager.LayoutParams#setBlurBehindRadius},
      * which blurs the whole screen behind the window. Background blur blurs the screen behind
      * only within the bounds of the window.
      *
+     * Some devices might not support cross-window blur due to GPU limitations. It can also be
+     * disabled at runtime, e.g. during battery saving mode, when multimedia tunneling is used or
+     * when minimal post processing is requested. In such situations, no blur will be computed or
+     * drawn, resulting in a transparent window background. To avoid this, the app might want to
+     * change its theme to one that does not use blurs. To listen for cross-window blur
+     * enabled/disabled events, use {@link WindowManager#addCrossWindowBlurEnabledListener}.
+     *
      * @param blurRadius The blur radius to use for window background blur in pixels
      *
      * @see android.R.styleable#Window_windowBackgroundBlurRadius
+     * @see WindowManager.LayoutParams#setBlurBehindRadius
+     * @see WindowManager#addCrossWindowBlurEnabledListener
      */
     public void setBackgroundBlurRadius(int blurRadius) {}
 
@@ -2621,7 +2630,6 @@
      * callback with the root view of the window.
      *
      * @param callback the callback to add
-     * @hide
      */
     public void registerScrollCaptureCallback(@NonNull ScrollCaptureCallback callback) {
     }
@@ -2630,7 +2638,6 @@
      * Unregisters a {@link ScrollCaptureCallback} previously registered with this window.
      *
      * @param callback the callback to remove
-     * @hide
      */
     public void unregisterScrollCaptureCallback(@NonNull ScrollCaptureCallback callback) {
     }
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 9e87c95..2053826 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -82,6 +82,7 @@
 
 import android.Manifest.permission;
 import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -120,6 +121,7 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
+import java.util.function.Consumer;
 
 /**
  * The interface that apps use to talk to the window manager.
@@ -808,6 +810,64 @@
         return DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
     }
 
+    /**
+     * Returns whether cross-window blur is currently enabled. This affects both window blur behind
+     * (see {@link LayoutParams#setBlurBehindRadius}) and window background blur (see
+     * {@link Window#setBackgroundBlurRadius}).
+     *
+     * Cross-window blur might not be supported by some devices due to GPU limitations. It can also
+     * be disabled at runtime, e.g. during battery saving mode, when multimedia tunneling is used or
+     * when minimal post processing is requested. In such situations, no blur will be computed or
+     * drawn, so the blur target area will not be blurred. To handle this, the app might want to
+     * change its theme to one that does not use blurs. To listen for cross-window blur
+     * enabled/disabled events, use {@link #addCrossWindowBlurEnabledListener}.
+     *
+     * @see #addCrossWindowBlurEnabledListener
+     * @see LayoutParams#setBlurBehindRadius
+     * @see Window#setBackgroundBlurRadius
+     */
+    default boolean isCrossWindowBlurEnabled() {
+        return false;
+    }
+
+    /**
+     * Adds a listener, which will be called when cross-window blurs are enabled/disabled at
+     * runtime. This affects both window blur behind (see {@link LayoutParams#setBlurBehindRadius})
+     * and window background blur (see {@link Window#setBackgroundBlurRadius}).
+     *
+     * Cross-window blur might not be supported by some devices due to GPU limitations. It can also
+     * be disabled at runtime, e.g. during battery saving mode, when multimedia tunneling is used or
+     * when minimal post processing is requested. In such situations, no blur will be computed or
+     * drawn, so the blur target area will not be blurred. To handle this, the app might want to
+     * change its theme to one that does not use blurs.
+     *
+     * The listener will be called on the main thread.
+     *
+     * If the listener is added successfully, it will be called immediately with the current
+     * cross-window blur enabled state.
+     *
+     *
+     * @param listener the listener to be added. It will be called back with a boolean parameter,
+     *                 which is true if cross-window blur is enabled and false if it is disabled
+     *
+     * @see #removeCrossWindowBlurEnabledListener
+     * @see #isCrossWindowBlurEnabled
+     * @see LayoutParams#setBlurBehindRadius
+     * @see Window#setBackgroundBlurRadius
+     */
+    default void addCrossWindowBlurEnabledListener(@NonNull Consumer<Boolean> listener) {
+    }
+
+    /**
+     * Removes a listener, previously added with {@link #addCrossWindowBlurEnabledListener}
+     *
+     * @param listener the listener to be removed
+     *
+     * @see #addCrossWindowBlurEnabledListener
+     */
+    default void removeCrossWindowBlurEnabledListener(@NonNull Consumer<Boolean> listener) {
+    }
+
     public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable {
         /**
          * X position for this window.  With the default gravity it is ignored.
@@ -3238,9 +3298,9 @@
          * The blur behind radius range starts at 0, which means no blur, and increases until 150
          * for the densest blur.
          *
-         * @see #FLAG_BLUR_BEHIND
+         * @see #setBlurBehindRadius
          */
-        public int blurBehindRadius = 0;
+        private int mBlurBehindRadius = 0;
 
         /**
          * The color mode requested by this window. The target display may
@@ -3534,6 +3594,50 @@
             return mColorMode;
         }
 
+        /**
+         * Blurs the screen behind the window. The effect is similar to that of {@link #dimAmount},
+         * but instead of dimmed, the content behind the window will be blurred (or combined with
+         * the dim amount, if such is specified).
+         *
+         * The density of the blur is set by the blur radius. The radius defines the size
+         * of the neighbouring area, from which pixels will be averaged to form the final
+         * color for each pixel. The operation approximates a Gaussian blur.
+         * A radius of 0 means no blur. The higher the radius, the denser the blur.
+         *
+         * Note the difference with {@link android.view.Window#setBackgroundBlurRadius},
+         * which blurs only within the bounds of the window. Blur behind blurs the whole screen
+         * behind the window.
+         *
+         * Requires {@link #FLAG_BLUR_BEHIND} to be set.
+         *
+         * Cross-window blur might not be supported by some devices due to GPU limitations. It can
+         * also be disabled at runtime, e.g. during battery saving mode, when multimedia tunneling
+         * is used or when minimal post processing is requested. In such situations, no blur will
+         * be computed or drawn, resulting in there being no depth separation between the window
+         * and the content behind it. To avoid this, the app might want to use more
+         * {@link #dimAmount} on its window. To listen for cross-window blur enabled/disabled
+         * events, use {@link #addCrossWindowBlurEnabledListener}.
+         *
+         * @param blurBehindRadius The blur radius to use for blur behind in pixels
+         *
+         * @see #FLAG_BLUR_BEHIND
+         * @see #getBlurBehindRadius
+         * @see WindowManager#addCrossWindowBlurEnabledListener
+         * @see Window#setBackgroundBlurRadius
+         */
+        public void setBlurBehindRadius(@IntRange(from = 0) int blurBehindRadius) {
+            mBlurBehindRadius = blurBehindRadius;
+        }
+
+        /**
+         * Returns the blur behind radius of the window.
+         *
+         * @see #setBlurBehindRadius
+         */
+        public int getBlurBehindRadius() {
+            return mBlurBehindRadius;
+        }
+
         /** @hide */
         @SystemApi
         public final void setUserActivityTimeout(long timeout) {
@@ -3629,7 +3733,7 @@
             out.writeInt(mFitInsetsSides);
             out.writeBoolean(mFitInsetsIgnoringVisibility);
             out.writeBoolean(preferMinimalPostProcessing);
-            out.writeInt(blurBehindRadius);
+            out.writeInt(mBlurBehindRadius);
             if (providesInsetsTypes != null) {
                 out.writeInt(providesInsetsTypes.length);
                 out.writeIntArray(providesInsetsTypes);
@@ -3698,7 +3802,7 @@
             mFitInsetsSides = in.readInt();
             mFitInsetsIgnoringVisibility = in.readBoolean();
             preferMinimalPostProcessing = in.readBoolean();
-            blurBehindRadius = in.readInt();
+            mBlurBehindRadius = in.readInt();
             int insetsTypesLength = in.readInt();
             if (insetsTypesLength > 0) {
                 providesInsetsTypes = new int[insetsTypesLength];
@@ -3752,7 +3856,7 @@
         /** {@hide} */
         public static final int MINIMAL_POST_PROCESSING_PREFERENCE_CHANGED = 1 << 28;
         /** {@hide} */
-        public static final int BACKGROUND_BLUR_RADIUS_CHANGED = 1 << 29;
+        public static final int BLUR_BEHIND_RADIUS_CHANGED = 1 << 29;
 
         // internal buffer to backup/restore parameters under compatibility mode.
         private int[] mCompatibilityParamsBackup = null;
@@ -3943,9 +4047,9 @@
                 changes |= MINIMAL_POST_PROCESSING_PREFERENCE_CHANGED;
             }
 
-            if (blurBehindRadius != o.blurBehindRadius) {
-                blurBehindRadius = o.blurBehindRadius;
-                changes |= BACKGROUND_BLUR_RADIUS_CHANGED;
+            if (mBlurBehindRadius != o.mBlurBehindRadius) {
+                mBlurBehindRadius = o.mBlurBehindRadius;
+                changes |= BLUR_BEHIND_RADIUS_CHANGED;
             }
 
             // This can't change, it's only set at window creation time.
@@ -4111,9 +4215,9 @@
                 sb.append(" preferMinimalPostProcessing=");
                 sb.append(preferMinimalPostProcessing);
             }
-            if (blurBehindRadius != 0) {
+            if (mBlurBehindRadius != 0) {
                 sb.append(" blurBehindRadius=");
-                sb.append(blurBehindRadius);
+                sb.append(mBlurBehindRadius);
             }
             sb.append(System.lineSeparator());
             sb.append(prefix).append("  fl=").append(
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 23842b3..b398707 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -40,6 +40,7 @@
 import com.android.internal.os.IResultReceiver;
 
 import java.util.List;
+import java.util.function.Consumer;
 
 /**
  * Provides low-level communication with the system window manager for
@@ -301,4 +302,19 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    @Override
+    public boolean isCrossWindowBlurEnabled() {
+        return CrossWindowBlurListeners.getInstance().isCrossWindowBlurEnabled();
+    }
+
+    @Override
+    public void addCrossWindowBlurEnabledListener(@NonNull Consumer<Boolean> listener) {
+        CrossWindowBlurListeners.getInstance().addListener(listener);
+    }
+
+    @Override
+    public void removeCrossWindowBlurEnabledListener(@NonNull Consumer<Boolean> listener) {
+        CrossWindowBlurListeners.getInstance().removeListener(listener);
+    }
 }
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 39d3c01..7cc2db1 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -23,8 +23,8 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.os.IBinder;
+import android.os.RemoteCallback;
 import android.os.RemoteException;
-import android.service.screenshot.ScreenshotHash;
 import android.util.Log;
 import android.util.MergedConfiguration;
 import android.window.ClientWindowFrames;
@@ -487,8 +487,7 @@
     }
 
     @Override
-    public ScreenshotHash generateScreenshotHash(IWindow window, Rect boundsInWindow,
-            String hashAlgorithm) {
-        return null;
+    public void generateDisplayHash(IWindow window, Rect boundsInWindow, String hashAlgorithm,
+            RemoteCallback callback) {
     }
 }
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index decbf8c..4f0c568 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -1975,7 +1975,10 @@
         if (client == null) {
             return false;
         }
-
+        if (mService == null) {
+            Log.w(TAG, "Autofill service is null!");
+            return false;
+        }
         if (mServiceClient == null) {
             mServiceClient = new AutofillManagerClient(this);
             try {
diff --git a/core/java/android/view/contentcapture/ContentCaptureContext.java b/core/java/android/view/contentcapture/ContentCaptureContext.java
index 9bf3626..9998fbc 100644
--- a/core/java/android/view/contentcapture/ContentCaptureContext.java
+++ b/core/java/android/view/contentcapture/ContentCaptureContext.java
@@ -22,6 +22,7 @@
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.app.TaskInfo;
+import android.app.assist.ActivityId;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.LocusId;
@@ -36,6 +37,8 @@
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
 /**
  * Context associated with a {@link ContentCaptureSession} - see {@link ContentCaptureManager} for
  * more info.
@@ -99,16 +102,17 @@
 
     // Fields below are set by server when the session starts
     private final @Nullable ComponentName mComponentName;
-    private final int mTaskId;
     private final int mFlags;
     private final int mDisplayId;
+    private final ActivityId mActivityId;
 
     // Fields below are set by the service upon "delivery" and are not marshalled in the parcel
     private int mParentSessionId = NO_SESSION_ID;
 
     /** @hide */
     public ContentCaptureContext(@Nullable ContentCaptureContext clientContext,
-            @NonNull ComponentName componentName, int taskId, int displayId, int flags) {
+            @NonNull ActivityId activityId, @NonNull ComponentName componentName, int displayId,
+            int flags) {
         if (clientContext != null) {
             mHasClientContext = true;
             mExtras = clientContext.mExtras;
@@ -118,10 +122,10 @@
             mExtras = null;
             mId = null;
         }
-        mComponentName = Preconditions.checkNotNull(componentName);
-        mTaskId = taskId;
-        mDisplayId = displayId;
+        mComponentName = Objects.requireNonNull(componentName);
         mFlags = flags;
+        mDisplayId = displayId;
+        mActivityId = activityId;
     }
 
     private ContentCaptureContext(@NonNull Builder builder) {
@@ -130,8 +134,9 @@
         mId = builder.mId;
 
         mComponentName  = null;
-        mTaskId = mFlags = 0;
+        mFlags = 0;
         mDisplayId = Display.INVALID_DISPLAY;
+        mActivityId = null;
     }
 
     /** @hide */
@@ -140,9 +145,9 @@
         mExtras = original.mExtras;
         mId = original.mId;
         mComponentName = original.mComponentName;
-        mTaskId = original.mTaskId;
         mFlags = original.mFlags | extraFlags;
         mDisplayId = original.mDisplayId;
+        mActivityId = original.mActivityId;
     }
 
     /**
@@ -170,7 +175,7 @@
      */
     @SystemApi
     public int getTaskId() {
-        return mTaskId;
+        return mHasClientContext ? 0 : mActivityId.getTaskId();
     }
 
     /**
@@ -184,6 +189,18 @@
     }
 
     /**
+     * Gets the Activity id information associated with this context, or {@code null} when it is a
+     * child session.
+     *
+     * @hide
+     */
+    @SystemApi
+    @Nullable
+    public ActivityId getActivityId() {
+        return mHasClientContext ? null : mActivityId;
+    }
+
+    /**
      * Gets the id of the session that originated this session (through
      * {@link ContentCaptureSession#createContentCaptureSession(ContentCaptureContext)}),
      * or {@code null} if this is the main session associated with the Activity's {@link Context}.
@@ -309,7 +326,7 @@
         if (mId != null) {
             pw.print(", id="); mId.dump(pw);
         }
-        pw.print(", taskId="); pw.print(mTaskId);
+        pw.print(", activityId="); pw.print(mActivityId);
         pw.print(", displayId="); pw.print(mDisplayId);
         if (mParentSessionId != NO_SESSION_ID) {
             pw.print(", parentId="); pw.print(mParentSessionId);
@@ -333,7 +350,7 @@
 
         if (fromServer()) {
             builder.append("act=").append(ComponentName.flattenToShortString(mComponentName))
-                .append(", taskId=").append(mTaskId)
+                .append(", activityId=").append(mActivityId)
                 .append(", displayId=").append(mDisplayId)
                 .append(", flags=").append(mFlags);
         } else {
@@ -363,9 +380,9 @@
         }
         parcel.writeParcelable(mComponentName, flags);
         if (fromServer()) {
-            parcel.writeInt(mTaskId);
             parcel.writeInt(mDisplayId);
             parcel.writeInt(mFlags);
+            mActivityId.writeToParcel(parcel, flags);
         }
     }
 
@@ -393,11 +410,12 @@
                 // Client-state only
                 return clientContext;
             } else {
-                final int taskId = parcel.readInt();
                 final int displayId = parcel.readInt();
                 final int flags = parcel.readInt();
-                return new ContentCaptureContext(clientContext, componentName, taskId, displayId,
-                        flags);
+                final ActivityId activityId = new ActivityId(parcel);
+
+                return new ContentCaptureContext(clientContext, activityId, componentName,
+                        displayId, flags);
             }
         }
 
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 10f6c61..9523bcd 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -23,10 +23,13 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.annotation.UiThread;
+import android.annotation.UserIdInt;
+import android.app.Service;
 import android.content.ComponentName;
 import android.content.ContentCaptureOptions;
 import android.content.Context;
@@ -432,10 +435,11 @@
     /** @hide */
     @UiThread
     public void onActivityCreated(@NonNull IBinder applicationToken,
-            @NonNull ComponentName activityComponent) {
+            @NonNull IBinder shareableActivityToken, @NonNull ComponentName activityComponent) {
         if (mOptions.lite) return;
         synchronized (mLock) {
-            getMainContentCaptureSession().start(applicationToken, activityComponent, mFlags);
+            getMainContentCaptureSession().start(applicationToken, shareableActivityToken,
+                    activityComponent, mFlags);
         }
     }
 
@@ -755,6 +759,74 @@
         }
     }
 
+    /**
+     * Resets the temporary content capture service implementation to the default component.
+     *
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_CONTENT_CAPTURE)
+    public static void resetTemporaryService(@UserIdInt int userId) {
+        final IContentCaptureManager service = getService();
+        if (service == null) {
+            Log.e(TAG, "IContentCaptureManager is null");
+        }
+        try {
+            service.resetTemporaryService(userId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Temporarily sets the content capture service implementation.
+     *
+     * @param userId user Id to set the temporary service on.
+     * @param serviceName name of the new component
+     * @param duration how long the change will be valid (the service will be automatically reset
+     * to the default component after this timeout expires).
+     *
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_CONTENT_CAPTURE)
+    public static void setTemporaryService(
+            @UserIdInt int userId, @NonNull String serviceName, int duration) {
+        final IContentCaptureManager service = getService();
+        if (service == null) {
+            Log.e(TAG, "IContentCaptureManager is null");
+        }
+        try {
+            service.setTemporaryService(userId, serviceName, duration);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Sets whether the default content capture service should be used.
+     *
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_CONTENT_CAPTURE)
+    public static void setDefaultServiceEnabled(@UserIdInt int userId, boolean enabled) {
+        final IContentCaptureManager service = getService();
+        if (service == null) {
+            Log.e(TAG, "IContentCaptureManager is null");
+        }
+        try {
+            service.setDefaultServiceEnabled(userId, enabled);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    private static IContentCaptureManager getService() {
+        return IContentCaptureManager.Stub.asInterface(ServiceManager.getService(
+                Service.CONTENT_CAPTURE_MANAGER_SERVICE));
+    }
+
     private interface MyRunnable {
         void run(@NonNull SyncResultReceiver receiver) throws RemoteException;
     }
diff --git a/core/java/android/view/contentcapture/IContentCaptureManager.aidl b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
index 01ead46..b1b443f 100644
--- a/core/java/android/view/contentcapture/IContentCaptureManager.aidl
+++ b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
@@ -44,8 +44,9 @@
      * @param flags Meta flags that enable or disable content capture (see
      *     {@link IContentCaptureContext#flags}).
      */
-    void startSession(IBinder activityToken, in ComponentName componentName,
-                      int sessionId, int flags, in IResultReceiver result);
+    void startSession(IBinder activityToken, IBinder shareableActivityToken,
+                      in ComponentName componentName, int sessionId, int flags,
+                      in IResultReceiver result);
 
     /**
      * Marks the end of a session for the calling user identified by
@@ -85,4 +86,19 @@
      * Returns a list with the ContentCaptureConditions for the package (or null if not defined).
      */
     void getContentCaptureConditions(String packageName, in IResultReceiver result);
+
+    /**
+     * Resets the temporary service implementation to the default component.
+     */
+    void resetTemporaryService(int userId);
+
+    /**
+     * Temporarily sets the service implementation.
+     */
+    void setTemporaryService(int userId, in String serviceName, int duration);
+
+    /**
+     * Sets whether the default service should be used.
+     */
+    void setDefaultServiceEnabled(int userId, boolean enabled);
 }
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index 3c18b6b..5ca793e 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -123,6 +123,8 @@
 
     @Nullable
     private IBinder mApplicationToken;
+    @Nullable
+    private IBinder mShareableActivityToken;
 
     @Nullable
     private ComponentName mComponentName;
@@ -217,8 +219,8 @@
      * Starts this session.
      */
     @UiThread
-    void start(@NonNull IBinder token, @NonNull ComponentName component,
-            int flags) {
+    void start(@NonNull IBinder token, @NonNull IBinder shareableActivityToken,
+            @NonNull ComponentName component, int flags) {
         if (!isContentCaptureEnabled()) return;
 
         if (sVerbose) {
@@ -237,6 +239,7 @@
         }
         mState = STATE_WAITING_FOR_SERVER;
         mApplicationToken = token;
+        mShareableActivityToken = shareableActivityToken;
         mComponentName = component;
 
         if (sVerbose) {
@@ -245,8 +248,8 @@
         }
 
         try {
-            mSystemServerInterface.startSession(mApplicationToken, component, mId, flags,
-                    mSessionStateReceiver);
+            mSystemServerInterface.startSession(mApplicationToken, mShareableActivityToken,
+                    component, mId, flags, mSessionStateReceiver);
         } catch (RemoteException e) {
             Log.w(TAG, "Error starting session for " + component.flattenToShortString() + ": " + e);
         }
@@ -583,6 +586,7 @@
         mDisabled.set((newState & STATE_DISABLED) != 0);
         // TODO(b/122454205): must reset children (which currently is owned by superclass)
         mApplicationToken = null;
+        mShareableActivityToken = null;
         mComponentName = null;
         mEvents = null;
         if (mDirectServiceInterface != null) {
@@ -721,6 +725,10 @@
         if (mApplicationToken != null) {
             pw.print(prefix); pw.print("app token: "); pw.println(mApplicationToken);
         }
+        if (mShareableActivityToken != null) {
+            pw.print(prefix); pw.print("sharable activity token: ");
+            pw.println(mShareableActivityToken);
+        }
         if (mComponentName != null) {
             pw.print(prefix); pw.print("component name: ");
             pw.println(mComponentName.flattenToShortString());
diff --git a/core/java/android/service/screenshot/ScreenshotHash.aidl b/core/java/android/view/displayhash/DisplayHash.aidl
similarity index 82%
copy from core/java/android/service/screenshot/ScreenshotHash.aidl
copy to core/java/android/view/displayhash/DisplayHash.aidl
index a7c50db..cabf575 100644
--- a/core/java/android/service/screenshot/ScreenshotHash.aidl
+++ b/core/java/android/view/displayhash/DisplayHash.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.service.screenshot;
+package android.view.displayhash;
 
-parcelable ScreenshotHash;
+parcelable DisplayHash;
diff --git a/core/java/android/view/displayhash/DisplayHash.java b/core/java/android/view/displayhash/DisplayHash.java
new file mode 100644
index 0000000..4148486
--- /dev/null
+++ b/core/java/android/view/displayhash/DisplayHash.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.displayhash;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.graphics.Rect;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.AnnotationValidations;
+
+/**
+ * The DisplayHash used to validate information about what was present on screen.
+ */
+public final class DisplayHash implements Parcelable {
+    /**
+     * The timestamp when the hash was generated.
+     */
+    private final long mTimeMillis;
+
+    /**
+     * The bounds of the requested area to generate the hash. This is in window space passed in
+     * by the client.
+     */
+    @NonNull
+    private final Rect mBoundsInWindow;
+
+    /**
+     * The selected hash algorithm that generated the image hash.
+     */
+    @NonNull
+    private final String mHashAlgorithm;
+
+    /**
+     * The image hash generated when creating the DisplayHash.
+     */
+    @NonNull
+    private final byte[] mImageHash;
+
+    /**
+     * The hmac generated by the system and used to verify whether this token was generated by
+     * the system.
+     */
+    @NonNull
+    private final byte[] mHmac;
+
+    /**
+     * Creates a new DisplayHash.
+     *
+     * @param timeMillis       The timestamp when the hash was generated.
+     * @param boundsInWindow   The bounds of the requested area to generate the hash. This is
+     *                         in window space passed in by the client.
+     * @param hashAlgorithm The selected hash algorithm that generated the image hash.
+     * @param imageHash        The image hash generated when creating the DisplayHash.
+     * @param hmac             The hmac generated by the system and used to verify whether this
+     *                         token was generated by
+     *                         the system. This should only be accessed by a system process.
+     * @hide
+     */
+    @SystemApi
+    public DisplayHash(long timeMillis, @NonNull Rect boundsInWindow,
+            @NonNull String hashAlgorithm, @NonNull byte[] imageHash, @NonNull byte[] hmac) {
+        mTimeMillis = timeMillis;
+        mBoundsInWindow = boundsInWindow;
+        AnnotationValidations.validate(NonNull.class, null, mBoundsInWindow);
+        mHashAlgorithm = hashAlgorithm;
+        AnnotationValidations.validate(NonNull.class, null, mHashAlgorithm);
+        mImageHash = imageHash;
+        AnnotationValidations.validate(NonNull.class, null, mImageHash);
+        mHmac = hmac;
+        AnnotationValidations.validate(NonNull.class, null, mHmac);
+    }
+
+    /**
+     * The timestamp when the hash was generated.
+     *
+     * @hide
+     */
+    @SystemApi
+    public long getTimeMillis() {
+        return mTimeMillis;
+    }
+
+    /**
+     * The bounds of the requested area to to generate the hash. This is in window space passed in
+     * by the client.
+     *
+     * @hide
+     */
+    @SystemApi
+    @NonNull
+    public Rect getBoundsInWindow() {
+        return mBoundsInWindow;
+    }
+
+    /**
+     * The selected hash algorithm that generated the image hash.
+     *
+     * @hide
+     */
+    @SystemApi
+    @NonNull
+    public String getHashAlgorithm() {
+        return mHashAlgorithm;
+    }
+
+    /**
+     * The image hash generated when creating the DisplayHash.
+     *
+     * @hide
+     */
+    @SystemApi
+    @NonNull
+    public byte[] getImageHash() {
+        return mImageHash;
+    }
+
+    /**
+     * The hmac generated by the system and used to verify whether this token was generated by
+     * the system. This should only be accessed by a system process.
+     *
+     * @hide
+     */
+    @SystemApi
+    @NonNull
+    public byte[] getHmac() {
+        return mHmac;
+    }
+
+    /** @hide **/
+    @Override
+    public String toString() {
+        return "DisplayHash { "
+                + "timeMillis = " + mTimeMillis + ", "
+                + "boundsInWindow = " + mBoundsInWindow + ", "
+                + "hashAlgorithm = " + mHashAlgorithm + ", "
+                + "imageHash = " + byteArrayToString(mImageHash) + ", "
+                + "hmac = " + byteArrayToString(mHmac)
+                + " }";
+    }
+
+    private String byteArrayToString(byte[] byteArray) {
+        if (byteArray == null) {
+            return "null";
+        }
+        int iMax = byteArray.length - 1;
+        if (iMax == -1) {
+            return "[]";
+        }
+
+        StringBuilder b = new StringBuilder();
+        b.append('[');
+        for (int i = 0; ; i++) {
+            String formatted = String.format("%02X", byteArray[i] & 0xFF);
+            b.append(formatted);
+            if (i == iMax) {
+                return b.append(']').toString();
+            }
+            b.append(", ");
+        }
+    }
+
+    /** @hide **/
+    @SystemApi
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeLong(mTimeMillis);
+        dest.writeTypedObject(mBoundsInWindow, flags);
+        dest.writeString(mHashAlgorithm);
+        dest.writeByteArray(mImageHash);
+        dest.writeByteArray(mHmac);
+    }
+
+    /** @hide **/
+    @SystemApi
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    private DisplayHash(@NonNull Parcel in) {
+        mTimeMillis = in.readLong();
+        Rect boundsInWindow = in.readTypedObject(Rect.CREATOR);
+        String hashAlgorithm = in.readString();
+        byte[] imageHash = in.createByteArray();
+        byte[] hmac = in.createByteArray();
+
+        mBoundsInWindow = boundsInWindow;
+        AnnotationValidations.validate(NonNull.class, null, mBoundsInWindow);
+        mHashAlgorithm = hashAlgorithm;
+        AnnotationValidations.validate(NonNull.class, null, mHashAlgorithm);
+        mImageHash = imageHash;
+        AnnotationValidations.validate(NonNull.class, null, mImageHash);
+        mHmac = hmac;
+        AnnotationValidations.validate(NonNull.class, null, mHmac);
+    }
+
+    @NonNull
+    public static final Parcelable.Creator<DisplayHash> CREATOR =
+            new Parcelable.Creator<DisplayHash>() {
+                @Override
+                public DisplayHash[] newArray(int size) {
+                    return new DisplayHash[size];
+                }
+
+                @Override
+                public DisplayHash createFromParcel(@NonNull Parcel in) {
+                    return new DisplayHash(in);
+                }
+            };
+}
diff --git a/core/java/android/view/displayhash/DisplayHashManager.java b/core/java/android/view/displayhash/DisplayHashManager.java
new file mode 100644
index 0000000..6b0c1a6
--- /dev/null
+++ b/core/java/android/view/displayhash/DisplayHashManager.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.displayhash;
+
+
+import static android.content.Context.DISPLAY_HASH_SERVICE;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemService;
+import android.os.RemoteException;
+import android.util.ArraySet;
+import android.util.Log;
+import android.view.WindowManagerGlobal;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * Utility class for DisplayHash requests.
+ */
+@SystemService(DISPLAY_HASH_SERVICE)
+public final class DisplayHashManager {
+    private static final String TAG = "DisplayHashManager";
+
+    private final Object mSupportedHashingAlgorithmLock = new Object();
+
+    @GuardedBy("mSupportedAlgorithmLock")
+    private static Set<String> sSupportedHashAlgorithms;
+
+    /**
+     * @hide
+     */
+    public DisplayHashManager() {
+    }
+
+    /**
+     * Get a Set of DisplayHash algorithms that the device supports.
+     *
+     * @return a String Set of supported hashing algorithms. The String value of one
+     * algorithm should be used when requesting to generate the DisplayHash.
+     */
+    @NonNull
+    public Set<String> getSupportedHashAlgorithms() {
+        synchronized (mSupportedHashingAlgorithmLock) {
+            if (sSupportedHashAlgorithms != null) {
+                return sSupportedHashAlgorithms;
+            }
+
+            try {
+                String[] supportedAlgorithms = WindowManagerGlobal.getWindowManagerService()
+                        .getSupportedDisplayHashAlgorithms();
+                if (supportedAlgorithms == null) {
+                    return Collections.emptySet();
+                }
+                sSupportedHashAlgorithms = new ArraySet<>(supportedAlgorithms);
+                return sSupportedHashAlgorithms;
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to send request getSupportedHashingAlgorithms", e);
+                return Collections.emptySet();
+            }
+        }
+    }
+
+    /**
+     * Call to verify that the DisplayHash passed in was generated by the system.
+     *
+     * @param displayHash The hash to verify that it was generated by the system.
+     * @return a {@link VerifiedDisplayHash} if the hash was generated by the system or null
+     * if the hash cannot be verified.
+     */
+    @Nullable
+    public VerifiedDisplayHash verifyDisplayHash(@NonNull DisplayHash displayHash) {
+        try {
+            return WindowManagerGlobal.getWindowManagerService().verifyDisplayHash(displayHash);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to send request verifyImpressionToken", e);
+            return null;
+        }
+    }
+}
diff --git a/core/java/android/view/displayhash/DisplayHashResultCallback.java b/core/java/android/view/displayhash/DisplayHashResultCallback.java
new file mode 100644
index 0000000..15b29ad
--- /dev/null
+++ b/core/java/android/view/displayhash/DisplayHashResultCallback.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.displayhash;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.graphics.Rect;
+import android.view.View;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
+
+/**
+ * Use when calling {@link View#generateDisplayHash(String, Rect, Executor,
+ * DisplayHashResultCallback)}.
+ *
+ * The callback will only invoke either {@link #onDisplayHashResult} when the system successfully
+ * generated the {@link DisplayHash} or {@link #onDisplayHashError(int)} when it failed.
+ */
+public interface DisplayHashResultCallback {
+    /**
+     * @hide
+     */
+    String EXTRA_DISPLAY_HASH = "DISPLAY_HASH";
+
+    /**
+     * @hide
+     */
+    String EXTRA_DISPLAY_HASH_ERROR_CODE = "DISPLAY_HASH_ERROR_CODE";
+
+    /**
+     * An unknown error occurred.
+     */
+    int DISPLAY_HASH_ERROR_UNKNOWN = -1;
+
+    /**
+     * The bounds used when requesting the hash hash were invalid or empty.
+     */
+    int DISPLAY_HASH_ERROR_INVALID_BOUNDS = -2;
+
+    /**
+     * The window for the view that requested the hash is no longer around. This can happen if the
+     * window is getting torn down.
+     */
+    int DISPLAY_HASH_ERROR_MISSING_WINDOW = -3;
+
+    /**
+     * The view that requested the hash is not visible on screen. This could either mean
+     * that the view bounds are offscreen, window bounds are offscreen, view is not visible, or
+     * window is not visible.
+     */
+    int DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN = -4;
+
+    /** @hide */
+    @IntDef(prefix = {"DISPLAY_HASH_ERROR_"}, value = {
+            DISPLAY_HASH_ERROR_UNKNOWN,
+            DISPLAY_HASH_ERROR_INVALID_BOUNDS,
+            DISPLAY_HASH_ERROR_MISSING_WINDOW,
+            DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface DisplayHashErrorCode {
+    }
+
+    /**
+     * Callback invoked when calling
+     * {@link android.view.View#generateDisplayHash(String, Rect, Executor,
+     * DisplayHashResultCallback)}
+     *
+     * @param displayHash The DisplayHash generated. If the hash cannot be generated,
+     *                    {@link #onDisplayHashError(int)} will be called instead
+     */
+    void onDisplayHashResult(@NonNull DisplayHash displayHash);
+
+    /**
+     * Callback invoked when
+     * {@link android.view.View#generateDisplayHash(String, Rect, Executor,
+     * DisplayHashResultCallback)} results in an error and cannot generate a display hash.
+     *
+     * @param errorCode One of the values in {@link DisplayHashErrorCode}
+     */
+    void onDisplayHashError(@DisplayHashErrorCode int errorCode);
+}
diff --git a/core/java/android/service/screenshot/OWNERS b/core/java/android/view/displayhash/OWNERS
similarity index 100%
copy from core/java/android/service/screenshot/OWNERS
copy to core/java/android/view/displayhash/OWNERS
diff --git a/core/java/android/service/screenshot/ScreenshotHash.aidl b/core/java/android/view/displayhash/VerifiedDisplayHash.aidl
similarity index 82%
copy from core/java/android/service/screenshot/ScreenshotHash.aidl
copy to core/java/android/view/displayhash/VerifiedDisplayHash.aidl
index a7c50db..9e7ebef 100644
--- a/core/java/android/service/screenshot/ScreenshotHash.aidl
+++ b/core/java/android/view/displayhash/VerifiedDisplayHash.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.service.screenshot;
+package android.view.displayhash;
 
-parcelable ScreenshotHash;
+parcelable VerifiedDisplayHash;
diff --git a/core/java/android/view/displayhash/VerifiedDisplayHash.java b/core/java/android/view/displayhash/VerifiedDisplayHash.java
new file mode 100644
index 0000000..16a428e
--- /dev/null
+++ b/core/java/android/view/displayhash/VerifiedDisplayHash.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.displayhash;
+
+import android.annotation.NonNull;
+import android.graphics.Rect;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * The verified display hash used to validate information about what was present on screen.
+ */
+@DataClass(genToString = true, genAidl = true)
+public final class VerifiedDisplayHash implements Parcelable {
+    /**
+     * The timestamp when the hash was generated.
+     */
+    private final long mTimeMillis;
+
+    /**
+     * The bounds of the requested area to generate the hash. This is in window space passed in
+     * by the client.
+     */
+    @NonNull
+    private final Rect mBoundsInWindow;
+
+    /**
+     * The selected hash algorithm that generated the image hash.
+     */
+    @NonNull
+    private final String mHashAlgorithm;
+
+    /**
+     * The image hash generated when creating the DisplayHash.
+     */
+    @NonNull
+    private final byte[] mImageHash;
+
+    private String imageHashToString() {
+        return byteArrayToString(mImageHash);
+    }
+
+    private String byteArrayToString(byte[] byteArray) {
+        if (byteArray == null) {
+            return "null";
+        }
+        int iMax = byteArray.length - 1;
+        if (iMax == -1) {
+            return "[]";
+        }
+
+        StringBuilder b = new StringBuilder();
+        b.append('[');
+        for (int i = 0; ; i++) {
+            String formatted = String.format("%02X", byteArray[i] & 0xFF);
+            b.append(formatted);
+            if (i == iMax) {
+                return b.append(']').toString();
+            }
+            b.append(", ");
+        }
+    }
+
+
+
+    // Code below generated by codegen v1.0.22.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/displayhash/VerifiedDisplayHash.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    /**
+     * Creates a new VerifiedDisplayHash.
+     *
+     * @param timeMillis
+     *   The timestamp when the hash was generated.
+     * @param boundsInWindow
+     *   The bounds of the requested area to generate the hash. This is in window space passed in
+     *   by the client.
+     * @param hashAlgorithm
+     *   The selected hash algorithm that generated the image hash.
+     * @param imageHash
+     *   The image hash generated when creating the DisplayHash.
+     */
+    @DataClass.Generated.Member
+    public VerifiedDisplayHash(
+            long timeMillis,
+            @NonNull Rect boundsInWindow,
+            @NonNull String hashAlgorithm,
+            @NonNull byte[] imageHash) {
+        this.mTimeMillis = timeMillis;
+        this.mBoundsInWindow = boundsInWindow;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mBoundsInWindow);
+        this.mHashAlgorithm = hashAlgorithm;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mHashAlgorithm);
+        this.mImageHash = imageHash;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mImageHash);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    /**
+     * The timestamp when the hash was generated.
+     */
+    @DataClass.Generated.Member
+    public long getTimeMillis() {
+        return mTimeMillis;
+    }
+
+    /**
+     * The bounds of the requested area to generate the hash. This is in window space passed in
+     * by the client.
+     */
+    @DataClass.Generated.Member
+    public @NonNull Rect getBoundsInWindow() {
+        return mBoundsInWindow;
+    }
+
+    /**
+     * The selected hash algorithm that generated the image hash.
+     */
+    @DataClass.Generated.Member
+    public @NonNull String getHashAlgorithm() {
+        return mHashAlgorithm;
+    }
+
+    /**
+     * The image hash generated when creating the DisplayHash.
+     */
+    @DataClass.Generated.Member
+    public @NonNull byte[] getImageHash() {
+        return mImageHash;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "VerifiedDisplayHash { " +
+                "timeMillis = " + mTimeMillis + ", " +
+                "boundsInWindow = " + mBoundsInWindow + ", " +
+                "hashAlgorithm = " + mHashAlgorithm + ", " +
+                "imageHash = " + imageHashToString() +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeLong(mTimeMillis);
+        dest.writeTypedObject(mBoundsInWindow, flags);
+        dest.writeString(mHashAlgorithm);
+        dest.writeByteArray(mImageHash);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ VerifiedDisplayHash(@NonNull android.os.Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        long timeMillis = in.readLong();
+        Rect boundsInWindow = (Rect) in.readTypedObject(Rect.CREATOR);
+        String hashAlgorithm = in.readString();
+        byte[] imageHash = in.createByteArray();
+
+        this.mTimeMillis = timeMillis;
+        this.mBoundsInWindow = boundsInWindow;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mBoundsInWindow);
+        this.mHashAlgorithm = hashAlgorithm;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mHashAlgorithm);
+        this.mImageHash = imageHash;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mImageHash);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<VerifiedDisplayHash> CREATOR
+            = new Parcelable.Creator<VerifiedDisplayHash>() {
+        @Override
+        public VerifiedDisplayHash[] newArray(int size) {
+            return new VerifiedDisplayHash[size];
+        }
+
+        @Override
+        public VerifiedDisplayHash createFromParcel(@NonNull android.os.Parcel in) {
+            return new VerifiedDisplayHash(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1613168749684L,
+            codegenVersion = "1.0.22",
+            sourceFile = "frameworks/base/core/java/android/view/displayhash/VerifiedDisplayHash.java",
+            inputSignatures = "private final  long mTimeMillis\nprivate final @android.annotation.NonNull android.graphics.Rect mBoundsInWindow\nprivate final @android.annotation.NonNull java.lang.String mHashAlgorithm\nprivate final @android.annotation.NonNull byte[] mImageHash\nprivate  java.lang.String imageHashToString()\nprivate  java.lang.String byteArrayToString(byte[])\nclass VerifiedDisplayHash extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genAidl=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/view/translation/UiTranslationController.java b/core/java/android/view/translation/UiTranslationController.java
index 802f01f..8100612 100644
--- a/core/java/android/view/translation/UiTranslationController.java
+++ b/core/java/android/view/translation/UiTranslationController.java
@@ -32,6 +32,9 @@
 import android.util.Log;
 import android.util.Pair;
 import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewRootImpl;
+import android.view.WindowManagerGlobal;
 import android.view.autofill.AutofillId;
 import android.view.translation.UiTranslationManager.UiTranslationState;
 
@@ -212,24 +215,19 @@
     private void onUiTranslationStarted(Translator translator, List<AutofillId> views) {
         synchronized (mLock) {
             // Find Views collect the translation data
-            // TODO(b/178084101): try to optimize, e.g. to this in a single traversal
-            final int viewCounts = views.size();
             final ArrayList<TranslationRequest> requests = new ArrayList<>();
-            for (int i = 0; i < viewCounts; i++) {
-                final AutofillId viewAutofillId = views.get(i);
-                final View view = mActivity.findViewByAutofillIdTraversal(viewAutofillId);
-                if (view == null) {
-                    Log.w(TAG, "Can not find the View for autofill id= " + viewAutofillId);
-                    continue;
-                }
-                mViews.put(viewAutofillId, new WeakReference<>(view));
+            final ArrayList<View> foundViews = new ArrayList<>();
+            findViewsTraversalByAutofillIds(views, foundViews);
+            for (int i = 0; i < foundViews.size(); i++) {
+                final View view = foundViews.get(i);
+                final int currentCount = i;
                 mActivity.runOnUiThread(() -> {
                     final TranslationRequest translationRequest = view.onCreateTranslationRequest();
                     if (translationRequest != null
                             && translationRequest.getTranslationText().length() > 0) {
                         requests.add(translationRequest);
                     }
-                    if (requests.size() == viewCounts) {
+                    if (currentCount == (foundViews.size() - 1)) {
                         Log.v(TAG, "onUiTranslationStarted: send " + requests.size() + " request.");
                         mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
                                 UiTranslationController::sendTranslationRequest,
@@ -240,6 +238,42 @@
         }
     }
 
+    private void findViewsTraversalByAutofillIds(List<AutofillId> sourceViewIds,
+            ArrayList<View> foundViews) {
+        final ArrayList<ViewRootImpl> roots =
+                WindowManagerGlobal.getInstance().getRootViews(mActivity.getActivityToken());
+        for (int rootNum = 0; rootNum < roots.size(); rootNum++) {
+            final View rootView = roots.get(rootNum).getView();
+            if (rootView instanceof ViewGroup) {
+                findViewsTraversalByAutofillIds((ViewGroup) rootView, sourceViewIds, foundViews);
+            } else {
+                addViewIfNeeded(sourceViewIds, rootView, foundViews);
+            }
+        }
+    }
+
+    private void findViewsTraversalByAutofillIds(ViewGroup viewGroup,
+            List<AutofillId> sourceViewIds, ArrayList<View> foundViews) {
+        final int childCount = viewGroup.getChildCount();
+        for (int i = 0; i < childCount; ++i) {
+            final View child = viewGroup.getChildAt(i);
+            if (child instanceof ViewGroup) {
+                findViewsTraversalByAutofillIds((ViewGroup) child, sourceViewIds, foundViews);
+            } else {
+                addViewIfNeeded(sourceViewIds, child, foundViews);
+            }
+        }
+    }
+
+    private void addViewIfNeeded(List<AutofillId> sourceViewIds, View view,
+            ArrayList<View> foundViews) {
+        final AutofillId autofillId = view.getAutofillId();
+        if (sourceViewIds.contains(autofillId)) {
+            mViews.put(autofillId, new WeakReference<>(view));
+            foundViews.add(view);
+        }
+    }
+
     private void runForEachView(Consumer<View> action) {
         synchronized (mLock) {
             final ArrayMap<AutofillId, WeakReference<View>> views = new ArrayMap<>(mViews);
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index e740cc2..39c09b4 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -85,7 +85,7 @@
 import android.view.inputmethod.SurroundingText;
 import android.view.inspector.InspectableProperty;
 import android.view.inspector.InspectableProperty.EnumEntry;
-import android.widget.RemoteViews.OnClickHandler;
+import android.widget.RemoteViews.InteractionHandler;
 
 import com.android.internal.R;
 
@@ -715,7 +715,7 @@
      */
     @NonNull
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769408)
-    private EdgeEffect mEdgeGlowTop = new EdgeEffect(mContext);
+    private EdgeEffect mEdgeGlowTop;
 
     /**
      * Tracks the state of the bottom edge glow.
@@ -725,7 +725,7 @@
      */
     @NonNull
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768444)
-    private EdgeEffect mEdgeGlowBottom = new EdgeEffect(mContext);
+    private EdgeEffect mEdgeGlowBottom;
 
     /**
      * An estimate of how many pixels are between the top of the list and
@@ -847,6 +847,8 @@
 
     public AbsListView(Context context) {
         super(context);
+        mEdgeGlowBottom = new EdgeEffect(context);
+        mEdgeGlowTop = new EdgeEffect(context);
         initAbsListView();
 
         mOwnerThread = Thread.currentThread();
@@ -867,6 +869,8 @@
 
     public AbsListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+        mEdgeGlowBottom = new EdgeEffect(context, attrs);
+        mEdgeGlowTop = new EdgeEffect(context, attrs);
         initAbsListView();
 
         mOwnerThread = Thread.currentThread();
@@ -3584,6 +3588,9 @@
                 mLastY != Integer.MIN_VALUE ? y - mLastY + scrollConsumedCorrection : deltaY;
         int lastYCorrection = 0;
 
+        // First allow releasing existing overscroll effect:
+        incrementalDeltaY = releaseGlow(incrementalDeltaY, x);
+
         if (mTouchMode == TOUCH_MODE_SCROLL) {
             if (PROFILE_SCROLLING) {
                 if (!mScrollProfilingStarted) {
@@ -3666,14 +3673,14 @@
                                     mTouchMode = TOUCH_MODE_OVERSCROLL;
                                 }
                                 if (incrementalDeltaY > 0) {
-                                    mEdgeGlowTop.onPull((float) -overscroll / getHeight(),
+                                    mEdgeGlowTop.onPullDistance((float) -overscroll / getHeight(),
                                             (float) x / getWidth());
                                     if (!mEdgeGlowBottom.isFinished()) {
                                         mEdgeGlowBottom.onRelease();
                                     }
                                     invalidateTopGlow();
                                 } else if (incrementalDeltaY < 0) {
-                                    mEdgeGlowBottom.onPull((float) overscroll / getHeight(),
+                                    mEdgeGlowBottom.onPullDistance((float) overscroll / getHeight(),
                                             1.f - (float) x / getWidth());
                                     if (!mEdgeGlowTop.isFinished()) {
                                         mEdgeGlowTop.onRelease();
@@ -3713,14 +3720,15 @@
                             (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS &&
                                     !contentFits())) {
                         if (rawDeltaY > 0) {
-                            mEdgeGlowTop.onPull((float) overScrollDistance / getHeight(),
+                            mEdgeGlowTop.onPullDistance((float) overScrollDistance / getHeight(),
                                     (float) x / getWidth());
                             if (!mEdgeGlowBottom.isFinished()) {
                                 mEdgeGlowBottom.onRelease();
                             }
                             invalidateTopGlow();
                         } else if (rawDeltaY < 0) {
-                            mEdgeGlowBottom.onPull((float) overScrollDistance / getHeight(),
+                            mEdgeGlowBottom.onPullDistance(
+                                    (float) -overScrollDistance / getHeight(),
                                     1.f - (float) x / getWidth());
                             if (!mEdgeGlowTop.isFinished()) {
                                 mEdgeGlowTop.onRelease();
@@ -3757,6 +3765,44 @@
         }
     }
 
+    /**
+     * If the edge glow is currently active, this consumes part or all of deltaY
+     * on the edge glow.
+     *
+     * @param deltaY The pointer motion, in pixels, in the vertical direction, positive
+     *                         for moving down and negative for moving up.
+     * @param x The horizontal position of the pointer.
+     * @return The remainder of <code>deltaY</code> that has not been consumed by the
+     * edge glow.
+     */
+    private int releaseGlow(int deltaY, int x) {
+        // First allow releasing existing overscroll effect:
+        float consumed = 0;
+        if (mEdgeGlowTop.getDistance() != 0) {
+            consumed = mEdgeGlowTop.onPullDistance((float) deltaY / getHeight(),
+                    (float) x / getWidth());
+            if (consumed != 0f) {
+                invalidateTopGlow();
+            }
+        } else if (mEdgeGlowBottom.getDistance() != 0) {
+            consumed = -mEdgeGlowBottom.onPullDistance((float) -deltaY / getHeight(),
+                    1f - (float) x / getWidth());
+            if (consumed != 0f) {
+                invalidateBottomGlow();
+            }
+        }
+        int pixelsConsumed = Math.round(consumed * getHeight());
+        return deltaY - pixelsConsumed;
+    }
+
+    /**
+     * @return <code>true</code> if either the top or bottom edge glow is currently active or
+     * <code>false</code> if it has no value to release.
+     */
+    private boolean isGlowActive() {
+        return mEdgeGlowBottom.getDistance() != 0 || mEdgeGlowTop.getDistance() != 0;
+    }
+
     private void invalidateTopGlow() {
         if (!shouldDisplayEdgeEffects()) {
             return;
@@ -3926,7 +3972,9 @@
 
         if (mTouchMode == TOUCH_MODE_OVERFLING) {
             // Stopped the fling. It is a scroll.
-            mFlingRunnable.endFling();
+            if (mFlingRunnable != null) {
+                mFlingRunnable.endFling();
+            }
             if (mPositionScroller != null) {
                 mPositionScroller.stop();
             }
@@ -3936,6 +3984,7 @@
             mLastY = mMotionY;
             mMotionCorrection = 0;
             mDirection = 0;
+            stopEdgeGlowRecede(ev.getX());
         } else {
             final int x = (int) ev.getX();
             final int y = (int) ev.getY();
@@ -3948,7 +3997,10 @@
                     mTouchMode = TOUCH_MODE_SCROLL;
                     mMotionCorrection = 0;
                     motionPosition = findMotionRow(y);
-                    mFlingRunnable.flywheelTouch();
+                    if (mFlingRunnable != null) {
+                        mFlingRunnable.flywheelTouch();
+                    }
+                    stopEdgeGlowRecede(x);
                 } else if ((motionPosition >= 0) && getAdapter().isEnabled(motionPosition)) {
                     // User clicked on an actual view (and was not stopping a
                     // fling). It might be a click or a scroll. Assume it is a
@@ -3984,6 +4036,15 @@
         }
     }
 
+    private void stopEdgeGlowRecede(float x) {
+        if (mEdgeGlowTop.getDistance() != 0) {
+            mEdgeGlowTop.onPullDistance(0, x / getWidth());
+        }
+        if (mEdgeGlowBottom.getDistance() != 0) {
+            mEdgeGlowBottom.onPullDistance(0, x / getWidth());
+        }
+    }
+
     private void onTouchMove(MotionEvent ev, MotionEvent vtev) {
         if (mHasPerformedLongPress) {
             // Consume all move events following a successful long press.
@@ -4489,73 +4550,76 @@
         }
 
         switch (actionMasked) {
-        case MotionEvent.ACTION_DOWN: {
-            int touchMode = mTouchMode;
-            if (touchMode == TOUCH_MODE_OVERFLING || touchMode == TOUCH_MODE_OVERSCROLL) {
-                mMotionCorrection = 0;
-                return true;
-            }
-
-            final int x = (int) ev.getX();
-            final int y = (int) ev.getY();
-            mActivePointerId = ev.getPointerId(0);
-
-            int motionPosition = findMotionRow(y);
-            if (touchMode != TOUCH_MODE_FLING && motionPosition >= 0) {
-                // User clicked on an actual view (and was not stopping a fling).
-                // Remember where the motion event started
-                v = getChildAt(motionPosition - mFirstPosition);
-                mMotionViewOriginalTop = v.getTop();
-                mMotionX = x;
-                mMotionY = y;
-                mMotionPosition = motionPosition;
-                mTouchMode = TOUCH_MODE_DOWN;
-                clearScrollingCache();
-            }
-            mLastY = Integer.MIN_VALUE;
-            initOrResetVelocityTracker();
-            mVelocityTracker.addMovement(ev);
-            mNestedYOffset = 0;
-            startNestedScroll(SCROLL_AXIS_VERTICAL);
-            if (touchMode == TOUCH_MODE_FLING) {
-                return true;
-            }
-            break;
-        }
-
-        case MotionEvent.ACTION_MOVE: {
-            switch (mTouchMode) {
-            case TOUCH_MODE_DOWN:
-                int pointerIndex = ev.findPointerIndex(mActivePointerId);
-                if (pointerIndex == -1) {
-                    pointerIndex = 0;
-                    mActivePointerId = ev.getPointerId(pointerIndex);
+            case MotionEvent.ACTION_DOWN: {
+                int touchMode = mTouchMode;
+                if (touchMode == TOUCH_MODE_OVERFLING || touchMode == TOUCH_MODE_OVERSCROLL) {
+                    mMotionCorrection = 0;
+                    return true;
                 }
-                final int y = (int) ev.getY(pointerIndex);
-                initVelocityTrackerIfNotExists();
+
+                final int x = (int) ev.getX();
+                final int y = (int) ev.getY();
+                mActivePointerId = ev.getPointerId(0);
+
+                int motionPosition = findMotionRow(y);
+                if (isGlowActive()) {
+                    // Pressed during edge effect, so this is considered the same as a fling catch.
+                    mTouchMode = TOUCH_MODE_FLING;
+                } else if (touchMode != TOUCH_MODE_FLING && motionPosition >= 0) {
+                    // User clicked on an actual view (and was not stopping a fling).
+                    // Remember where the motion event started
+                    v = getChildAt(motionPosition - mFirstPosition);
+                    mMotionViewOriginalTop = v.getTop();
+                    mMotionX = x;
+                    mMotionY = y;
+                    mMotionPosition = motionPosition;
+                    mTouchMode = TOUCH_MODE_DOWN;
+                    clearScrollingCache();
+                }
+                mLastY = Integer.MIN_VALUE;
+                initOrResetVelocityTracker();
                 mVelocityTracker.addMovement(ev);
-                if (startScrollIfNeeded((int) ev.getX(pointerIndex), y, null)) {
+                mNestedYOffset = 0;
+                startNestedScroll(SCROLL_AXIS_VERTICAL);
+                if (touchMode == TOUCH_MODE_FLING) {
                     return true;
                 }
                 break;
             }
-            break;
-        }
 
-        case MotionEvent.ACTION_CANCEL:
-        case MotionEvent.ACTION_UP: {
-            mTouchMode = TOUCH_MODE_REST;
-            mActivePointerId = INVALID_POINTER;
-            recycleVelocityTracker();
-            reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
-            stopNestedScroll();
-            break;
-        }
+            case MotionEvent.ACTION_MOVE: {
+                switch (mTouchMode) {
+                    case TOUCH_MODE_DOWN:
+                        int pointerIndex = ev.findPointerIndex(mActivePointerId);
+                        if (pointerIndex == -1) {
+                            pointerIndex = 0;
+                            mActivePointerId = ev.getPointerId(pointerIndex);
+                        }
+                        final int y = (int) ev.getY(pointerIndex);
+                        initVelocityTrackerIfNotExists();
+                        mVelocityTracker.addMovement(ev);
+                        if (startScrollIfNeeded((int) ev.getX(pointerIndex), y, null)) {
+                            return true;
+                        }
+                        break;
+                }
+                break;
+            }
 
-        case MotionEvent.ACTION_POINTER_UP: {
-            onSecondaryPointerUp(ev);
-            break;
-        }
+            case MotionEvent.ACTION_CANCEL:
+            case MotionEvent.ACTION_UP: {
+                mTouchMode = TOUCH_MODE_REST;
+                mActivePointerId = INVALID_POINTER;
+                recycleVelocityTracker();
+                reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
+                stopNestedScroll();
+                break;
+            }
+
+            case MotionEvent.ACTION_POINTER_UP: {
+                onSecondaryPointerUp(ev);
+                break;
+            }
         }
 
         return false;
@@ -6419,11 +6483,11 @@
      *
      * @hide
      */
-    public void setRemoteViewsOnClickHandler(OnClickHandler handler) {
+    public void setRemoteViewsInteractionHandler(InteractionHandler handler) {
         // Ensure that we don't already have a RemoteViewsAdapter that is bound to an existing
         // service handling the specified intent.
         if (mRemoteAdapter != null) {
-            mRemoteAdapter.setRemoteViewsOnClickHandler(handler);
+            mRemoteAdapter.setRemoteViewsInteractionHandler(handler);
         }
     }
 
@@ -6548,6 +6612,27 @@
     }
 
     /**
+     * Returns the {@link EdgeEffect#getType()} for the edge effects.
+     * @return the {@link EdgeEffect#getType()} for the edge effects.
+     * @attr ref android.R.styleable#EdgeEffect_edgeEffectType
+     */
+    @EdgeEffect.EdgeEffectType
+    public int getEdgeEffectType() {
+        return mEdgeGlowTop.getType();
+    }
+
+    /**
+     * Sets the {@link EdgeEffect#setType(int)} for the edge effects.
+     * @param type The edge effect type to use for the edge effects.
+     * @attr ref android.R.styleable#EdgeEffect_edgeEffectType
+     */
+    public void setEdgeEffectType(@EdgeEffect.EdgeEffectType int type) {
+        mEdgeGlowTop.setType(type);
+        mEdgeGlowBottom.setType(type);
+        invalidate();
+    }
+
+    /**
      * Sets the recycler listener to be notified whenever a View is set aside in
      * the recycler for later reuse. This listener can be used to free resources
      * associated to the View.
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java
index d93b635..d8f7f4c 100644
--- a/core/java/android/widget/AdapterViewAnimator.java
+++ b/core/java/android/widget/AdapterViewAnimator.java
@@ -29,7 +29,7 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
-import android.widget.RemoteViews.OnClickHandler;
+import android.widget.RemoteViews.InteractionHandler;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -1016,11 +1016,11 @@
      * 
      * @hide
      */
-    public void setRemoteViewsOnClickHandler(OnClickHandler handler) {
+    public void setRemoteViewsOnClickHandler(InteractionHandler handler) {
         // Ensure that we don't already have a RemoteViewsAdapter that is bound to an existing
         // service handling the specified intent.
         if (mRemoteViewsAdapter != null) {
-            mRemoteViewsAdapter.setRemoteViewsOnClickHandler(handler);
+            mRemoteViewsAdapter.setRemoteViewsInteractionHandler(handler);
         }
     }
 
diff --git a/core/java/android/widget/AnalogClock.java b/core/java/android/widget/AnalogClock.java
index 93b2d8a..34fe51e 100644
--- a/core/java/android/widget/AnalogClock.java
+++ b/core/java/android/widget/AnalogClock.java
@@ -23,8 +23,10 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
+import android.graphics.BlendMode;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
@@ -68,12 +70,16 @@
 
     @UnsupportedAppUsage
     private Drawable mHourHand;
+    private final TintInfo mHourHandTintInfo = new TintInfo();
     @UnsupportedAppUsage
     private Drawable mMinuteHand;
+    private final TintInfo mMinuteHandTintInfo = new TintInfo();
     @Nullable
     private Drawable mSecondHand;
+    private final TintInfo mSecondHandTintInfo = new TintInfo();
     @UnsupportedAppUsage
     private Drawable mDial;
+    private final TintInfo mDialTintInfo = new TintInfo();
 
     private int mDialWidth;
     private int mDialHeight;
@@ -111,18 +117,86 @@
             mDial = context.getDrawable(com.android.internal.R.drawable.clock_dial);
         }
 
+        ColorStateList dialTintList = a.getColorStateList(
+                com.android.internal.R.styleable.AnalogClock_dialTint);
+        if (dialTintList != null) {
+            mDialTintInfo.mTintList = dialTintList;
+            mDialTintInfo.mHasTintList = true;
+        }
+        BlendMode dialTintMode = Drawable.parseBlendMode(
+                a.getInt(com.android.internal.R.styleable.AnalogClock_dialTintMode, -1),
+                null);
+        if (dialTintMode != null) {
+            mDialTintInfo.mTintBlendMode = dialTintMode;
+            mDialTintInfo.mHasTintBlendMode = true;
+        }
+        if (mDialTintInfo.mHasTintList || mDialTintInfo.mHasTintBlendMode) {
+            mDial = mDialTintInfo.apply(mDial);
+        }
+
         mHourHand = a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_hour);
         if (mHourHand == null) {
             mHourHand = context.getDrawable(com.android.internal.R.drawable.clock_hand_hour);
         }
 
+        ColorStateList hourHandTintList = a.getColorStateList(
+                com.android.internal.R.styleable.AnalogClock_hand_hourTint);
+        if (hourHandTintList != null) {
+            mHourHandTintInfo.mTintList = hourHandTintList;
+            mHourHandTintInfo.mHasTintList = true;
+        }
+        BlendMode hourHandTintMode = Drawable.parseBlendMode(
+                a.getInt(com.android.internal.R.styleable.AnalogClock_hand_hourTintMode, -1),
+                null);
+        if (hourHandTintMode != null) {
+            mHourHandTintInfo.mTintBlendMode = hourHandTintMode;
+            mHourHandTintInfo.mHasTintBlendMode = true;
+        }
+        if (mHourHandTintInfo.mHasTintList || mHourHandTintInfo.mHasTintBlendMode) {
+            mHourHand = mHourHandTintInfo.apply(mHourHand);
+        }
+
         mMinuteHand = a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_minute);
         if (mMinuteHand == null) {
             mMinuteHand = context.getDrawable(com.android.internal.R.drawable.clock_hand_minute);
         }
 
+        ColorStateList minuteHandTintList = a.getColorStateList(
+                com.android.internal.R.styleable.AnalogClock_hand_minuteTint);
+        if (minuteHandTintList != null) {
+            mMinuteHandTintInfo.mTintList = minuteHandTintList;
+            mMinuteHandTintInfo.mHasTintList = true;
+        }
+        BlendMode minuteHandTintMode = Drawable.parseBlendMode(
+                a.getInt(com.android.internal.R.styleable.AnalogClock_hand_minuteTintMode, -1),
+                null);
+        if (minuteHandTintMode != null) {
+            mMinuteHandTintInfo.mTintBlendMode = minuteHandTintMode;
+            mMinuteHandTintInfo.mHasTintBlendMode = true;
+        }
+        if (mMinuteHandTintInfo.mHasTintList || mMinuteHandTintInfo.mHasTintBlendMode) {
+            mMinuteHand = mMinuteHandTintInfo.apply(mMinuteHand);
+        }
+
         mSecondHand = a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_second);
 
+        ColorStateList secondHandTintList = a.getColorStateList(
+                com.android.internal.R.styleable.AnalogClock_hand_secondTint);
+        if (secondHandTintList != null) {
+            mSecondHandTintInfo.mTintList = secondHandTintList;
+            mSecondHandTintInfo.mHasTintList = true;
+        }
+        BlendMode secondHandTintMode = Drawable.parseBlendMode(
+                a.getInt(com.android.internal.R.styleable.AnalogClock_hand_secondTintMode, -1),
+                null);
+        if (secondHandTintMode != null) {
+            mSecondHandTintInfo.mTintBlendMode = secondHandTintMode;
+            mSecondHandTintInfo.mHasTintBlendMode = true;
+        }
+        if (mSecondHandTintInfo.mHasTintList || mSecondHandTintInfo.mHasTintBlendMode) {
+            mSecondHand = mSecondHandTintInfo.apply(mSecondHand);
+        }
+
         mTimeZone = toZoneId(a.getString(com.android.internal.R.styleable.AnalogClock_timeZone));
         createClock();
 
@@ -141,6 +215,68 @@
         invalidate();
     }
 
+    /**
+     * Applies a tint to the dial drawable.
+     * <p>
+     * Subsequent calls to {@link #setDial(Icon)} will
+     * automatically mutate the drawable and apply the specified tint and tint
+     * mode using {@link Drawable#setTintList(ColorStateList)}.
+     *
+     * @param tint the tint to apply, may be {@code null} to clear tint
+     *
+     * @attr ref android.R.styleable#AnalogClock_dialTint
+     * @see #getDialTintList()
+     * @see Drawable#setTintList(ColorStateList)
+     */
+    @RemotableViewMethod
+    public void setDialTintList(@Nullable ColorStateList tint) {
+        mDialTintInfo.mTintList = tint;
+        mDialTintInfo.mHasTintList = true;
+
+        mDial = mDialTintInfo.apply(mDial);
+    }
+
+    /**
+     * @return the tint applied to the dial drawable
+     * @attr ref android.R.styleable#AnalogClock_dialTint
+     * @see #setDialTintList(ColorStateList)
+     */
+    @InspectableProperty(attributeId = com.android.internal.R.styleable.AnalogClock_dialTint)
+    @Nullable
+    public ColorStateList getDialTintList() {
+        return mDialTintInfo.mTintList;
+    }
+
+    /**
+     * Specifies the blending mode used to apply the tint specified by
+     * {@link #setDialTintList(ColorStateList)}} to the dial drawable.
+     * The default mode is {@link BlendMode#SRC_IN}.
+     *
+     * @param blendMode the blending mode used to apply the tint, may be
+     *                 {@code null} to clear tint
+     * @attr ref android.R.styleable#AnalogClock_dialTintMode
+     * @see #getDialTintBlendMode()
+     * @see Drawable#setTintBlendMode(BlendMode)
+     */
+    @RemotableViewMethod
+    public void setDialTintBlendMode(@Nullable BlendMode blendMode) {
+        mDialTintInfo.mTintBlendMode = blendMode;
+        mDialTintInfo.mHasTintBlendMode = true;
+
+        mDial = mDialTintInfo.apply(mDial);
+    }
+
+    /**
+     * @return the blending mode used to apply the tint to the dial drawable
+     * @attr ref android.R.styleable#AnalogClock_dialTintMode
+     * @see #setDialTintBlendMode(BlendMode)
+     */
+    @InspectableProperty(attributeId = com.android.internal.R.styleable.AnalogClock_dialTintMode)
+    @Nullable
+    public BlendMode getDialTintBlendMode() {
+        return mDialTintInfo.mTintBlendMode;
+    }
+
     /** Sets the hour hand of the clock to the specified Icon. */
     @RemotableViewMethod
     public void setHourHand(@NonNull Icon icon) {
@@ -150,6 +286,71 @@
         invalidate();
     }
 
+    /**
+     * Applies a tint to the hour hand drawable.
+     * <p>
+     * Subsequent calls to {@link #setHourHand(Icon)} will
+     * automatically mutate the drawable and apply the specified tint and tint
+     * mode using {@link Drawable#setTintList(ColorStateList)}.
+     *
+     * @param tint the tint to apply, may be {@code null} to clear tint
+     *
+     * @attr ref android.R.styleable#AnalogClock_hand_hourTint
+     * @see #getHourHandTintList()
+     * @see Drawable#setTintList(ColorStateList)
+     */
+    @RemotableViewMethod
+    public void setHourHandTintList(@Nullable ColorStateList tint) {
+        mHourHandTintInfo.mTintList = tint;
+        mHourHandTintInfo.mHasTintList = true;
+
+        mHourHand = mHourHandTintInfo.apply(mHourHand);
+    }
+
+    /**
+     * @return the tint applied to the hour hand drawable
+     * @attr ref android.R.styleable#AnalogClock_hand_hourTint
+     * @see #setHourHandTintList(ColorStateList)
+     */
+    @InspectableProperty(
+            attributeId = com.android.internal.R.styleable.AnalogClock_hand_hourTint
+    )
+    @Nullable
+    public ColorStateList getHourHandTintList() {
+        return mHourHandTintInfo.mTintList;
+    }
+
+    /**
+     * Specifies the blending mode used to apply the tint specified by
+     * {@link #setHourHandTintList(ColorStateList)}} to the hour hand drawable.
+     * The default mode is {@link BlendMode#SRC_IN}.
+     *
+     * @param blendMode the blending mode used to apply the tint, may be
+     *                 {@code null} to clear tint
+     * @attr ref android.R.styleable#AnalogClock_hand_hourTintMode
+     * @see #getHourHandTintBlendMode()
+     * @see Drawable#setTintBlendMode(BlendMode)
+     */
+    @RemotableViewMethod
+    public void setHourHandTintBlendMode(@Nullable BlendMode blendMode) {
+        mHourHandTintInfo.mTintBlendMode = blendMode;
+        mHourHandTintInfo.mHasTintBlendMode = true;
+
+        mHourHand = mHourHandTintInfo.apply(mHourHand);
+    }
+
+    /**
+     * @return the blending mode used to apply the tint to the hour hand drawable
+     * @attr ref android.R.styleable#AnalogClock_hand_hourTintMode
+     * @see #setHourHandTintBlendMode(BlendMode)
+     */
+    @InspectableProperty(
+            attributeId = com.android.internal.R.styleable.AnalogClock_hand_hourTintMode)
+    @Nullable
+    public BlendMode getHourHandTintBlendMode() {
+        return mHourHandTintInfo.mTintBlendMode;
+    }
+
     /** Sets the minute hand of the clock to the specified Icon. */
     @RemotableViewMethod
     public void setMinuteHand(@NonNull Icon icon) {
@@ -160,6 +361,71 @@
     }
 
     /**
+     * Applies a tint to the minute hand drawable.
+     * <p>
+     * Subsequent calls to {@link #setMinuteHand(Icon)} will
+     * automatically mutate the drawable and apply the specified tint and tint
+     * mode using {@link Drawable#setTintList(ColorStateList)}.
+     *
+     * @param tint the tint to apply, may be {@code null} to clear tint
+     *
+     * @attr ref android.R.styleable#AnalogClock_hand_minuteTint
+     * @see #getMinuteHandTintList()
+     * @see Drawable#setTintList(ColorStateList)
+     */
+    @RemotableViewMethod
+    public void setMinuteHandTintList(@Nullable ColorStateList tint) {
+        mMinuteHandTintInfo.mTintList = tint;
+        mMinuteHandTintInfo.mHasTintList = true;
+
+        mMinuteHand = mMinuteHandTintInfo.apply(mMinuteHand);
+    }
+
+    /**
+     * @return the tint applied to the minute hand drawable
+     * @attr ref android.R.styleable#AnalogClock_hand_minuteTint
+     * @see #setMinuteHandTintList(ColorStateList)
+     */
+    @InspectableProperty(
+            attributeId = com.android.internal.R.styleable.AnalogClock_hand_minuteTint
+    )
+    @Nullable
+    public ColorStateList getMinuteHandTintList() {
+        return mMinuteHandTintInfo.mTintList;
+    }
+
+    /**
+     * Specifies the blending mode used to apply the tint specified by
+     * {@link #setMinuteHandTintList(ColorStateList)}} to the minute hand drawable.
+     * The default mode is {@link BlendMode#SRC_IN}.
+     *
+     * @param blendMode the blending mode used to apply the tint, may be
+     *                 {@code null} to clear tint
+     * @attr ref android.R.styleable#AnalogClock_hand_minuteTintMode
+     * @see #getMinuteHandTintBlendMode()
+     * @see Drawable#setTintBlendMode(BlendMode)
+     */
+    @RemotableViewMethod
+    public void setMinuteHandTintBlendMode(@Nullable BlendMode blendMode) {
+        mMinuteHandTintInfo.mTintBlendMode = blendMode;
+        mMinuteHandTintInfo.mHasTintBlendMode = true;
+
+        mMinuteHand = mMinuteHandTintInfo.apply(mMinuteHand);
+    }
+
+    /**
+     * @return the blending mode used to apply the tint to the minute hand drawable
+     * @attr ref android.R.styleable#AnalogClock_hand_minuteTintMode
+     * @see #setMinuteHandTintBlendMode(BlendMode)
+     */
+    @InspectableProperty(
+            attributeId = com.android.internal.R.styleable.AnalogClock_hand_minuteTintMode)
+    @Nullable
+    public BlendMode getMinuteHandTintBlendMode() {
+        return mMinuteHandTintInfo.mTintBlendMode;
+    }
+
+    /**
      * Sets the second hand of the clock to the specified Icon, or hides the second hand if it is
      * null.
      */
@@ -173,6 +439,71 @@
     }
 
     /**
+     * Applies a tint to the second hand drawable.
+     * <p>
+     * Subsequent calls to {@link #setSecondHand(Icon)} will
+     * automatically mutate the drawable and apply the specified tint and tint
+     * mode using {@link Drawable#setTintList(ColorStateList)}.
+     *
+     * @param tint the tint to apply, may be {@code null} to clear tint
+     *
+     * @attr ref android.R.styleable#AnalogClock_hand_secondTint
+     * @see #getSecondHandTintList()
+     * @see Drawable#setTintList(ColorStateList)
+     */
+    @RemotableViewMethod
+    public void setSecondHandTintList(@Nullable ColorStateList tint) {
+        mSecondHandTintInfo.mTintList = tint;
+        mSecondHandTintInfo.mHasTintList = true;
+
+        mSecondHand = mSecondHandTintInfo.apply(mSecondHand);
+    }
+
+    /**
+     * @return the tint applied to the second hand drawable
+     * @attr ref android.R.styleable#AnalogClock_hand_secondTint
+     * @see #setSecondHandTintList(ColorStateList)
+     */
+    @InspectableProperty(
+            attributeId = com.android.internal.R.styleable.AnalogClock_hand_secondTint
+    )
+    @Nullable
+    public ColorStateList getSecondHandTintList() {
+        return mSecondHandTintInfo.mTintList;
+    }
+
+    /**
+     * Specifies the blending mode used to apply the tint specified by
+     * {@link #setSecondHandTintList(ColorStateList)}} to the second hand drawable.
+     * The default mode is {@link BlendMode#SRC_IN}.
+     *
+     * @param blendMode the blending mode used to apply the tint, may be
+     *                 {@code null} to clear tint
+     * @attr ref android.R.styleable#AnalogClock_hand_secondTintMode
+     * @see #getSecondHandTintBlendMode()
+     * @see Drawable#setTintBlendMode(BlendMode)
+     */
+    @RemotableViewMethod
+    public void setSecondHandTintBlendMode(@Nullable BlendMode blendMode) {
+        mSecondHandTintInfo.mTintBlendMode = blendMode;
+        mSecondHandTintInfo.mHasTintBlendMode = true;
+
+        mSecondHand = mSecondHandTintInfo.apply(mSecondHand);
+    }
+
+    /**
+     * @return the blending mode used to apply the tint to the second hand drawable
+     * @attr ref android.R.styleable#AnalogClock_hand_secondTintMode
+     * @see #setSecondHandTintBlendMode(BlendMode)
+     */
+    @InspectableProperty(
+            attributeId = com.android.internal.R.styleable.AnalogClock_hand_secondTintMode)
+    @Nullable
+    public BlendMode getSecondHandTintBlendMode() {
+        return mSecondHandTintInfo.mTintBlendMode;
+    }
+
+    /**
      * Indicates which time zone is currently used by this view.
      *
      * @return The ID of the current time zone or null if the default time zone,
@@ -462,4 +793,36 @@
             return null;
         }
     }
+
+    private final class TintInfo {
+        boolean mHasTintList;
+        @Nullable ColorStateList mTintList;
+        boolean mHasTintBlendMode;
+        @Nullable BlendMode mTintBlendMode;
+
+        /**
+         * Returns a mutated copy of {@code drawable} with tinting applied, or null if it's null.
+         */
+        @Nullable
+        Drawable apply(@Nullable Drawable drawable) {
+            if (drawable == null) return null;
+
+            Drawable newDrawable = drawable.mutate();
+
+            if (mHasTintList) {
+                newDrawable.setTintList(mTintList);
+            }
+
+            if (mHasTintBlendMode) {
+                newDrawable.setTintBlendMode(mTintBlendMode);
+            }
+
+            // All drawables should have the same state as the View itself.
+            if (drawable.isStateful()) {
+                newDrawable.setState(getDrawableState());
+            }
+
+            return newDrawable;
+        }
+    }
 }
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 6dedd12..23915e0 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -303,6 +303,27 @@
     }
 
     /**
+     * Returns the {@link EdgeEffect#getType()} for the edge effects.
+     * @return the {@link EdgeEffect#getType()} for the edge effects.
+     * @attr ref android.R.styleable#EdgeEffect_edgeEffectType
+     */
+    @EdgeEffect.EdgeEffectType
+    public int getEdgeEffectType() {
+        return mEdgeGlowLeft.getType();
+    }
+
+    /**
+     * Sets the {@link EdgeEffect#setType(int)} for the edge effects.
+     * @param type The edge effect type to use for the edge effects.
+     * @attr ref android.R.styleable#EdgeEffect_edgeEffectType
+     */
+    public void setEdgeEffectType(@EdgeEffect.EdgeEffectType int type) {
+        mEdgeGlowRight.setType(type);
+        mEdgeGlowLeft.setType(type);
+        invalidate();
+    }
+
+    /**
      * @return The maximum amount this scroll view will scroll in response to
      *   an arrow event.
      */
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 0a08ccd..8aa557b 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -648,6 +648,7 @@
      * @see #getImageTintList()
      * @see Drawable#setTintList(ColorStateList)
      */
+    @android.view.RemotableViewMethod
     public void setImageTintList(@Nullable ColorStateList tint) {
         mDrawableTintList = tint;
         mHasDrawableTint = true;
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index a44808e..1b76ebf 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -1308,6 +1308,7 @@
      * @see #getSecondaryProgressTintList()
      * @see Drawable#setTintList(ColorStateList)
      */
+    @RemotableViewMethod
     public void setSecondaryProgressTintList(@Nullable ColorStateList tint) {
         if (mProgressTintInfo == null) {
             mProgressTintInfo = new ProgressTintInfo();
@@ -1619,6 +1620,7 @@
      * @param stateDescription The state description.
      */
     @Override
+    @RemotableViewMethod
     public void setStateDescription(@Nullable CharSequence stateDescription) {
         mCustomStateDescription = stateDescription;
         if (stateDescription == null) {
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 81572b5..e0b4ec7 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -46,6 +46,8 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
+import android.content.res.loader.ResourcesLoader;
+import android.content.res.loader.ResourcesProvider;
 import android.graphics.Bitmap;
 import android.graphics.BlendMode;
 import android.graphics.Outline;
@@ -62,16 +64,19 @@
 import android.os.Bundle;
 import android.os.CancellationSignal;
 import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
 import android.os.Process;
 import android.os.StrictMode;
 import android.os.UserHandle;
+import android.system.Os;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.DisplayMetrics;
 import android.util.IntArray;
 import android.util.Log;
 import android.util.Pair;
+import android.util.SparseIntArray;
 import android.util.TypedValue;
 import android.util.TypedValue.ComplexDimensionUnit;
 import android.view.ContextThemeWrapper;
@@ -86,11 +91,18 @@
 import android.view.ViewParent;
 import android.view.ViewStub;
 import android.widget.AdapterView.OnItemClickListener;
+import android.widget.CompoundButton.OnCheckedChangeListener;
 
 import com.android.internal.R;
 import com.android.internal.util.ContrastColorUtil;
 import com.android.internal.util.Preconditions;
 
+import java.io.ByteArrayOutputStream;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -151,6 +163,9 @@
 
     private static final String LOG_TAG = "RemoteViews";
 
+    /** The intent extra for whether the view whose checked state changed is currently checked. */
+    public static final String EXTRA_CHECKED = "android.widget.extra.CHECKED";
+
     /**
      * The intent extra that contains the appWidgetId.
      * @hide
@@ -206,6 +221,8 @@
     private static final int SET_COMPOUND_BUTTON_CHECKED_TAG = 26;
     private static final int SET_RADIO_GROUP_CHECKED = 27;
     private static final int SET_VIEW_OUTLINE_RADIUS_TAG = 28;
+    private static final int SET_ON_CHECKED_CHANGE_RESPONSE_TAG = 29;
+    private static final int NIGHT_MODE_REFLECTION_ACTION_TAG = 30;
 
     /** @hide **/
     @IntDef(prefix = "MARGIN_", value = {
@@ -218,35 +235,17 @@
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface MarginType {}
-    /**
-     * The value will apply to the marginLeft.
-     * @hide
-     */
+    /** The value will apply to the marginLeft. */
     public static final int MARGIN_LEFT = 0;
-    /**
-     * The value will apply to the marginTop.
-     * @hide
-     */
+    /** The value will apply to the marginTop. */
     public static final int MARGIN_TOP = 1;
-    /**
-     * The value will apply to the marginRight.
-     * @hide
-     */
+    /** The value will apply to the marginRight. */
     public static final int MARGIN_RIGHT = 2;
-    /**
-     * The value will apply to the marginBottom.
-     * @hide
-     */
+    /** The value will apply to the marginBottom. */
     public static final int MARGIN_BOTTOM = 3;
-    /**
-     * The value will apply to the marginStart.
-     * @hide
-     */
+    /** The value will apply to the marginStart. */
     public static final int MARGIN_START = 4;
-    /**
-     * The value will apply to the marginEnd.
-     * @hide
-     */
+    /** The value will apply to the marginEnd. */
     public static final int MARGIN_END = 5;
 
     /** @hide **/
@@ -362,8 +361,9 @@
     /** Class cookies of the Parcel this instance was read from. */
     private Map<Class, Object> mClassCookies;
 
-    private static final OnClickHandler DEFAULT_ON_CLICK_HANDLER = (view, pendingIntent, response)
-            -> startPendingIntent(view, pendingIntent, response.getLaunchOptions(view));
+    private static final InteractionHandler DEFAULT_INTERACTION_HANDLER =
+            (view, pendingIntent, response) ->
+                    startPendingIntent(view, pendingIntent, response.getLaunchOptions(view));
 
     private static final ArrayMap<MethodKey, MethodArgs> sMethods = new ArrayMap<>();
 
@@ -502,11 +502,26 @@
         }
     }
 
-    /** @hide */
-    public interface OnClickHandler {
-
-        /** @hide */
-        boolean onClickHandler(View view, PendingIntent pendingIntent, RemoteResponse response);
+    /**
+     * Handler for view interactions (such as clicks) within a RemoteViews.
+     *
+     * @hide
+     */
+    public interface InteractionHandler {
+        /**
+         * Invoked when the user performs an interaction on the View.
+         *
+         * @param view the View with which the user interacted
+         * @param pendingIntent the base PendingIntent associated with the view
+         * @param response the response to the interaction, which knows how to fill in the
+         *                 attached PendingIntent
+         *
+         * @hide
+         */
+        boolean onInteraction(
+                View view,
+                PendingIntent pendingIntent,
+                RemoteResponse response);
     }
 
     /**
@@ -516,8 +531,8 @@
      *  SUBCLASSES MUST BE IMMUTABLE SO CLONE WORKS!!!!!
      */
     private abstract static class Action implements Parcelable {
-        public abstract void apply(View root, ViewGroup rootParent,
-                OnClickHandler handler) throws ActionException;
+        public abstract void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) throws ActionException;
 
         public static final int MERGE_REPLACE = 0;
         public static final int MERGE_APPEND = 1;
@@ -547,7 +562,8 @@
          * and return the final action which will run on the UI thread.
          * Override this if some of the tasks can be performed async.
          */
-        public Action initActionAsync(ViewTree root, ViewGroup rootParent, OnClickHandler handler) {
+        public Action initActionAsync(ViewTree root, ViewGroup rootParent,
+                InteractionHandler handler, ColorResources colorResources) {
             return this;
         }
 
@@ -590,7 +606,9 @@
     // Constant used during async execution. It is not parcelable.
     private static final Action ACTION_NOOP = new RuntimeAction() {
         @Override
-        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) { }
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) {
+        }
     };
 
     /**
@@ -708,7 +726,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) {
             final View view = root.findViewById(viewId);
             if (!(view instanceof AdapterView<?>)) return;
 
@@ -743,7 +762,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, final OnClickHandler handler) {
+        public void apply(View root, ViewGroup rootParent, final InteractionHandler handler,
+                ColorResources colorResources) {
             final View target = root.findViewById(viewId);
             if (target == null) return;
 
@@ -751,32 +771,29 @@
             if (target instanceof AdapterView<?>) {
                 AdapterView<?> av = (AdapterView<?>) target;
                 // The PendingIntent template is stored in the view's tag.
-                OnItemClickListener listener = new OnItemClickListener() {
-                    public void onItemClick(AdapterView<?> parent, View view,
-                            int position, long id) {
-                        // The view should be a frame layout
-                        if (view instanceof ViewGroup) {
-                            ViewGroup vg = (ViewGroup) view;
+                OnItemClickListener listener = (parent, view, position, id) -> {
+                    // The view should be a frame layout
+                    if (view instanceof ViewGroup) {
+                        ViewGroup vg = (ViewGroup) view;
 
-                            // AdapterViews contain their children in a frame
-                            // so we need to go one layer deeper here.
-                            if (parent instanceof AdapterViewAnimator) {
-                                vg = (ViewGroup) vg.getChildAt(0);
-                            }
-                            if (vg == null) return;
-
-                            RemoteResponse response = null;
-                            int childCount = vg.getChildCount();
-                            for (int i = 0; i < childCount; i++) {
-                                Object tag = vg.getChildAt(i).getTag(com.android.internal.R.id.fillInIntent);
-                                if (tag instanceof RemoteResponse) {
-                                    response = (RemoteResponse) tag;
-                                    break;
-                                }
-                            }
-                            if (response == null) return;
-                            response.handleViewClick(view, handler);
+                        // AdapterViews contain their children in a frame
+                        // so we need to go one layer deeper here.
+                        if (parent instanceof AdapterViewAnimator) {
+                            vg = (ViewGroup) vg.getChildAt(0);
                         }
+                        if (vg == null) return;
+
+                        RemoteResponse response = null;
+                        int childCount = vg.getChildCount();
+                        for (int i = 0; i < childCount; i++) {
+                            Object tag = vg.getChildAt(i).getTag(R.id.fillInIntent);
+                            if (tag instanceof RemoteResponse) {
+                                response = (RemoteResponse) tag;
+                                break;
+                            }
+                        }
+                        if (response == null) return;
+                        response.handleViewInteraction(view, handler);
                     }
                 };
                 av.setOnItemClickListener(listener);
@@ -818,7 +835,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) {
             final View target = root.findViewById(viewId);
             if (target == null) return;
 
@@ -841,7 +859,8 @@
                 if (a instanceof RemoteViewsListAdapter && viewTypeCount <= a.getViewTypeCount()) {
                     ((RemoteViewsListAdapter) a).setViewsList(list);
                 } else {
-                    v.setAdapter(new RemoteViewsListAdapter(v.getContext(), list, viewTypeCount));
+                    v.setAdapter(new RemoteViewsListAdapter(v.getContext(), list, viewTypeCount,
+                            colorResources));
                 }
             } else if (target instanceof AdapterViewAnimator) {
                 AdapterViewAnimator v = (AdapterViewAnimator) target;
@@ -849,7 +868,8 @@
                 if (a instanceof RemoteViewsListAdapter && viewTypeCount <= a.getViewTypeCount()) {
                     ((RemoteViewsListAdapter) a).setViewsList(list);
                 } else {
-                    v.setAdapter(new RemoteViewsListAdapter(v.getContext(), list, viewTypeCount));
+                    v.setAdapter(new RemoteViewsListAdapter(v.getContext(), list, viewTypeCount,
+                            colorResources));
                 }
             }
         }
@@ -880,7 +900,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) {
             final View target = root.findViewById(viewId);
             if (target == null) return;
 
@@ -907,7 +928,7 @@
             if (target instanceof AbsListView) {
                 AbsListView v = (AbsListView) target;
                 v.setRemoteViewsAdapter(intent, isAsync);
-                v.setRemoteViewsOnClickHandler(handler);
+                v.setRemoteViewsInteractionHandler(handler);
             } else if (target instanceof AdapterViewAnimator) {
                 AdapterViewAnimator v = (AdapterViewAnimator) target;
                 v.setRemoteViewsAdapter(intent, isAsync);
@@ -917,7 +938,7 @@
 
         @Override
         public Action initActionAsync(ViewTree root, ViewGroup rootParent,
-                OnClickHandler handler) {
+                InteractionHandler handler, ColorResources colorResources) {
             SetRemoteViewsAdapterIntent copy = new SetRemoteViewsAdapterIntent(viewId, intent);
             copy.isAsync = true;
             return copy;
@@ -956,7 +977,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, final OnClickHandler handler) {
+        public void apply(View root, ViewGroup rootParent, final InteractionHandler handler,
+                ColorResources colorResources) {
             final View target = root.findViewById(viewId);
             if (target == null) return;
 
@@ -991,11 +1013,13 @@
                     return;
                 }
             } else {
-                // No intent to apply
+                // No intent to apply, clear the listener and any tags that were previously set.
                 target.setOnClickListener(null);
+                target.setTagInternal(R.id.pending_intent_tag, null);
+                target.setTagInternal(com.android.internal.R.id.fillInIntent, null);
                 return;
             }
-            target.setOnClickListener(v -> mResponse.handleViewClick(v, handler));
+            target.setOnClickListener(v -> mResponse.handleViewInteraction(v, handler));
         }
 
         @Override
@@ -1006,6 +1030,78 @@
         final RemoteResponse mResponse;
     }
 
+    /**
+     * Equivalent to calling
+     * {@link android.widget.CompoundButton#setOnCheckedChangeListener(
+     * android.widget.CompoundButton.OnCheckedChangeListener)}
+     * to launch the provided {@link PendingIntent}.
+     */
+    private class SetOnCheckedChangeResponse extends Action {
+
+        private final RemoteResponse mResponse;
+
+        SetOnCheckedChangeResponse(@IdRes int id, RemoteResponse response) {
+            this.viewId = id;
+            this.mResponse = response;
+        }
+
+        SetOnCheckedChangeResponse(Parcel parcel) {
+            viewId = parcel.readInt();
+            mResponse = new RemoteResponse();
+            mResponse.readFromParcel(parcel);
+        }
+
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeInt(viewId);
+            mResponse.writeToParcel(dest, flags);
+        }
+
+        @Override
+        public void apply(View root, ViewGroup rootParent, final InteractionHandler handler,
+                ColorResources colorResources) {
+            final View target = root.findViewById(viewId);
+            if (target == null) return;
+            if (!(target instanceof CompoundButton)) {
+                Log.w(LOG_TAG, "setOnCheckedChange methods cannot be used on "
+                        + "non-CompoundButton child (id: " + viewId + ")");
+                return;
+            }
+            CompoundButton button = (CompoundButton) target;
+
+            if (mResponse.mPendingIntent != null) {
+                // setOnCheckedChangePendingIntent cannot be used with collection children, which
+                // must use setOnCheckedChangeFillInIntent instead.
+                if (hasFlags(FLAG_WIDGET_IS_COLLECTION_CHILD)) {
+                    Log.w(LOG_TAG, "Cannot setOnCheckedChangePendingIntent for collection item "
+                            + "(id: " + viewId + ")");
+                    return;
+                }
+                target.setTagInternal(R.id.pending_intent_tag, mResponse.mPendingIntent);
+            } else if (mResponse.mFillIntent != null) {
+                if (!hasFlags(FLAG_WIDGET_IS_COLLECTION_CHILD)) {
+                    Log.e(LOG_TAG, "The method setOnCheckedChangeFillInIntent is available "
+                            + "only from RemoteViewsFactory (ie. on collection items).");
+                    return;
+                }
+            } else {
+                // No intent to apply, clear any existing listener or tag.
+                button.setOnCheckedChangeListener(null);
+                button.setTagInternal(R.id.remote_checked_change_listener_tag, null);
+                return;
+            }
+
+            OnCheckedChangeListener onCheckedChangeListener =
+                    (v, isChecked) -> mResponse.handleViewInteraction(v, handler);
+            button.setTagInternal(R.id.remote_checked_change_listener_tag, onCheckedChangeListener);
+            button.setOnCheckedChangeListener(onCheckedChangeListener);
+        }
+
+        @Override
+        public int getActionTag() {
+            return SET_ON_CHECKED_CHANGE_RESPONSE_TAG;
+        }
+    }
+
     /** @hide **/
     public static Rect getSourceBounds(View v) {
         final float appScale = v.getContext().getResources()
@@ -1165,7 +1261,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) {
             final View target = root.findViewById(viewId);
             if (target == null) return;
 
@@ -1222,7 +1319,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) {
             final View target = root.findViewById(viewId);
             if (target == null) return;
 
@@ -1259,7 +1357,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) {
             final View view = root.findViewById(viewId);
             if (view == null) return;
 
@@ -1362,12 +1461,12 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent,
-                OnClickHandler handler) throws ActionException {
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) throws ActionException {
             ReflectionAction ra = new ReflectionAction(viewId, methodName,
                     BaseReflectionAction.BITMAP,
                     bitmap);
-            ra.apply(root, rootParent, handler);
+            ra.apply(root, rootParent, handler, colorResources);
         }
 
         @Override
@@ -1443,7 +1542,8 @@
         protected abstract Object getParameterValue(@Nullable View view) throws ActionException;
 
         @Override
-        public final void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+        public final void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) {
             final View view = root.findViewById(viewId);
             if (view == null) return;
 
@@ -1461,7 +1561,7 @@
 
         @Override
         public final Action initActionAsync(ViewTree root, ViewGroup rootParent,
-                OnClickHandler handler) {
+                InteractionHandler handler, ColorResources colorResources) {
             final View view = root.findViewById(viewId);
             if (view == null) return ACTION_NOOP;
 
@@ -1785,6 +1885,73 @@
         }
     }
 
+    private final class NightModeReflectionAction extends BaseReflectionAction {
+
+        private final Object mLightValue;
+        private final Object mDarkValue;
+
+        NightModeReflectionAction(
+                @IdRes int viewId,
+                String methodName,
+                int type,
+                Object lightValue,
+                Object darkValue) {
+            super(viewId, methodName, type);
+            mLightValue = lightValue;
+            mDarkValue = darkValue;
+        }
+
+        NightModeReflectionAction(Parcel in) {
+            super(in);
+            switch (this.type) {
+                case ICON:
+                    mLightValue = in.readTypedObject(Icon.CREATOR);
+                    mDarkValue = in.readTypedObject(Icon.CREATOR);
+                    break;
+                case COLOR_STATE_LIST:
+                    mLightValue = in.readTypedObject(ColorStateList.CREATOR);
+                    mDarkValue = in.readTypedObject(ColorStateList.CREATOR);
+                    break;
+                case INT:
+                    mLightValue = in.readInt();
+                    mDarkValue = in.readInt();
+                    break;
+                default:
+                    throw new ActionException("Unexpected night mode action type: " + this.type);
+            }
+        }
+
+        @Override
+        public void writeToParcel(Parcel out, int flags) {
+            super.writeToParcel(out, flags);
+            switch (this.type) {
+                case ICON:
+                case COLOR_STATE_LIST:
+                    out.writeTypedObject((Parcelable) mLightValue, flags);
+                    out.writeTypedObject((Parcelable) mDarkValue, flags);
+                    break;
+                case INT:
+                    out.writeInt((int) mLightValue);
+                    out.writeInt((int) mDarkValue);
+                    break;
+            }
+        }
+
+        @Nullable
+        @Override
+        protected Object getParameterValue(@Nullable View view) throws ActionException {
+            if (view == null) return null;
+
+            Configuration configuration = view.getResources().getConfiguration();
+            return configuration.isNightModeActive() ? mDarkValue : mLightValue;
+        }
+
+        @Override
+        public int getActionTag() {
+            return NIGHT_MODE_REFLECTION_ACTION_TAG;
+        }
+    }
+
     /**
      * This is only used for async execution of actions and it not parcelable.
      */
@@ -1796,7 +1963,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) {
             mRunnable.run();
         }
     }
@@ -1851,7 +2019,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) {
             final Context context = root.getContext();
             final ViewGroup target = root.findViewById(viewId);
 
@@ -1860,11 +2029,14 @@
             }
 
             // Inflate nested views and add as children
-            target.addView(mNestedViews.apply(context, target, handler), mIndex);
+            target.addView(
+                    mNestedViews.apply(context, target, handler, null /* size */, colorResources),
+                    mIndex);
         }
 
         @Override
-        public Action initActionAsync(ViewTree root, ViewGroup rootParent, OnClickHandler handler) {
+        public Action initActionAsync(ViewTree root, ViewGroup rootParent,
+                InteractionHandler handler, ColorResources colorResources) {
             // In the async implementation, update the view tree so that subsequent calls to
             // findViewById return the current view.
             root.createTree();
@@ -1876,8 +2048,8 @@
 
             // Inflate nested views and perform all the async tasks for the child remoteView.
             final Context context = root.mRoot.getContext();
-            final AsyncApplyTask task = mNestedViews.getAsyncApplyTask(
-                    context, targetVg, null, handler);
+            final AsyncApplyTask task = mNestedViews.getAsyncApplyTask(context, targetVg,
+                    null /* listener */, handler, null /* size */, colorResources);
             final ViewTree tree = task.doInBackground();
 
             if (tree == null) {
@@ -1890,8 +2062,8 @@
 
             return new RuntimeAction() {
                 @Override
-                public void apply(View root, ViewGroup rootParent, OnClickHandler handler)
-                        throws ActionException {
+                public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                        ColorResources colorResources) throws ActionException {
                     task.onPostExecute(tree);
                     targetVg.addView(task.mResult, mIndex);
                 }
@@ -1952,7 +2124,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) {
             final ViewGroup target = root.findViewById(viewId);
 
             if (target == null) {
@@ -1968,7 +2141,8 @@
         }
 
         @Override
-        public Action initActionAsync(ViewTree root, ViewGroup rootParent, OnClickHandler handler) {
+        public Action initActionAsync(ViewTree root, ViewGroup rootParent,
+                InteractionHandler handler, ColorResources colorResources) {
             // In the async implementation, update the view tree so that subsequent calls to
             // findViewById return the current view.
             root.createTree();
@@ -1992,8 +2166,8 @@
             }
             return new RuntimeAction() {
                 @Override
-                public void apply(View root, ViewGroup rootParent, OnClickHandler handler)
-                        throws ActionException {
+                public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                        ColorResources colorResources) throws ActionException {
                     if (mViewIdToKeep == REMOVE_ALL_VIEWS_ID) {
                         targetVg.removeAllViews();
                         return;
@@ -2048,7 +2222,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) {
             final View target = root.findViewById(viewId);
 
             if (target == null || target == root) {
@@ -2062,7 +2237,8 @@
         }
 
         @Override
-        public Action initActionAsync(ViewTree root, ViewGroup rootParent, OnClickHandler handler) {
+        public Action initActionAsync(ViewTree root, ViewGroup rootParent,
+                InteractionHandler handler, ColorResources colorResources) {
             // In the async implementation, update the view tree so that subsequent calls to
             // findViewById return the correct view.
             root.createTree();
@@ -2081,8 +2257,8 @@
             parent.mChildren.remove(target);
             return new RuntimeAction() {
                 @Override
-                public void apply(View root, ViewGroup rootParent, OnClickHandler handler)
-                        throws ActionException {
+                public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                        ColorResources colorResources) throws ActionException {
                     parentVg.removeView(target.mRoot);
                 }
             };
@@ -2161,7 +2337,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) {
             final TextView target = root.findViewById(viewId);
             if (target == null) return;
             if (drawablesLoaded) {
@@ -2191,7 +2368,8 @@
         }
 
         @Override
-        public Action initActionAsync(ViewTree root, ViewGroup rootParent, OnClickHandler handler) {
+        public Action initActionAsync(ViewTree root, ViewGroup rootParent,
+                InteractionHandler handler, ColorResources colorResources) {
             final TextView target = root.findViewById(viewId);
             if (target == null) return ACTION_NOOP;
 
@@ -2269,7 +2447,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) {
             final TextView target = root.findViewById(viewId);
             if (target == null) return;
             target.setTextSize(units, size);
@@ -2314,7 +2493,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) {
             final View target = root.findViewById(viewId);
             if (target == null) return;
             target.setPadding(left, top, right, bottom);
@@ -2387,7 +2567,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) {
             final View target = root.findViewById(viewId);
             if (target == null) {
                 return;
@@ -2500,7 +2681,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) {
             final View target = root.findViewById(viewId);
             if (target == null) return;
 
@@ -2535,7 +2717,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) {
             // Let's traverse the viewtree and override all textColors!
             Stack<View> viewsToProcess = new Stack<>();
             viewsToProcess.add(root);
@@ -2585,7 +2768,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) {
             final View target = root.findViewById(mViewId);
             if (target == null) return;
 
@@ -2619,7 +2803,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, OnClickHandler handler)
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources)
                 throws ActionException {
             final View target = root.findViewById(viewId);
             if (target == null) return;
@@ -2630,7 +2815,17 @@
                 return;
             }
 
-            ((CompoundButton) target).setChecked(mChecked);
+            CompoundButton button = (CompoundButton) target;
+            Object tag = button.getTag(R.id.remote_checked_change_listener_tag);
+            // Temporarily unset the checked change listener so calling setChecked doesn't launch
+            // the intent.
+            if (tag instanceof OnCheckedChangeListener) {
+                button.setOnCheckedChangeListener(null);
+                button.setChecked(mChecked);
+                button.setOnCheckedChangeListener((OnCheckedChangeListener) tag);
+            } else {
+                button.setChecked(mChecked);
+            }
         }
 
         @Override
@@ -2660,8 +2855,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, OnClickHandler handler)
-                throws ActionException {
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) throws ActionException {
             final View target = root.findViewById(viewId);
             if (target == null) return;
 
@@ -2670,7 +2865,32 @@
                 return;
             }
 
-            ((RadioGroup) target).check(mCheckedId);
+            RadioGroup group = (RadioGroup) target;
+
+            // Temporarily unset all the checked change listeners while we check the group.
+            for (int i = 0; i < group.getChildCount(); i++) {
+                View child = group.getChildAt(i);
+                if (!(child instanceof CompoundButton)) continue;
+
+                Object tag = child.getTag(R.id.remote_checked_change_listener_tag);
+                if (!(tag instanceof OnCheckedChangeListener)) continue;
+
+                // Clear the checked change listener, we'll restore it after the check.
+                ((CompoundButton) child).setOnCheckedChangeListener(null);
+            }
+
+            group.check(mCheckedId);
+
+            // Loop through the children again and restore the checked change listeners.
+            for (int i = 0; i < group.getChildCount(); i++) {
+                View child = group.getChildAt(i);
+                if (!(child instanceof CompoundButton)) continue;
+
+                Object tag = child.getTag(R.id.remote_checked_change_listener_tag);
+                if (!(tag instanceof OnCheckedChangeListener)) continue;
+
+                ((CompoundButton) child).setOnCheckedChangeListener((OnCheckedChangeListener) tag);
+            }
         }
 
         @Override
@@ -2712,8 +2932,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, OnClickHandler handler)
-                throws ActionException {
+        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+                ColorResources colorResources) throws ActionException {
             final View target = root.findViewById(viewId);
             if (target == null) return;
 
@@ -3110,6 +3330,10 @@
                 return new SetRadioGroupCheckedAction(parcel);
             case SET_VIEW_OUTLINE_RADIUS_TAG:
                 return new SetViewOutlinePreferredRadiusAction(parcel);
+            case SET_ON_CHECKED_CHANGE_RESPONSE_TAG:
+                return new SetOnCheckedChangeResponse(parcel);
+            case NIGHT_MODE_REFLECTION_ACTION_TAG:
+                return new NightModeReflectionAction(parcel);
             default:
                 throw new ActionException("Tag " + tag + " not found");
         }
@@ -3567,6 +3791,41 @@
     }
 
     /**
+     * Equivalent to calling
+     * {@link android.widget.CompoundButton#setOnCheckedChangeListener(
+     * android.widget.CompoundButton.OnCheckedChangeListener)}
+     * to launch the provided {@link RemoteResponse}.
+     *
+     * The intent will be filled with the current checked state of the view at the key
+     * {@link #EXTRA_CHECKED}.
+     *
+     * The {@link RemoteResponse} will not be launched in response to check changes arising from
+     * {@link #setCompoundButtonChecked(int, boolean)} or {@link #setRadioGroupChecked(int, int)}
+     * usages.
+     *
+     * The {@link RemoteResponse} must be created using
+     * {@link RemoteResponse#fromFillInIntent(Intent)} in conjunction with
+     * {@link RemoteViews#setPendingIntentTemplate(int, PendingIntent)} for items inside
+     * collections (eg. {@link ListView}, {@link StackView} etc.).
+     *
+     * Otherwise, create the {@link RemoteResponse} using
+     * {@link RemoteResponse#fromPendingIntent(PendingIntent)}.
+     *
+     * @param viewId The id of the view that will trigger the {@link PendingIntent} when checked
+     *               state changes.
+     * @param response The {@link RemoteResponse} to send when the checked state changes.
+     */
+    public void setOnCheckedChangeResponse(
+            @IdRes int viewId,
+            @NonNull RemoteResponse response) {
+        addAction(
+                new SetOnCheckedChangeResponse(
+                        viewId,
+                        response.setInteractionType(
+                                RemoteResponse.INTERACTION_TYPE_CHECKED_CHANGE)));
+    }
+
+    /**
      * @hide
      * Equivalent to calling
      * {@link Drawable#setColorFilter(int, android.graphics.PorterDuff.Mode)},
@@ -3764,7 +4023,6 @@
      * @param viewId The id of the view to change
      * @param type The margin being set e.g. {@link #MARGIN_END}
      * @param dimen a dimension resource to apply to the margin, or 0 to clear the margin.
-     * @hide
      */
     public void setViewLayoutMarginDimen(@IdRes int viewId, @MarginType int type,
             @DimenRes int dimen) {
@@ -3783,7 +4041,6 @@
      * @param type The margin being set e.g. {@link #MARGIN_END}
      * @param value a value for the margin the given units.
      * @param units The unit type of the value e.g. {@link TypedValue#COMPLEX_UNIT_DIP}
-     * @hide
      */
     public void setViewLayoutMargin(@IdRes int viewId, @MarginType int type, float value,
             @ComplexDimensionUnit int units) {
@@ -3801,7 +4058,6 @@
      *
      * @param width Width of the view in the given units
      * @param units The unit type of the value e.g. {@link TypedValue#COMPLEX_UNIT_DIP}
-     * @hide
      */
     public void setViewLayoutWidth(@IdRes int viewId, float width,
             @ComplexDimensionUnit int units) {
@@ -3813,7 +4069,6 @@
      * the result of {@link Resources#getDimensionPixelSize(int)}.
      *
      * @param widthDimen the dimension resource for the view's width
-     * @hide
      */
     public void setViewLayoutWidthDimen(@IdRes int viewId, @DimenRes int widthDimen) {
         addAction(new LayoutParamAction(viewId, LayoutParamAction.LAYOUT_WIDTH, widthDimen));
@@ -3830,7 +4085,6 @@
      *
      * @param height height of the view in the given units
      * @param units The unit type of the value e.g. {@link TypedValue#COMPLEX_UNIT_DIP}
-     * @hide
      */
     public void setViewLayoutHeight(@IdRes int viewId, float height,
             @ComplexDimensionUnit int units) {
@@ -3842,7 +4096,6 @@
      * the result of {@link Resources#getDimensionPixelSize(int)}.
      *
      * @param heightDimen a dimen resource to read the height from.
-     * @hide
      */
     public void setViewLayoutHeightDimen(@IdRes int viewId, @DimenRes int heightDimen) {
         addAction(new LayoutParamAction(viewId, LayoutParamAction.LAYOUT_HEIGHT, heightDimen));
@@ -3962,6 +4215,30 @@
                 ResourceReflectionAction.COLOR_RESOURCE, colorResource));
     }
 
+    /**
+     * Call a method taking one int, a color, on a view in the layout for this RemoteViews.
+     *
+     * @param viewId The id of the view on which to call the method.
+     * @param methodName The name of the method to call.
+     * @param notNight The value to pass to the method when the view's configuration is set to
+     *                 {@link Configuration#UI_MODE_NIGHT_NO}
+     * @param night The value to pass to the method when the view's configuration is set to
+     *                 {@link Configuration#UI_MODE_NIGHT_YES}
+     */
+    public void setColorInt(
+            @IdRes int viewId,
+            @NonNull String methodName,
+            @ColorInt int notNight,
+            @ColorInt int night) {
+        addAction(
+                new NightModeReflectionAction(
+                        viewId,
+                        methodName,
+                        BaseReflectionAction.INT,
+                        notNight,
+                        night));
+    }
+
 
     /**
      * Call a method taking one ColorStateList on a view in the layout for this RemoteViews.
@@ -3969,10 +4246,9 @@
      * @param viewId The id of the view on which to call the method.
      * @param methodName The name of the method to call.
      * @param value The value to pass to the method.
-     *
-     * @hide
      */
-    public void setColorStateList(@IdRes int viewId, String methodName, ColorStateList value) {
+    public void setColorStateList(@IdRes int viewId, @NonNull String methodName,
+            @Nullable ColorStateList value) {
         addAction(new ReflectionAction(viewId, methodName, BaseReflectionAction.COLOR_STATE_LIST,
                 value));
     }
@@ -3980,6 +4256,30 @@
     /**
      * Call a method taking one ColorStateList on a view in the layout for this RemoteViews.
      *
+     * @param viewId The id of the view on which to call the method.
+     * @param methodName The name of the method to call.
+     * @param notNight The value to pass to the method when the view's configuration is set to
+     *                 {@link Configuration#UI_MODE_NIGHT_NO}
+     * @param night The value to pass to the method when the view's configuration is set to
+     *                 {@link Configuration#UI_MODE_NIGHT_YES}
+     */
+    public void setColorStateList(
+            @IdRes int viewId,
+            @NonNull String methodName,
+            @Nullable ColorStateList notNight,
+            @Nullable ColorStateList night) {
+        addAction(
+                new NightModeReflectionAction(
+                        viewId,
+                        methodName,
+                        BaseReflectionAction.COLOR_STATE_LIST,
+                        notNight,
+                        night));
+    }
+
+    /**
+     * Call a method taking one ColorStateList on a view in the layout for this RemoteViews.
+     *
      * The ColorStateList will be resolved from the resources at the time of inflation.
      *
      * @param viewId The id of the view on which to call the method.
@@ -4188,6 +4488,30 @@
     }
 
     /**
+     * Call a method taking one Icon on a view in the layout for this RemoteViews.
+     *
+     * @param viewId The id of the view on which to call the method.
+     * @param methodName The name of the method to call.
+     * @param notNight The value to pass to the method when the view's configuration is set to
+     *                 {@link Configuration#UI_MODE_NIGHT_NO}
+     * @param night The value to pass to the method when the view's configuration is set to
+     *                 {@link Configuration#UI_MODE_NIGHT_YES}
+     */
+    public void setIcon(
+            @IdRes int viewId,
+            @NonNull String methodName,
+            @Nullable Icon notNight,
+            @Nullable Icon night) {
+        addAction(
+                new NightModeReflectionAction(
+                        viewId,
+                        methodName,
+                        BaseReflectionAction.ICON,
+                        notNight,
+                        night));
+    }
+
+    /**
      * Equivalent to calling View.setContentDescription(CharSequence).
      *
      * @param viewId The id of the view whose content description should change.
@@ -4367,49 +4691,61 @@
     }
 
     /** @hide */
-    public View apply(Context context, ViewGroup parent, OnClickHandler handler) {
+    public View apply(Context context, ViewGroup parent, InteractionHandler handler) {
         return apply(context, parent, handler, null);
     }
 
     /** @hide */
     public View apply(@NonNull Context context, @NonNull ViewGroup parent,
-            @Nullable OnClickHandler handler, @Nullable PointF size) {
+            @Nullable InteractionHandler handler, @Nullable PointF size) {
         RemoteViews rvToApply = getRemoteViewsToApply(context, size);
 
         View result = inflateView(context, rvToApply, parent);
-        rvToApply.performApply(result, parent, handler);
+        rvToApply.performApply(result, parent, handler, null);
         return result;
     }
 
     /** @hide */
     public View applyWithTheme(@NonNull Context context, @NonNull ViewGroup parent,
-            @Nullable OnClickHandler handler,
-            @StyleRes int applyThemeResId) {
+            @Nullable InteractionHandler handler, @StyleRes int applyThemeResId) {
         return applyWithTheme(context, parent, handler, applyThemeResId, null);
     }
 
     /** @hide */
     public View applyWithTheme(@NonNull Context context, @NonNull ViewGroup parent,
-            @Nullable OnClickHandler handler,
-            @StyleRes int applyThemeResId, @Nullable PointF size) {
+            @Nullable InteractionHandler handler, @StyleRes int applyThemeResId,
+            @Nullable PointF size) {
         RemoteViews rvToApply = getRemoteViewsToApply(context, size);
 
-        View result = inflateView(context, rvToApply, parent, applyThemeResId);
-        rvToApply.performApply(result, parent, handler);
+        View result = inflateView(context, rvToApply, parent, applyThemeResId, null);
+        rvToApply.performApply(result, parent, handler, null);
+        return result;
+    }
+
+    /** @hide */
+    public View apply(Context context, ViewGroup parent, InteractionHandler handler,
+            @NonNull PointF size, @Nullable ColorResources colorResources) {
+        RemoteViews rvToApply = getRemoteViewsToApply(context, size);
+
+        View result = inflateView(context, rvToApply, parent, 0, colorResources);
+        rvToApply.performApply(result, parent, handler, colorResources);
         return result;
     }
 
     private View inflateView(Context context, RemoteViews rv, ViewGroup parent) {
-        return inflateView(context, rv, parent, 0);
+        return inflateView(context, rv, parent, 0, null);
     }
 
     private View inflateView(Context context, RemoteViews rv, ViewGroup parent,
-            @StyleRes int applyThemeResId) {
+            @StyleRes int applyThemeResId, @Nullable ColorResources colorResources) {
         // RemoteViews may be built by an application installed in another
         // user. So build a context that loads resources from that user but
         // still returns the current users userId so settings like data / time formats
         // are loaded without requiring cross user persmissions.
         final Context contextForResources = getContextForResources(context);
+        if (colorResources != null) {
+            colorResources.apply(contextForResources);
+        }
         Context inflationContext = new RemoteViewsContextWrapper(context, contextForResources);
 
         // If mApplyThemeResId is not given, Theme.DeviceDefault will be used.
@@ -4471,33 +4807,37 @@
      */
     public CancellationSignal applyAsync(
             Context context, ViewGroup parent, Executor executor, OnViewAppliedListener listener) {
-        return applyAsync(context, parent, executor, listener, null);
+        return applyAsync(context, parent, executor, listener, null /* handler */);
+    }
+
+
+    /** @hide */
+    public CancellationSignal applyAsync(Context context, ViewGroup parent,
+            Executor executor, OnViewAppliedListener listener, InteractionHandler handler) {
+        return applyAsync(context, parent, executor, listener, handler, null /* size */);
     }
 
     /** @hide */
     public CancellationSignal applyAsync(Context context, ViewGroup parent,
-            Executor executor, OnViewAppliedListener listener, OnClickHandler handler) {
-        return applyAsync(context, parent, executor, listener, handler, null);
-    }
-
-    /** @hide */
-    public CancellationSignal applyAsync(Context context, ViewGroup parent,
-            Executor executor, OnViewAppliedListener listener, OnClickHandler handler,
+            Executor executor, OnViewAppliedListener listener, InteractionHandler handler,
             PointF size) {
-        return getAsyncApplyTask(context, parent, listener, handler, size).startTaskOnExecutor(
-                executor);
+        return getAsyncApplyTask(context, parent, listener, handler, size, null /* themeColors */)
+                .startTaskOnExecutor(executor);
+    }
+
+    /** @hide */
+    public CancellationSignal applyAsync(Context context, ViewGroup parent, Executor executor,
+            OnViewAppliedListener listener, InteractionHandler handler, PointF size,
+            ColorResources colorResources) {
+        return getAsyncApplyTask(context, parent, listener, handler, size, colorResources)
+                .startTaskOnExecutor(executor);
     }
 
     private AsyncApplyTask getAsyncApplyTask(Context context, ViewGroup parent,
-            OnViewAppliedListener listener, OnClickHandler handler) {
-        return getAsyncApplyTask(context, parent, listener, handler, null);
-    }
-
-    private AsyncApplyTask getAsyncApplyTask(Context context, ViewGroup parent,
-            OnViewAppliedListener listener, OnClickHandler handler, PointF size) {
-        return new AsyncApplyTask(getRemoteViewsToApply(context, size), parent, context,
-                listener,
-                handler, null);
+            OnViewAppliedListener listener, InteractionHandler handler, PointF size,
+            ColorResources colorResources) {
+        return new AsyncApplyTask(getRemoteViewsToApply(context, size), parent, context, listener,
+                handler, colorResources, null /* result */);
     }
 
     private class AsyncApplyTask extends AsyncTask<Void, Void, ViewTree>
@@ -4507,7 +4847,8 @@
         final ViewGroup mParent;
         final Context mContext;
         final OnViewAppliedListener mListener;
-        final OnClickHandler mHandler;
+        final InteractionHandler mHandler;
+        final ColorResources mColorResources;
 
         private View mResult;
         private ViewTree mTree;
@@ -4516,11 +4857,12 @@
 
         private AsyncApplyTask(
                 RemoteViews rv, ViewGroup parent, Context context, OnViewAppliedListener listener,
-                OnClickHandler handler, View result) {
+                InteractionHandler handler, ColorResources colorResources, View result) {
             mRV = rv;
             mParent = parent;
             mContext = context;
             mListener = listener;
+            mColorResources = colorResources;
             mHandler = handler;
 
             mResult = result;
@@ -4530,7 +4872,7 @@
         protected ViewTree doInBackground(Void... params) {
             try {
                 if (mResult == null) {
-                    mResult = inflateView(mContext, mRV, mParent);
+                    mResult = inflateView(mContext, mRV, mParent, 0, mColorResources);
                 }
 
                 mTree = new ViewTree(mResult);
@@ -4539,7 +4881,8 @@
                     mActions = new Action[count];
                     for (int i = 0; i < count && !isCancelled(); i++) {
                         // TODO: check if isCancelled in nested views.
-                        mActions[i] = mRV.mActions.get(i).initActionAsync(mTree, mParent, mHandler);
+                        mActions[i] = mRV.mActions.get(i).initActionAsync(mTree, mParent, mHandler,
+                                mColorResources);
                     }
                 } else {
                     mActions = null;
@@ -4561,10 +4904,10 @@
 
                 try {
                     if (mActions != null) {
-                        OnClickHandler handler = mHandler == null
-                                ? DEFAULT_ON_CLICK_HANDLER : mHandler;
+                        InteractionHandler handler = mHandler == null
+                                ? DEFAULT_INTERACTION_HANDLER : mHandler;
                         for (Action a : mActions) {
-                            a.apply(viewTree.mRoot, mParent, handler);
+                            a.apply(viewTree.mRoot, mParent, handler, mColorResources);
                         }
                     }
                 } catch (Exception e) {
@@ -4608,16 +4951,17 @@
      * the {@link #apply(Context,ViewGroup)} call.
      */
     public void reapply(Context context, View v) {
-        reapply(context, v, null);
+        reapply(context, v, null /* handler */);
     }
 
     /** @hide */
-    public void reapply(Context context, View v, OnClickHandler handler) {
-        reapply(context, v, handler, null);
+    public void reapply(Context context, View v, InteractionHandler handler) {
+        reapply(context, v, handler, null /* size */, null /* colorResources */);
     }
 
     /** @hide */
-    public void reapply(Context context, View v, OnClickHandler handler, PointF size) {
+    public void reapply(Context context, View v, InteractionHandler handler, PointF size,
+            ColorResources colorResources) {
         RemoteViews rvToApply = getRemoteViewsToApply(context, size);
 
         // In the case that a view has this RemoteViews applied in one orientation or size, is
@@ -4631,7 +4975,7 @@
             }
         }
 
-        rvToApply.performApply(v, (ViewGroup) v.getParent(), handler);
+        rvToApply.performApply(v, (ViewGroup) v.getParent(), handler, colorResources);
     }
 
     /**
@@ -4647,20 +4991,21 @@
      * @return CancellationSignal
      * @hide
      */
-    public CancellationSignal reapplyAsync(
-            Context context, View v, Executor executor, OnViewAppliedListener listener) {
+    public CancellationSignal reapplyAsync(Context context, View v, Executor executor,
+            OnViewAppliedListener listener) {
         return reapplyAsync(context, v, executor, listener, null);
     }
 
     /** @hide */
     public CancellationSignal reapplyAsync(Context context, View v, Executor executor,
-            OnViewAppliedListener listener, OnClickHandler handler) {
-        return reapplyAsync(context, v, executor, listener, handler, null);
+            OnViewAppliedListener listener, InteractionHandler handler) {
+        return reapplyAsync(context, v, executor, listener, handler, null, null);
     }
 
     /** @hide */
     public CancellationSignal reapplyAsync(Context context, View v, Executor executor,
-            OnViewAppliedListener listener, OnClickHandler handler, PointF size) {
+            OnViewAppliedListener listener, InteractionHandler handler, PointF size,
+            ColorResources colorResources) {
         RemoteViews rvToApply = getRemoteViewsToApply(context, size);
 
         // In the case that a view has this RemoteViews applied in one orientation, is persisted
@@ -4674,16 +5019,18 @@
         }
 
         return new AsyncApplyTask(rvToApply, (ViewGroup) v.getParent(),
-                context, listener, handler, v).startTaskOnExecutor(executor);
+                context, listener, handler, colorResources, v).startTaskOnExecutor(
+                executor);
     }
 
-    private void performApply(View v, ViewGroup parent, OnClickHandler handler) {
+    private void performApply(View v, ViewGroup parent, InteractionHandler handler,
+            ColorResources colorResources) {
         if (mActions != null) {
-            handler = handler == null ? DEFAULT_ON_CLICK_HANDLER : handler;
+            handler = handler == null ? DEFAULT_INTERACTION_HANDLER : handler;
             final int count = mActions.size();
             for (int i = 0; i < count; i++) {
                 Action a = mActions.get(i);
-                a.apply(v, parent, handler);
+                a.apply(v, parent, handler, colorResources);
             }
         }
     }
@@ -4724,6 +5071,122 @@
     }
 
     /**
+     * Object allowing the modification of a context to overload the system's dynamic colors.
+     *
+     * Only colors from {@link android.R.color#system_primary_0} to
+     * {@link android.R.color#system_neutral_1000} can be overloaded.
+     * @hide
+     */
+    public static final class ColorResources {
+        // Set of valid colors resources.
+        private static final int FIRST_RESOURCE_COLOR_ID = android.R.color.system_primary_0;
+        private static final int LAST_RESOURCE_COLOR_ID = android.R.color.system_neutral_1000;
+        // Size, in bytes, of an entry in the array of colors in an ARSC file.
+        private static final int ARSC_ENTRY_SIZE = 16;
+
+        private ResourcesLoader mLoader;
+
+        private ColorResources(ResourcesLoader loader) {
+            mLoader = loader;
+        }
+
+        /**
+         * Apply the color resources to the given context.
+         *
+         * No resource resolution must have be done on the context given to that method.
+         */
+        public void apply(Context context) {
+            context.getResources().addLoaders(mLoader);
+        }
+
+        private static ByteArrayOutputStream readFileContent(InputStream input) throws IOException {
+            ByteArrayOutputStream content = new ByteArrayOutputStream(2048);
+            byte[] buffer = new byte[4096];
+            while (input.available() > 0) {
+                int read = input.read(buffer);
+                content.write(buffer, 0, read);
+            }
+            return content;
+        }
+
+        /**
+         * Creates the compiled resources content from the asset stored in the APK.
+         *
+         * The asset is a compiled resource with the correct resources name and correct ids, only
+         * the values are incorrect. The last value is at the very end of the file. The resources
+         * are in an array, the array's entries are 16 bytes each. We use this to work out the
+         * location of all the positions of the various resources.
+         */
+        private static byte[] createCompiledResourcesContent(Context context,
+                SparseIntArray colorResources) throws IOException {
+            byte[] content;
+            try (InputStream input = context.getResources().openRawResource(
+                    com.android.internal.R.raw.remote_views_color_resources)) {
+                ByteArrayOutputStream rawContent = readFileContent(input);
+                content = rawContent.toByteArray();
+            }
+            int valuesOffset =
+                    content.length - (LAST_RESOURCE_COLOR_ID & 0xffff) * ARSC_ENTRY_SIZE - 4;
+            if (valuesOffset < 0) {
+                Log.e(LOG_TAG, "ARSC file for theme colors is invalid.");
+                return null;
+            }
+            for (int colorRes = FIRST_RESOURCE_COLOR_ID; colorRes <= LAST_RESOURCE_COLOR_ID;
+                    colorRes++) {
+                // The last 2 bytes are the index in the color array.
+                int index = colorRes & 0xffff;
+                int offset = valuesOffset + index * ARSC_ENTRY_SIZE;
+                int value = colorResources.get(colorRes, context.getColor(colorRes));
+                // Write the 32 bit integer in little endian
+                for (int b = 0; b < 4; b++) {
+                    content[offset + b] = (byte) (value & 0xff);
+                    value >>= 8;
+                }
+            }
+            return content;
+        }
+
+        /**
+         *  Adds a resource loader for theme colors to the given context.
+         *
+         * @param context Context of the view hosting the widget.
+         * @param colorMapping Mapping of resources to color values.
+         *
+         * @hide
+         */
+        public static ColorResources create(Context context, SparseIntArray colorMapping) {
+            try {
+                byte[] contentBytes = createCompiledResourcesContent(context, colorMapping);
+                if (contentBytes == null) {
+                    return null;
+                }
+                FileDescriptor arscFile = null;
+                try {
+                    arscFile = Os.memfd_create("remote_views_theme_colors.arsc", 0 /* flags */);
+                    // Note: This must not be closed through the OutputStream.
+                    try (OutputStream pipeWriter = new FileOutputStream(arscFile)) {
+                        pipeWriter.write(contentBytes);
+
+                        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(arscFile)) {
+                            ResourcesLoader colorsLoader = new ResourcesLoader();
+                            colorsLoader.addProvider(ResourcesProvider
+                                    .loadFromTable(pfd, null /* assetsProvider */));
+                            return new ColorResources(colorsLoader);
+                        }
+                    }
+                } finally {
+                    if (arscFile != null) {
+                        Os.close(arscFile);
+                    }
+                }
+            } catch (Exception ex) {
+                Log.e(LOG_TAG, "Failed to setup the context for theme colors", ex);
+            }
+            return null;
+        }
+    }
+
+    /**
      * Returns the number of actions in this RemoteViews. Can be used as a sequence number.
      *
      * @hide
@@ -4995,9 +5458,22 @@
      */
     public static class RemoteResponse {
 
+        /** @hide **/
+        @IntDef(prefix = "INTERACTION_TYPE_", value = {
+                INTERACTION_TYPE_CLICK,
+                INTERACTION_TYPE_CHECKED_CHANGE,
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        @interface InteractionType {}
+        /** @hide */
+        public static final int INTERACTION_TYPE_CLICK = 0;
+        /** @hide */
+        public static final int INTERACTION_TYPE_CHECKED_CHANGE = 1;
+
         private PendingIntent mPendingIntent;
         private Intent mFillIntent;
 
+        private int mInteractionType = INTERACTION_TYPE_CLICK;
         private IntArray mViewIds;
         private ArrayList<String> mElementNames;
 
@@ -5069,12 +5545,27 @@
             return this;
         }
 
+        /**
+         * Sets the interaction type for which this RemoteResponse responds.
+         *
+         * @param type the type of interaction for which this is a response, such as clicking or
+         *             checked state changing
+         *
+         * @hide
+         */
+        @NonNull
+        public RemoteResponse setInteractionType(@InteractionType int type) {
+            mInteractionType = type;
+            return this;
+        }
+
         private void writeToParcel(Parcel dest, int flags) {
             PendingIntent.writePendingIntentOrNullToParcel(mPendingIntent, dest);
             if (mPendingIntent == null) {
                 // Only write the intent if pending intent is null
                 dest.writeTypedObject(mFillIntent, flags);
             }
+            dest.writeInt(mInteractionType);
             dest.writeIntArray(mViewIds == null ? null : mViewIds.toArray());
             dest.writeStringList(mElementNames);
         }
@@ -5084,50 +5575,62 @@
             if (mPendingIntent == null) {
                 mFillIntent = parcel.readTypedObject(Intent.CREATOR);
             }
+            mInteractionType = parcel.readInt();
             int[] viewIds = parcel.createIntArray();
             mViewIds = viewIds == null ? null : IntArray.wrap(viewIds);
             mElementNames = parcel.createStringArrayList();
         }
 
-        private void handleViewClick(View v, OnClickHandler handler) {
+        private void handleViewInteraction(
+                View v,
+                InteractionHandler handler) {
             final PendingIntent pi;
             if (mPendingIntent != null) {
                 pi = mPendingIntent;
             } else if (mFillIntent != null) {
-                // Insure that this view is a child of an AdapterView
-                View parent = (View) v.getParent();
-                // Break the for loop on the first encounter of:
-                //    1) an AdapterView,
-                //    2) an AppWidgetHostView that is not a RemoteViewsFrameLayout, or
-                //    3) a null parent.
-                // 2) and 3) are unexpected and catch the case where a child is not
-                // correctly parented in an AdapterView.
-                while (parent != null && !(parent instanceof AdapterView<?>)
-                        && !((parent instanceof AppWidgetHostView)
-                        && !(parent instanceof RemoteViewsAdapter.RemoteViewsFrameLayout))) {
-                    parent = (View) parent.getParent();
-                }
-
-                if (!(parent instanceof AdapterView<?>)) {
-                    // Somehow they've managed to get this far without having
-                    // and AdapterView as a parent.
+                AdapterView<?> ancestor = getAdapterViewAncestor(v);
+                if (ancestor == null) {
                     Log.e(LOG_TAG, "Collection item doesn't have AdapterView parent");
                     return;
                 }
-                // Insure that a template pending intent has been set on an ancestor
-                if (!(parent.getTag() instanceof PendingIntent)) {
-                    Log.e(LOG_TAG, "Attempting setOnClickFillInIntent without"
-                            + " calling setPendingIntentTemplate on parent.");
+
+                // Ensure that a template pending intent has been set on the ancestor
+                if (!(ancestor.getTag() instanceof PendingIntent)) {
+                    Log.e(LOG_TAG, "Attempting setOnClickFillInIntent or "
+                            + "setOnCheckedChangeFillInIntent without calling "
+                            + "setPendingIntentTemplate on parent.");
                     return;
                 }
 
-                pi = (PendingIntent) parent.getTag();
+                pi = (PendingIntent) ancestor.getTag();
             } else {
                 Log.e(LOG_TAG, "Response has neither pendingIntent nor fillInIntent");
                 return;
             }
 
-            handler.onClickHandler(v, pi, this);
+            handler.onInteraction(v, pi, this);
+        }
+
+        /**
+         * Returns the closest ancestor of the view that is an AdapterView or null if none could be
+         * found.
+         */
+        @Nullable
+        private static AdapterView<?> getAdapterViewAncestor(@Nullable View view) {
+            View parent = (View) view.getParent();
+            // Break the for loop on the first encounter of:
+            //    1) an AdapterView,
+            //    2) an AppWidgetHostView that is not a RemoteViewsFrameLayout, or
+            //    3) a null parent.
+            // 2) and 3) are unexpected and catch the case where a child is not
+            // correctly parented in an AdapterView.
+            while (parent != null && !(parent instanceof AdapterView<?>)
+                    && !((parent instanceof AppWidgetHostView)
+                    && !(parent instanceof RemoteViewsAdapter.RemoteViewsFrameLayout))) {
+                parent = (View) parent.getParent();
+            }
+
+            return parent instanceof AdapterView<?> ? (AdapterView<?>) parent : null;
         }
 
         /** @hide */
@@ -5135,6 +5638,11 @@
             Intent intent = mPendingIntent != null ? new Intent() : new Intent(mFillIntent);
             intent.setSourceBounds(getSourceBounds(view));
 
+            if (view instanceof CompoundButton
+                    && mInteractionType == INTERACTION_TYPE_CHECKED_CHANGE) {
+                intent.putExtra(EXTRA_CHECKED, ((CompoundButton) view).isChecked());
+            }
+
             ActivityOptions opts = null;
 
             Context context = view.getContext();
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index c98ed6a..9749a68 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -47,7 +47,7 @@
 import android.view.View;
 import android.view.View.MeasureSpec;
 import android.view.ViewGroup;
-import android.widget.RemoteViews.OnClickHandler;
+import android.widget.RemoteViews.InteractionHandler;
 
 import com.android.internal.widget.IRemoteViewsFactory;
 
@@ -107,7 +107,7 @@
     private final boolean mOnLightBackground;
     private final Executor mAsyncViewLoadExecutor;
 
-    private OnClickHandler mRemoteViewsOnClickHandler;
+    private InteractionHandler mRemoteViewsInteractionHandler;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     private final FixedSizeRemoteViewsCache mCache;
     private int mVisibleWindowLowerBound;
@@ -386,9 +386,9 @@
          *                        asynchronously (for eg, when we are already showing the loading
          *                        view)
          */
-        public void onRemoteViewsLoaded(RemoteViews view, OnClickHandler handler,
+        public void onRemoteViewsLoaded(RemoteViews view, InteractionHandler handler,
                 boolean forceApplyAsync) {
-            setOnClickHandler(handler);
+            setInteractionHandler(handler);
             applyRemoteViews(view, forceApplyAsync || ((view != null) && view.prefersAsyncApply()));
         }
 
@@ -455,7 +455,7 @@
             if (refs != null) {
                 // Notify all the references for that position of the newly loaded RemoteViews
                 for (final RemoteViewsFrameLayout ref : refs) {
-                    ref.onRemoteViewsLoaded(view, mRemoteViewsOnClickHandler, true);
+                    ref.onRemoteViewsLoaded(view, mRemoteViewsInteractionHandler, true);
                 }
             }
         }
@@ -902,9 +902,9 @@
         return mDataReady;
     }
 
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public void setRemoteViewsOnClickHandler(OnClickHandler handler) {
-        mRemoteViewsOnClickHandler = handler;
+    /** @hide */
+    public void setRemoteViewsInteractionHandler(InteractionHandler handler) {
+        mRemoteViewsInteractionHandler = handler;
     }
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -1137,7 +1137,7 @@
 
             if (isInCache) {
                 // Apply the view synchronously if possible, to avoid flickering
-                layout.onRemoteViewsLoaded(rv, mRemoteViewsOnClickHandler, false);
+                layout.onRemoteViewsLoaded(rv, mRemoteViewsInteractionHandler, false);
                 if (hasNewItems) {
                     mServiceHandler.sendEmptyMessage(MSG_LOAD_NEXT_ITEM);
                 }
@@ -1146,7 +1146,7 @@
                 // exist, the layout will create a default view based on the firstView height.
                 layout.onRemoteViewsLoaded(
                         mCache.getMetaData().getLoadingTemplate(mContext).remoteViews,
-                        mRemoteViewsOnClickHandler,
+                        mRemoteViewsInteractionHandler,
                         false);
                 mRequestedViews.add(position, layout);
                 mCache.queueRequestedPositionToLoad(position);
diff --git a/core/java/android/widget/RemoteViewsListAdapter.java b/core/java/android/widget/RemoteViewsListAdapter.java
index b80fe48..827d033 100644
--- a/core/java/android/widget/RemoteViewsListAdapter.java
+++ b/core/java/android/widget/RemoteViewsListAdapter.java
@@ -31,12 +31,14 @@
     private ArrayList<RemoteViews> mRemoteViewsList;
     private ArrayList<Integer> mViewTypes = new ArrayList<Integer>();
     private int mViewTypeCount;
+    private RemoteViews.ColorResources mColorResources;
 
     public RemoteViewsListAdapter(Context context, ArrayList<RemoteViews> remoteViews,
-            int viewTypeCount) {
+            int viewTypeCount, RemoteViews.ColorResources colorResources) {
         mContext = context;
         mRemoteViewsList = remoteViews;
         mViewTypeCount = viewTypeCount;
+        mColorResources = colorResources;
         init();
     }
 
@@ -90,9 +92,10 @@
             if (convertView != null && rv != null &&
                     convertView.getId() == rv.getLayoutId()) {
                 v = convertView;
-                rv.reapply(mContext, v);
+                rv.reapply(mContext, v, null /* handler */, null /* size */, mColorResources);
             } else {
-                v = rv.apply(mContext, parent);
+                v = rv.apply(mContext, parent, null /* handler */, null /* size */,
+                        mColorResources);
             }
             return v;
         } else {
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 64d09de..65f3da7 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -335,6 +335,27 @@
     }
 
     /**
+     * Returns the {@link EdgeEffect#getType()} for the edge effects.
+     * @return the {@link EdgeEffect#getType()} for the edge effects.
+     * @attr ref android.R.styleable#EdgeEffect_edgeEffectType
+     */
+    @EdgeEffect.EdgeEffectType
+    public int getEdgeEffectType() {
+        return mEdgeGlowTop.getType();
+    }
+
+    /**
+     * Sets the {@link EdgeEffect#setType(int)} for the edge effects.
+     * @param type The edge effect type to use for the edge effects.
+     * @attr ref android.R.styleable#EdgeEffect_edgeEffectType
+     */
+    public void setEdgeEffectType(@EdgeEffect.EdgeEffectType int type) {
+        mEdgeGlowTop.setType(type);
+        mEdgeGlowBottom.setType(type);
+        invalidate();
+    }
+
+    /**
      * @return The maximum amount this scroll view will scroll in response to
      *   an arrow event.
      */
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 0f2089a..ca0747f 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4756,6 +4756,7 @@
      * @see #getJustificationMode()
      */
     @Layout.JustificationMode
+    @android.view.RemotableViewMethod
     public void setJustificationMode(@Layout.JustificationMode int justificationMode) {
         mJustificationMode = justificationMode;
         if (mLayout != null) {
@@ -5232,6 +5233,7 @@
      * @see android.view.Gravity
      * @attr ref android.R.styleable#TextView_gravity
      */
+    @android.view.RemotableViewMethod
     public void setGravity(int gravity) {
         if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
             gravity |= Gravity.START;
@@ -5826,6 +5828,7 @@
      *
      * @attr ref android.R.styleable#TextView_lineHeight
      */
+    @android.view.RemotableViewMethod
     public void setLineHeight(@Px @IntRange(from = 0) int lineHeight) {
         Preconditions.checkArgumentNonnegative(lineHeight);
 
@@ -10277,6 +10280,7 @@
      * @see #setTransformationMethod(TransformationMethod)
      * @attr ref android.R.styleable#TextView_textAllCaps
      */
+    @android.view.RemotableViewMethod
     public void setAllCaps(boolean allCaps) {
         if (allCaps) {
             setTransformationMethod(new AllCapsTransformationMethod(getContext()));
diff --git a/core/java/android/widget/ToastPresenter.java b/core/java/android/widget/ToastPresenter.java
index 2904a8c..0f2a3ca 100644
--- a/core/java/android/widget/ToastPresenter.java
+++ b/core/java/android/widget/ToastPresenter.java
@@ -184,7 +184,7 @@
         mParams.y = yOffset;
         mParams.horizontalMargin = horizontalMargin;
         mParams.verticalMargin = verticalMargin;
-        addToastView();
+        mView.setLayoutParams(mParams);
     }
 
     /**
diff --git a/core/java/android/window/ClientWindowFrames.java b/core/java/android/window/ClientWindowFrames.java
index e22a5eb..acf9882 100644
--- a/core/java/android/window/ClientWindowFrames.java
+++ b/core/java/android/window/ClientWindowFrames.java
@@ -58,9 +58,9 @@
 
     /** Needed for AIDL out parameters. */
     public void readFromParcel(Parcel in) {
-        frame.set(Rect.CREATOR.createFromParcel(in));
-        displayFrame.set(Rect.CREATOR.createFromParcel(in));
-        backdropFrame.set(Rect.CREATOR.createFromParcel(in));
+        frame.readFromParcel(in);
+        displayFrame.readFromParcel(in);
+        backdropFrame.readFromParcel(in);
     }
 
     @Override
diff --git a/core/java/android/window/StartingWindowInfo.java b/core/java/android/window/StartingWindowInfo.java
index 63b9e9b..d1c1e40 100644
--- a/core/java/android/window/StartingWindowInfo.java
+++ b/core/java/android/window/StartingWindowInfo.java
@@ -35,6 +35,31 @@
 @TestApi
 public final class StartingWindowInfo implements Parcelable {
     /**
+     * Prefer nothing or not care the type of starting window.
+     * @hide
+     */
+    public static final int STARTING_WINDOW_TYPE_NONE = 0;
+    /**
+     * Prefer splash screen starting window.
+     * @hide
+     */
+    public static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 1;
+    /**
+     * Prefer snapshot starting window.
+     * @hide
+     */
+    public static final int STARTING_WINDOW_TYPE_SNAPSHOT = 2;
+    /**
+     * @hide
+     */
+    @IntDef(flag = true, prefix = "STARTING_WINDOW_TYPE_", value = {
+            STARTING_WINDOW_TYPE_NONE,
+            STARTING_WINDOW_TYPE_SPLASH_SCREEN,
+            STARTING_WINDOW_TYPE_SNAPSHOT
+    })
+    public @interface StartingWindowType {}
+
+    /**
      * The {@link TaskInfo} from this task.
      *  @hide
      */
diff --git a/core/java/com/android/internal/app/IAppOpsNotedCallback.aidl b/core/java/com/android/internal/app/IAppOpsNotedCallback.aidl
index cb280cd..f3759e0 100644
--- a/core/java/com/android/internal/app/IAppOpsNotedCallback.aidl
+++ b/core/java/com/android/internal/app/IAppOpsNotedCallback.aidl
@@ -18,5 +18,5 @@
 
 // Iterface to observe op note/checks of ops
 oneway interface IAppOpsNotedCallback {
-    void opNoted(int op, int uid, String packageName, int flags, int mode);
+    void opNoted(int op, int uid, String packageName, String attributionTag, int flags, int mode);
 }
diff --git a/core/java/com/android/internal/app/IAppOpsStartedCallback.aidl b/core/java/com/android/internal/app/IAppOpsStartedCallback.aidl
index b0cb2a8..3a108e7 100644
--- a/core/java/com/android/internal/app/IAppOpsStartedCallback.aidl
+++ b/core/java/com/android/internal/app/IAppOpsStartedCallback.aidl
@@ -18,5 +18,5 @@
 
 // Iterface to observe op starts
 oneway interface IAppOpsStartedCallback {
-    void opStarted(int op, int uid, String packageName, int flags, int mode);
+    void opStarted(int op, int uid, String packageName, String attributionTag, int flags, int mode);
 }
diff --git a/core/java/com/android/internal/graphics/drawable/BackgroundBlurDrawable.java b/core/java/com/android/internal/graphics/drawable/BackgroundBlurDrawable.java
index 96dac56..402d7fe 100644
--- a/core/java/com/android/internal/graphics/drawable/BackgroundBlurDrawable.java
+++ b/core/java/com/android/internal/graphics/drawable/BackgroundBlurDrawable.java
@@ -19,6 +19,7 @@
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UiThread;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -31,12 +32,14 @@
 import android.graphics.Rect;
 import android.graphics.RenderNode;
 import android.graphics.drawable.Drawable;
-import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Log;
-import android.view.SurfaceControl;
+import android.util.LongSparseArray;
 import android.view.ViewRootImpl;
 
 import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 
 /**
  * A drawable that keeps track of a blur region, pokes a hole under it, and propagates its state
@@ -52,26 +55,40 @@
     private final Paint mPaint = new Paint();
     private final Path mRectPath = new Path();
     private final float[] mTmpRadii = new float[8];
-    private final SurfaceControl.BlurRegion mBlurRegion = new SurfaceControl.BlurRegion();
 
-    // This will be called from a thread pool.
-    private final RenderNode.PositionUpdateListener mPositionUpdateListener =
+    private boolean mVisible = true;
+
+    // Confined to UiThread. The values are copied into a BlurRegion, which lives on
+    // RenderThread to avoid interference with UiThread updates.
+    private int mBlurRadius;
+    private float mCornerRadiusTL;
+    private float mCornerRadiusTR;
+    private float mCornerRadiusBL;
+    private float mCornerRadiusBR;
+    private float mAlpha = 1;
+
+    // Do not update from UiThread. This holds the latest position for this drawable. It is used
+    // by the Aggregator from RenderThread to get the final position of the blur region sent to SF
+    private final Rect mRect = new Rect();
+    // This is called from a thread pool. The callbacks might come out of order w.r.t. the frame
+    // number, so we send a Runnable holding the actual update to the Aggregator. The Aggregator
+    // can apply the update on RenderThread when processing that same frame.
+    @VisibleForTesting
+    public final RenderNode.PositionUpdateListener mPositionUpdateListener =
             new RenderNode.PositionUpdateListener() {
             @Override
             public void positionChanged(long frameNumber, int left, int top, int right,
                     int bottom) {
-                synchronized (mAggregator) {
-                    mBlurRegion.rect.set(left, top, right, bottom);
-                    mAggregator.onBlurRegionUpdated(BackgroundBlurDrawable.this, mBlurRegion);
-                }
+                mAggregator.onRenderNodePositionChanged(frameNumber, () -> {
+                    mRect.set(left, top, right, bottom);
+                });
             }
 
             @Override
             public void positionLost(long frameNumber) {
-                synchronized (mAggregator) {
-                    mBlurRegion.rect.setEmpty();
-                    mAggregator.onBlurRegionUpdated(BackgroundBlurDrawable.this, mBlurRegion);
-                }
+                mAggregator.onRenderNodePositionChanged(frameNumber, () -> {
+                    mRect.setEmpty();
+                });
             }
         };
 
@@ -79,6 +96,7 @@
         mAggregator = aggregator;
         mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
         mPaint.setColor(Color.TRANSPARENT);
+        mPaint.setAntiAlias(true);
         mRenderNode = new RenderNode("BackgroundBlurDrawable");
         mRenderNode.addPositionUpdateListener(mPositionUpdateListener);
     }
@@ -104,23 +122,30 @@
     public boolean setVisible(boolean visible, boolean restart) {
         boolean changed = super.setVisible(visible, restart);
         if (changed) {
-            mBlurRegion.visible = visible;
+            mVisible = visible;
+            mAggregator.onBlurDrawableUpdated(this);
         }
         return changed;
     }
 
     @Override
     public void setAlpha(int alpha) {
-        mBlurRegion.alpha = alpha / 255f;
-        invalidateSelf();
+        if (mAlpha != alpha / 255f) {
+            mAlpha = alpha / 255f;
+            invalidateSelf();
+            mAggregator.onBlurDrawableUpdated(this);
+        }
     }
 
     /**
      * Blur radius in pixels.
      */
     public void setBlurRadius(int blurRadius) {
-        mBlurRegion.blurRadius = blurRadius;
-        invalidateSelf();
+        if (mBlurRadius != blurRadius) {
+            mBlurRadius = blurRadius;
+            invalidateSelf();
+            mAggregator.onBlurDrawableUpdated(this);
+        }
     }
 
     /**
@@ -139,14 +164,18 @@
      */
     public void setCornerRadius(float cornerRadiusTL, float cornerRadiusTR, float cornerRadiusBL,
             float cornerRadiusBR) {
-        synchronized (mAggregator) {
-            mBlurRegion.cornerRadiusTL = cornerRadiusTL;
-            mBlurRegion.cornerRadiusTR = cornerRadiusTR;
-            mBlurRegion.cornerRadiusBL = cornerRadiusBL;
-            mBlurRegion.cornerRadiusBR = cornerRadiusBR;
+        if (mCornerRadiusTL != cornerRadiusTL
+                || mCornerRadiusTR != cornerRadiusTR
+                || mCornerRadiusBL != cornerRadiusBL
+                || mCornerRadiusBR != cornerRadiusBR) {
+            mCornerRadiusTL = cornerRadiusTL;
+            mCornerRadiusTR = cornerRadiusTR;
+            mCornerRadiusBL = cornerRadiusBL;
+            mCornerRadiusBR = cornerRadiusBR;
+            updatePath();
+            invalidateSelf();
+            mAggregator.onBlurDrawableUpdated(this);
         }
-        updatePath();
-        invalidateSelf();
     }
 
     @Override
@@ -157,12 +186,10 @@
     }
 
     private void updatePath() {
-        synchronized (mAggregator) {
-            mTmpRadii[0] = mTmpRadii[1] = mBlurRegion.cornerRadiusTL;
-            mTmpRadii[2] = mTmpRadii[3] = mBlurRegion.cornerRadiusTR;
-            mTmpRadii[4] = mTmpRadii[5] = mBlurRegion.cornerRadiusBL;
-            mTmpRadii[6] = mTmpRadii[7] = mBlurRegion.cornerRadiusBR;
-        }
+        mTmpRadii[0] = mTmpRadii[1] = mCornerRadiusTL;
+        mTmpRadii[2] = mTmpRadii[3] = mCornerRadiusTR;
+        mTmpRadii[4] = mTmpRadii[5] = mCornerRadiusBL;
+        mTmpRadii[6] = mTmpRadii[7] = mCornerRadiusBR;
         mRectPath.reset();
         if (getAlpha() == 0 || !isVisible()) {
             return;
@@ -182,17 +209,32 @@
         return PixelFormat.TRANSLUCENT;
     }
 
+    @Override
+    public String toString() {
+        return "BackgroundBlurDrawable{"
+            + "blurRadius=" + mBlurRadius
+            + ", corners={" + mCornerRadiusTL
+            + "," + mCornerRadiusTR
+            + "," + mCornerRadiusBL
+            + "," + mCornerRadiusBR
+            + "}, alpha=" + mAlpha
+            + ", visible=" + mVisible
+            + "}";
+    }
+
     /**
      * Responsible for keeping track of all blur regions of a {@link ViewRootImpl} and posting a
      * message when it's time to propagate them.
      */
     public static final class Aggregator {
-
-        private final ArrayMap<BackgroundBlurDrawable, SurfaceControl.BlurRegion> mBlurRegions =
-                new ArrayMap<>();
+        private final Object mRtLock = new Object();
+        // Maintains a list of all *visible* blur drawables. Confined to  UI thread
+        private final ArraySet<BackgroundBlurDrawable> mDrawables = new ArraySet();
+        @GuardedBy("mRtLock")
+        private final LongSparseArray<ArraySet<Runnable>> mFrameRtUpdates = new LongSparseArray();
         private final ViewRootImpl mViewRoot;
-        private float[][] mTmpBlurRegionsArray;
-        private boolean mNeedsUpdate;
+        private BlurRegion[] mTmpBlurRegionsForFrame = new BlurRegion[0];
+        private boolean mHasUiUpdates;
 
         public Aggregator(ViewRootImpl viewRoot) {
             mViewRoot = viewRoot;
@@ -209,60 +251,191 @@
         }
 
         /**
-         * Called from RenderThread only, already locked.
-         * @param drawable
-         * @param blurRegion
+         * Called when a BackgroundBlurDrawable has been updated
          */
-        void onBlurRegionUpdated(BackgroundBlurDrawable drawable,
-                SurfaceControl.BlurRegion blurRegion) {
-            if (blurRegion.rect.isEmpty() || blurRegion.alpha == 0 || blurRegion.blurRadius == 0
-                    || !blurRegion.visible) {
-                mBlurRegions.remove(drawable);
-                mNeedsUpdate = true;
-                if (DEBUG) {
-                    Log.d(TAG, "Remove " + blurRegion);
+        @UiThread
+        void onBlurDrawableUpdated(BackgroundBlurDrawable drawable) {
+            final boolean shouldBeDrawn =
+                    drawable.mAlpha != 0 && drawable.mBlurRadius > 0 && drawable.mVisible;
+            final boolean isDrawn = mDrawables.contains(drawable);
+            if (shouldBeDrawn) {
+                mHasUiUpdates = true;
+                if (!isDrawn) {
+                    mDrawables.add(drawable);
+                    if (DEBUG) {
+                        Log.d(TAG, "Add " + drawable);
+                    }
+                } else {
+                    if (DEBUG) {
+                        Log.d(TAG, "Update " + drawable);
+                    }
                 }
-            } else {
-                mBlurRegions.put(drawable, blurRegion);
-                mNeedsUpdate = true;
+            } else if (!shouldBeDrawn && isDrawn) {
+                mHasUiUpdates = true;
+                mDrawables.remove(drawable);
                 if (DEBUG) {
-                    Log.d(TAG, "Update " + blurRegion);
+                    Log.d(TAG, "Remove " + drawable);
                 }
             }
         }
 
+        // Called from a thread pool
+        void onRenderNodePositionChanged(long frameNumber, Runnable update) {
+            // One of the blur region's position has changed, so we have to send an updated list
+            // of blur regions to SurfaceFlinger for this frame.
+            synchronized (mRtLock) {
+                ArraySet<Runnable> frameRtUpdates = mFrameRtUpdates.get(frameNumber);
+                if (frameRtUpdates == null) {
+                    frameRtUpdates = new ArraySet<>();
+                    mFrameRtUpdates.put(frameNumber, frameRtUpdates);
+                }
+                frameRtUpdates.add(update);
+            }
+        }
+
         /**
-         * If there are any blur regions visible on the screen at the moment.
+         * @return true if there are any updates that need to be sent to SF
          */
+        @UiThread
+        public boolean hasUpdates() {
+            return mHasUiUpdates;
+        }
+
+        /**
+         * @return true if there are any visible blur regions
+         */
+        @UiThread
         public boolean hasRegions() {
-            return mBlurRegions.size() > 0;
+            return mDrawables.size() > 0;
         }
 
         /**
-         * Dispatch blur updates, if there were any.
-         * @param frameNumber Frame where the update should happen.
+         * @return an array of BlurRegions, which are holding a copy of the information in
+         *         all the currently visible BackgroundBlurDrawables
          */
-        public void dispatchBlurTransactionIfNeeded(long frameNumber) {
-            synchronized (this) {
-                if (!mNeedsUpdate) {
-                    return;
+        @UiThread
+        public BlurRegion[] getBlurRegionsCopyForRT() {
+            if (mHasUiUpdates) {
+                mTmpBlurRegionsForFrame = new BlurRegion[mDrawables.size()];
+                for (int i = 0; i < mDrawables.size(); i++) {
+                    mTmpBlurRegionsForFrame[i] = new BlurRegion(mDrawables.valueAt(i));
                 }
-                mNeedsUpdate = false;
-
-                if (mTmpBlurRegionsArray == null
-                        || mTmpBlurRegionsArray.length != mBlurRegions.size()) {
-                    mTmpBlurRegionsArray = new float[mBlurRegions.size()][];
-                }
-                if (DEBUG) {
-                    Log.d(TAG, "onBlurRegionUpdated will dispatch " + mTmpBlurRegionsArray.length
-                            + " regions for frame " + frameNumber);
-                }
-                for (int i = 0; i < mTmpBlurRegionsArray.length; i++) {
-                    mTmpBlurRegionsArray[i] = mBlurRegions.valueAt(i).toFloatArray();
-                }
-
-                mViewRoot.dispatchBlurRegions(mTmpBlurRegionsArray, frameNumber);
+                mHasUiUpdates = false;
             }
+
+            return mTmpBlurRegionsForFrame;
+        }
+
+        /**
+         * Called on RenderThread.
+         *
+         * @return all blur regions if there are any ui or position updates for this frame,
+         *         null otherwise
+         */
+        @VisibleForTesting
+        public float[][] getBlurRegionsToDispatchToSf(long frameNumber,
+                BlurRegion[] blurRegionsForFrame, boolean hasUiUpdatesForFrame) {
+            synchronized (mRtLock) {
+                if (!hasUiUpdatesForFrame && (mFrameRtUpdates.size() == 0
+                            || mFrameRtUpdates.keyAt(0) > frameNumber)) {
+                    return null;
+                }
+
+                // mFrameRtUpdates holds position updates coming from a thread pool span from
+                // RenderThread. At this point, all position updates for frame frameNumber should
+                // have been added to mFrameRtUpdates.
+                // Here, we apply all updates for frames <= frameNumber in case some previous update
+                // has been missed. This also protects mFrameRtUpdates from memory leaks.
+                while (mFrameRtUpdates.size() != 0 && mFrameRtUpdates.keyAt(0) <= frameNumber) {
+                    final ArraySet<Runnable> frameUpdates = mFrameRtUpdates.valueAt(0);
+                    mFrameRtUpdates.removeAt(0);
+                    for (int i = 0; i < frameUpdates.size(); i++) {
+                        frameUpdates.valueAt(i).run();
+                    }
+                }
+            }
+
+            if (DEBUG) {
+                Log.d(TAG, "Dispatching " + blurRegionsForFrame.length + " blur regions:");
+            }
+
+            final float[][] blurRegionsArray = new float[blurRegionsForFrame.length][];
+            for (int i = 0; i < blurRegionsArray.length; i++) {
+                blurRegionsArray[i] = blurRegionsForFrame[i].toFloatArray();
+                if (DEBUG) {
+                    Log.d(TAG, blurRegionsForFrame[i].toString());
+                }
+            }
+            return blurRegionsArray;
+        }
+
+        /**
+         * Called on RenderThread in FrameDrawingCallback.
+         * Dispatch all blur regions if there are any ui or position updates.
+         */
+        public void dispatchBlurTransactionIfNeeded(long frameNumber,
+                BlurRegion[] blurRegionsForFrame, boolean hasUiUpdatesForFrame) {
+            final float[][] blurRegionsArray = getBlurRegionsToDispatchToSf(frameNumber,
+                    blurRegionsForFrame, hasUiUpdatesForFrame);
+            if (blurRegionsArray != null) {
+                mViewRoot.dispatchBlurRegions(blurRegionsArray, frameNumber);
+            }
+        }
+
+    }
+
+    /**
+     * Wrapper for sending blur data to SurfaceFlinger
+     * Confined to RenderThread.
+     */
+    public static final class BlurRegion {
+        public final int blurRadius;
+        public final float cornerRadiusTL;
+        public final float cornerRadiusTR;
+        public final float cornerRadiusBL;
+        public final float cornerRadiusBR;
+        public final float alpha;
+        public final Rect rect;
+
+        BlurRegion(BackgroundBlurDrawable drawable) {
+            alpha = drawable.mAlpha;
+            blurRadius = drawable.mBlurRadius;
+            cornerRadiusTL = drawable.mCornerRadiusTL;
+            cornerRadiusTR = drawable.mCornerRadiusTR;
+            cornerRadiusBL = drawable.mCornerRadiusBL;
+            cornerRadiusBR = drawable.mCornerRadiusBR;
+            rect = drawable.mRect;
+        }
+
+        /**
+         * Serializes this class into a float array that's more JNI friendly.
+         */
+        float[] toFloatArray() {
+            final float[] floatArray = new float[10];
+            floatArray[0] = blurRadius;
+            floatArray[1] = alpha;
+            floatArray[2] = rect.left;
+            floatArray[3] = rect.top;
+            floatArray[4] = rect.right;
+            floatArray[5] = rect.bottom;
+            floatArray[6] = cornerRadiusTL;
+            floatArray[7] = cornerRadiusTR;
+            floatArray[8] = cornerRadiusBL;
+            floatArray[9] = cornerRadiusBR;
+            return floatArray;
+        }
+
+        @Override
+        public String toString() {
+            return "BlurRegion{"
+                    + "blurRadius=" + blurRadius
+                    + ", corners={" + cornerRadiusTL
+                    + "," + cornerRadiusTR
+                    + "," + cornerRadiusBL
+                    + "," + cornerRadiusBR
+                    + "}, alpha=" + alpha
+                    + ", rect=" + rect
+                    + "}";
         }
     }
 }
diff --git a/core/java/com/android/internal/graphics/palette/CelebiQuantizer.java b/core/java/com/android/internal/graphics/palette/CelebiQuantizer.java
new file mode 100644
index 0000000..de6bf20
--- /dev/null
+++ b/core/java/com/android/internal/graphics/palette/CelebiQuantizer.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.graphics.palette;
+
+import java.util.List;
+
+/**
+ * An implementation of Celebi's WSM quantizer, or, a Kmeans quantizer that starts with centroids
+ * from a Wu quantizer to ensure 100% reproducible and quality results, and has some optimizations
+ * to the Kmeans algorithm.
+ *
+ * See Celebi 2011, “Improving the Performance of K-Means for Color Quantization”
+ */
+public class CelebiQuantizer implements Quantizer {
+    private List<Palette.Swatch> mSwatches;
+
+    public CelebiQuantizer() { }
+
+    @Override
+    public void quantize(int[] pixels, int maxColors) {
+        WuQuantizer wu = new WuQuantizer(pixels, maxColors);
+        wu.quantize(pixels, maxColors);
+        List<Palette.Swatch> wuSwatches = wu.getQuantizedColors();
+        LABCentroid labCentroidProvider = new LABCentroid();
+        WSMeansQuantizer kmeans =
+                new WSMeansQuantizer(WSMeansQuantizer.createStartingCentroids(labCentroidProvider,
+                        wuSwatches), labCentroidProvider, pixels, maxColors);
+        kmeans.quantize(pixels, maxColors);
+        mSwatches = kmeans.getQuantizedColors();
+    }
+
+    @Override
+    public List<Palette.Swatch> getQuantizedColors() {
+        return mSwatches;
+    }
+}
diff --git a/core/java/com/android/internal/graphics/palette/CentroidProvider.java b/core/java/com/android/internal/graphics/palette/CentroidProvider.java
new file mode 100644
index 0000000..5fcfcba
--- /dev/null
+++ b/core/java/com/android/internal/graphics/palette/CentroidProvider.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.graphics.palette;
+
+import android.annotation.ColorInt;
+
+interface CentroidProvider {
+    /**
+     * @return 3 dimensions representing the color
+     */
+    float[] getCentroid(@ColorInt int color);
+
+    /**
+     * @param centroid 3 dimensions representing the color
+     * @return 32-bit ARGB representation
+     */
+    @ColorInt
+    int getColor(float[] centroid);
+
+    /**
+     * Distance between two centroids.
+     */
+    float distance(float[] a, float[] b);
+}
diff --git a/core/java/com/android/internal/graphics/palette/ColorCutQuantizer.java b/core/java/com/android/internal/graphics/palette/ColorCutQuantizer.java
index 9ac753b..7779494 100644
--- a/core/java/com/android/internal/graphics/palette/ColorCutQuantizer.java
+++ b/core/java/com/android/internal/graphics/palette/ColorCutQuantizer.java
@@ -35,6 +35,8 @@
 import android.graphics.Color;
 import android.util.TimingLogger;
 
+import com.android.internal.graphics.palette.Palette.Swatch;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -42,9 +44,6 @@
 import java.util.List;
 import java.util.PriorityQueue;
 
-import com.android.internal.graphics.ColorUtils;
-import com.android.internal.graphics.palette.Palette.Swatch;
-
 /**
  * Copied from: frameworks/support/v7/palette/src/main/java/android/support/v7/
  * graphics/ColorCutQuantizer.java
@@ -77,20 +76,17 @@
     int[] mHistogram;
     List<Swatch> mQuantizedColors;
     TimingLogger mTimingLogger;
-    Palette.Filter[] mFilters;
 
     private final float[] mTempHsl = new float[3];
 
     /**
      * Execute color quantization.
      *
-     * @param pixels histogram representing an image's pixel data
+     * @param pixels    histogram representing an image's pixel data
      * @param maxColors The maximum number of colors that should be in the result palette.
-     * @param filters Set of filters to use in the quantization stage
      */
-    public void quantize(final int[] pixels, final int maxColors, final Palette.Filter[] filters) {
+    public void quantize(final int[] pixels, final int maxColors) {
         mTimingLogger = LOG_TIMINGS ? new TimingLogger(LOG_TAG, "Creation") : null;
-        mFilters = filters;
 
         final int[] hist = mHistogram = new int[1 << (QUANTIZE_WORD_WIDTH * 3)];
         for (int i = 0; i < pixels.length; i++) {
@@ -108,10 +104,6 @@
         // Now let's count the number of distinct colors
         int distinctColorCount = 0;
         for (int color = 0; color < hist.length; color++) {
-            if (hist[color] > 0 && shouldIgnoreColor(color)) {
-                // If we should ignore the color, set the population to 0
-                hist[color] = 0;
-            }
             if (hist[color] > 0) {
                 // If the color has population, increase the distinct color count
                 distinctColorCount++;
@@ -186,7 +178,7 @@
      * and splitting them. Once split, the new box and the remaining box are offered back to the
      * queue.
      *
-     * @param queue {@link java.util.PriorityQueue} to poll for boxes
+     * @param queue   {@link java.util.PriorityQueue} to poll for boxes
      * @param maxSize Maximum amount of boxes to split
      */
     private void splitBoxes(final PriorityQueue<Vbox> queue, final int maxSize) {
@@ -216,11 +208,7 @@
         ArrayList<Swatch> colors = new ArrayList<>(vboxes.size());
         for (Vbox vbox : vboxes) {
             Swatch swatch = vbox.getAverageColor();
-            if (!shouldIgnoreColor(swatch)) {
-                // As we're averaging a color box, we can still get colors which we do not want, so
-                // we check again here
-                colors.add(swatch);
-            }
+            colors.add(swatch);
         }
         return colors;
     }
@@ -230,7 +218,7 @@
      */
     private class Vbox {
         // lower and upper index are inclusive
-        private int mLowerIndex;
+        private final int mLowerIndex;
         private int mUpperIndex;
         // Population of colors within this box
         private int mPopulation;
@@ -373,7 +361,7 @@
             modifySignificantOctet(colors, longestDimension, mLowerIndex, mUpperIndex);
 
             final int midPoint = mPopulation / 2;
-            for (int i = mLowerIndex, count = 0; i <= mUpperIndex; i++)  {
+            for (int i = mLowerIndex, count = 0; i <= mUpperIndex; i++) {
                 count += hist[colors[i]];
                 if (count >= midPoint) {
                     // we never want to split on the upperIndex, as this will result in the same
@@ -447,27 +435,6 @@
         }
     }
 
-    private boolean shouldIgnoreColor(int color565) {
-        final int rgb = approximateToRgb888(color565);
-        ColorUtils.colorToHSL(rgb, mTempHsl);
-        return shouldIgnoreColor(rgb, mTempHsl);
-    }
-
-    private boolean shouldIgnoreColor(Swatch color) {
-        return shouldIgnoreColor(color.getRgb(), color.getHsl());
-    }
-
-    private boolean shouldIgnoreColor(int rgb, float[] hsl) {
-        if (mFilters != null && mFilters.length > 0) {
-            for (int i = 0, count = mFilters.length; i < count; i++) {
-                if (!mFilters[i].isAllowed(rgb, hsl)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
     /**
      * Comparator which sorts {@link Vbox} instances based on their volume, in descending order
      */
@@ -498,7 +465,8 @@
     }
 
     private static int approximateToRgb888(int color) {
-        return approximateToRgb888(quantizedRed(color), quantizedGreen(color), quantizedBlue(color));
+        return approximateToRgb888(quantizedRed(color), quantizedGreen(color),
+                quantizedBlue(color));
     }
 
     /**
diff --git a/core/java/com/android/internal/graphics/palette/Contrast.java b/core/java/com/android/internal/graphics/palette/Contrast.java
new file mode 100644
index 0000000..3dd1b8d
--- /dev/null
+++ b/core/java/com/android/internal/graphics/palette/Contrast.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.graphics.palette;
+
+/**
+ * Helper methods for determining contrast between two colors, either via the colors themselves
+ * or components in different color spaces.
+ */
+public class Contrast {
+    /**
+     *
+     * @param y Y in XYZ that contrasts with the returned Y value
+     * @param contrast contrast ratio between color argument and returned Y value. Must be >= 1
+     *    or an exception will be thrown
+     * @return the lower Y coordinate in XYZ space that contrasts with color, or -1 if reaching
+     *    no Y coordinate reaches contrast with color.
+     */
+    public static float lighterY(float y, float contrast) {
+        assert (contrast >= 1);
+        float answer = -5 + contrast * (5 + y);
+        if (answer > 100.0) {
+            return -1;
+        }
+        return answer;
+    }
+
+
+    /**
+     * @param y Y in XYZ that contrasts with the returned Y value
+     * @param contrast contrast ratio between color argument and returned Y value. Must be >= 1
+     *    or an exception will be thrown
+     * @return the lower Y coordinate in XYZ space that contrasts with color, or -1 if reaching
+     *    no Y coordinate reaches contrast with color.
+     */
+    public static float darkerY(float y, float contrast) {
+        assert (contrast >= 1);
+        float answer = (5 - 5 * contrast + y) / contrast;
+        if (answer < 0.0) {
+            return -1;
+        }
+        return answer;
+    }
+
+    /**
+     * Convert L* in L*a*b* to Y in XYZ.
+     *
+     * @param lstar L* in L*a*b*
+     * @return Y in XYZ
+     */
+    public static float lstarToY(float lstar) {
+        // http://www.brucelindbloom.com/index.html?Eqn_Lab_to_XYZ.html
+        float ke = 8.0f;
+        if (lstar > ke) {
+            return (float) (Math.pow(((lstar + 16.0) / 116.0), 3) * 100.0);
+        } else {
+            return (float) (lstar / (24389 / 27) * 100.0);
+        }
+    }
+
+    /**
+     * Convert Y in XYZ to L* in L*a*b*.
+     *
+     * @param y Y in XYZ
+     * @return L* in L*a*b*
+     */
+    public static float yToLstar(float y) {
+        y = y / 100.0f;
+        float e = 216.0f / 24389.0f;
+        float y_intermediate;
+        if (y <= e) {
+            y_intermediate = (24389.f / 27.f) * y;
+            // If y < e, can skip consecutive steps of / 116 + 16 followed by * 116 - 16.
+            return y_intermediate;
+        } else {
+            y_intermediate = (float) Math.cbrt(y);
+        }
+        return 116.f * y_intermediate - 16.f;
+    }
+
+
+    /**
+     * @return Contrast ratio between two Y values in XYZ space.
+     */
+    public static float contrastYs(float y1, float y2) {
+        final float lighter = Math.max(y1, y2);
+        final float darker = (lighter == y1) ? y2 : y1;
+        return (lighter + 5) / (darker + 5);
+    }
+}
diff --git a/core/java/com/android/internal/graphics/palette/LABCentroid.java b/core/java/com/android/internal/graphics/palette/LABCentroid.java
new file mode 100644
index 0000000..98d5d26
--- /dev/null
+++ b/core/java/com/android/internal/graphics/palette/LABCentroid.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.graphics.palette;
+
+import android.graphics.Color;
+import android.graphics.ColorSpace;
+
+/**
+ *  Allows quantizers to operate in the L*a*b* colorspace.
+ *  L*a*b* is a good choice for measuring distance between colors.
+ *  Better spaces, and better distance calculations even in L*a*b* exist, but measuring distance
+ *  in L*a*b* space, also known as deltaE, is a universally accepted standard across industries
+ *  and worldwide.
+ */
+public class LABCentroid implements CentroidProvider {
+    final ColorSpace.Connector mRgbToLab;
+    final ColorSpace.Connector mLabToRgb;
+
+    public LABCentroid() {
+        mRgbToLab = ColorSpace.connect(
+                ColorSpace.get(ColorSpace.Named.SRGB),
+                ColorSpace.get(ColorSpace.Named.CIE_LAB));
+        mLabToRgb = ColorSpace.connect(ColorSpace.get(ColorSpace.Named.CIE_LAB),
+                ColorSpace.get(ColorSpace.Named.SRGB));
+    }
+
+    @Override
+    public float[] getCentroid(int color) {
+        float r = Color.red(color) / 255.f;
+        float g =  Color.green(color) / 255.f;
+        float b = Color.blue(color) / 255.f;
+
+        float[] transform = mRgbToLab.transform(r, g, b);
+        return transform;
+    }
+
+    @Override
+    public int getColor(float[] centroid) {
+        float[] rgb = mLabToRgb.transform(centroid);
+        int color = Color.rgb(rgb[0], rgb[1], rgb[2]);
+        return color;
+    }
+
+    @Override
+    public float distance(float[] a, float[] b) {
+        // Standard v1 CIELAB deltaE formula, 1976 - easily improved upon, however,
+        // improvements do not significantly impact the Palette algorithm's results.
+        double dL = a[0] - b[0];
+        double dA = a[1] - b[1];
+        double dB = a[2] - b[2];
+        return (float) (Math.pow(dL, 2) + Math.pow(dA, 2) + Math.pow(dB, 2));
+    }
+}
diff --git a/core/java/com/android/internal/graphics/palette/Mean.java b/core/java/com/android/internal/graphics/palette/Mean.java
new file mode 100644
index 0000000..894f91b
--- /dev/null
+++ b/core/java/com/android/internal/graphics/palette/Mean.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.graphics.palette;
+
+import java.util.Random;
+
+/**
+ * Represents a centroid in Kmeans algorithms.
+ */
+public class Mean {
+    private static final Random RANDOM = new Random(0);
+
+    public float[] center;
+
+    /**
+     * Constructor.
+     *
+     * @param upperBound maximum value of a dimension in the space Kmeans is optimizing in
+     */
+    Mean(int upperBound) {
+        center =
+                new float[]{
+                        RANDOM.nextInt(upperBound + 1), RANDOM.nextInt(upperBound + 1),
+                        RANDOM.nextInt(upperBound + 1)
+                };
+    }
+
+    Mean(float[] center) {
+        this.center = center;
+    }
+}
diff --git a/core/java/com/android/internal/graphics/palette/MeanBucket.java b/core/java/com/android/internal/graphics/palette/MeanBucket.java
new file mode 100644
index 0000000..ae8858a
--- /dev/null
+++ b/core/java/com/android/internal/graphics/palette/MeanBucket.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.graphics.palette;
+
+import java.util.HashSet;
+import java.util.Set;
+
+class MeanBucket {
+    float[] mTotal = {0.f, 0.f, 0.f};
+    int mCount = 0;
+    Set<Integer> mColors = new HashSet<>();
+
+    void add(float[] colorAsDoubles, int color, int colorCount) {
+        assert (colorAsDoubles.length == 3);
+        mColors.add(color);
+        mTotal[0] += (colorAsDoubles[0] * colorCount);
+        mTotal[1] += (colorAsDoubles[1] * colorCount);
+        mTotal[2] += (colorAsDoubles[2] * colorCount);
+        mCount += colorCount;
+    }
+
+    float[] getCentroid() {
+        if (mCount == 0) {
+            return null;
+        }
+        return new float[]{mTotal[0] / mCount, mTotal[1] / mCount, mTotal[2] / mCount};
+    }
+}
diff --git a/core/java/com/android/internal/graphics/palette/OWNERS b/core/java/com/android/internal/graphics/palette/OWNERS
new file mode 100644
index 0000000..731dca9
--- /dev/null
+++ b/core/java/com/android/internal/graphics/palette/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 484670

+dupin@google.com

+jamesoleary@google.com
\ No newline at end of file
diff --git a/core/java/com/android/internal/graphics/palette/Palette.java b/core/java/com/android/internal/graphics/palette/Palette.java
index a4f9a59..8b1137d 100644
--- a/core/java/com/android/internal/graphics/palette/Palette.java
+++ b/core/java/com/android/internal/graphics/palette/Palette.java
@@ -19,48 +19,24 @@
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.Px;
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.graphics.Rect;
-import android.os.AsyncTask;
-import android.util.ArrayMap;
 import android.util.Log;
-import android.util.SparseBooleanArray;
-import android.util.TimingLogger;
 
-import com.android.internal.graphics.ColorUtils;
-
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 
 
 /**
- * Copied from: /frameworks/support/v7/palette/src/main/java/android/support/v7/
- * graphics/Palette.java
- *
  * A helper class to extract prominent colors from an image.
- * <p>
- * A number of colors with different profiles are extracted from the image:
- * <ul>
- *     <li>Vibrant</li>
- *     <li>Vibrant Dark</li>
- *     <li>Vibrant Light</li>
- *     <li>Muted</li>
- *     <li>Muted Dark</li>
- *     <li>Muted Light</li>
- * </ul>
- * These can be retrieved from the appropriate getter method.
  *
- * <p>
- * Instances are created with a {@link Palette.Builder} which supports several options to tweak the
+ * <p>Instances are created with a {@link Builder} which supports several options to tweak the
  * generated Palette. See that class' documentation for more information.
- * <p>
- * Generation should always be completed on a background thread, ideally the one in
- * which you load your image on. {@link Palette.Builder} supports both synchronous and asynchronous
- * generation:
+ *
+ * <p>Generation should always be completed on a background thread, ideally the one in which you
+ * load your image on. {@link Builder} supports both synchronous and asynchronous generation:
  *
  * <pre>
  * // Synchronous
@@ -85,346 +61,59 @@
         /**
          * Called when the {@link Palette} has been generated.
          */
-        void onGenerated(Palette palette);
+        void onGenerated(@Nullable Palette palette);
     }
 
     static final int DEFAULT_RESIZE_BITMAP_AREA = 112 * 112;
     static final int DEFAULT_CALCULATE_NUMBER_COLORS = 16;
-
-    static final float MIN_CONTRAST_TITLE_TEXT = 3.0f;
-    static final float MIN_CONTRAST_BODY_TEXT = 4.5f;
-
     static final String LOG_TAG = "Palette";
-    static final boolean LOG_TIMINGS = false;
 
-    /**
-     * Start generating a {@link Palette} with the returned {@link Palette.Builder} instance.
-     */
-    public static Palette.Builder from(Bitmap bitmap) {
-        return new Palette.Builder(bitmap);
+    /** Start generating a {@link Palette} with the returned {@link Builder} instance. */
+    @NonNull
+    public static Builder from(@NonNull Bitmap bitmap, @NonNull Quantizer quantizer) {
+        return new Builder(bitmap, quantizer);
     }
 
     /**
      * Generate a {@link Palette} from the pre-generated list of {@link Palette.Swatch} swatches.
-     * This is useful for testing, or if you want to resurrect a {@link Palette} instance from a
-     * list of swatches. Will return null if the {@code swatches} is null.
+     * This
+     * is useful for testing, or if you want to resurrect a {@link Palette} instance from a list of
+     * swatches. Will return null if the {@code swatches} is null.
      */
-    public static Palette from(List<Palette.Swatch> swatches) {
-        return new Palette.Builder(swatches).generate();
+    @NonNull
+    public static Palette from(@NonNull List<Swatch> swatches) {
+        return new Builder(swatches).generate();
     }
 
-    /**
-     * @deprecated Use {@link Palette.Builder} to generate the Palette.
-     */
-    @Deprecated
-    public static Palette generate(Bitmap bitmap) {
-        return from(bitmap).generate();
-    }
+    private final List<Swatch> mSwatches;
 
-    /**
-     * @deprecated Use {@link Palette.Builder} to generate the Palette.
-     */
-    @Deprecated
-    public static Palette generate(Bitmap bitmap, int numColors) {
-        return from(bitmap).maximumColorCount(numColors).generate();
-    }
 
-    /**
-     * @deprecated Use {@link Palette.Builder} to generate the Palette.
-     */
-    @Deprecated
-    public static AsyncTask<Bitmap, Void, Palette> generateAsync(
-            Bitmap bitmap, Palette.PaletteAsyncListener listener) {
-        return from(bitmap).generate(listener);
-    }
+    @Nullable
+    private final Swatch mDominantSwatch;
 
-    /**
-     * @deprecated Use {@link Palette.Builder} to generate the Palette.
-     */
-    @Deprecated
-    public static AsyncTask<Bitmap, Void, Palette> generateAsync(
-            final Bitmap bitmap, final int numColors, final Palette.PaletteAsyncListener listener) {
-        return from(bitmap).maximumColorCount(numColors).generate(listener);
-    }
-
-    private final List<Palette.Swatch> mSwatches;
-    private final List<Target> mTargets;
-
-    private final Map<Target, Palette.Swatch> mSelectedSwatches;
-    private final SparseBooleanArray mUsedColors;
-
-    private final Palette.Swatch mDominantSwatch;
-
-    Palette(List<Palette.Swatch> swatches, List<Target> targets) {
+    Palette(List<Swatch> swatches) {
         mSwatches = swatches;
-        mTargets = targets;
-
-        mUsedColors = new SparseBooleanArray();
-        mSelectedSwatches = new ArrayMap<>();
-
         mDominantSwatch = findDominantSwatch();
     }
 
-    /**
-     * Returns all of the swatches which make up the palette.
-     */
+    /** Returns all of the swatches which make up the palette. */
     @NonNull
-    public List<Palette.Swatch> getSwatches() {
+    public List<Swatch> getSwatches() {
         return Collections.unmodifiableList(mSwatches);
     }
 
-    /**
-     * Returns the targets used to generate this palette.
-     */
-    @NonNull
-    public List<Target> getTargets() {
-        return Collections.unmodifiableList(mTargets);
-    }
-
-    /**
-     * Returns the most vibrant swatch in the palette. Might be null.
-     *
-     * @see Target#VIBRANT
-     */
+    /** Returns the swatch with the highest population, or null if there are no swatches. */
     @Nullable
-    public Palette.Swatch getVibrantSwatch() {
-        return getSwatchForTarget(Target.VIBRANT);
-    }
-
-    /**
-     * Returns a light and vibrant swatch from the palette. Might be null.
-     *
-     * @see Target#LIGHT_VIBRANT
-     */
-    @Nullable
-    public Palette.Swatch getLightVibrantSwatch() {
-        return getSwatchForTarget(Target.LIGHT_VIBRANT);
-    }
-
-    /**
-     * Returns a dark and vibrant swatch from the palette. Might be null.
-     *
-     * @see Target#DARK_VIBRANT
-     */
-    @Nullable
-    public Palette.Swatch getDarkVibrantSwatch() {
-        return getSwatchForTarget(Target.DARK_VIBRANT);
-    }
-
-    /**
-     * Returns a muted swatch from the palette. Might be null.
-     *
-     * @see Target#MUTED
-     */
-    @Nullable
-    public Palette.Swatch getMutedSwatch() {
-        return getSwatchForTarget(Target.MUTED);
-    }
-
-    /**
-     * Returns a muted and light swatch from the palette. Might be null.
-     *
-     * @see Target#LIGHT_MUTED
-     */
-    @Nullable
-    public Palette.Swatch getLightMutedSwatch() {
-        return getSwatchForTarget(Target.LIGHT_MUTED);
-    }
-
-    /**
-     * Returns a muted and dark swatch from the palette. Might be null.
-     *
-     * @see Target#DARK_MUTED
-     */
-    @Nullable
-    public Palette.Swatch getDarkMutedSwatch() {
-        return getSwatchForTarget(Target.DARK_MUTED);
-    }
-
-    /**
-     * Returns the most vibrant color in the palette as an RGB packed int.
-     *
-     * @param defaultColor value to return if the swatch isn't available
-     * @see #getVibrantSwatch()
-     */
-    @ColorInt
-    public int getVibrantColor(@ColorInt final int defaultColor) {
-        return getColorForTarget(Target.VIBRANT, defaultColor);
-    }
-
-    /**
-     * Returns a light and vibrant color from the palette as an RGB packed int.
-     *
-     * @param defaultColor value to return if the swatch isn't available
-     * @see #getLightVibrantSwatch()
-     */
-    @ColorInt
-    public int getLightVibrantColor(@ColorInt final int defaultColor) {
-        return getColorForTarget(Target.LIGHT_VIBRANT, defaultColor);
-    }
-
-    /**
-     * Returns a dark and vibrant color from the palette as an RGB packed int.
-     *
-     * @param defaultColor value to return if the swatch isn't available
-     * @see #getDarkVibrantSwatch()
-     */
-    @ColorInt
-    public int getDarkVibrantColor(@ColorInt final int defaultColor) {
-        return getColorForTarget(Target.DARK_VIBRANT, defaultColor);
-    }
-
-    /**
-     * Returns a muted color from the palette as an RGB packed int.
-     *
-     * @param defaultColor value to return if the swatch isn't available
-     * @see #getMutedSwatch()
-     */
-    @ColorInt
-    public int getMutedColor(@ColorInt final int defaultColor) {
-        return getColorForTarget(Target.MUTED, defaultColor);
-    }
-
-    /**
-     * Returns a muted and light color from the palette as an RGB packed int.
-     *
-     * @param defaultColor value to return if the swatch isn't available
-     * @see #getLightMutedSwatch()
-     */
-    @ColorInt
-    public int getLightMutedColor(@ColorInt final int defaultColor) {
-        return getColorForTarget(Target.LIGHT_MUTED, defaultColor);
-    }
-
-    /**
-     * Returns a muted and dark color from the palette as an RGB packed int.
-     *
-     * @param defaultColor value to return if the swatch isn't available
-     * @see #getDarkMutedSwatch()
-     */
-    @ColorInt
-    public int getDarkMutedColor(@ColorInt final int defaultColor) {
-        return getColorForTarget(Target.DARK_MUTED, defaultColor);
-    }
-
-    /**
-     * Returns the selected swatch for the given target from the palette, or {@code null} if one
-     * could not be found.
-     */
-    @Nullable
-    public Palette.Swatch getSwatchForTarget(@NonNull final Target target) {
-        return mSelectedSwatches.get(target);
-    }
-
-    /**
-     * Returns the selected color for the given target from the palette as an RGB packed int.
-     *
-     * @param defaultColor value to return if the swatch isn't available
-     */
-    @ColorInt
-    public int getColorForTarget(@NonNull final Target target, @ColorInt final int defaultColor) {
-        Palette.Swatch swatch = getSwatchForTarget(target);
-        return swatch != null ? swatch.getRgb() : defaultColor;
-    }
-
-    /**
-     * Returns the dominant swatch from the palette.
-     *
-     * <p>The dominant swatch is defined as the swatch with the greatest population (frequency)
-     * within the palette.</p>
-     */
-    @Nullable
-    public Palette.Swatch getDominantSwatch() {
+    public Swatch getDominantSwatch() {
         return mDominantSwatch;
     }
 
-    /**
-     * Returns the color of the dominant swatch from the palette, as an RGB packed int.
-     *
-     * @param defaultColor value to return if the swatch isn't available
-     * @see #getDominantSwatch()
-     */
-    @ColorInt
-    public int getDominantColor(@ColorInt int defaultColor) {
-        return mDominantSwatch != null ? mDominantSwatch.getRgb() : defaultColor;
-    }
-
-    void generate() {
-        // We need to make sure that the scored targets are generated first. This is so that
-        // inherited targets have something to inherit from
-        for (int i = 0, count = mTargets.size(); i < count; i++) {
-            final Target target = mTargets.get(i);
-            target.normalizeWeights();
-            mSelectedSwatches.put(target, generateScoredTarget(target));
-        }
-        // We now clear out the used colors
-        mUsedColors.clear();
-    }
-
-    private Palette.Swatch generateScoredTarget(final Target target) {
-        final Palette.Swatch maxScoreSwatch = getMaxScoredSwatchForTarget(target);
-        if (maxScoreSwatch != null && target.isExclusive()) {
-            // If we have a swatch, and the target is exclusive, add the color to the used list
-            mUsedColors.append(maxScoreSwatch.getRgb(), true);
-        }
-        return maxScoreSwatch;
-    }
-
-    private Palette.Swatch getMaxScoredSwatchForTarget(final Target target) {
-        float maxScore = 0;
-        Palette.Swatch maxScoreSwatch = null;
-        for (int i = 0, count = mSwatches.size(); i < count; i++) {
-            final Palette.Swatch swatch = mSwatches.get(i);
-            if (shouldBeScoredForTarget(swatch, target)) {
-                final float score = generateScore(swatch, target);
-                if (maxScoreSwatch == null || score > maxScore) {
-                    maxScoreSwatch = swatch;
-                    maxScore = score;
-                }
-            }
-        }
-        return maxScoreSwatch;
-    }
-
-    private boolean shouldBeScoredForTarget(final Palette.Swatch swatch, final Target target) {
-        // Check whether the HSL values are within the correct ranges, and this color hasn't
-        // been used yet.
-        final float hsl[] = swatch.getHsl();
-        return hsl[1] >= target.getMinimumSaturation() && hsl[1] <= target.getMaximumSaturation()
-                && hsl[2] >= target.getMinimumLightness() && hsl[2] <= target.getMaximumLightness()
-                && !mUsedColors.get(swatch.getRgb());
-    }
-
-    private float generateScore(Palette.Swatch swatch, Target target) {
-        final float[] hsl = swatch.getHsl();
-
-        float saturationScore = 0;
-        float luminanceScore = 0;
-        float populationScore = 0;
-
-        final int maxPopulation = mDominantSwatch != null ? mDominantSwatch.getPopulation() : 1;
-
-        if (target.getSaturationWeight() > 0) {
-            saturationScore = target.getSaturationWeight()
-                    * (1f - Math.abs(hsl[1] - target.getTargetSaturation()));
-        }
-        if (target.getLightnessWeight() > 0) {
-            luminanceScore = target.getLightnessWeight()
-                    * (1f - Math.abs(hsl[2] - target.getTargetLightness()));
-        }
-        if (target.getPopulationWeight() > 0) {
-            populationScore = target.getPopulationWeight()
-                    * (swatch.getPopulation() / (float) maxPopulation);
-        }
-
-        return saturationScore + luminanceScore + populationScore;
-    }
-
-    private Palette.Swatch findDominantSwatch() {
+    @Nullable
+    private Swatch findDominantSwatch() {
         int maxPop = Integer.MIN_VALUE;
-        Palette.Swatch maxSwatch = null;
+        Swatch maxSwatch = null;
         for (int i = 0, count = mSwatches.size(); i < count; i++) {
-            Palette.Swatch swatch = mSwatches.get(i);
+            Swatch swatch = mSwatches.get(i);
             if (swatch.getPopulation() > maxPop) {
                 maxSwatch = swatch;
                 maxPop = swatch.getPopulation();
@@ -433,148 +122,42 @@
         return maxSwatch;
     }
 
-    private static float[] copyHslValues(Palette.Swatch color) {
-        final float[] newHsl = new float[3];
-        System.arraycopy(color.getHsl(), 0, newHsl, 0, 3);
-        return newHsl;
-    }
-
     /**
      * Represents a color swatch generated from an image's palette. The RGB color can be retrieved
-     * by calling {@link #getRgb()}.
+     * by
+     * calling {@link #getInt()}.
      */
-    public static final class Swatch {
-        private final int mRed, mGreen, mBlue;
-        private final int mRgb;
+    public static class Swatch {
+        private final Color mColor;
         private final int mPopulation;
 
-        private boolean mGeneratedTextColors;
-        private int mTitleTextColor;
-        private int mBodyTextColor;
 
-        private float[] mHsl;
-
-        public Swatch(@ColorInt int color, int population) {
-            mRed = Color.red(color);
-            mGreen = Color.green(color);
-            mBlue = Color.blue(color);
-            mRgb = color;
+        public Swatch(@ColorInt int colorInt, int population) {
+            mColor = Color.valueOf(colorInt);
             mPopulation = population;
         }
 
-        Swatch(int red, int green, int blue, int population) {
-            mRed = red;
-            mGreen = green;
-            mBlue = blue;
-            mRgb = Color.rgb(red, green, blue);
-            mPopulation = population;
-        }
-
-        Swatch(float[] hsl, int population) {
-            this(ColorUtils.HSLToColor(hsl), population);
-            mHsl = hsl;
-        }
-
-        /**
-         * @return this swatch's RGB color value
-         */
+        /** @return this swatch's RGB color value */
         @ColorInt
-        public int getRgb() {
-            return mRgb;
+        public int getInt() {
+            return mColor.toArgb();
         }
 
-        /**
-         * Return this swatch's HSL values.
-         *     hsv[0] is Hue [0 .. 360)
-         *     hsv[1] is Saturation [0...1]
-         *     hsv[2] is Lightness [0...1]
-         */
-        public float[] getHsl() {
-            if (mHsl == null) {
-                mHsl = new float[3];
-            }
-            ColorUtils.RGBToHSL(mRed, mGreen, mBlue, mHsl);
-            return mHsl;
-        }
-
-        /**
-         * @return the number of pixels represented by this swatch
-         */
+        /** @return the number of pixels represented by this swatch */
         public int getPopulation() {
             return mPopulation;
         }
 
-        /**
-         * Returns an appropriate color to use for any 'title' text which is displayed over this
-         * {@link Palette.Swatch}'s color. This color is guaranteed to have sufficient contrast.
-         */
-        @ColorInt
-        public int getTitleTextColor() {
-            ensureTextColorsGenerated();
-            return mTitleTextColor;
-        }
-
-        /**
-         * Returns an appropriate color to use for any 'body' text which is displayed over this
-         * {@link Palette.Swatch}'s color. This color is guaranteed to have sufficient contrast.
-         */
-        @ColorInt
-        public int getBodyTextColor() {
-            ensureTextColorsGenerated();
-            return mBodyTextColor;
-        }
-
-        private void ensureTextColorsGenerated() {
-            if (!mGeneratedTextColors) {
-                // First check white, as most colors will be dark
-                final int lightBodyAlpha = ColorUtils.calculateMinimumAlpha(
-                        Color.WHITE, mRgb, MIN_CONTRAST_BODY_TEXT);
-                final int lightTitleAlpha = ColorUtils.calculateMinimumAlpha(
-                        Color.WHITE, mRgb, MIN_CONTRAST_TITLE_TEXT);
-
-                if (lightBodyAlpha != -1 && lightTitleAlpha != -1) {
-                    // If we found valid light values, use them and return
-                    mBodyTextColor = ColorUtils.setAlphaComponent(Color.WHITE, lightBodyAlpha);
-                    mTitleTextColor = ColorUtils.setAlphaComponent(Color.WHITE, lightTitleAlpha);
-                    mGeneratedTextColors = true;
-                    return;
-                }
-
-                final int darkBodyAlpha = ColorUtils.calculateMinimumAlpha(
-                        Color.BLACK, mRgb, MIN_CONTRAST_BODY_TEXT);
-                final int darkTitleAlpha = ColorUtils.calculateMinimumAlpha(
-                        Color.BLACK, mRgb, MIN_CONTRAST_TITLE_TEXT);
-
-                if (darkBodyAlpha != -1 && darkTitleAlpha != -1) {
-                    // If we found valid dark values, use them and return
-                    mBodyTextColor = ColorUtils.setAlphaComponent(Color.BLACK, darkBodyAlpha);
-                    mTitleTextColor = ColorUtils.setAlphaComponent(Color.BLACK, darkTitleAlpha);
-                    mGeneratedTextColors = true;
-                    return;
-                }
-
-                // If we reach here then we can not find title and body values which use the same
-                // lightness, we need to use mismatched values
-                mBodyTextColor = lightBodyAlpha != -1
-                        ? ColorUtils.setAlphaComponent(Color.WHITE, lightBodyAlpha)
-                        : ColorUtils.setAlphaComponent(Color.BLACK, darkBodyAlpha);
-                mTitleTextColor = lightTitleAlpha != -1
-                        ? ColorUtils.setAlphaComponent(Color.WHITE, lightTitleAlpha)
-                        : ColorUtils.setAlphaComponent(Color.BLACK, darkTitleAlpha);
-                mGeneratedTextColors = true;
-            }
-        }
-
         @Override
         public String toString() {
             return new StringBuilder(getClass().getSimpleName())
-                    .append(" [RGB: #").append(Integer.toHexString(getRgb())).append(']')
-                    .append(" [HSL: ").append(Arrays.toString(getHsl())).append(']')
-                    .append(" [Population: ").append(mPopulation).append(']')
-                    .append(" [Title Text: #").append(Integer.toHexString(getTitleTextColor()))
+                    .append(" [")
+                    .append(mColor)
                     .append(']')
-                    .append(" [Body Text: #").append(Integer.toHexString(getBodyTextColor()))
-                    .append(']').toString();
+                    .append(" [Population: ")
+                    .append(mPopulation)
+                    .append(']')
+                    .toString();
         }
 
         @Override
@@ -586,243 +169,168 @@
                 return false;
             }
 
-            Palette.Swatch
-                    swatch = (Palette.Swatch) o;
-            return mPopulation == swatch.mPopulation && mRgb == swatch.mRgb;
+            Swatch swatch = (Swatch) o;
+            return mPopulation == swatch.mPopulation && mColor.toArgb() == swatch.mColor.toArgb();
         }
 
         @Override
         public int hashCode() {
-            return 31 * mRgb + mPopulation;
+            return 31 * mColor.toArgb() + mPopulation;
         }
     }
 
-    /**
-     * Builder class for generating {@link Palette} instances.
-     */
-    public static final class Builder {
-        private final List<Palette.Swatch> mSwatches;
+    /** Builder class for generating {@link Palette} instances. */
+    public static class Builder {
+        @Nullable
+        private final List<Swatch> mSwatches;
+        @Nullable
         private final Bitmap mBitmap;
+        @Nullable
+        private Quantizer mQuantizer = new ColorCutQuantizer();
 
-        private final List<Target> mTargets = new ArrayList<>();
 
         private int mMaxColors = DEFAULT_CALCULATE_NUMBER_COLORS;
         private int mResizeArea = DEFAULT_RESIZE_BITMAP_AREA;
         private int mResizeMaxDimension = -1;
 
-        private final List<Palette.Filter> mFilters = new ArrayList<>();
+        @Nullable
         private Rect mRegion;
 
-        private Quantizer mQuantizer;
-
-        /**
-         * Construct a new {@link Palette.Builder} using a source {@link Bitmap}
-         */
-        public Builder(Bitmap bitmap) {
+        /** Construct a new {@link Builder} using a source {@link Bitmap} */
+        public Builder(@NonNull Bitmap bitmap, @NonNull Quantizer quantizer) {
             if (bitmap == null || bitmap.isRecycled()) {
                 throw new IllegalArgumentException("Bitmap is not valid");
             }
-            mFilters.add(DEFAULT_FILTER);
-            mBitmap = bitmap;
             mSwatches = null;
-
-            // Add the default targets
-            mTargets.add(Target.LIGHT_VIBRANT);
-            mTargets.add(Target.VIBRANT);
-            mTargets.add(Target.DARK_VIBRANT);
-            mTargets.add(Target.LIGHT_MUTED);
-            mTargets.add(Target.MUTED);
-            mTargets.add(Target.DARK_MUTED);
+            mBitmap = bitmap;
+            mQuantizer = quantizer == null ? new ColorCutQuantizer() : quantizer;
         }
 
         /**
-         * Construct a new {@link Palette.Builder} using a list of {@link Palette.Swatch} instances.
-         * Typically only used for testing.
+         * Construct a new {@link Builder} using a list of {@link Swatch} instances. Typically only
+         * used
+         * for testing.
          */
-        public Builder(List<Palette.Swatch> swatches) {
+        public Builder(@NonNull List<Swatch> swatches) {
             if (swatches == null || swatches.isEmpty()) {
                 throw new IllegalArgumentException("List of Swatches is not valid");
             }
-            mFilters.add(DEFAULT_FILTER);
             mSwatches = swatches;
             mBitmap = null;
+            mQuantizer = null;
         }
 
         /**
-         * Set the maximum number of colors to use in the quantization step when using a
-         * {@link android.graphics.Bitmap} as the source.
-         * <p>
-         * Good values for depend on the source image type. For landscapes, good values are in
-         * the range 10-16. For images which are largely made up of people's faces then this
-         * value should be increased to ~24.
+         * Set the maximum number of colors to use in the quantization step when using a {@link
+         * android.graphics.Bitmap} as the source.
+         *
+         * <p>Good values for depend on the source image type. For landscapes, good values are in
+         * the
+         * range 10-16. For images which are largely made up of people's faces then this value
+         * should be
+         * increased to ~24.
          */
         @NonNull
-        public Palette.Builder maximumColorCount(int colors) {
+        public Builder maximumColorCount(int colors) {
             mMaxColors = colors;
             return this;
         }
 
         /**
-         * Set the resize value when using a {@link android.graphics.Bitmap} as the source.
-         * If the bitmap's largest dimension is greater than the value specified, then the bitmap
-         * will be resized so that its largest dimension matches {@code maxDimension}. If the
-         * bitmap is smaller or equal, the original is used as-is.
-         *
-         * @deprecated Using {@link #resizeBitmapArea(int)} is preferred since it can handle
-         * abnormal aspect ratios more gracefully.
+         * Set the resize value when using a {@link android.graphics.Bitmap} as the source. If the
+         * bitmap's largest dimension is greater than the value specified, then the bitmap will be
+         * resized so that its largest dimension matches {@code maxDimension}. If the bitmap is
+         * smaller
+         * or equal, the original is used as-is.
          *
          * @param maxDimension the number of pixels that the max dimension should be scaled down to,
-         *                     or any value <= 0 to disable resizing.
+         *                     or
+         *                     any value <= 0 to disable resizing.
+         * @deprecated Using {@link #resizeBitmapArea(int)} is preferred since it can handle
+         * abnormal
+         * aspect ratios more gracefully.
          */
         @NonNull
         @Deprecated
-        public Palette.Builder resizeBitmapSize(final int maxDimension) {
+        public Builder resizeBitmapSize(int maxDimension) {
             mResizeMaxDimension = maxDimension;
             mResizeArea = -1;
             return this;
         }
 
         /**
-         * Set the resize value when using a {@link android.graphics.Bitmap} as the source.
-         * If the bitmap's area is greater than the value specified, then the bitmap
-         * will be resized so that its area matches {@code area}. If the
-         * bitmap is smaller or equal, the original is used as-is.
-         * <p>
-         * This value has a large effect on the processing time. The larger the resized image is,
-         * the greater time it will take to generate the palette. The smaller the image is, the
-         * more detail is lost in the resulting image and thus less precision for color selection.
+         * Set the resize value when using a {@link android.graphics.Bitmap} as the source. If the
+         * bitmap's area is greater than the value specified, then the bitmap will be resized so
+         * that
+         * its area matches {@code area}. If the bitmap is smaller or equal, the original is used
+         * as-is.
+         *
+         * <p>This value has a large effect on the processing time. The larger the resized image is,
+         * the
+         * greater time it will take to generate the palette. The smaller the image is, the more
+         * detail
+         * is lost in the resulting image and thus less precision for color selection.
          *
          * @param area the number of pixels that the intermediary scaled down Bitmap should cover,
-         *             or any value <= 0 to disable resizing.
+         *             or
+         *             any value <= 0 to disable resizing.
          */
         @NonNull
-        public Palette.Builder resizeBitmapArea(final int area) {
+        public Builder resizeBitmapArea(int area) {
             mResizeArea = area;
             mResizeMaxDimension = -1;
             return this;
         }
 
         /**
-         * Clear all added filters. This includes any default filters added automatically by
-         * {@link Palette}.
-         */
-        @NonNull
-        public Palette.Builder clearFilters() {
-            mFilters.clear();
-            return this;
-        }
-
-        /**
-         * Add a filter to be able to have fine grained control over which colors are
-         * allowed in the resulting palette.
-         *
-         * @param filter filter to add.
-         */
-        @NonNull
-        public Palette.Builder addFilter(
-                Palette.Filter filter) {
-            if (filter != null) {
-                mFilters.add(filter);
-            }
-            return this;
-        }
-
-        /**
-         * Set a specific quantization algorithm. {@link ColorCutQuantizer} will
-         * be used if unspecified.
-         *
-         * @param quantizer Quantizer implementation.
-         */
-        @NonNull
-        public Palette.Builder setQuantizer(Quantizer quantizer) {
-            mQuantizer = quantizer;
-            return this;
-        }
-
-        /**
          * Set a region of the bitmap to be used exclusively when calculating the palette.
-         * <p>This only works when the original input is a {@link Bitmap}.</p>
          *
-         * @param left The left side of the rectangle used for the region.
-         * @param top The top of the rectangle used for the region.
-         * @param right The right side of the rectangle used for the region.
+         * <p>This only works when the original input is a {@link Bitmap}.
+         *
+         * @param left   The left side of the rectangle used for the region.
+         * @param top    The top of the rectangle used for the region.
+         * @param right  The right side of the rectangle used for the region.
          * @param bottom The bottom of the rectangle used for the region.
          */
         @NonNull
-        public Palette.Builder setRegion(int left, int top, int right, int bottom) {
+        public Builder setRegion(@Px int left, @Px int top, @Px int right, @Px int bottom) {
             if (mBitmap != null) {
                 if (mRegion == null) mRegion = new Rect();
                 // Set the Rect to be initially the whole Bitmap
                 mRegion.set(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
                 // Now just get the intersection with the region
                 if (!mRegion.intersect(left, top, right, bottom)) {
-                    throw new IllegalArgumentException("The given region must intersect with "
-                            + "the Bitmap's dimensions.");
+                    throw new IllegalArgumentException(
+                            "The given region must intersect with " + "the Bitmap's dimensions.");
                 }
             }
             return this;
         }
 
-        /**
-         * Clear any previously region set via {@link #setRegion(int, int, int, int)}.
-         */
+        /** Clear any previously region set via {@link #setRegion(int, int, int, int)}. */
         @NonNull
-        public Palette.Builder clearRegion() {
+        public Builder clearRegion() {
             mRegion = null;
             return this;
         }
 
-        /**
-         * Add a target profile to be generated in the palette.
-         *
-         * <p>You can retrieve the result via {@link Palette#getSwatchForTarget(Target)}.</p>
-         */
-        @NonNull
-        public Palette.Builder addTarget(@NonNull final Target target) {
-            if (!mTargets.contains(target)) {
-                mTargets.add(target);
-            }
-            return this;
-        }
 
-        /**
-         * Clear all added targets. This includes any default targets added automatically by
-         * {@link Palette}.
-         */
-        @NonNull
-        public Palette.Builder clearTargets() {
-            if (mTargets != null) {
-                mTargets.clear();
-            }
-            return this;
-        }
-
-        /**
-         * Generate and return the {@link Palette} synchronously.
-         */
+        /** Generate and return the {@link Palette} synchronously. */
         @NonNull
         public Palette generate() {
-            final TimingLogger logger = LOG_TIMINGS
-                    ? new TimingLogger(LOG_TAG, "Generation")
-                    : null;
-
-            List<Palette.Swatch> swatches;
+            List<Swatch> swatches;
 
             if (mBitmap != null) {
                 // We have a Bitmap so we need to use quantization to reduce the number of colors
 
                 // First we'll scale down the bitmap if needed
-                final Bitmap bitmap = scaleBitmapDown(mBitmap);
+                Bitmap bitmap = scaleBitmapDown(mBitmap);
 
-                if (logger != null) {
-                    logger.addSplit("Processed Bitmap");
-                }
-
-                final Rect region = mRegion;
+                Rect region = mRegion;
                 if (bitmap != mBitmap && region != null) {
                     // If we have a scaled bitmap and a selected region, we need to scale down the
                     // region to match the new scale
-                    final double scale = bitmap.getWidth() / (double) mBitmap.getWidth();
+                    double scale = bitmap.getWidth() / (double) mBitmap.getWidth();
                     region.left = (int) Math.floor(region.left * scale);
                     region.top = (int) Math.floor(region.top * scale);
                     region.right = Math.min((int) Math.ceil(region.right * scale),
@@ -832,54 +340,47 @@
                 }
 
                 // Now generate a quantizer from the Bitmap
-                if (mQuantizer == null) {
-                    mQuantizer = new ColorCutQuantizer();
-                }
-                mQuantizer.quantize(getPixelsFromBitmap(bitmap),
-                            mMaxColors, mFilters.isEmpty() ? null :
-                            mFilters.toArray(new Palette.Filter[mFilters.size()]));
 
+                mQuantizer.quantize(
+                        getPixelsFromBitmap(bitmap),
+                        mMaxColors);
                 // If created a new bitmap, recycle it
                 if (bitmap != mBitmap) {
                     bitmap.recycle();
                 }
-
                 swatches = mQuantizer.getQuantizedColors();
-
-                if (logger != null) {
-                    logger.addSplit("Color quantization completed");
-                }
-            } else {
+            } else if (mSwatches != null) {
                 // Else we're using the provided swatches
                 swatches = mSwatches;
+            } else {
+                // The constructors enforce either a bitmap or swatches are present.
+                throw new AssertionError();
             }
 
             // Now create a Palette instance
-            final Palette p = new Palette(swatches, mTargets);
+            Palette p = new Palette(swatches);
             // And make it generate itself
-            p.generate();
-
-            if (logger != null) {
-                logger.addSplit("Created Palette");
-                logger.dumpToLog();
-            }
 
             return p;
         }
 
         /**
-         * Generate the {@link Palette} asynchronously. The provided listener's
-         * {@link Palette.PaletteAsyncListener#onGenerated} method will be called with the palette when
-         * generated.
+         * Generate the {@link Palette} asynchronously. The provided listener's {@link
+         * PaletteAsyncListener#onGenerated} method will be called with the palette when generated.
+         *
+         * @deprecated Use the standard <code>java.util.concurrent</code> or <a
+         * href="https://developer.android.com/topic/libraries/architecture/coroutines">Kotlin
+         * concurrency utilities</a> to call {@link #generate()} instead.
          */
         @NonNull
-        public AsyncTask<Bitmap, Void, Palette> generate(final Palette.PaletteAsyncListener listener) {
-            if (listener == null) {
-                throw new IllegalArgumentException("listener can not be null");
-            }
+        @Deprecated
+        public android.os.AsyncTask<Bitmap, Void, Palette> generate(
+                @NonNull PaletteAsyncListener listener) {
+            assert (listener != null);
 
-            return new AsyncTask<Bitmap, Void, Palette>() {
+            return new android.os.AsyncTask<Bitmap, Void, Palette>() {
                 @Override
+                @Nullable
                 protected Palette doInBackground(Bitmap... params) {
                     try {
                         return generate();
@@ -890,16 +391,16 @@
                 }
 
                 @Override
-                protected void onPostExecute(Palette colorExtractor) {
+                protected void onPostExecute(@Nullable Palette colorExtractor) {
                     listener.onGenerated(colorExtractor);
                 }
-            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, mBitmap);
+            }.executeOnExecutor(android.os.AsyncTask.THREAD_POOL_EXECUTOR, mBitmap);
         }
 
         private int[] getPixelsFromBitmap(Bitmap bitmap) {
-            final int bitmapWidth = bitmap.getWidth();
-            final int bitmapHeight = bitmap.getHeight();
-            final int[] pixels = new int[bitmapWidth * bitmapHeight];
+            int bitmapWidth = bitmap.getWidth();
+            int bitmapHeight = bitmap.getHeight();
+            int[] pixels = new int[bitmapWidth * bitmapHeight];
             bitmap.getPixels(pixels, 0, bitmapWidth, 0, 0, bitmapWidth, bitmapHeight);
 
             if (mRegion == null) {
@@ -908,32 +409,34 @@
             } else {
                 // If we do have a region, lets create a subset array containing only the region's
                 // pixels
-                final int regionWidth = mRegion.width();
-                final int regionHeight = mRegion.height();
+                int regionWidth = mRegion.width();
+                int regionHeight = mRegion.height();
                 // pixels contains all of the pixels, so we need to iterate through each row and
                 // copy the regions pixels into a new smaller array
-                final int[] subsetPixels = new int[regionWidth * regionHeight];
+                int[] subsetPixels = new int[regionWidth * regionHeight];
                 for (int row = 0; row < regionHeight; row++) {
-                    System.arraycopy(pixels, ((row + mRegion.top) * bitmapWidth) + mRegion.left,
-                            subsetPixels, row * regionWidth, regionWidth);
+                    System.arraycopy(
+                            pixels,
+                            ((row + mRegion.top) * bitmapWidth) + mRegion.left,
+                            subsetPixels,
+                            row * regionWidth,
+                            regionWidth);
                 }
                 return subsetPixels;
             }
         }
 
-        /**
-         * Scale the bitmap down as needed.
-         */
-        private Bitmap scaleBitmapDown(final Bitmap bitmap) {
+        /** Scale the bitmap down as needed. */
+        private Bitmap scaleBitmapDown(Bitmap bitmap) {
             double scaleRatio = -1;
 
             if (mResizeArea > 0) {
-                final int bitmapArea = bitmap.getWidth() * bitmap.getHeight();
+                int bitmapArea = bitmap.getWidth() * bitmap.getHeight();
                 if (bitmapArea > mResizeArea) {
                     scaleRatio = Math.sqrt(mResizeArea / (double) bitmapArea);
                 }
             } else if (mResizeMaxDimension > 0) {
-                final int maxDimension = Math.max(bitmap.getWidth(), bitmap.getHeight());
+                int maxDimension = Math.max(bitmap.getWidth(), bitmap.getHeight());
                 if (maxDimension > mResizeMaxDimension) {
                     scaleRatio = mResizeMaxDimension / (double) maxDimension;
                 }
@@ -944,11 +447,13 @@
                 return bitmap;
             }
 
-            return Bitmap.createScaledBitmap(bitmap,
+            return Bitmap.createScaledBitmap(
+                    bitmap,
                     (int) Math.ceil(bitmap.getWidth() * scaleRatio),
                     (int) Math.ceil(bitmap.getHeight() * scaleRatio),
                     false);
         }
+
     }
 
     /**
@@ -961,9 +466,7 @@
          *
          * @param rgb the color in RGB888.
          * @param hsl HSL representation of the color.
-         *
          * @return true if the color is allowed, false if not.
-         *
          * @see Palette.Builder#addFilter(Palette.Filter)
          */
         boolean isAllowed(int rgb, float[] hsl);
@@ -1004,3 +507,4 @@
         }
     };
 }
+
diff --git a/core/java/com/android/internal/graphics/palette/Quantizer.java b/core/java/com/android/internal/graphics/palette/Quantizer.java
index db60f2e..a219ea3 100644
--- a/core/java/com/android/internal/graphics/palette/Quantizer.java
+++ b/core/java/com/android/internal/graphics/palette/Quantizer.java
@@ -22,6 +22,15 @@
  * Definition of an algorithm that receives pixels and outputs a list of colors.
  */
 public interface Quantizer {
-    void quantize(final int[] pixels, final int maxColors, final Palette.Filter[] filters);
+    /**
+     * Create colors representative of the colors present in pixels.
+     * @param pixels Set of ARGB representation of a color.
+     * @param maxColors number of colors to generate
+     */
+    void quantize(int[] pixels, int maxColors);
+
+    /**
+     * List of colors generated by previous call to quantize.
+     */
     List<Palette.Swatch> getQuantizedColors();
 }
diff --git a/core/java/com/android/internal/graphics/palette/Target.java b/core/java/com/android/internal/graphics/palette/Target.java
index 0540d80..96e7faa 100644
--- a/core/java/com/android/internal/graphics/palette/Target.java
+++ b/core/java/com/android/internal/graphics/palette/Target.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,368 +16,234 @@
 
 package com.android.internal.graphics.palette;
 
-/*
- * Copyright 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
 
 import android.annotation.FloatRange;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
 
 /**
- * Copied from: frameworks/support/v7/palette/src/main/java/android/support/v7/graphics/Target.java
- *
- * A class which allows custom selection of colors in a {@link Palette}'s generation. Instances
- * can be created via the {@link android.support.v7.graphics.Target.Builder} class.
- *
- * <p>To use the target, use the {@link Palette.Builder#addTarget(Target)} API when building a
- * Palette.</p>
+ * A class which allows custom selection of colors in a {@link Palette}'s generation. Instances can
+ * be created via the {@link Builder} class.
  */
+
 public final class Target {
+    private static final float WEIGHT_CHROMA = 0.5f;
+    private static final float WEIGHT_RELATIVE_LUMINANCE = 0.5f;
+    private static final float WEIGHT_POPULATION = 0.3f;
+    private static final float WEIGHT_HUE = 0.2f;
 
-    private static final float TARGET_DARK_LUMA = 0.26f;
-    private static final float MAX_DARK_LUMA = 0.45f;
+    // Arbitrarily chosen, except max - CAM16 chroma has a ceiling of 130, based on unit testing.
+    private static final float DEFAULT_CHROMA_MIN = 0.f;
+    private static final float DEFAULT_CHROMA_MAX = 130.f;
+    private static final float DEFAULT_CHROMA_TARGET = 30.f;
 
-    private static final float MIN_LIGHT_LUMA = 0.55f;
-    private static final float TARGET_LIGHT_LUMA = 0.74f;
-
-    private static final float MIN_NORMAL_LUMA = 0.3f;
-    private static final float TARGET_NORMAL_LUMA = 0.5f;
-    private static final float MAX_NORMAL_LUMA = 0.7f;
-
-    private static final float TARGET_MUTED_SATURATION = 0.3f;
-    private static final float MAX_MUTED_SATURATION = 0.4f;
-
-    private static final float TARGET_VIBRANT_SATURATION = 1f;
-    private static final float MIN_VIBRANT_SATURATION = 0.35f;
-
-    private static final float WEIGHT_SATURATION = 0.24f;
-    private static final float WEIGHT_LUMA = 0.52f;
-    private static final float WEIGHT_POPULATION = 0.24f;
-
-    static final int INDEX_MIN = 0;
-    static final int INDEX_TARGET = 1;
-    static final int INDEX_MAX = 2;
-
-    static final int INDEX_WEIGHT_SAT = 0;
-    static final int INDEX_WEIGHT_LUMA = 1;
-    static final int INDEX_WEIGHT_POP = 2;
-
-    /**
-     * A target which has the characteristics of a vibrant color which is light in luminance.
-     */
-    public static final Target LIGHT_VIBRANT;
-
-    /**
-     * A target which has the characteristics of a vibrant color which is neither light or dark.
-     */
-    public static final Target VIBRANT;
-
-    /**
-     * A target which has the characteristics of a vibrant color which is dark in luminance.
-     */
-    public static final Target DARK_VIBRANT;
-
-    /**
-     * A target which has the characteristics of a muted color which is light in luminance.
-     */
-    public static final Target LIGHT_MUTED;
-
-    /**
-     * A target which has the characteristics of a muted color which is neither light or dark.
-     */
-    public static final Target MUTED;
-
-    /**
-     * A target which has the characteristics of a muted color which is dark in luminance.
-     */
-    public static final Target DARK_MUTED;
-
-    static {
-        LIGHT_VIBRANT = new Target();
-        setDefaultLightLightnessValues(LIGHT_VIBRANT);
-        setDefaultVibrantSaturationValues(LIGHT_VIBRANT);
-
-        VIBRANT = new Target();
-        setDefaultNormalLightnessValues(VIBRANT);
-        setDefaultVibrantSaturationValues(VIBRANT);
-
-        DARK_VIBRANT = new Target();
-        setDefaultDarkLightnessValues(DARK_VIBRANT);
-        setDefaultVibrantSaturationValues(DARK_VIBRANT);
-
-        LIGHT_MUTED = new Target();
-        setDefaultLightLightnessValues(LIGHT_MUTED);
-        setDefaultMutedSaturationValues(LIGHT_MUTED);
-
-        MUTED = new Target();
-        setDefaultNormalLightnessValues(MUTED);
-        setDefaultMutedSaturationValues(MUTED);
-
-        DARK_MUTED = new Target();
-        setDefaultDarkLightnessValues(DARK_MUTED);
-        setDefaultMutedSaturationValues(DARK_MUTED);
-    }
-
-    final float[] mSaturationTargets = new float[3];
-    final float[] mLightnessTargets = new float[3];
-    final float[] mWeights = new float[3];
-    boolean mIsExclusive = true; // default to true
+    private float mTargetRelativeLuminance = -1.0f;
+    private float mChromaWeight;
+    private float mChromaTarget;
+    private float mChromaMin;
+    private float mChromaMax;
+    private float mRelativeLuminanceWeight;
+    private float mPopulationWeight;
+    private float mHueWeight;
+    private float mTargetHue;
 
     Target() {
-        setTargetDefaultValues(mSaturationTargets);
-        setTargetDefaultValues(mLightnessTargets);
-        setDefaultWeights();
+        mChromaMax = DEFAULT_CHROMA_MAX;
+        mChromaMin = DEFAULT_CHROMA_MIN;
+        mChromaTarget = DEFAULT_CHROMA_TARGET;
+        mChromaWeight =   WEIGHT_CHROMA;
+        mRelativeLuminanceWeight = WEIGHT_RELATIVE_LUMINANCE;
+        mPopulationWeight = WEIGHT_POPULATION;
+        mHueWeight = WEIGHT_HUE;
     }
 
-    Target(Target from) {
-        System.arraycopy(from.mSaturationTargets, 0, mSaturationTargets, 0,
-                mSaturationTargets.length);
-        System.arraycopy(from.mLightnessTargets, 0, mLightnessTargets, 0,
-                mLightnessTargets.length);
-        System.arraycopy(from.mWeights, 0, mWeights, 0, mWeights.length);
+    Target(@NonNull Target from) {
+        mTargetRelativeLuminance = from.mTargetRelativeLuminance;
+        mChromaWeight = from.mChromaWeight;
+        mRelativeLuminanceWeight = from.mRelativeLuminanceWeight;
+        mPopulationWeight = from.mPopulationWeight;
+        mHueWeight = from.mHueWeight;
+        mChromaTarget = from.mChromaTarget;
+        mChromaMin = from.mChromaMin;
+        mChromaMax = from.mChromaMax;
+    }
+
+    /** The relative luminance value for this target. */
+    @FloatRange(from = 0, to = 100)
+    public float getTargetRelativeLuminance() {
+        return mTargetRelativeLuminance;
+    }
+
+    /** The relative luminance value for this target. */
+    @FloatRange(from = 0, to = 100)
+    public float getTargetPerceptualLuminance() {
+        return Contrast.yToLstar(mTargetRelativeLuminance);
+    }
+
+    /** The minimum chroma value for this target. */
+    @FloatRange(from = 0, to = 100)
+    public float getMinimumChroma() {
+        return mChromaMin;
+    }
+
+    /** The target chroma value for this target. */
+    @FloatRange(from = 0, to = 100)
+    public float getTargetChroma() {
+        return mChromaTarget;
+    }
+
+    /** The maximum chroma value for this target. */
+    @FloatRange(from = 0, to = 130)
+    public float getMaximumChroma() {
+        return mChromaMax;
+    }
+
+    /** The target hue value for this target. */
+    @FloatRange(from = 0, to = 100)
+    public float getTargetHue() {
+        return mTargetHue;
     }
 
     /**
-     * The minimum saturation value for this target.
-     */
-    @FloatRange(from = 0, to = 1)
-    public float getMinimumSaturation() {
-        return mSaturationTargets[INDEX_MIN];
-    }
-
-    /**
-     * The target saturation value for this target.
-     */
-    @FloatRange(from = 0, to = 1)
-    public float getTargetSaturation() {
-        return mSaturationTargets[INDEX_TARGET];
-    }
-
-    /**
-     * The maximum saturation value for this target.
-     */
-    @FloatRange(from = 0, to = 1)
-    public float getMaximumSaturation() {
-        return mSaturationTargets[INDEX_MAX];
-    }
-
-    /**
-     * The minimum lightness value for this target.
-     */
-    @FloatRange(from = 0, to = 1)
-    public float getMinimumLightness() {
-        return mLightnessTargets[INDEX_MIN];
-    }
-
-    /**
-     * The target lightness value for this target.
-     */
-    @FloatRange(from = 0, to = 1)
-    public float getTargetLightness() {
-        return mLightnessTargets[INDEX_TARGET];
-    }
-
-    /**
-     * The maximum lightness value for this target.
-     */
-    @FloatRange(from = 0, to = 1)
-    public float getMaximumLightness() {
-        return mLightnessTargets[INDEX_MAX];
-    }
-
-    /**
-     * Returns the weight of importance that this target places on a color's saturation within
-     * the image.
+     * Returns the weight of importance that this target places on a color's chroma within the
+     * image.
      *
      * <p>The larger the weight, relative to the other weights, the more important that a color
-     * being close to the target value has on selection.</p>
+     * being
+     * close to the target value has on selection.
      *
-     * @see #getTargetSaturation()
+     * @see #getTargetChroma()
      */
-    public float getSaturationWeight() {
-        return mWeights[INDEX_WEIGHT_SAT];
+    public float getChromaWeight() {
+        return mChromaWeight;
     }
 
     /**
-     * Returns the weight of importance that this target places on a color's lightness within
-     * the image.
+     * Returns the weight of importance that this target places on a color's lightness within the
+     * image.
      *
      * <p>The larger the weight, relative to the other weights, the more important that a color
-     * being close to the target value has on selection.</p>
+     * being
+     * close to the target value has on selection.
      *
-     * @see #getTargetLightness()
+     * @see #getTargetRelativeLuminance()
      */
     public float getLightnessWeight() {
-        return mWeights[INDEX_WEIGHT_LUMA];
+        return mRelativeLuminanceWeight;
     }
 
     /**
-     * Returns the weight of importance that this target places on a color's population within
-     * the image.
+     * Returns the weight of importance that this target places on a color's population within the
+     * image.
      *
-     * <p>The larger the weight, relative to the other weights, the more important that a
-     * color's population being close to the most populous has on selection.</p>
+     * <p>The larger the weight, relative to the other weights, the more important that a color's
+     * population being close to the most populous has on selection.
      */
     public float getPopulationWeight() {
-        return mWeights[INDEX_WEIGHT_POP];
+        return mPopulationWeight;
     }
 
     /**
-     * Returns whether any color selected for this target is exclusive for this target only.
+     * Returns the weight of importance that this target places on a color's hue.
      *
-     * <p>If false, then the color can be selected for other targets.</p>
+     * <p>The larger the weight, relative to the other weights, the more important that a color's
+     * hue being close to the desired hue has on selection.
      */
-    public boolean isExclusive() {
-        return mIsExclusive;
+    public float getHueWeight() {
+        return mHueWeight;
     }
 
-    private static void setTargetDefaultValues(final float[] values) {
-        values[INDEX_MIN] = 0f;
-        values[INDEX_TARGET] = 0.5f;
-        values[INDEX_MAX] = 1f;
-    }
 
-    private void setDefaultWeights() {
-        mWeights[INDEX_WEIGHT_SAT] = WEIGHT_SATURATION;
-        mWeights[INDEX_WEIGHT_LUMA] = WEIGHT_LUMA;
-        mWeights[INDEX_WEIGHT_POP] = WEIGHT_POPULATION;
-    }
-
-    void normalizeWeights() {
-        float sum = 0;
-        for (int i = 0, z = mWeights.length; i < z; i++) {
-            float weight = mWeights[i];
-            if (weight > 0) {
-                sum += weight;
-            }
-        }
-        if (sum != 0) {
-            for (int i = 0, z = mWeights.length; i < z; i++) {
-                if (mWeights[i] > 0) {
-                    mWeights[i] /= sum;
-                }
-            }
-        }
-    }
-
-    private static void setDefaultDarkLightnessValues(Target target) {
-        target.mLightnessTargets[INDEX_TARGET] = TARGET_DARK_LUMA;
-        target.mLightnessTargets[INDEX_MAX] = MAX_DARK_LUMA;
-    }
-
-    private static void setDefaultNormalLightnessValues(Target target) {
-        target.mLightnessTargets[INDEX_MIN] = MIN_NORMAL_LUMA;
-        target.mLightnessTargets[INDEX_TARGET] = TARGET_NORMAL_LUMA;
-        target.mLightnessTargets[INDEX_MAX] = MAX_NORMAL_LUMA;
-    }
-
-    private static void setDefaultLightLightnessValues(Target target) {
-        target.mLightnessTargets[INDEX_MIN] = MIN_LIGHT_LUMA;
-        target.mLightnessTargets[INDEX_TARGET] = TARGET_LIGHT_LUMA;
-    }
-
-    private static void setDefaultVibrantSaturationValues(Target target) {
-        target.mSaturationTargets[INDEX_MIN] = MIN_VIBRANT_SATURATION;
-        target.mSaturationTargets[INDEX_TARGET] = TARGET_VIBRANT_SATURATION;
-    }
-
-    private static void setDefaultMutedSaturationValues(Target target) {
-        target.mSaturationTargets[INDEX_TARGET] = TARGET_MUTED_SATURATION;
-        target.mSaturationTargets[INDEX_MAX] = MAX_MUTED_SATURATION;
-    }
-
-    /**
-     * Builder class for generating custom {@link Target} instances.
-     */
-    public final static class Builder {
+    /** Builder class for generating custom {@link Target} instances. */
+    public static class Builder {
         private final Target mTarget;
 
-        /**
-         * Create a new {@link Target} builder from scratch.
-         */
+        /** Create a new {@link Target} builder from scratch. */
         public Builder() {
             mTarget = new Target();
         }
 
-        /**
-         * Create a new builder based on an existing {@link Target}.
-         */
-        public Builder(Target target) {
+        /** Create a new builder based on an existing {@link Target}. */
+        public Builder(@NonNull Target target) {
             mTarget = new Target(target);
         }
 
-        /**
-         * Set the minimum saturation value for this target.
-         */
-        public Target.Builder setMinimumSaturation(@FloatRange(from = 0, to = 1) float value) {
-            mTarget.mSaturationTargets[INDEX_MIN] = value;
+        /** Set the minimum chroma value for this target. */
+        @NonNull
+        public Builder setMinimumChroma(@FloatRange(from = 0, to = 100) float value) {
+            mTarget.mChromaMin = value;
+            return this;
+        }
+
+        /** Set the target/ideal chroma value for this target. */
+        @NonNull
+        public Builder setTargetChroma(@FloatRange(from = 0, to = 100) float value) {
+            mTarget.mChromaTarget = value;
+            return this;
+        }
+
+        /** Set the maximum chroma value for this target. */
+        @NonNull
+        public Builder setMaximumChroma(@FloatRange(from = 0, to = 100) float value) {
+            mTarget.mChromaMax = value;
+            return this;
+        }
+
+        /** Set the minimum lightness value for this target, using Y in XYZ color space. */
+        @NonNull
+        public Builder setTargetRelativeLuminance(@FloatRange(from = 0, to = 100) float value) {
+            mTarget.mTargetRelativeLuminance = value;
+            return this;
+        }
+
+        /** Set the minimum lightness value for this target, using L* in LAB color space. */
+        @NonNull
+        public Builder setTargetPerceptualLuminance(@FloatRange(from = 0, to = 100) float value) {
+            mTarget.mTargetRelativeLuminance = Contrast.lstarToY(value);
             return this;
         }
 
         /**
-         * Set the target/ideal saturation value for this target.
+         * Set the hue desired from the target. This hue is not enforced, the only consequence
+         * is points will be awarded to seed colors the closer they are to this hue.
          */
-        public Target.Builder setTargetSaturation(@FloatRange(from = 0, to = 1) float value) {
-            mTarget.mSaturationTargets[INDEX_TARGET] = value;
+        @NonNull
+        public Builder setTargetHue(@IntRange(from = 0, to = 360) int hue) {
+            mTarget.mTargetHue = hue;
+            return this;
+        }
+
+        /** Sets lightness value for this target. */
+        @NonNull
+        public Builder setContrastRatio(
+                @FloatRange(from = 1, to = 21) float value,
+                @FloatRange(from = 0, to = 100) float relativeLuminance) {
+            float counterpartY = relativeLuminance;
+            float lstar = Contrast.yToLstar(counterpartY);
+
+            float targetY;
+            if (lstar < 50) {
+                targetY = Contrast.lighterY(counterpartY, value);
+            } else {
+                targetY = Contrast.darkerY(counterpartY, value);
+            }
+            mTarget.mTargetRelativeLuminance = targetY;
             return this;
         }
 
         /**
-         * Set the maximum saturation value for this target.
-         */
-        public Target.Builder setMaximumSaturation(@FloatRange(from = 0, to = 1) float value) {
-            mTarget.mSaturationTargets[INDEX_MAX] = value;
-            return this;
-        }
-
-        /**
-         * Set the minimum lightness value for this target.
-         */
-        public Target.Builder setMinimumLightness(@FloatRange(from = 0, to = 1) float value) {
-            mTarget.mLightnessTargets[INDEX_MIN] = value;
-            return this;
-        }
-
-        /**
-         * Set the target/ideal lightness value for this target.
-         */
-        public Target.Builder setTargetLightness(@FloatRange(from = 0, to = 1) float value) {
-            mTarget.mLightnessTargets[INDEX_TARGET] = value;
-            return this;
-        }
-
-        /**
-         * Set the maximum lightness value for this target.
-         */
-        public Target.Builder setMaximumLightness(@FloatRange(from = 0, to = 1) float value) {
-            mTarget.mLightnessTargets[INDEX_MAX] = value;
-            return this;
-        }
-
-        /**
-         * Set the weight of importance that this target will place on saturation values.
+         * Set the weight of importance that this target will place on chroma values.
          *
          * <p>The larger the weight, relative to the other weights, the more important that a color
-         * being close to the target value has on selection.</p>
+         * being close to the target value has on selection.
          *
-         * <p>A weight of 0 means that it has no weight, and thus has no
-         * bearing on the selection.</p>
+         * <p>A weight of 0 means that it has no weight, and thus has no bearing on the selection.
          *
-         * @see #setTargetSaturation(float)
+         * @see #setTargetChroma(float)
          */
-        public Target.Builder setSaturationWeight(@FloatRange(from = 0) float weight) {
-            mTarget.mWeights[INDEX_WEIGHT_SAT] = weight;
+        @NonNull
+        public Builder setChromaWeight(@FloatRange(from = 0) float weight) {
+            mTarget.mChromaWeight = weight;
             return this;
         }
 
@@ -385,51 +251,40 @@
          * Set the weight of importance that this target will place on lightness values.
          *
          * <p>The larger the weight, relative to the other weights, the more important that a color
-         * being close to the target value has on selection.</p>
+         * being close to the target value has on selection.
          *
-         * <p>A weight of 0 means that it has no weight, and thus has no
-         * bearing on the selection.</p>
+         * <p>A weight of 0 means that it has no weight, and thus has no bearing on the selection.
          *
-         * @see #setTargetLightness(float)
+         * @see #setTargetRelativeLuminance(float)
          */
-        public Target.Builder setLightnessWeight(@FloatRange(from = 0) float weight) {
-            mTarget.mWeights[INDEX_WEIGHT_LUMA] = weight;
+        @NonNull
+        public Builder setLightnessWeight(@FloatRange(from = 0) float weight) {
+            mTarget.mRelativeLuminanceWeight = weight;
             return this;
         }
 
         /**
          * Set the weight of importance that this target will place on a color's population within
-         * the image.
+         * the
+         * image.
          *
          * <p>The larger the weight, relative to the other weights, the more important that a
-         * color's population being close to the most populous has on selection.</p>
+         * color's
+         * population being close to the most populous has on selection.
          *
-         * <p>A weight of 0 means that it has no weight, and thus has no
-         * bearing on the selection.</p>
+         * <p>A weight of 0 means that it has no weight, and thus has no bearing on the selection.
          */
-        public Target.Builder setPopulationWeight(@FloatRange(from = 0) float weight) {
-            mTarget.mWeights[INDEX_WEIGHT_POP] = weight;
+        @NonNull
+        public Builder setPopulationWeight(@FloatRange(from = 0) float weight) {
+            mTarget.mPopulationWeight = weight;
             return this;
         }
 
-        /**
-         * Set whether any color selected for this target is exclusive to this target only.
-         * Defaults to true.
-         *
-         * @param exclusive true if any the color is exclusive to this target, or false is the
-         *                  color can be selected for other targets.
-         */
-        public Target.Builder setExclusive(boolean exclusive) {
-            mTarget.mIsExclusive = exclusive;
-            return this;
-        }
 
-        /**
-         * Builds and returns the resulting {@link Target}.
-         */
+        /** Builds and returns the resulting {@link Target}. */
+        @NonNull
         public Target build() {
             return mTarget;
         }
     }
-
-}
\ No newline at end of file
+}
diff --git a/core/java/com/android/internal/graphics/palette/VariationalKMeansQuantizer.java b/core/java/com/android/internal/graphics/palette/VariationalKMeansQuantizer.java
index b035535..d791f7b 100644
--- a/core/java/com/android/internal/graphics/palette/VariationalKMeansQuantizer.java
+++ b/core/java/com/android/internal/graphics/palette/VariationalKMeansQuantizer.java
@@ -70,10 +70,9 @@
      *
      * @param pixels Pixels to quantize.
      * @param maxColors Maximum number of clusters to extract.
-     * @param filters Colors that should be ignored
      */
     @Override
-    public void quantize(int[] pixels, int maxColors, Palette.Filter[] filters) {
+    public void quantize(int[] pixels, int maxColors) {
         // Start by converting all colors to HSL.
         // HLS is way more meaningful for clustering than RGB.
         final float[] hsl = {0, 0, 0};
@@ -111,16 +110,18 @@
 
         // Convert data to final format, de-normalizing the hue.
         mQuantizedColors = new ArrayList<>();
+        float[] mHsl = new float[3];
         for (KMeans.Mean mean : optimalMeans) {
             if (mean.getItems().size() == 0) {
                 continue;
             }
             float[] centroid = mean.getCentroid();
-            mQuantizedColors.add(new Palette.Swatch(new float[]{
-                    centroid[0] * 360f,
-                    centroid[1],
-                    centroid[2]
-            }, mean.getItems().size()));
+
+            mHsl[0] = centroid[0] * 360f;
+            mHsl[1] = centroid[1];
+            mHsl[2] = centroid[2];
+            int color = ColorUtils.HSLToColor(mHsl);
+            mQuantizedColors.add(new Palette.Swatch(color, mean.getItems().size()));
         }
     }
 
diff --git a/core/java/com/android/internal/graphics/palette/WSMeansQuantizer.java b/core/java/com/android/internal/graphics/palette/WSMeansQuantizer.java
new file mode 100644
index 0000000..a87a34f
--- /dev/null
+++ b/core/java/com/android/internal/graphics/palette/WSMeansQuantizer.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.graphics.palette;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * A color quantizer based on the Kmeans algorithm.
+ *
+ * This is an implementation of Kmeans based on Celebi's 2011 paper,
+ * "Improving the Performance of K-Means for Color Quantization". In the paper, this algorithm is
+ * referred to as "WSMeans", or, "Weighted Square Means" The main advantages of this Kmeans
+ * implementation are taking advantage of triangle properties to avoid distance calculations, as
+ * well as indexing colors by their count, thus minimizing the number of points to move around.
+ *
+ * Celebi's paper also stabilizes results and guarantees high quality by using starting centroids
+ * from Wu's quantization algorithm. See CelebiQuantizer for more info.
+ */
+public class WSMeansQuantizer implements Quantizer {
+    Mean[] mMeans;
+    private final Map<Integer, Integer> mCountByColor = new HashMap<>();
+    private final Map<Integer, Integer> mMeanIndexByColor = new HashMap<>();
+    private final Set<Integer> mUniqueColors = new HashSet<>();
+    private final List<Palette.Swatch> mSwatches = new ArrayList<>();
+    private final CentroidProvider mCentroidProvider;
+
+    public WSMeansQuantizer(
+            float[][] means, CentroidProvider centroidProvider, int[] pixels, int maxColors) {
+        if (pixels == null) {
+            pixels = new int[]{};
+        }
+        mCentroidProvider = centroidProvider;
+        mMeans = new Mean[maxColors];
+        for (int i = 0; i < means.length; i++) {
+            mMeans[i] = new Mean(means[i]);
+        }
+
+        if (maxColors > means.length) {
+            int randomMeansToCreate = maxColors - means.length;
+            for (int i = 0; i < randomMeansToCreate; i++) {
+                mMeans[means.length + i] = new Mean(100);
+            }
+        }
+
+        for (int pixel : pixels) {
+            Integer currentCount = mCountByColor.get(pixel);
+            if (currentCount == null) {
+                currentCount = 0;
+                mUniqueColors.add(pixel);
+            }
+            mCountByColor.put(pixel, currentCount + 1);
+        }
+        for (int color : mUniqueColors) {
+            int closestMeanIndex = -1;
+            double closestMeanDistance = -1;
+            float[] centroid = mCentroidProvider.getCentroid(color);
+            for (int i = 0; i < mMeans.length; i++) {
+                double distance = mCentroidProvider.distance(centroid, mMeans[i].center);
+                if (closestMeanIndex == -1 || distance < closestMeanDistance) {
+                    closestMeanIndex = i;
+                    closestMeanDistance = distance;
+                }
+            }
+            mMeanIndexByColor.put(color, closestMeanIndex);
+        }
+
+        if (pixels.length == 0) {
+            return;
+        }
+
+        predict(maxColors, 0);
+    }
+
+    /** Create starting centroids for K-means from a set of colors. */
+    public static float[][] createStartingCentroids(CentroidProvider centroidProvider,
+            List<Palette.Swatch> swatches) {
+        float[][] startingCentroids = new float[swatches.size()][];
+        for (int i = 0; i < swatches.size(); i++) {
+            startingCentroids[i] = centroidProvider.getCentroid(swatches.get(i).getInt());
+        }
+        return startingCentroids;
+    }
+
+    /** Create random starting centroids for K-means. */
+    public static float[][] randomMeans(int maxColors, int upperBound) {
+        float[][] means = new float[maxColors][];
+        for (int i = 0; i < maxColors; i++) {
+            means[i] = new Mean(upperBound).center;
+        }
+        return means;
+    }
+
+
+    @Override
+    public void quantize(int[] pixels, int maxColors) {
+
+    }
+
+    @Override
+    public List<Palette.Swatch> getQuantizedColors() {
+        return mSwatches;
+    }
+
+    private void predict(int maxColors, int iterationsCompleted) {
+        double[][] centroidDistance = new double[maxColors][maxColors];
+        for (int i = 0; i <= maxColors; i++) {
+            for (int j = i + 1; j < maxColors; j++) {
+                float[] meanI = mMeans[i].center;
+                float[] meanJ = mMeans[j].center;
+                double distance = mCentroidProvider.distance(meanI, meanJ);
+                centroidDistance[i][j] = distance;
+                centroidDistance[j][i] = distance;
+            }
+        }
+
+        // Construct a K×K matrix M in which row i is a permutation of
+        // 1,2,…,K that represents the clusters in increasing order of
+        // distance of their centers from ci;
+        int[][] distanceMatrix = new int[maxColors][maxColors];
+        for (int i = 0; i < maxColors; i++) {
+            double[] distancesFromIToAnotherMean = centroidDistance[i];
+            double[] sortedByDistanceAscending = distancesFromIToAnotherMean.clone();
+            Arrays.sort(sortedByDistanceAscending);
+            int[] outputRow = new int[maxColors];
+            for (int j = 0; j < maxColors; j++) {
+                outputRow[j] = findIndex(distancesFromIToAnotherMean, sortedByDistanceAscending[j]);
+            }
+            distanceMatrix[i] = outputRow;
+        }
+
+        //   for (i=1;i≤N′;i=i+ 1) do
+        //   Let Sp be the cluster that xi was assigned to in the previous
+        //   iteration;
+        //   p=m[i];
+        //   min_dist=prev_dist=jjxi−cpjj2;
+        boolean anyColorMoved = false;
+        for (int intColor : mUniqueColors) {
+            float[] color = mCentroidProvider.getCentroid(intColor);
+            int indexOfCurrentMean = mMeanIndexByColor.get(intColor);
+            Mean currentMean = mMeans[indexOfCurrentMean];
+            double minDistance = mCentroidProvider.distance(color, currentMean.center);
+            for (int j = 1; j < maxColors; j++) {
+                int indexOfClusterFromCurrentToJ = distanceMatrix[indexOfCurrentMean][j];
+                double distanceBetweenJAndCurrent =
+                        centroidDistance[indexOfCurrentMean][indexOfClusterFromCurrentToJ];
+                if (distanceBetweenJAndCurrent >= (4 * minDistance)) {
+                    break;
+                }
+                double distanceBetweenJAndColor = mCentroidProvider.distance(mMeans[j].center,
+                        color);
+                if (distanceBetweenJAndColor < minDistance) {
+                    minDistance = distanceBetweenJAndColor;
+                    mMeanIndexByColor.remove(intColor);
+                    mMeanIndexByColor.put(intColor, j);
+                    anyColorMoved = true;
+                }
+            }
+        }
+
+        List<MeanBucket> buckets = new ArrayList<>();
+        for (int i = 0; i < maxColors; i++) {
+            buckets.add(new MeanBucket());
+        }
+
+        for (int intColor : mUniqueColors) {
+            int meanIndex = mMeanIndexByColor.get(intColor);
+            MeanBucket meanBucket = buckets.get(meanIndex);
+            meanBucket.add(mCentroidProvider.getCentroid(intColor), intColor,
+                    mCountByColor.get(intColor));
+        }
+
+        List<Palette.Swatch> swatches = new ArrayList<>();
+        boolean done = !anyColorMoved && iterationsCompleted > 0 || iterationsCompleted >= 100;
+        if (done) {
+            for (int i = 0; i < buckets.size(); i++) {
+                MeanBucket a = buckets.get(i);
+                if (a.mCount <= 0) {
+                    continue;
+                }
+                List<MeanBucket> bucketsToMerge = new ArrayList<>();
+                for (int j = i + 1; j < buckets.size(); j++) {
+                    MeanBucket b = buckets.get(j);
+                    if (b.mCount == 0) {
+                        continue;
+                    }
+                    float[] bCentroid = b.getCentroid();
+                    assert (a.mCount > 0);
+                    assert (a.getCentroid() != null);
+
+                    assert (bCentroid != null);
+                    if (mCentroidProvider.distance(a.getCentroid(), b.getCentroid()) < 5) {
+                        bucketsToMerge.add(b);
+                    }
+                }
+
+                for (MeanBucket bucketToMerge : bucketsToMerge) {
+                    float[] centroid = bucketToMerge.getCentroid();
+                    a.add(centroid, mCentroidProvider.getColor(centroid), bucketToMerge.mCount);
+                    buckets.remove(bucketToMerge);
+                }
+            }
+
+            for (MeanBucket bucket : buckets) {
+                float[] centroid = bucket.getCentroid();
+                if (centroid == null) {
+                    continue;
+                }
+
+                int rgb = mCentroidProvider.getColor(centroid);
+                swatches.add(new Palette.Swatch(rgb, bucket.mCount));
+                mSwatches.clear();
+                mSwatches.addAll(swatches);
+            }
+        } else {
+            List<MeanBucket> emptyBuckets = new ArrayList<>();
+            for (int i = 0; i < buckets.size(); i++) {
+                MeanBucket bucket = buckets.get(i);
+                if ((bucket.getCentroid() == null) || (bucket.mCount == 0)) {
+                    emptyBuckets.add(bucket);
+                    for (Integer color : mUniqueColors) {
+                        int meanIndex = mMeanIndexByColor.get(color);
+                        if (meanIndex > i) {
+                            mMeanIndexByColor.put(color, meanIndex--);
+                        }
+                    }
+                }
+            }
+
+            Mean[] newMeans = new Mean[buckets.size()];
+            for (int i = 0; i < buckets.size(); i++) {
+                float[] centroid = buckets.get(i).getCentroid();
+                newMeans[i] = new Mean(centroid);
+            }
+
+            predict(buckets.size(), iterationsCompleted + 1);
+        }
+
+    }
+
+    private static int findIndex(double[] list, double element) {
+        for (int i = 0; i < list.length; i++) {
+            if (list[i] == element) {
+                return i;
+            }
+        }
+        throw new IllegalArgumentException("Element not in list");
+    }
+}
diff --git a/core/java/com/android/internal/graphics/palette/WuQuantizer.java b/core/java/com/android/internal/graphics/palette/WuQuantizer.java
new file mode 100644
index 0000000..01e45f6
--- /dev/null
+++ b/core/java/com/android/internal/graphics/palette/WuQuantizer.java
@@ -0,0 +1,442 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.graphics.palette;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+// All reference Wu implementations are based on the original C code by Wu.
+// Comments on methods are the same as in the original implementation, and the comment below
+// is the original class header.
+
+/**
+ * Wu's Color Quantizer (v. 2) (see Graphics Gems vol. II, pp. 126-133) Author: Xiaolin Wu
+ *
+ * <p>Algorithm: Greedy orthogonal bipartition of RGB space for variance minimization aided by
+ * inclusion-exclusion tricks. For speed no nearest neighbor search is done. Slightly better
+ * performance can be expected by more sophisticated but more expensive versions.
+ */
+public class WuQuantizer implements Quantizer {
+    private static final int MAX_COLORS = 256;
+    private static final int RED = 2;
+    private static final int GREEN = 1;
+    private static final int BLUE = 0;
+
+    private static final int QUANT_SIZE = 33;
+    private final List<Palette.Swatch> mSwatches = new ArrayList<>();
+
+    @Override
+    public List<Palette.Swatch> getQuantizedColors() {
+        return mSwatches;
+    }
+
+    private static final class Box {
+        int mR0; /* min value, exclusive */
+        int mR1; /* max value, inclusive */
+        int mG0;
+        int mG1;
+        int mB0;
+        int mB1;
+        int mVol;
+    }
+
+    private final int mSize; /* image size, in bytes. */
+    private int mMaxColors;
+    private int[] mQadd;
+    private final int[] mPixels;
+
+    private final double[][][] mM2 = new double[QUANT_SIZE][QUANT_SIZE][QUANT_SIZE];
+    private final long[][][] mWt = new long[QUANT_SIZE][QUANT_SIZE][QUANT_SIZE];
+    private final long[][][] mMr = new long[QUANT_SIZE][QUANT_SIZE][QUANT_SIZE];
+    private final long[][][] mMg = new long[QUANT_SIZE][QUANT_SIZE][QUANT_SIZE];
+    private final long[][][] mMb = new long[QUANT_SIZE][QUANT_SIZE][QUANT_SIZE];
+
+    public WuQuantizer(int[] pixels, int maxColorCount) {
+        if (pixels == null) {
+            pixels = new int[]{};
+        }
+        this.mPixels = pixels;
+        this.mSize = pixels.length;
+    }
+
+    @Override
+    public void quantize(int[] colors, int maxColorCount) {
+        // All of the sample Wu implementations are reimplementations of a snippet of C code from
+        // the early 90s. They all cap the maximum # of colors at 256, and it is impossible to tell
+        // if this is a requirement, a consequence of QUANT_SIZE, or arbitrary.
+        this.mMaxColors = Math.min(MAX_COLORS, maxColorCount);
+        Box[] cube = new Box[mMaxColors];
+        int red, green, blue;
+
+        int next, i, k;
+        long weight;
+        double[] vv = new double[mMaxColors];
+        double temp;
+
+        compute3DHistogram(mWt, mMr, mMg, mMb, mM2);
+        computeMoments(mWt, mMr, mMg, mMb, mM2);
+
+        for (i = 0; i < mMaxColors; i++) {
+            cube[i] = new Box();
+        }
+
+        cube[0].mR0 = cube[0].mG0 = cube[0].mB0 = 0;
+        cube[0].mR1 = cube[0].mG1 = cube[0].mB1 = QUANT_SIZE - 1;
+        next = 0;
+
+        for (i = 1; i < mMaxColors; ++i) {
+            if (cut(cube[next], cube[i])) {
+                vv[next] = (cube[next].mVol > 1) ? getVariance(cube[next]) : 0.0f;
+                vv[i] = (cube[i].mVol > 1) ? getVariance(cube[i]) : 0.0f;
+            } else {
+                vv[next] = 0.0f;
+                i--;
+            }
+            next = 0;
+            temp = vv[0];
+            for (k = 1; k <= i; ++k) {
+                if (vv[k] > temp) {
+                    temp = vv[k];
+                    next = k;
+                }
+            }
+            if (temp <= 0.0f) {
+                break;
+            }
+        }
+
+        for (k = 0; k < mMaxColors; ++k) {
+            weight = getVolume(cube[k], mWt);
+            if (weight > 0) {
+                red = (int) (getVolume(cube[k], mMr) / weight);
+                green = (int) (getVolume(cube[k], mMg) / weight);
+                blue = (int) (getVolume(cube[k], mMb) / weight);
+                colors[k] = ((red & 0x0ff) << 16) | ((green & 0x0ff) << 8) | (blue & 0x0ff);
+            } else {
+                colors[k] = 0;
+            }
+        }
+
+        int bitsPerPixel = 0;
+        while ((1 << bitsPerPixel) < mMaxColors) {
+            bitsPerPixel++;
+        }
+
+        List<Palette.Swatch> swatches = new ArrayList<>();
+        for (int l = 0; l < k; l++) {
+            int pixel = colors[l];
+            if (pixel == 0) {
+                continue;
+            }
+            swatches.add(new Palette.Swatch(pixel, 0));
+        }
+        mSwatches.clear();
+        mSwatches.addAll(swatches);
+    }
+
+    /* Histogram is in elements 1..HISTSIZE along each axis,
+     * element 0 is for base or marginal value
+     * NB: these must start out 0!
+     */
+    private void compute3DHistogram(
+            long[][][] vwt, long[][][] vmr, long[][][] vmg, long[][][] vmb, double[][][] m2) {
+        // build 3-D color histogram of counts, r/g/b, and c^2
+        int r, g, b;
+        int i;
+        int inr;
+        int ing;
+        int inb;
+        int[] table = new int[256];
+
+        for (i = 0; i < 256; i++) {
+            table[i] = i * i;
+        }
+
+        mQadd = new int[mSize];
+
+        for (i = 0; i < mSize; ++i) {
+            int rgb = mPixels[i];
+            // Skip less than opaque pixels. They're not meaningful in the context of palette
+            // generation for UI schemes.
+            if ((rgb >>> 24) < 0xff) {
+                continue;
+            }
+            r = ((rgb >> 16) & 0xff);
+            g = ((rgb >> 8) & 0xff);
+            b = (rgb & 0xff);
+            inr = (r >> 3) + 1;
+            ing = (g >> 3) + 1;
+            inb = (b >> 3) + 1;
+            mQadd[i] = (inr << 10) + (inr << 6) + inr + (ing << 5) + ing + inb;
+            /*[inr][ing][inb]*/
+            ++vwt[inr][ing][inb];
+            vmr[inr][ing][inb] += r;
+            vmg[inr][ing][inb] += g;
+            vmb[inr][ing][inb] += b;
+            m2[inr][ing][inb] += table[r] + table[g] + table[b];
+        }
+    }
+
+    /* At conclusion of the histogram step, we can interpret
+     *   wt[r][g][b] = sum over voxel of P(c)
+     *   mr[r][g][b] = sum over voxel of r*P(c)  ,  similarly for mg, mb
+     *   m2[r][g][b] = sum over voxel of c^2*P(c)
+     * Actually each of these should be divided by 'size' to give the usual
+     * interpretation of P() as ranging from 0 to 1, but we needn't do that here.
+     *
+     * We now convert histogram into moments so that we can rapidly calculate
+     * the sums of the above quantities over any desired box.
+     */
+    private void computeMoments(
+            long[][][] vwt, long[][][] vmr, long[][][] vmg, long[][][] vmb, double[][][] m2) {
+        /* compute cumulative moments. */
+        int i, r, g, b;
+        int line, line_r, line_g, line_b;
+        int[] area = new int[QUANT_SIZE];
+        int[] area_r = new int[QUANT_SIZE];
+        int[] area_g = new int[QUANT_SIZE];
+        int[] area_b = new int[QUANT_SIZE];
+        double line2;
+        double[] area2 = new double[QUANT_SIZE];
+
+        for (r = 1; r < QUANT_SIZE; ++r) {
+            for (i = 0; i < QUANT_SIZE; ++i) {
+                area2[i] = area[i] = area_r[i] = area_g[i] = area_b[i] = 0;
+            }
+            for (g = 1; g < QUANT_SIZE; ++g) {
+                line2 = line = line_r = line_g = line_b = 0;
+                for (b = 1; b < QUANT_SIZE; ++b) {
+                    line += vwt[r][g][b];
+                    line_r += vmr[r][g][b];
+                    line_g += vmg[r][g][b];
+                    line_b += vmb[r][g][b];
+                    line2 += m2[r][g][b];
+
+                    area[b] += line;
+                    area_r[b] += line_r;
+                    area_g[b] += line_g;
+                    area_b[b] += line_b;
+                    area2[b] += line2;
+
+                    vwt[r][g][b] = vwt[r - 1][g][b] + area[b];
+                    vmr[r][g][b] = vmr[r - 1][g][b] + area_r[b];
+                    vmg[r][g][b] = vmg[r - 1][g][b] + area_g[b];
+                    vmb[r][g][b] = vmb[r - 1][g][b] + area_b[b];
+                    m2[r][g][b] = m2[r - 1][g][b] + area2[b];
+                }
+            }
+        }
+    }
+
+    private long getVolume(Box cube, long[][][] mmt) {
+        /* Compute sum over a box of any given statistic */
+        return (mmt[cube.mR1][cube.mG1][cube.mB1]
+                - mmt[cube.mR1][cube.mG1][cube.mB0]
+                - mmt[cube.mR1][cube.mG0][cube.mB1]
+                + mmt[cube.mR1][cube.mG0][cube.mB0]
+                - mmt[cube.mR0][cube.mG1][cube.mB1]
+                + mmt[cube.mR0][cube.mG1][cube.mB0]
+                + mmt[cube.mR0][cube.mG0][cube.mB1]
+                - mmt[cube.mR0][cube.mG0][cube.mB0]);
+    }
+
+    /* The next two routines allow a slightly more efficient calculation
+     * of Vol() for a proposed subbox of a given box.  The sum of Top()
+     * and Bottom() is the Vol() of a subbox split in the given direction
+     * and with the specified new upper bound.
+     */
+    private long getBottom(Box cube, int dir, long[][][] mmt) {
+        /* Compute part of Vol(cube, mmt) that doesn't depend on r1, g1, or b1 */
+        /* (depending on dir) */
+        switch (dir) {
+            case RED:
+                return (-mmt[cube.mR0][cube.mG1][cube.mB1]
+                        + mmt[cube.mR0][cube.mG1][cube.mB0]
+                        + mmt[cube.mR0][cube.mG0][cube.mB1]
+                        - mmt[cube.mR0][cube.mG0][cube.mB0]);
+            case GREEN:
+                return (-mmt[cube.mR1][cube.mG0][cube.mB1]
+                        + mmt[cube.mR1][cube.mG0][cube.mB0]
+                        + mmt[cube.mR0][cube.mG0][cube.mB1]
+                        - mmt[cube.mR0][cube.mG0][cube.mB0]);
+            case BLUE:
+                return (-mmt[cube.mR1][cube.mG1][cube.mB0]
+                        + mmt[cube.mR1][cube.mG0][cube.mB0]
+                        + mmt[cube.mR0][cube.mG1][cube.mB0]
+                        - mmt[cube.mR0][cube.mG0][cube.mB0]);
+            default:
+                return 0;
+        }
+    }
+
+    private long getTop(Box cube, int dir, int pos, long[][][] mmt) {
+        /* Compute remainder of Vol(cube, mmt), substituting pos for */
+        /* r1, g1, or b1 (depending on dir) */
+        switch (dir) {
+            case RED:
+                return (mmt[pos][cube.mG1][cube.mB1]
+                        - mmt[pos][cube.mG1][cube.mB0]
+                        - mmt[pos][cube.mG0][cube.mB1]
+                        + mmt[pos][cube.mG0][cube.mB0]);
+            case GREEN:
+                return (mmt[cube.mR1][pos][cube.mB1]
+                        - mmt[cube.mR1][pos][cube.mB0]
+                        - mmt[cube.mR0][pos][cube.mB1]
+                        + mmt[cube.mR0][pos][cube.mB0]);
+            case BLUE:
+                return (mmt[cube.mR1][cube.mG1][pos]
+                        - mmt[cube.mR1][cube.mG0][pos]
+                        - mmt[cube.mR0][cube.mG1][pos]
+                        + mmt[cube.mR0][cube.mG0][pos]);
+            default:
+                return 0;
+        }
+    }
+
+    private double getVariance(Box cube) {
+        /* Compute the weighted variance of a box */
+        /* NB: as with the raw statistics, this is really the variance * size */
+        double dr, dg, db, xx;
+        dr = getVolume(cube, mMr);
+        dg = getVolume(cube, mMg);
+        db = getVolume(cube, mMb);
+        xx =
+                mM2[cube.mR1][cube.mG1][cube.mB1]
+                        - mM2[cube.mR1][cube.mG1][cube.mB0]
+                        - mM2[cube.mR1][cube.mG0][cube.mB1]
+                        + mM2[cube.mR1][cube.mG0][cube.mB0]
+                        - mM2[cube.mR0][cube.mG1][cube.mB1]
+                        + mM2[cube.mR0][cube.mG1][cube.mB0]
+                        + mM2[cube.mR0][cube.mG0][cube.mB1]
+                        - mM2[cube.mR0][cube.mG0][cube.mB0];
+        return xx - (dr * dr + dg * dg + db * db) / getVolume(cube, mWt);
+    }
+
+    /* We want to minimize the sum of the variances of two subboxes.
+     * The sum(c^2) terms can be ignored since their sum over both subboxes
+     * is the same (the sum for the whole box) no matter where we split.
+     * The remaining terms have a minus sign in the variance formula,
+     * so we drop the minus sign and MAXIMIZE the sum of the two terms.
+     */
+    private double maximize(
+            Box cube,
+            int dir,
+            int first,
+            int last,
+            int[] cut,
+            long wholeR,
+            long wholeG,
+            long wholeB,
+            long wholeW) {
+        long half_r, half_g, half_b, half_w;
+        long base_r, base_g, base_b, base_w;
+        int i;
+        double temp, max;
+
+        base_r = getBottom(cube, dir, mMr);
+        base_g = getBottom(cube, dir, mMg);
+        base_b = getBottom(cube, dir, mMb);
+        base_w = getBottom(cube, dir, mWt);
+
+        max = 0.0f;
+        cut[0] = -1;
+
+        for (i = first; i < last; ++i) {
+            half_r = base_r + getTop(cube, dir, i, mMr);
+            half_g = base_g + getTop(cube, dir, i, mMg);
+            half_b = base_b + getTop(cube, dir, i, mMb);
+            half_w = base_w + getTop(cube, dir, i, mWt);
+            /* now half_x is sum over lower half of box, if split at i */
+            if (half_w == 0) /* subbox could be empty of pixels! */ {
+                continue; /* never split into an empty box */
+            }
+            temp = (half_r * half_r + half_g * half_g + half_b * half_b) / (double) half_w;
+            half_r = wholeR - half_r;
+            half_g = wholeG - half_g;
+            half_b = wholeB - half_b;
+            half_w = wholeW - half_w;
+            if (half_w == 0) /* subbox could be empty of pixels! */ {
+                continue; /* never split into an empty box */
+            }
+            temp += (half_r * half_r + half_g * half_g + half_b * half_b) / (double) half_w;
+
+            if (temp > max) {
+                max = temp;
+                cut[0] = i;
+            }
+        }
+
+        return max;
+    }
+
+    private boolean cut(Box set1, Box set2) {
+        int dir;
+        int[] cutr = new int[1];
+        int[] cutg = new int[1];
+        int[] cutb = new int[1];
+        double maxr, maxg, maxb;
+        long whole_r, whole_g, whole_b, whole_w;
+
+        whole_r = getVolume(set1, mMr);
+        whole_g = getVolume(set1, mMg);
+        whole_b = getVolume(set1, mMb);
+        whole_w = getVolume(set1, mWt);
+
+        maxr = maximize(set1, RED, set1.mR0 + 1, set1.mR1, cutr, whole_r, whole_g, whole_b,
+                whole_w);
+        maxg = maximize(set1, GREEN, set1.mG0 + 1, set1.mG1, cutg, whole_r, whole_g, whole_b,
+                whole_w);
+        maxb = maximize(set1, BLUE, set1.mB0 + 1, set1.mB1, cutb, whole_r, whole_g, whole_b,
+                whole_w);
+
+        if (maxr >= maxg && maxr >= maxb) {
+            dir = RED;
+            if (cutr[0] < 0) return false; /* can't split the box */
+        } else if (maxg >= maxr && maxg >= maxb) {
+            dir = GREEN;
+        } else {
+            dir = BLUE;
+        }
+
+        set2.mR1 = set1.mR1;
+        set2.mG1 = set1.mG1;
+        set2.mB1 = set1.mB1;
+
+        switch (dir) {
+            case RED:
+                set2.mR0 = set1.mR1 = cutr[0];
+                set2.mG0 = set1.mG0;
+                set2.mB0 = set1.mB0;
+                break;
+            case GREEN:
+                set2.mG0 = set1.mG1 = cutg[0];
+                set2.mR0 = set1.mR0;
+                set2.mB0 = set1.mB0;
+                break;
+            case BLUE:
+                set2.mB0 = set1.mB1 = cutb[0];
+                set2.mR0 = set1.mR0;
+                set2.mG0 = set1.mG0;
+                break;
+        }
+        set1.mVol = (set1.mR1 - set1.mR0) * (set1.mG1 - set1.mG0) * (set1.mB1 - set1.mB0);
+        set2.mVol = (set2.mR1 - set2.mR0) * (set2.mG1 - set2.mG0) * (set2.mB1 - set2.mB0);
+
+        return true;
+    }
+}
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index e82cc73..342456a 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -25,6 +25,9 @@
 import static android.view.SurfaceControl.JankData.PREDICTION_ERROR;
 import static android.view.SurfaceControl.JankData.SURFACE_FLINGER_SCHEDULING;
 
+import static com.android.internal.jank.InteractionJankMonitor.ACTION_METRICS_LOGGED;
+import static com.android.internal.jank.InteractionJankMonitor.ACTION_SESSION_BEGIN;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.graphics.HardwareRendererObserver;
@@ -72,6 +75,7 @@
     private long mEndVsyncId = INVALID_ID;
     private boolean mMetricsFinalized;
     private boolean mCancelled = false;
+    private FrameTrackerListener mListener;
 
     private static class JankInfo {
         long frameVsyncId;
@@ -109,7 +113,7 @@
             @NonNull SurfaceControlWrapper surfaceControlWrapper,
             @NonNull ChoreographerWrapper choreographer,
             @NonNull FrameMetricsWrapper metrics, int traceThresholdMissedFrames,
-            int traceThresholdFrameTimeMillis) {
+            int traceThresholdFrameTimeMillis, @Nullable FrameTrackerListener listener) {
         mSession = session;
         mRendererWrapper = renderer;
         mMetricsWrapper = metrics;
@@ -120,6 +124,7 @@
         mObserver = new HardwareRendererObserver(this, mMetricsWrapper.getTiming(), handler);
         mTraceThresholdMissedFrames = traceThresholdMissedFrames;
         mTraceThresholdFrameTimeMillis = traceThresholdFrameTimeMillis;
+        mListener = listener;
 
         // If the surface isn't valid yet, wait until it's created.
         if (viewRootWrapper.getSurfaceControl().isValid()) {
@@ -165,11 +170,15 @@
      */
     public synchronized void begin() {
         mBeginVsyncId = mChoreographer.getVsyncId() + 1;
+        mSession.setTimeStamp(System.nanoTime());
         Trace.beginAsyncSection(mSession.getName(), (int) mBeginVsyncId);
         mRendererWrapper.addObserver(mObserver);
         if (mSurfaceControl != null) {
             mSurfaceControlWrapper.addJankStatsListener(this, mSurfaceControl);
         }
+        if (mListener != null) {
+            mListener.onNotifyCujEvents(mSession, ACTION_SESSION_BEGIN);
+        }
     }
 
     /**
@@ -224,7 +233,6 @@
     }
 
     private boolean isInRange(long vsyncId) {
-
         // It's possible that we may miss a callback for the frame with vsyncId == mEndVsyncId.
         // Because of that, we collect all frames even if they happen after the end so we eventually
         // have a frame after the end with both callbacks present.
@@ -371,6 +379,9 @@
                     missedAppFramesCount + missedSfFramesCounts,
                     maxFrameTimeNanos,
                     missedSfFramesCounts);
+            if (mListener != null) {
+                mListener.onNotifyCujEvents(mSession, ACTION_METRICS_LOGGED);
+            }
         }
         if (DEBUG) {
             Log.i(TAG, "FrameTracker: CUJ=" + mSession.getName()
@@ -495,4 +506,17 @@
             return mChoreographer.getVsyncId();
         }
     }
+
+    /**
+     * A listener that notifies cuj events.
+     */
+    public interface FrameTrackerListener {
+        /**
+         * Notify that the CUJ session was created.
+         *
+         * @param session the CUJ session
+         * @param action the specific action
+         */
+        void onNotifyCujEvents(Session session, String action);
+    }
 }
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index cba6af9..0294ec3 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -16,6 +16,8 @@
 
 package com.android.internal.jank;
 
+import static android.content.Intent.FLAG_RECEIVER_REGISTERED_ONLY;
+
 import static com.android.internal.jank.FrameTracker.ChoreographerWrapper;
 import static com.android.internal.jank.FrameTracker.SurfaceControlWrapper;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_ALL_APPS_SCROLL;
@@ -48,9 +50,12 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.content.Context;
+import android.content.Intent;
 import android.os.Build;
 import android.os.HandlerExecutor;
 import android.os.HandlerThread;
+import android.os.SystemProperties;
 import android.provider.DeviceConfig;
 import android.util.Log;
 import android.util.SparseArray;
@@ -59,6 +64,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.jank.FrameTracker.FrameMetricsWrapper;
+import com.android.internal.jank.FrameTracker.FrameTrackerListener;
 import com.android.internal.jank.FrameTracker.ThreadedRendererWrapper;
 import com.android.internal.jank.FrameTracker.ViewRootWrapper;
 import com.android.internal.util.PerfettoTrigger;
@@ -74,6 +80,8 @@
  */
 public class InteractionJankMonitor {
     private static final String TAG = InteractionJankMonitor.class.getSimpleName();
+    private static final String ACTION_PREFIX = InteractionJankMonitor.class.getCanonicalName();
+
     private static final String DEFAULT_WORKER_NAME = TAG + "-Worker";
     private static final long DEFAULT_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(5L);
     private static final String SETTINGS_ENABLED_KEY = "enabled";
@@ -90,6 +98,14 @@
     private static final int DEFAULT_TRACE_THRESHOLD_MISSED_FRAMES = 3;
     private static final int DEFAULT_TRACE_THRESHOLD_FRAME_TIME_MILLIS = 64;
 
+    public static final String ACTION_SESSION_BEGIN = ACTION_PREFIX + ".ACTION_SESSION_BEGIN";
+    public static final String ACTION_SESSION_END = ACTION_PREFIX + ".ACTION_SESSION_END";
+    public static final String ACTION_METRICS_LOGGED = ACTION_PREFIX + ".ACTION_METRICS_LOGGED";
+    public static final String BUNDLE_KEY_CUJ_NAME = ACTION_PREFIX + ".CUJ_NAME";
+    public static final String BUNDLE_KEY_TIMESTAMP = ACTION_PREFIX + ".TIMESTAMP";
+    @VisibleForTesting
+    public static final String PROP_NOTIFY_CUJ_EVENT = "debug.notify_cuj_events";
+
     // Every value must have a corresponding entry in CUJ_STATSD_INTERACTION_TYPE.
     public static final int CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE = 0;
     public static final int CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE_LOCK = 1;
@@ -256,15 +272,28 @@
      */
     @VisibleForTesting
     public FrameTracker createFrameTracker(View v, Session session) {
+        final Context c = v.getContext().getApplicationContext();
         synchronized (this) {
+            boolean needListener = SystemProperties.getBoolean(PROP_NOTIFY_CUJ_EVENT, false);
+            FrameTrackerListener eventsListener =
+                    !needListener ? null : (s, act) -> notifyEvents(c, act, s);
+
             return new FrameTracker(session, mWorker.getThreadHandler(),
                     new ThreadedRendererWrapper(v.getThreadedRenderer()),
                     new ViewRootWrapper(v.getViewRootImpl()), new SurfaceControlWrapper(),
                     new ChoreographerWrapper(Choreographer.getInstance()), mMetrics,
-                    mTraceThresholdMissedFrames, mTraceThresholdFrameTimeMillis);
+                    mTraceThresholdMissedFrames, mTraceThresholdFrameTimeMillis, eventsListener);
         }
     }
 
+    private void notifyEvents(Context context, String action, Session session) {
+        Intent intent = new Intent(action);
+        intent.putExtra(BUNDLE_KEY_CUJ_NAME, getNameOfCuj(session.getCuj()));
+        intent.putExtra(BUNDLE_KEY_TIMESTAMP, session.getTimeStamp());
+        intent.addFlags(FLAG_RECEIVER_REGISTERED_ONLY);
+        context.sendBroadcast(intent);
+    }
+
     /**
      * Begin a trace session.
      *
@@ -479,6 +508,7 @@
     public static class Session {
         @CujType
         private int mCujType;
+        private long mTimeStamp;
 
         public Session(@CujType int cujType) {
             mCujType = cujType;
@@ -505,5 +535,13 @@
         public String getName() {
             return "J<" + getNameOfCuj(mCujType) + ">";
         }
+
+        public void setTimeStamp(long timeStamp) {
+            mTimeStamp = timeStamp;
+        }
+
+        public long getTimeStamp() {
+            return mTimeStamp;
+        }
     }
 }
diff --git a/core/java/com/android/internal/listeners/ListenerTransportManager.java b/core/java/com/android/internal/listeners/ListenerTransportManager.java
index 0d5d1b7b..d5b5619 100644
--- a/core/java/com/android/internal/listeners/ListenerTransportManager.java
+++ b/core/java/com/android/internal/listeners/ListenerTransportManager.java
@@ -17,6 +17,7 @@
 package com.android.internal.listeners;
 
 import android.os.RemoteException;
+import android.util.ArrayMap;
 
 import com.android.internal.annotations.GuardedBy;
 
@@ -36,13 +37,17 @@
     @GuardedBy("mRegistrations")
     private final Map<Object, WeakReference<TTransport>> mRegistrations;
 
-    protected ListenerTransportManager() {
+    protected ListenerTransportManager(boolean allowServerSideTransportRemoval) {
         // using weakhashmap means that the transport may be GCed if the server drops its reference,
         // and thus the listener may be GCed as well if the client drops that reference. if the
         // server will never drop a reference without warning (ie, transport removal may only be
         // initiated from the client side), then arraymap or similar may be used without fear of
         // memory leaks.
-        mRegistrations = new WeakHashMap<>();
+        if (allowServerSideTransportRemoval) {
+            mRegistrations = new WeakHashMap<>();
+        } else {
+            mRegistrations = new ArrayMap<>();
+        }
     }
 
     /**
@@ -53,16 +58,21 @@
             synchronized (mRegistrations) {
                 // ordering of operations is important so that if an error occurs at any point we
                 // are left in a reasonable state
-                registerTransport(transport);
-                WeakReference<TTransport> oldTransportRef = mRegistrations.put(key,
-                        new WeakReference<>(transport));
+                TTransport oldTransport;
+                WeakReference<TTransport> oldTransportRef = mRegistrations.get(key);
                 if (oldTransportRef != null) {
-                    TTransport oldTransport = oldTransportRef.get();
-                    if (oldTransport != null) {
-                        oldTransport.unregister();
-                        unregisterTransport(oldTransport);
-                    }
+                    oldTransport = oldTransportRef.get();
+                } else {
+                    oldTransport = null;
                 }
+
+                if (oldTransport == null) {
+                    registerTransport(transport);
+                } else {
+                    registerTransport(transport, oldTransport);
+                    oldTransport.unregister();
+                }
+                mRegistrations.put(key, new WeakReference<>(transport));
             }
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -91,7 +101,33 @@
         }
     }
 
+    /**
+     * Registers a new transport.
+     */
     protected abstract void registerTransport(TTransport transport) throws RemoteException;
 
+    /**
+     * Registers a new transport that is replacing the given old transport. Implementations must
+     * ensure that if they throw a remote exception, the call does not have any side effects.
+     */
+    protected void registerTransport(TTransport transport, TTransport oldTransport)
+            throws RemoteException {
+        registerTransport(transport);
+        try {
+            unregisterTransport(oldTransport);
+        } catch (RemoteException e) {
+            try {
+                // best effort to ensure there are no side effects
+                unregisterTransport(transport);
+            } catch (RemoteException suppressed) {
+                e.addSuppressed(suppressed);
+            }
+            throw e;
+        }
+    }
+
+    /**
+     * Unregisters an existing transport.
+     */
     protected abstract void unregisterTransport(TTransport transport) throws RemoteException;
 }
diff --git a/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java b/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java
index 1313090..e153eb2 100644
--- a/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java
+++ b/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java
@@ -46,14 +46,12 @@
             long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
         final long durationMs = calculateDuration(batteryStats, rawRealtimeUs,
                 BatteryStats.STATS_SINCE_CHARGED);
-        final double powerMah = mPowerEstimator.calculatePower(durationMs);
-        if (powerMah > 0) {
-            builder.getOrCreateSystemBatteryConsumerBuilder(
-                    SystemBatteryConsumer.DRAIN_TYPE_AMBIENT_DISPLAY)
-                    .setConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE, powerMah)
-                    .setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_USAGE, durationMs);
-        }
-        // TODO(b/178140704): Attribute *measured* total usage for BatteryUsageStats.
+        final double powerMah = getMeasuredOrEstimatedPower(batteryStats.getScreenDozeEnergy(),
+                mPowerEstimator, durationMs, query.shouldForceUsePowerProfileModel());
+        builder.getOrCreateSystemBatteryConsumerBuilder(
+                        SystemBatteryConsumer.DRAIN_TYPE_AMBIENT_DISPLAY)
+                .setConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE, powerMah)
+                .setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_USAGE, durationMs);
     }
 
     /**
@@ -66,8 +64,8 @@
     public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
             long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
         final long durationMs = calculateDuration(batteryStats, rawRealtimeUs, statsType);
-        final double powerMah = getMeasuredOrEstimatedPower(
-                batteryStats.getScreenDozeEnergy(), durationMs);
+        final double powerMah = getMeasuredOrEstimatedPower(batteryStats.getScreenDozeEnergy(),
+                mPowerEstimator, durationMs, false);
         if (powerMah > 0) {
             BatterySipper bs = new BatterySipper(BatterySipper.DrainType.AMBIENT_DISPLAY, null, 0);
             bs.usagePowerMah = powerMah;
@@ -81,11 +79,4 @@
         return batteryStats.getScreenDozeTime(rawRealtimeUs, statsType) / 1000;
     }
 
-    private double getMeasuredOrEstimatedPower(long measuredEnergyUJ, long durationMs) {
-        if (measuredEnergyUJ != BatteryStats.ENERGY_DATA_UNAVAILABLE) {
-            return uJtoMah(measuredEnergyUJ);
-        } else {
-            return mPowerEstimator.calculatePower(durationMs);
-        }
-    }
 }
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
index bdb65f3..879e0a8 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistory.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -16,6 +16,8 @@
 
 package com.android.internal.os;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.os.BatteryStats;
 import android.os.Parcel;
 import android.os.StatFs;
@@ -61,6 +63,7 @@
     public static final String FILE_SUFFIX = ".bin";
     private static final int MIN_FREE_SPACE = 100 * 1024 * 1024;
 
+    @Nullable
     private final BatteryStatsImpl mStats;
     private final Parcel mHistoryBuffer;
     private final File mHistoryDir;
@@ -107,7 +110,8 @@
      * @param systemDir typically /data/system
      * @param historyBuffer The in-memory history buffer.
      */
-    public BatteryStatsHistory(BatteryStatsImpl stats, File systemDir, Parcel historyBuffer) {
+    public BatteryStatsHistory(@NonNull BatteryStatsImpl stats, File systemDir,
+            Parcel historyBuffer) {
         mStats = stats;
         mHistoryBuffer = historyBuffer;
         mHistoryDir = new File(systemDir, HISTORY_DIR);
@@ -149,11 +153,10 @@
     /**
      * Used when BatteryStatsImpl object is created from deserialization of a parcel,
      * such as Settings app or checkin file.
-     * @param stats BatteryStatsImpl object.
-     * @param historyBuffer the history buffer inside BatteryStatsImpl
+     * @param historyBuffer the history buffer
      */
-    public BatteryStatsHistory(BatteryStatsImpl stats, Parcel historyBuffer) {
-        mStats = stats;
+    public BatteryStatsHistory(Parcel historyBuffer) {
+        mStats = null;
         mHistoryDir = null;
         mHistoryBuffer = historyBuffer;
     }
@@ -184,10 +187,16 @@
      * create next history file.
      */
     public void startNextFile() {
+        if (mStats == null) {
+            Slog.wtf(TAG, "mStats should not be null when writing history");
+            return;
+        }
+
         if (mFileNumbers.isEmpty()) {
             Slog.wtf(TAG, "mFileNumbers should never be empty");
             return;
         }
+
         // The last number in mFileNumbers is the highest number. The next file number is highest
         // number plus one.
         final int next = mFileNumbers.get(mFileNumbers.size() - 1) + 1;
@@ -357,7 +366,7 @@
     private boolean skipHead(Parcel p) {
         p.setDataPosition(0);
         final int version = p.readInt();
-        if (version != mStats.VERSION) {
+        if (version != BatteryStatsImpl.VERSION) {
             return false;
         }
         // skip historyBaseTime field.
diff --git a/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
new file mode 100644
index 0000000..1871ac5
--- /dev/null
+++ b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.annotation.NonNull;
+import android.os.BatteryManager;
+import android.os.BatteryStats;
+import android.os.Parcel;
+import android.util.Slog;
+
+import java.util.List;
+
+/**
+ * An iterator for {@link BatteryStats.HistoryItem}'s.
+ */
+public class BatteryStatsHistoryIterator {
+    private static final boolean DEBUG = false;
+    private static final String TAG = "BatteryStatsHistoryItr";
+    private final BatteryStatsHistory mBatteryStatsHistory;
+    private final BatteryStats.HistoryStepDetails mReadHistoryStepDetails =
+            new BatteryStats.HistoryStepDetails();
+    private final String[] mReadHistoryStrings;
+    private final int[] mReadHistoryUids;
+
+    public BatteryStatsHistoryIterator(@NonNull BatteryStatsHistory history,
+            @NonNull List<BatteryStats.HistoryTag> historyTagPool) {
+        mBatteryStatsHistory = history;
+
+        mBatteryStatsHistory.startIteratingHistory();
+
+        mReadHistoryStrings = new String[historyTagPool.size()];
+        mReadHistoryUids = new int[historyTagPool.size()];
+        for (int i = historyTagPool.size() - 1; i >= 0; i--) {
+            BatteryStats.HistoryTag tag = historyTagPool.get(i);
+            final int idx = tag.poolIdx;
+            mReadHistoryStrings[idx] = tag.string;
+            mReadHistoryUids[idx] = tag.uid;
+        }
+    }
+
+    /**
+     * Retrieves the next HistoryItem from battery history, if available. Returns false if there
+     * are no more items.
+     */
+    public boolean next(BatteryStats.HistoryItem out) {
+        Parcel p = mBatteryStatsHistory.getNextParcel(out);
+        if (p == null) {
+            mBatteryStatsHistory.finishIteratingHistory();
+            return false;
+        }
+
+        final long lastRealtimeMs = out.time;
+        final long lastWalltimeMs = out.currentTime;
+        readHistoryDelta(p, out);
+        if (out.cmd != BatteryStats.HistoryItem.CMD_CURRENT_TIME
+                && out.cmd != BatteryStats.HistoryItem.CMD_RESET && lastWalltimeMs != 0) {
+            out.currentTime = lastWalltimeMs + (out.time - lastRealtimeMs);
+        }
+        return true;
+    }
+
+    void readHistoryDelta(Parcel src, BatteryStats.HistoryItem cur) {
+        int firstToken = src.readInt();
+        int deltaTimeToken = firstToken & BatteryStatsImpl.DELTA_TIME_MASK;
+        cur.cmd = BatteryStats.HistoryItem.CMD_UPDATE;
+        cur.numReadInts = 1;
+        if (DEBUG) {
+            Slog.i(TAG, "READ DELTA: firstToken=0x" + Integer.toHexString(firstToken)
+                    + " deltaTimeToken=" + deltaTimeToken);
+        }
+
+        if (deltaTimeToken < BatteryStatsImpl.DELTA_TIME_ABS) {
+            cur.time += deltaTimeToken;
+        } else if (deltaTimeToken == BatteryStatsImpl.DELTA_TIME_ABS) {
+            cur.readFromParcel(src);
+            if (DEBUG) Slog.i(TAG, "READ DELTA: ABS time=" + cur.time);
+            return;
+        } else if (deltaTimeToken == BatteryStatsImpl.DELTA_TIME_INT) {
+            int delta = src.readInt();
+            cur.time += delta;
+            cur.numReadInts += 1;
+            if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
+        } else {
+            long delta = src.readLong();
+            if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
+            cur.time += delta;
+            cur.numReadInts += 2;
+        }
+
+        final int batteryLevelInt;
+        if ((firstToken & BatteryStatsImpl.DELTA_BATTERY_LEVEL_FLAG) != 0) {
+            batteryLevelInt = src.readInt();
+            readBatteryLevelInt(batteryLevelInt, cur);
+            cur.numReadInts += 1;
+            if (DEBUG) {
+                Slog.i(TAG, "READ DELTA: batteryToken=0x"
+                        + Integer.toHexString(batteryLevelInt)
+                        + " batteryLevel=" + cur.batteryLevel
+                        + " batteryTemp=" + cur.batteryTemperature
+                        + " batteryVolt=" + (int) cur.batteryVoltage);
+            }
+        } else {
+            batteryLevelInt = 0;
+        }
+
+        if ((firstToken & BatteryStatsImpl.DELTA_STATE_FLAG) != 0) {
+            int stateInt = src.readInt();
+            cur.states = (firstToken & BatteryStatsImpl.DELTA_STATE_MASK) | (stateInt
+                    & (~BatteryStatsImpl.STATE_BATTERY_MASK));
+            cur.batteryStatus = (byte) ((stateInt >> BatteryStatsImpl.STATE_BATTERY_STATUS_SHIFT)
+                    & BatteryStatsImpl.STATE_BATTERY_STATUS_MASK);
+            cur.batteryHealth = (byte) ((stateInt >> BatteryStatsImpl.STATE_BATTERY_HEALTH_SHIFT)
+                    & BatteryStatsImpl.STATE_BATTERY_HEALTH_MASK);
+            cur.batteryPlugType = (byte) ((stateInt >> BatteryStatsImpl.STATE_BATTERY_PLUG_SHIFT)
+                    & BatteryStatsImpl.STATE_BATTERY_PLUG_MASK);
+            switch (cur.batteryPlugType) {
+                case 1:
+                    cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_AC;
+                    break;
+                case 2:
+                    cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_USB;
+                    break;
+                case 3:
+                    cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
+                    break;
+            }
+            cur.numReadInts += 1;
+            if (DEBUG) {
+                Slog.i(TAG, "READ DELTA: stateToken=0x"
+                        + Integer.toHexString(stateInt)
+                        + " batteryStatus=" + cur.batteryStatus
+                        + " batteryHealth=" + cur.batteryHealth
+                        + " batteryPlugType=" + cur.batteryPlugType
+                        + " states=0x" + Integer.toHexString(cur.states));
+            }
+        } else {
+            cur.states = (firstToken & BatteryStatsImpl.DELTA_STATE_MASK) | (cur.states
+                    & (~BatteryStatsImpl.STATE_BATTERY_MASK));
+        }
+
+        if ((firstToken & BatteryStatsImpl.DELTA_STATE2_FLAG) != 0) {
+            cur.states2 = src.readInt();
+            if (DEBUG) {
+                Slog.i(TAG, "READ DELTA: states2=0x"
+                        + Integer.toHexString(cur.states2));
+            }
+        }
+
+        if ((firstToken & BatteryStatsImpl.DELTA_WAKELOCK_FLAG) != 0) {
+            int indexes = src.readInt();
+            int wakeLockIndex = indexes & 0xffff;
+            int wakeReasonIndex = (indexes >> 16) & 0xffff;
+            if (wakeLockIndex != 0xffff) {
+                cur.wakelockTag = cur.localWakelockTag;
+                readHistoryTag(wakeLockIndex, cur.wakelockTag);
+                if (DEBUG) {
+                    Slog.i(TAG, "READ DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
+                            + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
+                }
+            } else {
+                cur.wakelockTag = null;
+            }
+            if (wakeReasonIndex != 0xffff) {
+                cur.wakeReasonTag = cur.localWakeReasonTag;
+                readHistoryTag(wakeReasonIndex, cur.wakeReasonTag);
+                if (DEBUG) {
+                    Slog.i(TAG, "READ DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
+                            + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
+                }
+            } else {
+                cur.wakeReasonTag = null;
+            }
+            cur.numReadInts += 1;
+        } else {
+            cur.wakelockTag = null;
+            cur.wakeReasonTag = null;
+        }
+
+        if ((firstToken & BatteryStatsImpl.DELTA_EVENT_FLAG) != 0) {
+            cur.eventTag = cur.localEventTag;
+            final int codeAndIndex = src.readInt();
+            cur.eventCode = (codeAndIndex & 0xffff);
+            final int index = ((codeAndIndex >> 16) & 0xffff);
+            readHistoryTag(index, cur.eventTag);
+            cur.numReadInts += 1;
+            if (DEBUG) {
+                Slog.i(TAG, "READ DELTA: event=" + cur.eventCode + " tag=#"
+                        + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
+                        + cur.eventTag.string);
+            }
+        } else {
+            cur.eventCode = BatteryStats.HistoryItem.EVENT_NONE;
+        }
+
+        if ((batteryLevelInt & BatteryStatsImpl.BATTERY_DELTA_LEVEL_FLAG) != 0) {
+            cur.stepDetails = mReadHistoryStepDetails;
+            cur.stepDetails.readFromParcel(src);
+        } else {
+            cur.stepDetails = null;
+        }
+
+        if ((firstToken & BatteryStatsImpl.DELTA_BATTERY_CHARGE_FLAG) != 0) {
+            cur.batteryChargeUah = src.readInt();
+        }
+        cur.modemRailChargeMah = src.readDouble();
+        cur.wifiRailChargeMah = src.readDouble();
+    }
+
+    int getHistoryStringPoolSize() {
+        return mReadHistoryStrings.length;
+    }
+
+    int getHistoryStringPoolBytes() {
+        int totalChars = 0;
+        for (int i = mReadHistoryStrings.length - 1; i >= 0; i--) {
+            if (mReadHistoryStrings[i] != null) {
+                totalChars += mReadHistoryStrings[i].length() + 1;
+            }
+        }
+
+        // Each entry is a fixed 12 bytes: 4 for index, 4 for uid, 4 for string size
+        // Each string character is 2 bytes.
+        return (mReadHistoryStrings.length * 12) + (totalChars * 2);
+    }
+
+    String getHistoryTagPoolString(int index) {
+        return mReadHistoryStrings[index];
+    }
+
+    int getHistoryTagPoolUid(int index) {
+        return mReadHistoryUids[index];
+    }
+
+    private void readHistoryTag(int index, BatteryStats.HistoryTag tag) {
+        if (index < mReadHistoryStrings.length) {
+            tag.string = mReadHistoryStrings[index];
+            tag.uid = mReadHistoryUids[index];
+        } else {
+            tag.string = null;
+            tag.uid = 0;
+        }
+        tag.poolIdx = index;
+    }
+
+    private static void readBatteryLevelInt(int batteryLevelInt, BatteryStats.HistoryItem out) {
+        out.batteryLevel = (byte) ((batteryLevelInt & 0xfe000000) >>> 25);
+        out.batteryTemperature = (short) ((batteryLevelInt & 0x01ff8000) >>> 15);
+        out.batteryVoltage = (char) ((batteryLevelInt & 0x00007ffe) >>> 1);
+    }
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index e599888..73527d4 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -81,7 +81,6 @@
 import android.util.IntArray;
 import android.util.KeyValueListParser;
 import android.util.Log;
-import android.util.LogWriter;
 import android.util.LongSparseArray;
 import android.util.LongSparseLongArray;
 import android.util.MutableInt;
@@ -108,7 +107,6 @@
 import com.android.internal.power.MeasuredEnergyStats;
 import com.android.internal.power.MeasuredEnergyStats.StandardEnergyBucket;
 import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.util.XmlUtils;
 import com.android.net.module.util.NetworkCapabilitiesUtils;
@@ -164,7 +162,6 @@
     private static final boolean DEBUG_BINDER_STATS = false;
     private static final boolean DEBUG_MEMORY = false;
     private static final boolean DEBUG_HISTORY = false;
-    private static final boolean USE_OLD_HISTORY = false;   // for debugging.
 
     // TODO: remove "tcp" from network methods, since we measure total stats.
 
@@ -172,7 +169,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    static final int VERSION = 193 + (USE_OLD_HISTORY ? 1000 : 0);
+    static final int VERSION = 193;
 
     // The maximum number of names wakelocks we will keep track of
     // per uid; once the limit is reached, we batch the remaining wakelocks
@@ -740,15 +737,11 @@
     protected boolean mRecordingHistory = false;
     int mNumHistoryItems;
 
+    final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<>();
     final Parcel mHistoryBuffer = Parcel.obtain();
     final HistoryItem mHistoryLastWritten = new HistoryItem();
     final HistoryItem mHistoryLastLastWritten = new HistoryItem();
-    final HistoryItem mHistoryReadTmp = new HistoryItem();
     final HistoryItem mHistoryAddTmp = new HistoryItem();
-    final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<>();
-    String[] mReadHistoryStrings;
-    int[] mReadHistoryUids;
-    int mReadHistoryChars;
     int mNextHistoryTagIdx = 0;
     int mNumHistoryTagChars = 0;
     int mHistoryBufferLastPos = -1;
@@ -767,7 +760,7 @@
     // Last recorded battery energy capacity.
     // This is used for computing foregrund power per application.
     // See: PowerForUid below
-    private long mLastBatteryEnergyCapacityNWh = 0;
+    private long mLastBatteryEnergyCapacityNwh = 0;
 
     private static final class PowerForUid {
         public long energyNwh = 0;
@@ -789,6 +782,7 @@
     private final HashMap<Integer, PowerForUid> mUidToPower = ENABLE_FOREGROUND_STATS_COLLECTION
             ? new HashMap<>() : null;
 
+    @NonNull
     final BatteryStatsHistory mBatteryStatsHistory;
 
     final HistoryItem mHistoryCur = new HistoryItem();
@@ -831,9 +825,9 @@
     long mCurStepStatSoftIrqTimeMs;
     long mCurStepStatIdleTimeMs;
 
+    private BatteryStatsHistoryIterator mBatteryStatsHistoryIterator;
     private HistoryItem mHistoryIterator;
     private boolean mReadOverflow;
-    private boolean mIteratingHistory;
 
     int mStartCount;
 
@@ -1089,12 +1083,12 @@
 
     private int mNumConnectivityChange;
 
-    private int mBatteryVolt = -1;
-    private int mBatteryCharge = -1;
-    private int mEstimatedBatteryCapacity = -1;
+    private int mBatteryVoltageMv = -1;
+    private int mBatteryChargeUah = -1;
+    private int mEstimatedBatteryCapacityMah = -1;
 
-    private int mMinLearnedBatteryCapacity = -1;
-    private int mMaxLearnedBatteryCapacity = -1;
+    private int mMinLearnedBatteryCapacityUah = -1;
+    private int mMaxLearnedBatteryCapacityUah = -1;
 
     private long mBatteryTimeToFullSeconds = -1;
 
@@ -1175,17 +1169,17 @@
 
     @Override
     public int getEstimatedBatteryCapacity() {
-        return mEstimatedBatteryCapacity;
+        return mEstimatedBatteryCapacityMah;
     }
 
     @Override
     public int getMinLearnedBatteryCapacity() {
-        return mMinLearnedBatteryCapacity;
+        return mMinLearnedBatteryCapacityUah;
     }
 
     @Override
     public int getMaxLearnedBatteryCapacity() {
-        return mMaxLearnedBatteryCapacity;
+        return mMaxLearnedBatteryCapacityUah;
     }
 
     public BatteryStatsImpl() {
@@ -1197,7 +1191,7 @@
         mStatsFile = null;
         mCheckinFile = null;
         mDailyFile = null;
-        mBatteryStatsHistory = null;
+        mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
         mHandler = null;
         mPlatformIdleStateCallback = null;
         mMeasuredEnergyRetriever = null;
@@ -3244,17 +3238,6 @@
         return idx;
     }
 
-    private void readHistoryTag(int index, HistoryTag tag) {
-        if (index < mReadHistoryStrings.length) {
-            tag.string = mReadHistoryStrings[index];
-            tag.uid = mReadHistoryUids[index];
-        } else {
-            tag.string = null;
-            tag.uid = 0;
-        }
-        tag.poolIdx = index;
-    }
-
     /*
         The history delta format uses flags to denote further data in subsequent ints in the parcel.
 
@@ -3416,7 +3399,7 @@
             firstToken |= DELTA_EVENT_FLAG;
         }
 
-        final boolean batteryChargeChanged = cur.batteryChargeUAh != last.batteryChargeUAh;
+        final boolean batteryChargeChanged = cur.batteryChargeUah != last.batteryChargeUah;
         if (batteryChargeChanged) {
             firstToken |= DELTA_BATTERY_CHARGE_FLAG;
         }
@@ -3505,8 +3488,8 @@
         mLastHistoryStepLevel = cur.batteryLevel;
 
         if (batteryChargeChanged) {
-            if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUAh=" + cur.batteryChargeUAh);
-            dest.writeInt(cur.batteryChargeUAh);
+            if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUah=" + cur.batteryChargeUah);
+            dest.writeInt(cur.batteryChargeUah);
         }
         dest.writeDouble(cur.modemRailChargeMah);
         dest.writeDouble(cur.wifiRailChargeMah);
@@ -3631,137 +3614,6 @@
         mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
     }
 
-    public void readHistoryDelta(Parcel src, HistoryItem cur) {
-        int firstToken = src.readInt();
-        int deltaTimeToken = firstToken&DELTA_TIME_MASK;
-        cur.cmd = HistoryItem.CMD_UPDATE;
-        cur.numReadInts = 1;
-        if (DEBUG) Slog.i(TAG, "READ DELTA: firstToken=0x" + Integer.toHexString(firstToken)
-                + " deltaTimeToken=" + deltaTimeToken);
-
-        if (deltaTimeToken < DELTA_TIME_ABS) {
-            cur.time += deltaTimeToken;
-        } else if (deltaTimeToken == DELTA_TIME_ABS) {
-            cur.readFromParcel(src);
-            if (DEBUG) Slog.i(TAG, "READ DELTA: ABS time=" + cur.time);
-            return;
-        } else if (deltaTimeToken == DELTA_TIME_INT) {
-            int delta = src.readInt();
-            cur.time += delta;
-            cur.numReadInts += 1;
-            if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
-        } else {
-            long delta = src.readLong();
-            if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
-            cur.time += delta;
-            cur.numReadInts += 2;
-        }
-
-        final int batteryLevelInt;
-        if ((firstToken&DELTA_BATTERY_LEVEL_FLAG) != 0) {
-            batteryLevelInt = src.readInt();
-            readBatteryLevelInt(batteryLevelInt, cur);
-            cur.numReadInts += 1;
-            if (DEBUG) Slog.i(TAG, "READ DELTA: batteryToken=0x"
-                    + Integer.toHexString(batteryLevelInt)
-                    + " batteryLevel=" + cur.batteryLevel
-                    + " batteryTemp=" + cur.batteryTemperature
-                    + " batteryVolt=" + (int)cur.batteryVoltage);
-        } else {
-            batteryLevelInt = 0;
-        }
-
-        if ((firstToken&DELTA_STATE_FLAG) != 0) {
-            int stateInt = src.readInt();
-            cur.states = (firstToken&DELTA_STATE_MASK) | (stateInt&(~STATE_BATTERY_MASK));
-            cur.batteryStatus = (byte)((stateInt>>STATE_BATTERY_STATUS_SHIFT)
-                    & STATE_BATTERY_STATUS_MASK);
-            cur.batteryHealth = (byte)((stateInt>>STATE_BATTERY_HEALTH_SHIFT)
-                    & STATE_BATTERY_HEALTH_MASK);
-            cur.batteryPlugType = (byte)((stateInt>>STATE_BATTERY_PLUG_SHIFT)
-                    & STATE_BATTERY_PLUG_MASK);
-            switch (cur.batteryPlugType) {
-                case 1:
-                    cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_AC;
-                    break;
-                case 2:
-                    cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_USB;
-                    break;
-                case 3:
-                    cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
-                    break;
-            }
-            cur.numReadInts += 1;
-            if (DEBUG) Slog.i(TAG, "READ DELTA: stateToken=0x"
-                    + Integer.toHexString(stateInt)
-                    + " batteryStatus=" + cur.batteryStatus
-                    + " batteryHealth=" + cur.batteryHealth
-                    + " batteryPlugType=" + cur.batteryPlugType
-                    + " states=0x" + Integer.toHexString(cur.states));
-        } else {
-            cur.states = (firstToken&DELTA_STATE_MASK) | (cur.states&(~STATE_BATTERY_MASK));
-        }
-
-        if ((firstToken&DELTA_STATE2_FLAG) != 0) {
-            cur.states2 = src.readInt();
-            if (DEBUG) Slog.i(TAG, "READ DELTA: states2=0x"
-                    + Integer.toHexString(cur.states2));
-        }
-
-        if ((firstToken&DELTA_WAKELOCK_FLAG) != 0) {
-            int indexes = src.readInt();
-            int wakeLockIndex = indexes&0xffff;
-            int wakeReasonIndex = (indexes>>16)&0xffff;
-            if (wakeLockIndex != 0xffff) {
-                cur.wakelockTag = cur.localWakelockTag;
-                readHistoryTag(wakeLockIndex, cur.wakelockTag);
-                if (DEBUG) Slog.i(TAG, "READ DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
-                    + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
-            } else {
-                cur.wakelockTag = null;
-            }
-            if (wakeReasonIndex != 0xffff) {
-                cur.wakeReasonTag = cur.localWakeReasonTag;
-                readHistoryTag(wakeReasonIndex, cur.wakeReasonTag);
-                if (DEBUG) Slog.i(TAG, "READ DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
-                    + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
-            } else {
-                cur.wakeReasonTag = null;
-            }
-            cur.numReadInts += 1;
-        } else {
-            cur.wakelockTag = null;
-            cur.wakeReasonTag = null;
-        }
-
-        if ((firstToken&DELTA_EVENT_FLAG) != 0) {
-            cur.eventTag = cur.localEventTag;
-            final int codeAndIndex = src.readInt();
-            cur.eventCode = (codeAndIndex&0xffff);
-            final int index = ((codeAndIndex>>16)&0xffff);
-            readHistoryTag(index, cur.eventTag);
-            cur.numReadInts += 1;
-            if (DEBUG) Slog.i(TAG, "READ DELTA: event=" + cur.eventCode + " tag=#"
-                    + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
-                    + cur.eventTag.string);
-        } else {
-            cur.eventCode = HistoryItem.EVENT_NONE;
-        }
-
-        if ((batteryLevelInt&BATTERY_DELTA_LEVEL_FLAG) != 0) {
-            cur.stepDetails = mReadHistoryStepDetails;
-            cur.stepDetails.readFromParcel(src);
-        } else {
-            cur.stepDetails = null;
-        }
-
-        if ((firstToken&DELTA_BATTERY_CHARGE_FLAG) != 0) {
-            cur.batteryChargeUAh = src.readInt();
-        }
-        cur.modemRailChargeMah = src.readDouble();
-        cur.wifiRailChargeMah = src.readDouble();
-    }
-
     @Override
     public void commitCurrentHistoryBatchLocked() {
         mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
@@ -3873,7 +3725,7 @@
     }
 
     private void addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur) {
-        if (mIteratingHistory) {
+        if (mBatteryStatsHistoryIterator != null) {
             throw new IllegalStateException("Can't do this while iterating history!");
         }
         mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
@@ -3917,44 +3769,6 @@
 
     void addHistoryRecordInnerLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
         addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, cur);
-
-        if (!USE_OLD_HISTORY) {
-            return;
-        }
-
-        if (!mHaveBatteryLevel || !mRecordingHistory) {
-            return;
-        }
-
-        // If the current time is basically the same as the last time,
-        // and no states have since the last recorded entry changed and
-        // are now resetting back to their original value, then just collapse
-        // into one record.
-        if (mHistoryEnd != null && mHistoryEnd.cmd == HistoryItem.CMD_UPDATE
-                && (mHistoryBaseTimeMs + elapsedRealtimeMs) < (mHistoryEnd.time + 1000)
-                && ((mHistoryEnd.states^cur.states)&mChangedStates&mActiveHistoryStates) == 0
-                && ((mHistoryEnd.states2^cur.states2)&mChangedStates2&mActiveHistoryStates2) == 0) {
-            // If the current is the same as the one before, then we no
-            // longer need the entry.
-            if (mHistoryLastEnd != null && mHistoryLastEnd.cmd == HistoryItem.CMD_UPDATE
-                    && (mHistoryBaseTimeMs + elapsedRealtimeMs) < (mHistoryEnd.time + 500)
-                    && mHistoryLastEnd.sameNonEvent(cur)) {
-                mHistoryLastEnd.next = null;
-                mHistoryEnd.next = mHistoryCache;
-                mHistoryCache = mHistoryEnd;
-                mHistoryEnd = mHistoryLastEnd;
-                mHistoryLastEnd = null;
-            } else {
-                mChangedStates |= mHistoryEnd.states^(cur.states&mActiveHistoryStates);
-                mChangedStates2 |= mHistoryEnd.states^(cur.states2&mActiveHistoryStates2);
-                mHistoryEnd.setTo(mHistoryEnd.time, HistoryItem.CMD_UPDATE, cur);
-            }
-            return;
-        }
-
-        mChangedStates = 0;
-        mChangedStates2 = 0;
-        addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
     }
 
     public void addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
@@ -3992,15 +3806,6 @@
 
     void clearHistoryLocked() {
         if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!");
-        if (USE_OLD_HISTORY) {
-            if (mHistory != null) {
-                mHistoryEnd.next = mHistoryCache;
-                mHistoryCache = mHistory;
-                mHistory = mHistoryLastEnd = mHistoryEnd = null;
-            }
-            mNumHistoryItems = 0;
-        }
-
         mHistoryBaseTimeMs = 0;
         mLastHistoryElapsedRealtimeMs = 0;
         mTrackRunningHistoryElapsedRealtimeMs = 0;
@@ -7222,6 +7027,10 @@
         return mOnBattery;
     }
 
+    @Override public long getStatsStartRealtime() {
+        return mRealtimeStartUs;
+    }
+
     @UnsupportedAppUsage
     @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
         return mUidStats;
@@ -7961,16 +7770,14 @@
 
         /** Adds the given energy to the given standard energy bucket for this uid. */
         private void addEnergyToStandardBucketLocked(long energyDeltaUJ,
-                @StandardEnergyBucket int energyBucket, boolean accumulate) {
+                @StandardEnergyBucket int energyBucket) {
             getOrCreateMeasuredEnergyStatsLocked()
-                    .updateStandardBucket(energyBucket, energyDeltaUJ, accumulate);
+                    .updateStandardBucket(energyBucket, energyDeltaUJ);
         }
 
         /** Adds the given energy to the given custom energy bucket for this uid. */
-        private void addEnergyToCustomBucketLocked(long energyDeltaUJ, int energyBucket,
-                boolean accumulate) {
-            getOrCreateMeasuredEnergyStatsLocked()
-                    .updateCustomBucket(energyBucket, energyDeltaUJ, accumulate);
+        private void addEnergyToCustomBucketLocked(long energyDeltaUJ, int energyBucket) {
+            getOrCreateMeasuredEnergyStatsLocked().updateCustomBucket(energyBucket, energyDeltaUJ);
         }
 
         /**
@@ -10729,7 +10536,7 @@
 
         if (systemDir == null) {
             mStatsFile = null;
-            mBatteryStatsHistory = new BatteryStatsHistory(this, mHistoryBuffer);
+            mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
         } else {
             mStatsFile = new AtomicFile(new File(systemDir, "batterystats.bin"));
             mBatteryStatsHistory = new BatteryStatsHistory(this, systemDir, mHistoryBuffer);
@@ -10745,11 +10552,6 @@
         long realtimeUs = mClocks.elapsedRealtime() * 1000;
         initTimes(uptimeUs, realtimeUs);
         mStartPlatformVersion = mEndPlatformVersion = Build.ID;
-        mDischargeStartLevel = 0;
-        mDischargeUnplugLevel = 0;
-        mDischargePlugLevel = -1;
-        mDischargeCurrentLevel = 0;
-        mCurrentBatteryLevel = 0;
         initDischarge(realtimeUs);
         clearHistoryLocked();
         updateDailyDeadlineLocked();
@@ -10835,6 +10637,11 @@
         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
+        mDischargeStartLevel = 0;
+        mDischargeUnplugLevel = 0;
+        mDischargePlugLevel = -1;
+        mDischargeCurrentLevel = 0;
+        mCurrentBatteryLevel = 0;
     }
 
     @UnsupportedAppUsage
@@ -10851,7 +10658,7 @@
         mExternalSync = null;
         mConstants = new Constants(mHandler);
         clearHistoryLocked();
-        mBatteryStatsHistory = new BatteryStatsHistory(this, mHistoryBuffer);
+        mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
         readFromParcel(p);
         mPlatformIdleStateCallback = null;
         mMeasuredEnergyRetriever = null;
@@ -10873,9 +10680,9 @@
             firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
         }
 
-        if (mEstimatedBatteryCapacity == -1) {
+        if (mEstimatedBatteryCapacityMah == -1) {
             // Initialize the estimated battery capacity to a known preset one.
-            mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
+            mEstimatedBatteryCapacityMah = (int) mPowerProfile.getBatteryCapacity();
         }
     }
 
@@ -11218,60 +11025,6 @@
         return mNextMaxDailyDeadlineMs;
     }
 
-    @Override
-    public boolean startIteratingOldHistoryLocked() {
-        if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
-                + " pos=" + mHistoryBuffer.dataPosition());
-        if ((mHistoryIterator = mHistory) == null) {
-            return false;
-        }
-        mHistoryBuffer.setDataPosition(0);
-        mHistoryReadTmp.clear();
-        mReadOverflow = false;
-        mIteratingHistory = true;
-        return true;
-    }
-
-    @Override
-    public boolean getNextOldHistoryLocked(HistoryItem out) {
-        boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize();
-        if (!end) {
-            readHistoryDelta(mHistoryBuffer, mHistoryReadTmp);
-            mReadOverflow |= mHistoryReadTmp.cmd == HistoryItem.CMD_OVERFLOW;
-        }
-        HistoryItem cur = mHistoryIterator;
-        if (cur == null) {
-            if (!mReadOverflow && !end) {
-                Slog.w(TAG, "Old history ends before new history!");
-            }
-            return false;
-        }
-        out.setTo(cur);
-        mHistoryIterator = cur.next;
-        if (!mReadOverflow) {
-            if (end) {
-                Slog.w(TAG, "New history ends before old history!");
-            } else if (!out.same(mHistoryReadTmp)) {
-                PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG));
-                pw.println("Histories differ!");
-                pw.println("Old history:");
-                (new HistoryPrinter()).printNextItem(pw, out, 0, false, true);
-                pw.println("New history:");
-                (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, 0, false,
-                        true);
-                pw.flush();
-            }
-        }
-        return true;
-    }
-
-    @Override
-    public void finishIteratingOldHistoryLocked() {
-        mIteratingHistory = false;
-        mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
-        mHistoryIterator = null;
-    }
-
     public int getHistoryTotalSize() {
         return mConstants.MAX_HISTORY_BUFFER * mConstants.MAX_HISTORY_FILES;
     }
@@ -11283,67 +11036,55 @@
     @Override
     @UnsupportedAppUsage
     public boolean startIteratingHistoryLocked() {
-        mBatteryStatsHistory.startIteratingHistory();
         mReadOverflow = false;
-        mIteratingHistory = true;
-        mReadHistoryStrings = new String[mHistoryTagPool.size()];
-        mReadHistoryUids = new int[mHistoryTagPool.size()];
-        mReadHistoryChars = 0;
-        for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
-            final HistoryTag tag = ent.getKey();
-            final int idx = ent.getValue();
-            mReadHistoryStrings[idx] = tag.string;
-            mReadHistoryUids[idx] = tag.uid;
-            mReadHistoryChars += tag.string.length() + 1;
-        }
+        mBatteryStatsHistoryIterator = createBatteryStatsHistoryIterator();
         return true;
     }
 
+    /**
+     * Creates an iterator for battery stats history.
+     */
+    @VisibleForTesting
+    public BatteryStatsHistoryIterator createBatteryStatsHistoryIterator() {
+        ArrayList<HistoryTag> tags = new ArrayList<>(mHistoryTagPool.size());
+        for (Map.Entry<HistoryTag, Integer> entry: mHistoryTagPool.entrySet()) {
+            final HistoryTag tag = entry.getKey();
+            tag.poolIdx = entry.getValue();
+            tags.add(tag);
+        }
+
+        return new BatteryStatsHistoryIterator(mBatteryStatsHistory, tags);
+    }
+
     @Override
     public int getHistoryStringPoolSize() {
-        return mReadHistoryStrings.length;
+        return mBatteryStatsHistoryIterator.getHistoryStringPoolSize();
     }
 
     @Override
     public int getHistoryStringPoolBytes() {
-        // Each entry is a fixed 12 bytes: 4 for index, 4 for uid, 4 for string size
-        // Each string character is 2 bytes.
-        return (mReadHistoryStrings.length * 12) + (mReadHistoryChars * 2);
+        return mBatteryStatsHistoryIterator.getHistoryStringPoolBytes();
     }
 
     @Override
     public String getHistoryTagPoolString(int index) {
-        return mReadHistoryStrings[index];
+        return mBatteryStatsHistoryIterator.getHistoryTagPoolString(index);
     }
 
     @Override
     public int getHistoryTagPoolUid(int index) {
-        return mReadHistoryUids[index];
+        return mBatteryStatsHistoryIterator.getHistoryTagPoolUid(index);
     }
 
     @Override
     @UnsupportedAppUsage
     public boolean getNextHistoryLocked(HistoryItem out) {
-        Parcel p = mBatteryStatsHistory.getNextParcel(out);
-        if (p == null) {
-            return false;
-        }
-        final long lastRealtimeMs = out.time;
-        final long lastWalltimeMs = out.currentTime;
-        readHistoryDelta(p, out);
-        if (out.cmd != HistoryItem.CMD_CURRENT_TIME
-                && out.cmd != HistoryItem.CMD_RESET && lastWalltimeMs != 0) {
-            out.currentTime = lastWalltimeMs + (out.time - lastRealtimeMs);
-        }
-        return true;
+        return mBatteryStatsHistoryIterator.next(out);
     }
 
     @Override
     public void finishIteratingHistoryLocked() {
-        mBatteryStatsHistory.finishIteratingHistory();
-        mIteratingHistory = false;
-        mReadHistoryStrings = null;
-        mReadHistoryUids = null;
+        mBatteryStatsHistoryIterator = null;
     }
 
     @Override
@@ -11439,12 +11180,12 @@
         }
 
         if (mPowerProfile != null) {
-            mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
+            mEstimatedBatteryCapacityMah = (int) mPowerProfile.getBatteryCapacity();
         } else {
-            mEstimatedBatteryCapacity = -1;
+            mEstimatedBatteryCapacityMah = -1;
         }
-        mMinLearnedBatteryCapacity = -1;
-        mMaxLearnedBatteryCapacity = -1;
+        mMinLearnedBatteryCapacityUah = -1;
+        mMaxLearnedBatteryCapacityUah = -1;
         mInteractiveTimer.reset(false, elapsedRealtimeUs);
         mPowerSaveModeEnabledTimer.reset(false, elapsedRealtimeUs);
         mLastIdleTimeStartMs = elapsedRealtimeMillis;
@@ -11563,7 +11304,9 @@
         initDischarge(elapsedRealtimeUs);
 
         clearHistoryLocked();
-        mBatteryStatsHistory.resetAllFiles();
+        if (mBatteryStatsHistory != null) {
+            mBatteryStatsHistory.resetAllFiles();
+        }
 
         // Flush external data, gathering snapshots, but don't process it since it is pre-reset data
         mIgnoreNextExternalStats = true;
@@ -12462,7 +12205,7 @@
             return;
         }
 
-        mGlobalMeasuredEnergyStats.updateStandardBucket(energyBucket, energyUJ, true);
+        mGlobalMeasuredEnergyStats.updateStandardBucket(energyBucket, energyUJ);
 
         // Now we blame individual apps, but only if the display was ON.
         if (energyBucket != MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON) {
@@ -12500,7 +12243,7 @@
             final long appDisplayEnergyMJ =
                     (totalDisplayEnergyMJ * fgTimeMs + (totalFgTimeMs / 2))
                     / totalFgTimeMs;
-            uid.addEnergyToStandardBucketLocked(appDisplayEnergyMJ * 1000, energyBucket, true);
+            uid.addEnergyToStandardBucketLocked(appDisplayEnergyMJ * 1000, energyBucket);
 
             // To mitigate round-off errors, remove this app from numerator & denominator totals
             totalDisplayEnergyMJ -= appDisplayEnergyMJ;
@@ -12514,6 +12257,7 @@
      * @param totalEnergyUJ energy (microjoules) used for this bucket since this was last called.
      * @param uidEnergies map of uid->energy (microjoules) for this bucket since last called.
      *                    Data inside uidEnergies will not be modified (treated immutable).
+     *                    Uids not already known to BatteryStats will be ignored.
      */
     public void updateCustomMeasuredEnergyDataLocked(int customEnergyBucket,
             long totalEnergyUJ, @Nullable SparseLongArray uidEnergies) {
@@ -12526,7 +12270,7 @@
         if (mGlobalMeasuredEnergyStats == null) return;
         if (!mOnBatteryInternal || mIgnoreNextExternalStats || totalEnergyUJ <= 0) return;
 
-        mGlobalMeasuredEnergyStats.updateCustomBucket(customEnergyBucket, totalEnergyUJ, true);
+        mGlobalMeasuredEnergyStats.updateCustomBucket(customEnergyBucket, totalEnergyUJ);
 
         if (uidEnergies == null) return;
         final int numUids = uidEnergies.size();
@@ -12534,10 +12278,20 @@
             final int uidInt = mapUid(uidEnergies.keyAt(i));
             final long uidEnergyUJ = uidEnergies.valueAt(i);
             if (uidEnergyUJ == 0) continue;
-            // TODO(b/180030409): Worry about dead Uids (no longer in BSI) being revived by this,
-            //  or converse problem of not creating a new Uid if its first blame is recorded here.
-            final Uid uidObj = getUidStatsLocked(uidInt);
-            uidObj.addEnergyToCustomBucketLocked(uidEnergyUJ, customEnergyBucket, true);
+            final Uid uidObj = getAvailableUidStatsLocked(uidInt);
+            if (uidObj != null) {
+                uidObj.addEnergyToCustomBucketLocked(uidEnergyUJ, customEnergyBucket);
+            } else {
+                // Ignore any uid not already known to BatteryStats, rather than creating a new Uid.
+                // Otherwise we could end up reviving dead Uids. Note that the CPU data is updated
+                // first, so any uid that has used any CPU should already be known to BatteryStats.
+                // Recently removed uids (especially common for isolated uids) can reach this path
+                // and are ignored.
+                if (!Process.isIsolated(uidInt)) {
+                    Slog.w(TAG, "Received measured energy " + totalEnergyUJ + " for custom bucket "
+                        + customEnergyBucket + " for non-existent uid " + uidInt);
+                }
+            }
         }
     }
 
@@ -13212,7 +12966,7 @@
 
     @GuardedBy("this")
     protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime,
-            final boolean onBattery, final int oldStatus, final int level, final int chargeUAh) {
+            final boolean onBattery, final int oldStatus, final int level, final int chargeUah) {
         boolean doWrite = false;
         Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
         m.arg1 = onBattery ? 1 : 0;
@@ -13268,10 +13022,10 @@
                 }
                 doWrite = true;
                 resetAllStatsLocked(mSecUptime, mSecRealtime);
-                if (chargeUAh > 0 && level > 0) {
-                    mBatteryCharge = chargeUAh;
+                if (chargeUah > 0 && level > 0) {
+                    mBatteryChargeUah = chargeUah;
                     // Only use the reported coulomb charge value if it is supported and reported.
-                    mEstimatedBatteryCapacity = (int) ((chargeUAh / 1000) / (level / 100.0));
+                    mEstimatedBatteryCapacityMah = (int) ((chargeUah / 1000) / (level / 100.0));
                 }
                 mDischargeStartLevel = level;
                 reset = true;
@@ -13386,16 +13140,16 @@
 
     @GuardedBy("this")
     public void setBatteryStateLocked(final int status, final int health, final int plugType,
-            final int level, /* not final */ int temp, final int volt, final int chargeUAh,
-            final int chargeFullUAh, final long chargeTimeToFullSeconds) {
-        setBatteryStateLocked(status, health, plugType, level, temp, volt, chargeUAh,
-                chargeFullUAh, chargeTimeToFullSeconds,
+            final int level, /* not final */ int temp, final int voltageMv, final int chargeUah,
+            final int chargeFullUah, final long chargeTimeToFullSeconds) {
+        setBatteryStateLocked(status, health, plugType, level, temp, voltageMv, chargeUah,
+                chargeFullUah, chargeTimeToFullSeconds,
                 mClocks.elapsedRealtime(), mClocks.uptimeMillis(), System.currentTimeMillis());
     }
 
     public void setBatteryStateLocked(final int status, final int health, final int plugType,
-            final int level, /* not final */ int temp, final int volt, final int chargeUAh,
-            final int chargeFullUAh, final long chargeTimeToFullSeconds,
+            final int level, /* not final */ int temp, final int voltageMv, final int chargeUah,
+            final int chargeFullUah, final long chargeTimeToFullSeconds,
             final long elapsedRealtimeMs, final long uptimeMs, final long currentTimeMs) {
         // Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
         temp = Math.max(0, temp);
@@ -13421,7 +13175,7 @@
             mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
             mHistoryCur.batteryStatus = (byte)status;
             mHistoryCur.batteryLevel = (byte)level;
-            mHistoryCur.batteryChargeUAh = chargeUAh;
+            mHistoryCur.batteryChargeUah = chargeUah;
             mMaxChargeStepLevel = mMinDischargeStepLevel =
                     mLastChargeStepLevel = mLastDischargeStepLevel = level;
             mLastChargingStateLevel = level;
@@ -13444,10 +13198,10 @@
         }
 
         if (ENABLE_FOREGROUND_STATS_COLLECTION) {
-            mBatteryVolt = volt;
+            mBatteryVoltageMv = voltageMv;
             if (onBattery) {
-                final long energyNwh = (volt * (long) chargeUAh);
-                final long energyDelta = mLastBatteryEnergyCapacityNWh - energyNwh;
+                final long energyNwh = (voltageMv * (long) chargeUah);
+                final long energyDelta = mLastBatteryEnergyCapacityNwh - energyNwh;
                 for (int i = 0; i < mForegroundUids.size(); i++) {
                     final int uid = mForegroundUids.get(i);
                     if (uid == INVALID_UID) {
@@ -13458,7 +13212,7 @@
                     if (pfu.baseTimeMs <= 0) {
                         pfu.baseTimeMs = currentTimeMs;
                     } else {
-                        // Check if mLastBatteryEnergyCapacityNWh > energyNwh,
+                        // Check if mLastBatteryEnergyCapacityNwh > energyNwh,
                         // to make sure we only count discharges
                         if (energyDelta > 0) {
                             pfu.energyNwh += energyDelta;
@@ -13476,7 +13230,7 @@
                         pfu.baseTimeMs = currentTimeMs;
                     }
                 }
-                mLastBatteryEnergyCapacityNWh = energyNwh;
+                mLastBatteryEnergyCapacityNwh = energyNwh;
             } else if (onBattery != mOnBattery) {
                 // Transition to onBattery = false
                 mUidToPower.values().forEach(v -> v.baseTimeMs = 0);
@@ -13494,10 +13248,10 @@
             mHistoryCur.batteryHealth = (byte)health;
             mHistoryCur.batteryPlugType = (byte)plugType;
             mHistoryCur.batteryTemperature = (short)temp;
-            mHistoryCur.batteryVoltage = (char)volt;
-            if (chargeUAh < mHistoryCur.batteryChargeUAh) {
+            mHistoryCur.batteryVoltage = (char) voltageMv;
+            if (chargeUah < mHistoryCur.batteryChargeUah) {
                 // Only record discharges
-                final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
+                final long chargeDiff = mHistoryCur.batteryChargeUah - chargeUah;
                 mDischargeCounter.addCountLocked(chargeDiff);
                 mDischargeScreenOffCounter.addCountLocked(chargeDiff);
                 if (Display.isDozeState(mScreenState)) {
@@ -13509,8 +13263,8 @@
                     mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
                 }
             }
-            mHistoryCur.batteryChargeUAh = chargeUAh;
-            setOnBatteryLocked(elapsedRealtimeMs, uptimeMs, onBattery, oldStatus, level, chargeUAh);
+            mHistoryCur.batteryChargeUah = chargeUah;
+            setOnBatteryLocked(elapsedRealtimeMs, uptimeMs, onBattery, oldStatus, level, chargeUah);
         } else {
             boolean changed = false;
             if (mHistoryCur.batteryLevel != level) {
@@ -13539,16 +13293,16 @@
                 mHistoryCur.batteryTemperature = (short)temp;
                 changed = true;
             }
-            if (volt > (mHistoryCur.batteryVoltage+20)
-                    || volt < (mHistoryCur.batteryVoltage-20)) {
-                mHistoryCur.batteryVoltage = (char)volt;
+            if (voltageMv > (mHistoryCur.batteryVoltage + 20)
+                    || voltageMv < (mHistoryCur.batteryVoltage - 20)) {
+                mHistoryCur.batteryVoltage = (char) voltageMv;
                 changed = true;
             }
-            if (chargeUAh >= (mHistoryCur.batteryChargeUAh+10)
-                    || chargeUAh <= (mHistoryCur.batteryChargeUAh-10)) {
-                if (chargeUAh < mHistoryCur.batteryChargeUAh) {
+            if (chargeUah >= (mHistoryCur.batteryChargeUah + 10)
+                    || chargeUah <= (mHistoryCur.batteryChargeUah - 10)) {
+                if (chargeUah < mHistoryCur.batteryChargeUah) {
                     // Only record discharges
-                    final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
+                    final long chargeDiff = mHistoryCur.batteryChargeUah - chargeUah;
                     mDischargeCounter.addCountLocked(chargeDiff);
                     mDischargeScreenOffCounter.addCountLocked(chargeDiff);
                     if (Display.isDozeState(mScreenState)) {
@@ -13560,7 +13314,7 @@
                         mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
                     }
                 }
-                mHistoryCur.batteryChargeUAh = chargeUAh;
+                mHistoryCur.batteryChargeUah = chargeUah;
                 changed = true;
             }
             long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
@@ -13632,12 +13386,12 @@
             mRecordingHistory = DEBUG;
         }
 
-        if (mMinLearnedBatteryCapacity == -1) {
-            mMinLearnedBatteryCapacity = chargeFullUAh;
+        if (mMinLearnedBatteryCapacityUah == -1) {
+            mMinLearnedBatteryCapacityUah = chargeFullUah;
         } else {
-            mMinLearnedBatteryCapacity = Math.min(mMinLearnedBatteryCapacity, chargeFullUAh);
+            mMinLearnedBatteryCapacityUah = Math.min(mMinLearnedBatteryCapacityUah, chargeFullUah);
         }
-        mMaxLearnedBatteryCapacity = Math.max(mMaxLearnedBatteryCapacity, chargeFullUAh);
+        mMaxLearnedBatteryCapacityUah = Math.max(mMaxLearnedBatteryCapacityUah, chargeFullUah);
 
         mBatteryTimeToFullSeconds = chargeTimeToFullSeconds;
     }
@@ -14620,7 +14374,7 @@
 
         Parcel p = Parcel.obtain();
         final long start = SystemClock.uptimeMillis();
-        writeHistoryBuffer(p, true, true);
+        writeHistoryBuffer(p, true);
         if (DEBUG) {
             Slog.d(TAG, "writeHistoryBuffer duration ms:"
                     + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
@@ -14714,7 +14468,7 @@
                 if (raw.length > 0) {
                     history.unmarshall(raw, 0, raw.length);
                     history.setDataPosition(0);
-                    readHistoryBuffer(history, true);
+                    readHistoryBuffer(history);
                 }
                 if (DEBUG) {
                     Slog.d(TAG, "readLocked history file::"
@@ -14738,10 +14492,6 @@
             mRecordingHistory = true;
             final long elapsedRealtimeMs = mClocks.elapsedRealtime();
             final long uptimeMs = mClocks.uptimeMillis();
-            if (USE_OLD_HISTORY) {
-                addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs,
-                        HistoryItem.CMD_START, mHistoryCur);
-            }
             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_START, mHistoryCur);
             startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
         }
@@ -14753,7 +14503,7 @@
         return 0;
     }
 
-    void  readHistoryBuffer(Parcel in, boolean andOldHistory) throws ParcelFormatException {
+    void  readHistoryBuffer(Parcel in) throws ParcelFormatException {
         final int version = in.readInt();
         if (version != VERSION) {
             Slog.w("BatteryStats", "readHistoryBuffer: version got " + version
@@ -14781,10 +14531,6 @@
             in.setDataPosition(curPos + bufSize);
         }
 
-        if (andOldHistory) {
-            readOldHistory(in);
-        }
-
         if (DEBUG_HISTORY) {
             StringBuilder sb = new StringBuilder(128);
             sb.append("****************** OLD mHistoryBaseTimeMs: ");
@@ -14813,18 +14559,7 @@
         }
     }
 
-    void readOldHistory(Parcel in) {
-        if (!USE_OLD_HISTORY) {
-            return;
-        }
-        mHistory = mHistoryEnd = mHistoryCache = null;
-        while (in.dataAvail() > 0) {
-            HistoryItem rec = new HistoryItem(in);
-            addHistoryRecordLocked(rec);
-        }
-    }
-
-    void writeHistoryBuffer(Parcel out, boolean inclData, boolean andOldHistory) {
+    void writeHistoryBuffer(Parcel out, boolean inclData) {
         if (DEBUG_HISTORY) {
             StringBuilder sb = new StringBuilder(128);
             sb.append("****************** WRITING mHistoryBaseTimeMs: ");
@@ -14845,22 +14580,6 @@
         if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
                 + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
         out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
-
-        if (andOldHistory) {
-            writeOldHistory(out);
-        }
-    }
-
-    void writeOldHistory(Parcel out) {
-        if (!USE_OLD_HISTORY) {
-            return;
-        }
-        HistoryItem rec = mHistory;
-        while (rec != null) {
-            if (rec.time >= 0) rec.writeToParcel(out, 0);
-            rec = rec.next;
-        }
-        out.writeLong(-1);
     }
 
     public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
@@ -14873,7 +14592,7 @@
 
         boolean inclHistory = in.readBoolean();
         if (inclHistory) {
-            readHistoryBuffer(in, true);
+            readHistoryBuffer(in);
             mBatteryStatsHistory.readFromParcel(in);
         }
 
@@ -14912,9 +14631,9 @@
         mDischargePlugLevel = in.readInt();
         mDischargeCurrentLevel = in.readInt();
         mCurrentBatteryLevel = in.readInt();
-        mEstimatedBatteryCapacity = in.readInt();
-        mMinLearnedBatteryCapacity = in.readInt();
-        mMaxLearnedBatteryCapacity = in.readInt();
+        mEstimatedBatteryCapacityMah = in.readInt();
+        mMinLearnedBatteryCapacityUah = in.readInt();
+        mMaxLearnedBatteryCapacityUah = in.readInt();
         mLowDischargeAmountSinceCharge = in.readInt();
         mHighDischargeAmountSinceCharge = in.readInt();
         mDischargeAmountScreenOnSinceCharge = in.readInt();
@@ -15392,7 +15111,7 @@
 
         out.writeBoolean(inclHistory);
         if (inclHistory) {
-            writeHistoryBuffer(out, true, true);
+            writeHistoryBuffer(out, true);
             mBatteryStatsHistory.writeToParcel(out);
         }
 
@@ -15416,9 +15135,9 @@
         out.writeInt(mDischargePlugLevel);
         out.writeInt(mDischargeCurrentLevel);
         out.writeInt(mCurrentBatteryLevel);
-        out.writeInt(mEstimatedBatteryCapacity);
-        out.writeInt(mMinLearnedBatteryCapacity);
-        out.writeInt(mMaxLearnedBatteryCapacity);
+        out.writeInt(mEstimatedBatteryCapacityMah);
+        out.writeInt(mMinLearnedBatteryCapacityUah);
+        out.writeInt(mMaxLearnedBatteryCapacityUah);
         out.writeInt(getLowDischargeAmountSinceCharge());
         out.writeInt(getHighDischargeAmountSinceCharge());
         out.writeInt(getDischargeAmountScreenOnSinceCharge());
@@ -15905,7 +15624,7 @@
             throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
         }
 
-        readHistoryBuffer(in, false);
+        readHistoryBuffer(in);
         mBatteryStatsHistory.readFromParcel(in);
 
         mStartCount = in.readInt();
@@ -15917,9 +15636,9 @@
         mRealtimeUs = in.readLong();
         mRealtimeStartUs = in.readLong();
         mOnBattery = in.readInt() != 0;
-        mEstimatedBatteryCapacity = in.readInt();
-        mMinLearnedBatteryCapacity = in.readInt();
-        mMaxLearnedBatteryCapacity = in.readInt();
+        mEstimatedBatteryCapacityMah = in.readInt();
+        mMinLearnedBatteryCapacityUah = in.readInt();
+        mMaxLearnedBatteryCapacityUah = in.readInt();
         mOnBatteryInternal = false; // we are no longer really running.
         mOnBatteryTimeBase.readFromParcel(in);
         mOnBatteryScreenOffTimeBase.readFromParcel(in);
@@ -16144,7 +15863,7 @@
 
         out.writeInt(MAGIC);
 
-        writeHistoryBuffer(out, true, false);
+        writeHistoryBuffer(out, true);
         mBatteryStatsHistory.writeToParcel(out);
 
         out.writeInt(mStartCount);
@@ -16156,9 +15875,9 @@
         out.writeLong(mRealtimeUs);
         out.writeLong(mRealtimeStartUs);
         out.writeInt(mOnBattery ? 1 : 0);
-        out.writeInt(mEstimatedBatteryCapacity);
-        out.writeInt(mMinLearnedBatteryCapacity);
-        out.writeInt(mMaxLearnedBatteryCapacity);
+        out.writeInt(mEstimatedBatteryCapacityMah);
+        out.writeInt(mMinLearnedBatteryCapacityUah);
+        out.writeInt(mMaxLearnedBatteryCapacityUah);
         mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
         mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
 
@@ -16414,8 +16133,8 @@
 
     public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
         if (ENABLE_FOREGROUND_STATS_COLLECTION) {
-            long actualCharge = -1;
-            long actualEnergy = -1;
+            long actualChargeUah = -1;
+            long actualEnergyNwh = -1;
             try {
                 IBatteryPropertiesRegistrar registrar =
                         IBatteryPropertiesRegistrar.Stub.asInterface(
@@ -16424,27 +16143,27 @@
                     BatteryProperty prop = new BatteryProperty();
                     if (registrar.getProperty(
                                 BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER, prop) == 0) {
-                        actualCharge = prop.getLong();
+                        actualChargeUah = prop.getLong();
                     }
                     prop = new BatteryProperty();
                     if (registrar.getProperty(
                                 BatteryManager.BATTERY_PROPERTY_ENERGY_COUNTER, prop) == 0) {
-                        actualEnergy = prop.getLong();
+                        actualEnergyNwh = prop.getLong();
                     }
                 }
             } catch (RemoteException e) {
                 // Ignore.
             }
-            pw.printf("ActualCharge (uAh): %d\n", (int) actualCharge);
-            pw.printf("ActualEnergy (nWh): %d\n", actualEnergy);
-            pw.printf("mBatteryCharge (uAh): %d\n", mBatteryCharge);
-            pw.printf("mBatteryVolts (mV): %d\n", mBatteryVolt);
-            pw.printf("est energy (nWh): %d\n", mBatteryVolt * (long) mBatteryCharge);
-            pw.printf("mEstimatedBatteryCapacity (mAh): %d\n", mEstimatedBatteryCapacity);
-            pw.printf("mMinLearnedBatteryCapacity (uAh): %d\n", mMinLearnedBatteryCapacity);
-            pw.printf("mMaxLearnedBatteryCapacity (uAh): %d\n", mMaxLearnedBatteryCapacity);
+            pw.printf("ActualCharge (uAh): %d\n", (int) actualChargeUah);
+            pw.printf("ActualEnergy (nWh): %d\n", actualEnergyNwh);
+            pw.printf("mBatteryCharge (uAh): %d\n", mBatteryChargeUah);
+            pw.printf("mBatteryVolts (mV): %d\n", mBatteryVoltageMv);
+            pw.printf("est energy (nWh): %d\n", mBatteryVoltageMv * (long) mBatteryChargeUah);
+            pw.printf("mEstimatedBatteryCapacity (mAh): %d\n", mEstimatedBatteryCapacityMah);
+            pw.printf("mMinLearnedBatteryCapacity (uAh): %d\n", mMinLearnedBatteryCapacityUah);
+            pw.printf("mMaxLearnedBatteryCapacity (uAh): %d\n", mMaxLearnedBatteryCapacityUah);
             pw.printf("est. capacity: %f\n",
-                    (float) actualCharge / (mEstimatedBatteryCapacity * 1000));
+                    (float) actualChargeUah / (mEstimatedBatteryCapacityMah * 1000));
             pw.printf("mCurrentBatteryLevel: %d\n", mCurrentBatteryLevel);
             pw.println("Total Power per app:");
             mUidToPower.entrySet().forEach(e ->
diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
index 233ba19..15b584d 100644
--- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
+++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
@@ -22,12 +22,15 @@
 import android.os.BatteryUsageStats;
 import android.os.BatteryUsageStatsQuery;
 import android.os.Bundle;
-import android.os.SystemClock;
+import android.os.UidBatteryConsumer;
 import android.os.UserHandle;
 import android.util.SparseArray;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Uses accumulated battery stats data and PowerCalculators to produce power
@@ -52,6 +55,7 @@
                 mPowerCalculators = new ArrayList<>();
 
                 // Power calculators are applied in the order of registration
+                mPowerCalculators.add(new DischargedPowerCalculator(mPowerProfile));
                 mPowerCalculators.add(new CpuPowerCalculator(mPowerProfile));
                 mPowerCalculators.add(new MemoryPowerCalculator(mPowerProfile));
                 mPowerCalculators.add(new WakelockPowerCalculator(mPowerProfile));
@@ -84,7 +88,7 @@
     }
 
     /**
-     * Returns a snapshot of battery attribution data.
+     * Returns snapshots of battery attribution data, one per supplied query.
      */
     public List<BatteryUsageStats> getBatteryUsageStats(List<BatteryUsageStatsQuery> queries) {
 
@@ -106,30 +110,42 @@
 
         ArrayList<BatteryUsageStats> results = new ArrayList<>(queries.size());
         for (int i = 0; i < queries.size(); i++) {
-            results.add(getBatteryUsageStats(queries.get(i), batteryStatsHelper));
+            results.add(getBatteryUsageStats(queries.get(i)));
         }
         return results;
     }
 
-    private BatteryUsageStats getBatteryUsageStats(BatteryUsageStatsQuery query,
-            BatteryStatsHelper batteryStatsHelper) {
-        // TODO(b/174186358): read extra power component number from configuration
-        final int customPowerComponentCount = 0;
+    /**
+     * Returns a snapshot of battery attribution data.
+     */
+    @VisibleForTesting
+    public BatteryUsageStats getBatteryUsageStats(BatteryUsageStatsQuery query) {
+        final long realtimeUs = mStats.mClocks.elapsedRealtime() * 1000;
+        final long uptimeUs = mStats.mClocks.uptimeMillis() * 1000;
+
+        final long[] customMeasuredEnergiesMicroJoules =
+                mStats.getCustomMeasuredEnergiesMicroJoules();
+        final int customPowerComponentCount = customMeasuredEnergiesMicroJoules != null
+                ? customMeasuredEnergiesMicroJoules.length
+                : 0;
+
+        // TODO(b/174186358): read extra time component number from configuration
         final int customTimeComponentCount = 0;
 
         final BatteryUsageStats.Builder batteryUsageStatsBuilder =
                 new BatteryUsageStats.Builder(customPowerComponentCount, customTimeComponentCount)
-                        .setDischargePercentage(batteryStatsHelper.getStats().getDischargeAmount(0))
-                        .setConsumedPower(batteryStatsHelper.getTotalPower());
+                        .setStatsStartRealtime(mStats.getStatsStartRealtime() / 1000);
 
         SparseArray<? extends BatteryStats.Uid> uidStats = mStats.getUidStats();
         for (int i = uidStats.size() - 1; i >= 0; i--) {
-            batteryUsageStatsBuilder.getOrCreateUidBatteryConsumerBuilder(uidStats.valueAt(i));
+            final BatteryStats.Uid uid = uidStats.valueAt(i);
+            batteryUsageStatsBuilder.getOrCreateUidBatteryConsumerBuilder(uid)
+                    .setTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND,
+                            getProcessBackgroundTimeMs(uid, realtimeUs))
+                    .setTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND,
+                            getProcessForegroundTimeMs(uid, realtimeUs));
         }
 
-        final long realtimeUs = SystemClock.elapsedRealtime() * 1000;
-        final long uptimeUs = SystemClock.uptimeMillis() * 1000;
-
         final List<PowerCalculator> powerCalculators = getPowerCalculators();
         for (int i = 0, count = powerCalculators.size(); i < count; i++) {
             PowerCalculator powerCalculator = powerCalculators.get(i);
@@ -137,6 +153,51 @@
                     query);
         }
 
+        if ((query.getFlags()
+                & BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_HISTORY) != 0) {
+            ArrayList<BatteryStats.HistoryTag> tags = new ArrayList<>(
+                    mStats.mHistoryTagPool.size());
+            for (Map.Entry<BatteryStats.HistoryTag, Integer> entry :
+                    mStats.mHistoryTagPool.entrySet()) {
+                final BatteryStats.HistoryTag tag = entry.getKey();
+                tag.poolIdx = entry.getValue();
+                tags.add(tag);
+            }
+
+            batteryUsageStatsBuilder.setBatteryHistory(mStats.mHistoryBuffer, tags);
+        }
+
         return batteryUsageStatsBuilder.build();
     }
+
+    private long getProcessForegroundTimeMs(BatteryStats.Uid uid, long realtimeUs) {
+        final long topStateDurationMs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_TOP,
+                realtimeUs, BatteryStats.STATS_SINCE_CHARGED) / 1000;
+
+        long foregroundActivityDurationMs = 0;
+        final BatteryStats.Timer foregroundActivityTimer = uid.getForegroundActivityTimer();
+        if (foregroundActivityTimer != null) {
+            foregroundActivityDurationMs = foregroundActivityTimer.getTotalTimeLocked(realtimeUs,
+                    BatteryStats.STATS_SINCE_CHARGED) / 1000;
+        }
+
+        // Use the min value of STATE_TOP time and foreground activity time, since both of these
+        // times are imprecise
+        final long foregroundDurationMs = Math.min(topStateDurationMs,
+                foregroundActivityDurationMs);
+
+        long foregroundServiceDurationMs = 0;
+        final BatteryStats.Timer foregroundServiceTimer = uid.getForegroundServiceTimer();
+        if (foregroundServiceTimer != null) {
+            foregroundServiceDurationMs = foregroundServiceTimer.getTotalTimeLocked(realtimeUs,
+                    BatteryStats.STATS_SINCE_CHARGED) / 1000;
+        }
+
+        return foregroundDurationMs + foregroundServiceDurationMs;
+    }
+
+    private long getProcessBackgroundTimeMs(BatteryStats.Uid uid, long realtimeUs) {
+        return uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_BACKGROUND, realtimeUs,
+                BatteryStats.STATS_SINCE_CHARGED) / 1000;
+    }
 }
diff --git a/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java b/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java
index 4babe8d..2606d80 100644
--- a/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java
+++ b/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java
@@ -15,7 +15,12 @@
  */
 package com.android.internal.os;
 
+import android.os.BatteryConsumer;
 import android.os.BatteryStats;
+import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
+import android.os.SystemBatteryConsumer;
+import android.os.UidBatteryConsumer;
 
 /**
  * Calculates the amount of power consumed by custom energy consumers (i.e. consumers of type
@@ -26,6 +31,38 @@
     }
 
     @Override
+    public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
+            long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
+        super.calculate(builder, batteryStats, rawRealtimeUs, rawUptimeUs, query);
+        final double[] customMeasuredPowerMah = calculateMeasuredEnergiesMah(
+                batteryStats.getCustomMeasuredEnergiesMicroJoules());
+        if (customMeasuredPowerMah != null) {
+            final SystemBatteryConsumer.Builder systemBatteryConsumerBuilder =
+                    builder.getOrCreateSystemBatteryConsumerBuilder(
+                            SystemBatteryConsumer.DRAIN_TYPE_CUSTOM);
+            for (int i = 0; i < customMeasuredPowerMah.length; i++) {
+                systemBatteryConsumerBuilder.setConsumedPowerForCustomComponent(
+                        BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + i,
+                        customMeasuredPowerMah[i]);
+            }
+        }
+    }
+
+    @Override
+    protected void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
+            long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
+        final double[] customMeasuredPowerMah = calculateMeasuredEnergiesMah(
+                u.getCustomMeasuredEnergiesMicroJoules());
+        if (customMeasuredPowerMah != null) {
+            for (int i = 0; i < customMeasuredPowerMah.length; i++) {
+                app.setConsumedPowerForCustomComponent(
+                        BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + i,
+                        customMeasuredPowerMah[i]);
+            }
+        }
+    }
+
+    @Override
     protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
             long rawUptimeUs, int statsType) {
         updateCustomMeasuredPowerMah(app, u.getCustomMeasuredEnergiesMicroJoules());
diff --git a/core/java/com/android/internal/os/DischargedPowerCalculator.java b/core/java/com/android/internal/os/DischargedPowerCalculator.java
new file mode 100644
index 0000000..e94020c
--- /dev/null
+++ b/core/java/com/android/internal/os/DischargedPowerCalculator.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.os.BatteryStats;
+import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
+import android.os.UserHandle;
+import android.util.SparseArray;
+
+import java.util.List;
+
+/**
+ * Estimates the battery discharge amounts.
+ */
+public class DischargedPowerCalculator extends PowerCalculator {
+    private final double mBatteryCapacity;
+
+    public DischargedPowerCalculator(PowerProfile powerProfile) {
+        mBatteryCapacity = powerProfile.getBatteryCapacity();
+    }
+
+    @Override
+    public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
+            long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
+        builder.setDischargePercentage(
+                        batteryStats.getDischargeAmount(BatteryStats.STATS_SINCE_CHARGED))
+                .setDischargedPowerRange(
+                        batteryStats.getLowDischargeAmountSinceCharge() * mBatteryCapacity / 100,
+                        batteryStats.getHighDischargeAmountSinceCharge() * mBatteryCapacity / 100);
+    }
+
+    @Override
+    public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
+            long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
+        // Not implemented. The computation is done by BatteryStatsHelper
+    }
+}
diff --git a/core/java/com/android/internal/os/KernelCpuBpfTracking.java b/core/java/com/android/internal/os/KernelCpuBpfTracking.java
index 2852547..387d327 100644
--- a/core/java/com/android/internal/os/KernelCpuBpfTracking.java
+++ b/core/java/com/android/internal/os/KernelCpuBpfTracking.java
@@ -16,11 +16,79 @@
 
 package com.android.internal.os;
 
-/** CPU tracking using eBPF. */
+import android.annotation.Nullable;
+
+/**
+ * CPU tracking using eBPF.
+ *
+ * The tracking state and data about available frequencies are cached to avoid JNI calls and
+ * creating temporary arrays. The data is stored in a format that is convenient for metrics
+ * computation.
+ *
+ * Synchronization is not needed because the underlying native library can be invoked concurrently
+ * and getters are idempotent.
+ */
 public final class KernelCpuBpfTracking {
+    private static boolean sTracking = false;
+
+    /** Cached mapping from frequency index to frequency in kHz. */
+    private static long[] sFreqs = null;
+
+    /** Cached mapping from frequency index to CPU cluster / policy. */
+    private static int[] sFreqsClusters = null;
+
     private KernelCpuBpfTracking() {
     }
 
     /** Returns whether CPU tracking using eBPF is supported. */
     public static native boolean isSupported();
+
+    /** Starts CPU tracking using eBPF. */
+    public static boolean startTracking() {
+        if (!sTracking) {
+            sTracking = startTrackingInternal();
+        }
+        return sTracking;
+    }
+
+    private static native boolean startTrackingInternal();
+
+    /** Returns frequencies in kHz on which CPU is tracked. Empty if not supported. */
+    public static long[] getFreqs() {
+        if (sFreqs == null) {
+            long[] freqs = getFreqsInternal();
+            if (freqs == null) {
+                return new long[0];
+            }
+            sFreqs = freqs;
+        }
+        return sFreqs;
+    }
+
+    @Nullable
+    static native long[] getFreqsInternal();
+
+    /**
+     * Returns the cluster (policy) number  for each frequency on which CPU is tracked. Empty if
+     * not supported.
+     */
+    public static int[] getFreqsClusters() {
+        if (sFreqsClusters == null) {
+            int[] freqsClusters = getFreqsClustersInternal();
+            if (freqsClusters == null) {
+                return new int[0];
+            }
+            sFreqsClusters = freqsClusters;
+        }
+        return sFreqsClusters;
+    }
+
+    @Nullable
+    private static native int[] getFreqsClustersInternal();
+
+    /** Returns the number of clusters (policies). */
+    public static int getClusters() {
+        int[] freqClusters = getFreqsClusters();
+        return freqClusters.length > 0 ? freqClusters[freqClusters.length - 1] + 1 : 0;
+    }
 }
diff --git a/core/java/com/android/internal/os/KernelCpuTotalBpfMapReader.java b/core/java/com/android/internal/os/KernelCpuTotalBpfMapReader.java
index 06760e1..553eda4 100644
--- a/core/java/com/android/internal/os/KernelCpuTotalBpfMapReader.java
+++ b/core/java/com/android/internal/os/KernelCpuTotalBpfMapReader.java
@@ -16,22 +16,22 @@
 
 package com.android.internal.os;
 
-/**
- * Reads total CPU time bpf map.
- */
+import android.annotation.Nullable;
+
+/** Reads total CPU time bpf map. */
 public final class KernelCpuTotalBpfMapReader {
     private KernelCpuTotalBpfMapReader() {
     }
 
-    /** Reads total CPU time from bpf map. */
-    public static native boolean read(Callback callback);
-
-    /** Callback accepting values read from bpf map. */
-    public interface Callback {
-        /**
-         * Accepts values read from bpf map: cluster index, frequency in kilohertz and time in
-         * milliseconds that the cpu cluster spent at the frequency (excluding sleep).
-         */
-        void accept(int cluster, int freqKhz, long timeMs);
+    /** Reads total CPU times (excluding sleep) per frequency in milliseconds from bpf map. */
+    @Nullable
+    public static long[] read() {
+        if (!KernelCpuBpfTracking.startTracking()) {
+            return null;
+        }
+        return readInternal();
     }
+
+    @Nullable
+    private static native long[] readInternal();
 }
diff --git a/core/java/com/android/internal/os/KernelCpuUidBpfMapReader.java b/core/java/com/android/internal/os/KernelCpuUidBpfMapReader.java
index dafb924..52c0c3f 100644
--- a/core/java/com/android/internal/os/KernelCpuUidBpfMapReader.java
+++ b/core/java/com/android/internal/os/KernelCpuUidBpfMapReader.java
@@ -68,14 +68,15 @@
 
     final String mTag = this.getClass().getSimpleName();
     private int mErrors = 0;
-    private boolean mTracking = false;
     protected SparseArray<long[]> mData = new SparseArray<>();
     private long mLastReadTime = 0;
     protected final ReentrantReadWriteLock mLock = new ReentrantReadWriteLock();
     protected final ReentrantReadWriteLock.ReadLock mReadLock = mLock.readLock();
     protected final ReentrantReadWriteLock.WriteLock mWriteLock = mLock.writeLock();
 
-    public native boolean startTrackingBpfTimes();
+    public boolean startTrackingBpfTimes() {
+        return KernelCpuBpfTracking.startTracking();
+    }
 
     protected abstract boolean readBpfData();
 
@@ -116,7 +117,7 @@
         if (mErrors > ERROR_THRESHOLD) {
             return null;
         }
-        if (!mTracking && !startTrackingBpfTimes()) {
+        if (!startTrackingBpfTimes()) {
             Slog.w(mTag, "Failed to start tracking");
             mErrors++;
             return null;
@@ -182,7 +183,9 @@
         protected final native boolean readBpfData();
 
         @Override
-        public final native long[] getDataDimensions();
+        public final long[] getDataDimensions() {
+            return KernelCpuBpfTracking.getFreqsInternal();
+        }
 
         @Override
         public void removeUidsInRange(int startUid, int endUid) {
diff --git a/core/java/com/android/internal/os/KernelCpuUidTimeReader.java b/core/java/com/android/internal/os/KernelCpuUidTimeReader.java
index 4299f09..64c68ce 100644
--- a/core/java/com/android/internal/os/KernelCpuUidTimeReader.java
+++ b/core/java/com/android/internal/os/KernelCpuUidTimeReader.java
@@ -152,6 +152,10 @@
      */
     public void removeUid(int uid) {
         mLastTimes.delete(uid);
+
+        if (mBpfTimesAvailable) {
+            mBpfReader.removeUidsInRange(uid, uid);
+        }
     }
 
     /**
diff --git a/core/java/com/android/internal/os/PowerCalculator.java b/core/java/com/android/internal/os/PowerCalculator.java
index 7c45cc0..fe4fb7a 100644
--- a/core/java/com/android/internal/os/PowerCalculator.java
+++ b/core/java/com/android/internal/os/PowerCalculator.java
@@ -113,6 +113,19 @@
     }
 
     /**
+     * Returns either the measured energy converted to mAh or a usage-based estimate.
+     */
+    protected static double getMeasuredOrEstimatedPower(long measuredEnergyUj,
+            UsageBasedPowerEstimator powerEstimator, long durationMs,
+            boolean forceUsePowerProfileModel) {
+        if (measuredEnergyUj != BatteryStats.ENERGY_DATA_UNAVAILABLE
+                && !forceUsePowerProfileModel) {
+            return uJtoMah(measuredEnergyUj);
+        }
+        return powerEstimator.calculatePower(durationMs);
+    }
+
+    /**
      * Converts charge in mAh to string.
      */
     public static String formatCharge(double power) {
diff --git a/core/java/com/android/internal/os/ScreenPowerCalculator.java b/core/java/com/android/internal/os/ScreenPowerCalculator.java
index c1dd7ce..5dca8d5 100644
--- a/core/java/com/android/internal/os/ScreenPowerCalculator.java
+++ b/core/java/com/android/internal/os/ScreenPowerCalculator.java
@@ -61,12 +61,10 @@
     public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
             long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
         final PowerAndDuration totalPowerAndDuration = new PowerAndDuration();
-        final boolean forceUsePowerProfileModel = (query.getFlags()
-                & BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_POWER_PROFILE_MODEL) != 0;
 
         final boolean useEnergyData = calculateTotalDurationAndPower(totalPowerAndDuration,
                 batteryStats, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED,
-                forceUsePowerProfileModel);
+                query.shouldForceUsePowerProfileModel());
 
         builder.getOrCreateSystemBatteryConsumerBuilder(SystemBatteryConsumer.DRAIN_TYPE_SCREEN)
                 .setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_USAGE,
diff --git a/core/java/com/android/internal/os/TEST_MAPPING b/core/java/com/android/internal/os/TEST_MAPPING
index 9698f19..791e9ad 100644
--- a/core/java/com/android/internal/os/TEST_MAPPING
+++ b/core/java/com/android/internal/os/TEST_MAPPING
@@ -1,6 +1,23 @@
 {
   "presubmit": [
     {
+      "file_patterns": ["Battery[^/]*\\.java"],
+      "name": "FrameworksCoreTests",
+      "options": [
+        { "include-filter": "com.android.internal.os.BatteryStatsTests" },
+        { "exclude-annotation": "com.android.internal.os.SkipPresubmit" }
+      ]
+    },
+    {
+      "file_patterns": ["Battery[^/]*\\.java"],
+      "name": "FrameworksServicesTests",
+      "options": [
+        { "include-filter": "com.android.server.am.BatteryStatsServiceTest" },
+        { "include-filter": "com.android.server.am.MeasuredEnergySnapshotTest" },
+        { "include-filter": "com.android.server.am.BatteryExternalStatsWorkerTest" }
+      ]
+    },
+    {
       "name": "FrameworksCoreTests",
       "options": [
         {
diff --git a/core/java/com/android/internal/os/UsageBasedPowerEstimator.java b/core/java/com/android/internal/os/UsageBasedPowerEstimator.java
index 5910b61..fd52014 100644
--- a/core/java/com/android/internal/os/UsageBasedPowerEstimator.java
+++ b/core/java/com/android/internal/os/UsageBasedPowerEstimator.java
@@ -32,6 +32,10 @@
         mAveragePowerMahPerMs = averagePowerMilliAmp / MILLIS_IN_HOUR;
     }
 
+    public boolean isSupported() {
+        return mAveragePowerMahPerMs != 0;
+    }
+
     /**
      * Given a {@link BatteryStats.Timer}, returns the accumulated duration.
      */
diff --git a/core/java/com/android/internal/os/WifiPowerCalculator.java b/core/java/com/android/internal/os/WifiPowerCalculator.java
index 63763f7..98f613f 100644
--- a/core/java/com/android/internal/os/WifiPowerCalculator.java
+++ b/core/java/com/android/internal/os/WifiPowerCalculator.java
@@ -15,8 +15,13 @@
  */
 package com.android.internal.os;
 
+import android.os.BatteryConsumer;
 import android.os.BatteryStats;
+import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
 import android.os.Process;
+import android.os.SystemBatteryConsumer;
+import android.os.UidBatteryConsumer;
 import android.os.UserHandle;
 import android.util.Log;
 import android.util.SparseArray;
@@ -30,25 +35,93 @@
 public class WifiPowerCalculator extends PowerCalculator {
     private static final boolean DEBUG = BatteryStatsHelper.DEBUG;
     private static final String TAG = "WifiPowerCalculator";
-    private final double mIdleCurrentMa;
-    private final double mTxCurrentMa;
-    private final double mRxCurrentMa;
-    private final PowerProfile mPowerProfile;
+    private final UsageBasedPowerEstimator mIdlePowerEstimator;
+    private final UsageBasedPowerEstimator mTxPowerEstimator;
+    private final UsageBasedPowerEstimator mRxPowerEstimator;
+    private final UsageBasedPowerEstimator mPowerOnPowerEstimator;
+    private final UsageBasedPowerEstimator mScanPowerEstimator;
+    private final UsageBasedPowerEstimator mBatchScanPowerEstimator;
     private final boolean mHasWifiPowerController;
-    private double mTotalAppPowerDrain = 0;
-    private long mTotalAppRunningTime = 0;
-    private WifiPowerEstimator mWifiPowerEstimator;
-    private boolean mHasWifiPowerReporting;
+    private final double mWifiPowerPerPacket;
+
+    private static class PowerDurationAndTraffic {
+        public double powerMah;
+        public long durationMs;
+
+        public long wifiRxPackets;
+        public long wifiTxPackets;
+        public long wifiRxBytes;
+        public long wifiTxBytes;
+    }
 
     public WifiPowerCalculator(PowerProfile profile) {
-        mPowerProfile = profile;
+        mPowerOnPowerEstimator = new UsageBasedPowerEstimator(
+                profile.getAveragePower(PowerProfile.POWER_WIFI_ON));
+        mScanPowerEstimator = new UsageBasedPowerEstimator(
+                profile.getAveragePower(PowerProfile.POWER_WIFI_SCAN));
+        mBatchScanPowerEstimator = new UsageBasedPowerEstimator(
+                profile.getAveragePower(PowerProfile.POWER_WIFI_BATCHED_SCAN));
+        mIdlePowerEstimator = new UsageBasedPowerEstimator(
+                profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_IDLE));
+        mTxPowerEstimator = new UsageBasedPowerEstimator(
+                profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_TX));
+        mRxPowerEstimator = new UsageBasedPowerEstimator(
+                profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_RX));
 
-        mIdleCurrentMa = profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_IDLE);
-        mTxCurrentMa = profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_TX);
-        mRxCurrentMa = profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_RX);
+        mWifiPowerPerPacket = getWifiPowerPerPacket(profile);
 
-        mHasWifiPowerController = mIdleCurrentMa != 0 && mTxCurrentMa != 0 && mRxCurrentMa != 0;
-        mWifiPowerEstimator = new WifiPowerEstimator(mPowerProfile);
+        mHasWifiPowerController =
+                mIdlePowerEstimator.isSupported() && mTxPowerEstimator.isSupported()
+                        && mRxPowerEstimator.isSupported();
+    }
+
+    @Override
+    public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
+            long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
+
+        // batteryStats.hasWifiActivityReporting can change if we get energy data at a later point,
+        // so always check this field.
+        final boolean hasWifiPowerReporting =
+                mHasWifiPowerController && batteryStats.hasWifiActivityReporting();
+
+        final SystemBatteryConsumer.Builder systemBatteryConsumerBuilder =
+                builder.getOrCreateSystemBatteryConsumerBuilder(
+                        SystemBatteryConsumer.DRAIN_TYPE_WIFI);
+
+        long totalAppDurationMs = 0;
+        double totalAppPowerMah = 0;
+        final PowerDurationAndTraffic powerDurationAndTraffic = new PowerDurationAndTraffic();
+        final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =
+                builder.getUidBatteryConsumerBuilders();
+        for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
+            final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
+            calculateApp(powerDurationAndTraffic, app.getBatteryStatsUid(), rawRealtimeUs,
+                    BatteryStats.STATS_SINCE_CHARGED,
+                    hasWifiPowerReporting);
+
+            totalAppDurationMs += powerDurationAndTraffic.durationMs;
+            totalAppPowerMah += powerDurationAndTraffic.powerMah;
+
+            app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI,
+                    powerDurationAndTraffic.durationMs);
+            app.setConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI,
+                    powerDurationAndTraffic.powerMah);
+
+            if (app.getUid() == Process.WIFI_UID) {
+                systemBatteryConsumerBuilder.addUidBatteryConsumer(app);
+                app.excludeFromBatteryUsageStats();
+            }
+        }
+
+        calculateRemaining(powerDurationAndTraffic, batteryStats, rawRealtimeUs,
+                BatteryStats.STATS_SINCE_CHARGED,
+                hasWifiPowerReporting, totalAppDurationMs, totalAppPowerMah);
+
+        systemBatteryConsumerBuilder
+                .setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI,
+                        powerDurationAndTraffic.durationMs)
+                .setConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI,
+                        powerDurationAndTraffic.powerMah);
     }
 
     /**
@@ -64,100 +137,151 @@
 
         // batteryStats.hasWifiActivityReporting can change if we get energy data at a later point,
         // so always check this field.
-        mHasWifiPowerReporting = mHasWifiPowerController && batteryStats.hasWifiActivityReporting();
+        final boolean hasWifiPowerReporting =
+                mHasWifiPowerController && batteryStats.hasWifiActivityReporting();
 
-        super.calculate(sippers, batteryStats, rawRealtimeUs, rawUptimeUs, statsType, asUsers);
+        final BatterySipper bs = new BatterySipper(BatterySipper.DrainType.WIFI, null, 0);
 
-        BatterySipper bs = new BatterySipper(BatterySipper.DrainType.WIFI, null, 0);
-        calculateRemaining(bs, batteryStats, rawRealtimeUs, rawUptimeUs, statsType);
-
+        long totalAppDurationMs = 0;
+        double totalAppPowerMah = 0;
+        final PowerDurationAndTraffic powerDurationAndTraffic = new PowerDurationAndTraffic();
         for (int i = sippers.size() - 1; i >= 0; i--) {
-            BatterySipper app = sippers.get(i);
-            if (app.getUid() == Process.WIFI_UID) {
-                if (DEBUG) Log.d(TAG, "WiFi adding sipper " + app + ": cpu=" + app.cpuTimeMs);
-                app.isAggregated = true;
-                bs.add(app);
+            final BatterySipper app = sippers.get(i);
+            if (app.drainType == BatterySipper.DrainType.APP) {
+                calculateApp(powerDurationAndTraffic, app.uidObj, rawRealtimeUs, statsType,
+                        hasWifiPowerReporting);
+
+                totalAppDurationMs += powerDurationAndTraffic.durationMs;
+                totalAppPowerMah += powerDurationAndTraffic.powerMah;
+
+                app.wifiPowerMah = powerDurationAndTraffic.powerMah;
+                app.wifiRunningTimeMs = powerDurationAndTraffic.durationMs;
+                app.wifiRxBytes = powerDurationAndTraffic.wifiRxBytes;
+                app.wifiRxPackets = powerDurationAndTraffic.wifiRxPackets;
+                app.wifiTxBytes = powerDurationAndTraffic.wifiTxBytes;
+                app.wifiTxPackets = powerDurationAndTraffic.wifiTxPackets;
+                if (app.getUid() == Process.WIFI_UID) {
+                    if (DEBUG) Log.d(TAG, "WiFi adding sipper " + app + ": cpu=" + app.cpuTimeMs);
+                    app.isAggregated = true;
+                    bs.add(app);
+                }
             }
         }
+
+        calculateRemaining(powerDurationAndTraffic, batteryStats, rawRealtimeUs, statsType,
+                hasWifiPowerReporting, totalAppDurationMs, totalAppPowerMah);
+
+        bs.wifiRunningTimeMs += powerDurationAndTraffic.durationMs;
+        bs.wifiPowerMah += powerDurationAndTraffic.powerMah;
+
         if (bs.sumPower() > 0) {
             sippers.add(bs);
         }
     }
 
-    @Override
-    protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
-            long rawUptimeUs, int statsType) {
-        if (!mHasWifiPowerReporting) {
-            mWifiPowerEstimator.calculateApp(app, u, rawRealtimeUs, rawUptimeUs, statsType);
-            return;
-        }
-
-        final BatteryStats.ControllerActivityCounter counter = u.getWifiControllerActivity();
-        if (counter == null) {
-            return;
-        }
-
-        final long idleTime = counter.getIdleTimeCounter().getCountLocked(statsType);
-        final long txTime = counter.getTxTimeCounters()[0].getCountLocked(statsType);
-        final long rxTime = counter.getRxTimeCounter().getCountLocked(statsType);
-        app.wifiRunningTimeMs = idleTime + rxTime + txTime;
-        mTotalAppRunningTime += app.wifiRunningTimeMs;
-
-        app.wifiPowerMah =
-                ((idleTime * mIdleCurrentMa) + (txTime * mTxCurrentMa) + (rxTime * mRxCurrentMa))
-                        / (1000 * 60 * 60);
-        mTotalAppPowerDrain += app.wifiPowerMah;
-
-        app.wifiRxPackets = u.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_RX_DATA,
+    private void calculateApp(PowerDurationAndTraffic powerDurationAndTraffic, BatteryStats.Uid u,
+            long rawRealtimeUs,
+            int statsType, boolean hasWifiPowerReporting) {
+        powerDurationAndTraffic.wifiRxPackets = u.getNetworkActivityPackets(
+                BatteryStats.NETWORK_WIFI_RX_DATA,
                 statsType);
-        app.wifiTxPackets = u.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_TX_DATA,
+        powerDurationAndTraffic.wifiTxPackets = u.getNetworkActivityPackets(
+                BatteryStats.NETWORK_WIFI_TX_DATA,
                 statsType);
-        app.wifiRxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_RX_DATA,
+        powerDurationAndTraffic.wifiRxBytes = u.getNetworkActivityBytes(
+                BatteryStats.NETWORK_WIFI_RX_DATA,
                 statsType);
-        app.wifiTxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_TX_DATA,
+        powerDurationAndTraffic.wifiTxBytes = u.getNetworkActivityBytes(
+                BatteryStats.NETWORK_WIFI_TX_DATA,
                 statsType);
 
-        if (DEBUG && app.wifiPowerMah != 0) {
-            Log.d(TAG, "UID " + u.getUid() + ": idle=" + idleTime + "ms rx=" + rxTime + "ms tx=" +
-                    txTime + "ms power=" + formatCharge(app.wifiPowerMah));
+        if (hasWifiPowerReporting) {
+            final BatteryStats.ControllerActivityCounter counter = u.getWifiControllerActivity();
+            if (counter != null) {
+                final long idleTime = counter.getIdleTimeCounter().getCountLocked(statsType);
+                final long txTime = counter.getTxTimeCounters()[0].getCountLocked(statsType);
+                final long rxTime = counter.getRxTimeCounter().getCountLocked(statsType);
+
+                powerDurationAndTraffic.durationMs = idleTime + rxTime + txTime;
+                powerDurationAndTraffic.powerMah = mIdlePowerEstimator.calculatePower(idleTime)
+                        + mTxPowerEstimator.calculatePower(txTime)
+                        + mRxPowerEstimator.calculatePower(rxTime);
+
+                if (DEBUG && powerDurationAndTraffic.powerMah != 0) {
+                    Log.d(TAG, "UID " + u.getUid() + ": idle=" + idleTime + "ms rx=" + rxTime
+                            + "ms tx=" + txTime + "ms power=" + formatCharge(
+                            powerDurationAndTraffic.powerMah));
+                }
+            }
+        } else {
+            final double wifiPacketPower = (
+                    powerDurationAndTraffic.wifiRxPackets + powerDurationAndTraffic.wifiTxPackets)
+                    * mWifiPowerPerPacket;
+            final long wifiRunningTime = u.getWifiRunningTime(rawRealtimeUs, statsType) / 1000;
+            final long wifiScanTimeMs = u.getWifiScanTime(rawRealtimeUs, statsType) / 1000;
+            long batchScanTimeMs = 0;
+            for (int bin = 0; bin < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bin++) {
+                batchScanTimeMs += u.getWifiBatchedScanTime(bin, rawRealtimeUs, statsType) / 1000;
+            }
+
+            powerDurationAndTraffic.durationMs = wifiRunningTime;
+            powerDurationAndTraffic.powerMah = wifiPacketPower
+                    + mPowerOnPowerEstimator.calculatePower(wifiRunningTime)
+                    + mScanPowerEstimator.calculatePower(wifiScanTimeMs)
+                    + mBatchScanPowerEstimator.calculatePower(batchScanTimeMs);
+
+            if (DEBUG && powerDurationAndTraffic.powerMah != 0) {
+                Log.d(TAG, "UID " + u.getUid() + ": power=" + formatCharge(
+                        powerDurationAndTraffic.powerMah));
+            }
         }
     }
 
-    private void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs,
-            long rawUptimeUs, int statsType) {
-        if (!mHasWifiPowerReporting) {
-            mWifiPowerEstimator.calculateRemaining(app, stats, rawRealtimeUs, rawUptimeUs,
-                    statsType);
-            return;
+    private void calculateRemaining(PowerDurationAndTraffic powerDurationAndTraffic,
+            BatteryStats stats, long rawRealtimeUs,
+            int statsType, boolean hasWifiPowerReporting, long totalAppDurationMs,
+            double totalAppPowerMah) {
+        long totalDurationMs;
+        double totalPowerMah;
+        if (hasWifiPowerReporting) {
+            final BatteryStats.ControllerActivityCounter counter =
+                    stats.getWifiControllerActivity();
+
+            final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);
+            final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);
+            final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);
+
+            totalDurationMs = idleTimeMs + rxTimeMs + txTimeMs;
+
+            totalPowerMah =
+                    counter.getPowerCounter().getCountLocked(statsType) / (double) (1000 * 60 * 60);
+            if (totalPowerMah == 0) {
+                // Some controllers do not report power drain, so we can calculate it here.
+                totalPowerMah = mIdlePowerEstimator.calculatePower(idleTimeMs)
+                        + mTxPowerEstimator.calculatePower(txTimeMs)
+                        + mRxPowerEstimator.calculatePower(rxTimeMs);
+            }
+        } else {
+            totalDurationMs = stats.getGlobalWifiRunningTime(rawRealtimeUs, statsType) / 1000;
+            totalPowerMah = mPowerOnPowerEstimator.calculatePower(totalDurationMs);
         }
 
-        final BatteryStats.ControllerActivityCounter counter = stats.getWifiControllerActivity();
-
-        final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);
-        final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);
-        final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);
-
-        app.wifiRunningTimeMs = Math.max(0,
-                (idleTimeMs + rxTimeMs + txTimeMs) - mTotalAppRunningTime);
-
-        double powerDrainMah = counter.getPowerCounter().getCountLocked(statsType)
-                / (double) (1000 * 60 * 60);
-        if (powerDrainMah == 0) {
-            // Some controllers do not report power drain, so we can calculate it here.
-            powerDrainMah = ((idleTimeMs * mIdleCurrentMa) + (txTimeMs * mTxCurrentMa)
-                    + (rxTimeMs * mRxCurrentMa)) / (1000 * 60 * 60);
-        }
-        app.wifiPowerMah = Math.max(0, powerDrainMah - mTotalAppPowerDrain);
+        powerDurationAndTraffic.durationMs = Math.max(0, totalDurationMs - totalAppDurationMs);
+        powerDurationAndTraffic.powerMah = Math.max(0, totalPowerMah - totalAppPowerMah);
 
         if (DEBUG) {
-            Log.d(TAG, "left over WiFi power: " + formatCharge(app.wifiPowerMah));
+            Log.d(TAG, "left over WiFi power: " + formatCharge(powerDurationAndTraffic.powerMah));
         }
     }
 
-    @Override
-    public void reset() {
-        mTotalAppPowerDrain = 0;
-        mTotalAppRunningTime = 0;
-        mWifiPowerEstimator.reset();
+    /**
+     * Return estimated power per Wi-Fi packet in mAh/packet where 1 packet = 2 KB.
+     */
+    private static double getWifiPowerPerPacket(PowerProfile profile) {
+        // TODO(b/179392913): Extract average bit rates from system
+        final long wifiBps = 1000000;
+        final double averageWifiActivePower =
+                profile.getAveragePower(PowerProfile.POWER_WIFI_ACTIVE) / 3600;
+        return averageWifiActivePower / (((double) wifiBps) / 8 / 2048);
     }
 }
diff --git a/core/java/com/android/internal/os/WifiPowerEstimator.java b/core/java/com/android/internal/os/WifiPowerEstimator.java
deleted file mode 100644
index d0a105c..0000000
--- a/core/java/com/android/internal/os/WifiPowerEstimator.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.internal.os;
-
-import android.os.BatteryStats;
-import android.os.Process;
-import android.os.UserHandle;
-import android.util.Log;
-import android.util.SparseArray;
-
-import java.util.List;
-
-/**
- * Estimates WiFi power usage based on timers in BatteryStats.
- */
-public class WifiPowerEstimator extends PowerCalculator {
-    private static final boolean DEBUG = BatteryStatsHelper.DEBUG;
-    private static final String TAG = "WifiPowerEstimator";
-    private final double mWifiPowerPerPacket;
-    private final double mWifiPowerOn;
-    private final double mWifiPowerScan;
-    private final double mWifiPowerBatchScan;
-    private long mTotalAppWifiRunningTimeMs = 0;
-
-    public WifiPowerEstimator(PowerProfile profile) {
-        mWifiPowerPerPacket = getWifiPowerPerPacket(profile);
-        mWifiPowerOn = profile.getAveragePower(PowerProfile.POWER_WIFI_ON);
-        mWifiPowerScan = profile.getAveragePower(PowerProfile.POWER_WIFI_SCAN);
-        mWifiPowerBatchScan = profile.getAveragePower(PowerProfile.POWER_WIFI_BATCHED_SCAN);
-    }
-
-    @Override
-    public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
-            long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
-        super.calculate(sippers, batteryStats, rawRealtimeUs, rawUptimeUs, statsType, asUsers);
-
-        BatterySipper bs = new BatterySipper(BatterySipper.DrainType.WIFI, null, 0);
-        calculateRemaining(bs, batteryStats, rawRealtimeUs, rawUptimeUs, statsType);
-
-        for (int i = sippers.size() - 1; i >= 0; i--) {
-            BatterySipper app = sippers.get(i);
-            if (app.getUid() == Process.WIFI_UID) {
-                if (DEBUG) Log.d(TAG, "WiFi adding sipper " + app + ": cpu=" + app.cpuTimeMs);
-                app.isAggregated = true;
-                bs.add(app);
-            }
-        }
-        if (bs.sumPower() > 0) {
-            sippers.add(bs);
-        }
-    }
-
-    /**
-     * Return estimated power per Wi-Fi packet in mAh/packet where 1 packet = 2 KB.
-     */
-    private static double getWifiPowerPerPacket(PowerProfile profile) {
-        final long WIFI_BPS = 1000000; // TODO: Extract average bit rates from system
-        final double WIFI_POWER = profile.getAveragePower(PowerProfile.POWER_WIFI_ACTIVE)
-                / 3600;
-        return WIFI_POWER / (((double)WIFI_BPS) / 8 / 2048);
-    }
-
-    @Override
-    protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
-                             long rawUptimeUs, int statsType) {
-        app.wifiRxPackets = u.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_RX_DATA,
-                statsType);
-        app.wifiTxPackets = u.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_TX_DATA,
-                statsType);
-        app.wifiRxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_RX_DATA,
-                statsType);
-        app.wifiTxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_TX_DATA,
-                statsType);
-
-        final double wifiPacketPower = (app.wifiRxPackets + app.wifiTxPackets)
-                * mWifiPowerPerPacket;
-
-        app.wifiRunningTimeMs = u.getWifiRunningTime(rawRealtimeUs, statsType) / 1000;
-        mTotalAppWifiRunningTimeMs += app.wifiRunningTimeMs;
-        final double wifiLockPower = (app.wifiRunningTimeMs * mWifiPowerOn) / (1000*60*60);
-
-        final long wifiScanTimeMs = u.getWifiScanTime(rawRealtimeUs, statsType) / 1000;
-        final double wifiScanPower = (wifiScanTimeMs * mWifiPowerScan) / (1000*60*60);
-
-        double wifiBatchScanPower = 0;
-        for (int bin = 0; bin < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bin++) {
-            final long batchScanTimeMs =
-                    u.getWifiBatchedScanTime(bin, rawRealtimeUs, statsType) / 1000;
-            final double batchScanPower = (batchScanTimeMs * mWifiPowerBatchScan) / (1000*60*60);
-            wifiBatchScanPower += batchScanPower;
-        }
-
-        app.wifiPowerMah = wifiPacketPower + wifiLockPower + wifiScanPower + wifiBatchScanPower;
-        if (DEBUG && app.wifiPowerMah != 0) {
-            Log.d(TAG, "UID " + u.getUid() + ": power=" + formatCharge(app.wifiPowerMah));
-        }
-    }
-
-    void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs,
-                                   long rawUptimeUs, int statsType) {
-        final long totalRunningTimeMs = stats.getGlobalWifiRunningTime(rawRealtimeUs, statsType)
-                / 1000;
-        final double powerDrain = ((totalRunningTimeMs - mTotalAppWifiRunningTimeMs) * mWifiPowerOn)
-                / (1000*60*60);
-        app.wifiRunningTimeMs = totalRunningTimeMs;
-        app.wifiPowerMah = Math.max(0, powerDrain);
-    }
-
-    @Override
-    public void reset() {
-        mTotalAppWifiRunningTimeMs = 0;
-    }
-}
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index c8afea9..6b1d408 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -18,8 +18,8 @@
 
 import static android.system.OsConstants.O_CLOEXEC;
 
-import static com.android.internal.os.ZygoteConnectionConstants.MAX_ZYGOTE_ARGC;
-
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.pm.ApplicationInfo;
 import android.net.Credentials;
 import android.net.LocalServerSocket;
@@ -36,17 +36,16 @@
 
 import com.android.internal.net.NetworkUtilsInternal;
 
+import dalvik.annotation.optimization.CriticalNative;
 import dalvik.annotation.optimization.FastNative;
 import dalvik.system.ZygoteHooks;
 
 import libcore.io.IoUtils;
 
-import java.io.BufferedReader;
 import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
 import java.io.FileDescriptor;
 import java.io.IOException;
-import java.io.InputStreamReader;
 
 /** @hide */
 public final class Zygote {
@@ -103,7 +102,7 @@
      */
     public static final int PROFILE_FROM_SHELL = 1 << 15;
 
-    /**
+    /*
      * Enable using the ART app image startup cache
      */
     public static final int USE_APP_IMAGE_STARTUP_CACHE = 1 << 16;
@@ -116,6 +115,13 @@
      */
     public static final int DEBUG_IGNORE_APP_SIGNAL_HANDLER = 1 << 17;
 
+    /**
+     * Disable runtime access to {@link android.annotation.TestApi} annotated members.
+     *
+     * <p>This only takes effect if Hidden API access restrictions are enabled as well.
+     */
+    public static final int DISABLE_TEST_API_ENFORCEMENT_POLICY = 1 << 18;
+
     public static final int MEMORY_TAG_LEVEL_MASK = (1 << 19) | (1 << 20);
 
     public static final int MEMORY_TAG_LEVEL_NONE = 0;
@@ -231,6 +237,8 @@
      */
     public static final String CHILD_ZYGOTE_UID_RANGE_END = "--uid-range-end=";
 
+    private static final String TAG = "Zygote";
+
     /** Prefix prepended to socket names created by init */
     private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
 
@@ -401,6 +409,10 @@
         // Note that this event ends at the end of handleChildProc.
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
 
+        if (gids != null && gids.length > 0) {
+            NetworkUtilsInternal.setAllowNetworkingForProcess(containsInetGid(gids));
+        }
+
         // Set the Java Language thread priority to the default value for new apps.
         Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
 
@@ -573,114 +585,163 @@
     private static native int nativeGetUsapPoolEventFD();
 
     /**
-     * Fork a new unspecialized app process from the zygote
+     * Fork a new unspecialized app process from the zygote. Adds the Usap to the native
+     * Usap table.
      *
      * @param usapPoolSocket  The server socket the USAP will call accept on
-     * @param sessionSocketRawFDs  Anonymous session sockets that are currently open
-     * @param isPriorityFork  Value controlling the process priority level until accept is called
-     * @return In the Zygote process this function will always return null; in unspecialized app
-     *         processes this function will return a Runnable object representing the new
-     *         application that is passed up from usapMain.
+     * @param sessionSocketRawFDs  Anonymous session sockets that are currently open.
+     *         These are closed in the child.
+     * @param isPriorityFork Raise the initial process priority level because this is on the
+     *         critical path for application startup.
+     * @return In the child process, this returns a Runnable that waits for specialization
+     *         info to start an app process. In the sygote/parent process this returns null.
      */
-    static Runnable forkUsap(LocalServerSocket usapPoolSocket,
-                             int[] sessionSocketRawFDs,
-                             boolean isPriorityFork) {
-        FileDescriptor[] pipeFDs;
+    static @Nullable Runnable forkUsap(LocalServerSocket usapPoolSocket,
+                                       int[] sessionSocketRawFDs,
+                                       boolean isPriorityFork) {
+        FileDescriptor readFD;
+        FileDescriptor writeFD;
 
         try {
-            pipeFDs = Os.pipe2(O_CLOEXEC);
+            FileDescriptor[] pipeFDs = Os.pipe2(O_CLOEXEC);
+            readFD = pipeFDs[0];
+            writeFD = pipeFDs[1];
         } catch (ErrnoException errnoEx) {
             throw new IllegalStateException("Unable to create USAP pipe.", errnoEx);
         }
 
-        int pid =
-                nativeForkUsap(pipeFDs[0].getInt$(), pipeFDs[1].getInt$(),
-                               sessionSocketRawFDs, isPriorityFork);
-
+        int pid = nativeForkApp(readFD.getInt$(), writeFD.getInt$(),
+                                sessionSocketRawFDs, /*argsKnown=*/ false, isPriorityFork);
         if (pid == 0) {
-            IoUtils.closeQuietly(pipeFDs[0]);
-            return usapMain(usapPoolSocket, pipeFDs[1]);
+            IoUtils.closeQuietly(readFD);
+            return childMain(null, usapPoolSocket, writeFD);
+        } else if (pid == -1) {
+            // Fork failed.
+            return null;
         } else {
-            // The read-end of the pipe will be closed by the native code.
-            // See removeUsapTableEntry();
-            IoUtils.closeQuietly(pipeFDs[1]);
+            // readFD will be closed by the native code. See removeUsapTableEntry();
+            IoUtils.closeQuietly(writeFD);
+            nativeAddUsapTableEntry(pid, readFD.getInt$());
             return null;
         }
     }
 
-    private static native int nativeForkUsap(int readPipeFD,
-                                             int writePipeFD,
-                                             int[] sessionSocketRawFDs,
-                                             boolean isPriorityFork);
+    private static native int nativeForkApp(int readPipeFD,
+                                            int writePipeFD,
+                                            int[] sessionSocketRawFDs,
+                                            boolean argsKnown,
+                                            boolean isPriorityFork);
 
     /**
-     * This function is used by unspecialized app processes to wait for specialization requests from
-     * the system server.
+     * Add an entry for a new Usap to the table maintained in native code.
+     */
+    @CriticalNative
+    private static native void nativeAddUsapTableEntry(int pid, int readPipeFD);
+
+    /**
+     * Fork a new app process from the zygote. argBuffer contains a fork command that
+     * request neither a child zygote, nor a wrapped process. Continue to accept connections
+     * on the specified socket, use those to refill argBuffer, and continue to process
+     * sufficiently simple fork requests. We presume that the only open file descriptors
+     * requiring special treatment are the session socket embedded in argBuffer, and
+     * zygoteSocket.
+     * @param argBuffer containing initial command and the connected socket from which to
+     *         read more
+     * @param zygoteSocket socket from which to obtain new connections when current argBuffer
+     *         one is disconnected
+     * @param expectedUId Uid of peer for initial requests. Subsequent requests from a different
+     *               peer will cause us to return rather than perform the requested fork.
+     * @param minUid Minimum Uid enforced for all but first fork request. The caller checks
+     *               the Uid policy for the initial request.
+     * @param firstNiceName name of first created process. Used for error reporting only.
+     * @return A Runnable in each child process, null in the parent.
+     * If this returns in then argBuffer still contains a command needing to be executed.
+     */
+    static @Nullable Runnable forkSimpleApps(@NonNull ZygoteCommandBuffer argBuffer,
+                                             @NonNull FileDescriptor zygoteSocket,
+                                             int expectedUid,
+                                             int minUid,
+                                             @Nullable String firstNiceName) {
+        boolean in_child =
+                argBuffer.forkRepeatedly(zygoteSocket, expectedUid, minUid, firstNiceName);
+        if (in_child) {
+            return childMain(argBuffer, /*usapPoolSocket=*/null, /*writePipe=*/null);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Specialize the current process into one described by argBuffer or the command read from
+     * usapPoolSocket. Exactly one of those must be null. If we are given an argBuffer, we close
+     * it. Used both for a specializing a USAP process, and for process creation without USAPs.
+     * In both cases, we specialize the process after first returning to Java code.
      *
      * @param writePipe  The write end of the reporting pipe used to communicate with the poll loop
      *                   of the ZygoteServer.
      * @return A runnable oject representing the new application.
      */
-    private static Runnable usapMain(LocalServerSocket usapPoolSocket,
-                                     FileDescriptor writePipe) {
+    private static Runnable childMain(@Nullable ZygoteCommandBuffer argBuffer,
+                                      @Nullable LocalServerSocket usapPoolSocket,
+                                      FileDescriptor writePipe) {
         final int pid = Process.myPid();
-        Process.setArgV0(Process.is64Bit() ? "usap64" : "usap32");
 
-        LocalSocket sessionSocket = null;
         DataOutputStream usapOutputStream = null;
-        Credentials peerCredentials = null;
         ZygoteArguments args = null;
 
-        // Change the priority to max before calling accept so we can respond to new specialization
-        // requests as quickly as possible.  This will be reverted to the default priority in the
-        // native specialization code.
-        boostUsapPriority();
+        // Block SIGTERM so we won't be killed if the Zygote flushes the USAP pool.
+        blockSigTerm();
 
-        while (true) {
-            try {
-                sessionSocket = usapPoolSocket.accept();
+        LocalSocket sessionSocket = null;
+        if (argBuffer == null) {
+            // Read arguments from usapPoolSocket instead.
 
-                // Block SIGTERM so we won't be killed if the Zygote flushes the USAP pool.
-                blockSigTerm();
+            Process.setArgV0(Process.is64Bit() ? "usap64" : "usap32");
 
-                BufferedReader usapReader =
-                        new BufferedReader(new InputStreamReader(sessionSocket.getInputStream()));
-                usapOutputStream =
-                        new DataOutputStream(sessionSocket.getOutputStream());
+            // Change the priority to max before calling accept so we can respond to new
+            // specialization requests as quickly as possible.  This will be reverted to the
+            // default priority in the native specialization code.
+            boostUsapPriority();
 
-                peerCredentials = sessionSocket.getPeerCredentials();
+            while (true) {
+                ZygoteCommandBuffer tmpArgBuffer = null;
+                try {
+                    sessionSocket = usapPoolSocket.accept();
 
-                String[] argStrings = readArgumentList(usapReader);
-
-                if (argStrings != null) {
-                    args = new ZygoteArguments(argStrings);
-
+                    usapOutputStream =
+                            new DataOutputStream(sessionSocket.getOutputStream());
+                    Credentials peerCredentials = sessionSocket.getPeerCredentials();
+                    tmpArgBuffer = new ZygoteCommandBuffer(sessionSocket);
+                    args = ZygoteArguments.getInstance(argBuffer);
+                    applyUidSecurityPolicy(args, peerCredentials);
                     // TODO (chriswailes): Should this only be run for debug builds?
                     validateUsapCommand(args);
                     break;
-                } else {
-                    Log.e("USAP", "Truncated command received.");
-                    IoUtils.closeQuietly(sessionSocket);
-
-                    // Re-enable SIGTERM so the USAP can be flushed from the pool if necessary.
-                    unblockSigTerm();
+                } catch (Exception ex) {
+                    Log.e("USAP", ex.getMessage());
                 }
-            } catch (Exception ex) {
-                Log.e("USAP", ex.getMessage());
-                IoUtils.closeQuietly(sessionSocket);
-
                 // Re-enable SIGTERM so the USAP can be flushed from the pool if necessary.
                 unblockSigTerm();
+                IoUtils.closeQuietly(sessionSocket);
+                IoUtils.closeQuietly(tmpArgBuffer);
+                blockSigTerm();
             }
+        } else {
+            try {
+                args = ZygoteArguments.getInstance(argBuffer);
+            } catch (Exception ex) {
+                Log.e("AppStartup", ex.getMessage());
+                throw new AssertionError("Failed to parse application start command", ex);
+            }
+            // peerCredentials were checked in parent.
         }
-
+        if (args == null) {
+            throw new AssertionError("Empty command line");
+        }
         try {
-            // SIGTERM is blocked on loop exit.  This prevents a USAP that is specializing from
-            // being killed during a pool flush.
+            // SIGTERM is blocked here.  This prevents a USAP that is specializing from being
+            // killed during a pool flush.
 
-            setAppProcessName(args, "USAP");
-
-            applyUidSecurityPolicy(args, peerCredentials);
             applyDebuggerSystemProperty(args);
 
             int[][] rlimits = null;
@@ -689,53 +750,57 @@
                 rlimits = args.mRLimits.toArray(INT_ARRAY_2D);
             }
 
-            // This must happen before the SELinux policy for this process is
-            // changed when specializing.
-            try {
-                // Used by ZygoteProcess.zygoteSendArgsAndGetResult to fill in a
-                // Process.ProcessStartResult object.
-                usapOutputStream.writeInt(pid);
-            } catch (IOException ioEx) {
-                Log.e("USAP", "Failed to write response to session socket: "
-                        + ioEx.getMessage());
-                throw new RuntimeException(ioEx);
-            } finally {
-                IoUtils.closeQuietly(sessionSocket);
-
+            if (argBuffer == null) {
+                // This must happen before the SELinux policy for this process is
+                // changed when specializing.
                 try {
-                    // This socket is closed using Os.close due to an issue with the implementation
-                    // of LocalSocketImp.close().  Because the raw FD is created by init and then
-                    // loaded from an environment variable (as opposed to being created by the
-                    // LocalSocketImpl itself) the current implementation will not actually close
-                    // the underlying FD.
-                    //
-                    // See b/130309968 for discussion of this issue.
-                    Os.close(usapPoolSocket.getFileDescriptor());
-                } catch (ErrnoException ex) {
-                    Log.e("USAP", "Failed to close USAP pool socket");
-                    throw new RuntimeException(ex);
+                    // Used by ZygoteProcess.zygoteSendArgsAndGetResult to fill in a
+                    // Process.ProcessStartResult object.
+                    usapOutputStream.writeInt(pid);
+                } catch (IOException ioEx) {
+                    Log.e("USAP", "Failed to write response to session socket: "
+                            + ioEx.getMessage());
+                    throw new RuntimeException(ioEx);
+                } finally {
+                    try {
+                        // Since the raw FD is created by init and then loaded from an environment
+                        // variable (as opposed to being created by the LocalSocketImpl itself),
+                        // the LocalSocket/LocalSocketImpl does not own the Os-level socket. See
+                        // the spec for LocalSocket.createConnectedLocalSocket(FileDescriptor fd).
+                        // Thus closing the LocalSocket does not suffice. See b/130309968 for more
+                        // discussion.
+                        FileDescriptor fd = usapPoolSocket.getFileDescriptor();
+                        usapPoolSocket.close();
+                        Os.close(fd);
+                    } catch (ErrnoException | IOException ex) {
+                        Log.e("USAP", "Failed to close USAP pool socket");
+                        throw new RuntimeException(ex);
+                    }
                 }
             }
 
-            try {
-                ByteArrayOutputStream buffer =
-                        new ByteArrayOutputStream(Zygote.USAP_MANAGEMENT_MESSAGE_BYTES);
-                DataOutputStream outputStream = new DataOutputStream(buffer);
+            if (writePipe != null) {
+                try {
+                    ByteArrayOutputStream buffer =
+                            new ByteArrayOutputStream(Zygote.USAP_MANAGEMENT_MESSAGE_BYTES);
+                    DataOutputStream outputStream = new DataOutputStream(buffer);
 
-                // This is written as a long so that the USAP reporting pipe and USAP pool event FD
-                // handlers in ZygoteServer.runSelectLoop can be unified.  These two cases should
-                // both send/receive 8 bytes.
-                outputStream.writeLong(pid);
-                outputStream.flush();
-
-                Os.write(writePipe, buffer.toByteArray(), 0, buffer.size());
-            } catch (Exception ex) {
-                Log.e("USAP",
-                        String.format("Failed to write PID (%d) to pipe (%d): %s",
-                                pid, writePipe.getInt$(), ex.getMessage()));
-                throw new RuntimeException(ex);
-            } finally {
-                IoUtils.closeQuietly(writePipe);
+                    // This is written as a long so that the USAP reporting pipe and USAP pool
+                    // event FD handlers in ZygoteServer.runSelectLoop can be unified.  These two
+                    // cases should both send/receive 8 bytes.
+                    // TODO: Needs tweaking to handle the non-Usap invoke-with case, which expects
+                    // a different format.
+                    outputStream.writeLong(pid);
+                    outputStream.flush();
+                    Os.write(writePipe, buffer.toByteArray(), 0, buffer.size());
+                } catch (Exception ex) {
+                    Log.e("USAP",
+                            String.format("Failed to write PID (%d) to pipe (%d): %s",
+                                    pid, writePipe.getInt$(), ex.getMessage()));
+                    throw new RuntimeException(ex);
+                } finally {
+                    IoUtils.closeQuietly(writePipe);
+                }
             }
 
             specializeAppProcess(args.mUid, args.mGid, args.mGids,
@@ -842,13 +907,29 @@
         return nativeRemoveUsapTableEntry(usapPID);
     }
 
+    @CriticalNative
     private static native boolean nativeRemoveUsapTableEntry(int usapPID);
 
     /**
-     * uid 1000 (Process.SYSTEM_UID) may specify any uid &gt; 1000 in normal
+     * Return the minimum child uid that the given peer is allowed to create.
+     * uid 1000 (Process.SYSTEM_UID) may specify any uid &ge; 1000 in normal
      * operation. It may also specify any gid and setgroups() list it chooses.
      * In factory test mode, it may specify any UID.
-     *
+     */
+    static int minChildUid(Credentials peer) {
+        if (peer.getUid() == Process.SYSTEM_UID
+                && FactoryTest.getMode() == FactoryTest.FACTORY_TEST_OFF) {
+            /* In normal operation, SYSTEM_UID can only specify a restricted
+             * set of UIDs. In factory test mode, SYSTEM_UID may specify any uid.
+             */
+            return Process.SYSTEM_UID;
+        } else {
+            return 0;
+        }
+    }
+
+    /*
+     * Adjust uid and gid arguments, ensuring that the security policy is satisfied.
      * @param args non-null; zygote spawner arguments
      * @param peer non-null; peer credentials
      * @throws ZygoteSecurityException Indicates a security issue when applying the UID based
@@ -857,17 +938,10 @@
     static void applyUidSecurityPolicy(ZygoteArguments args, Credentials peer)
             throws ZygoteSecurityException {
 
-        if (peer.getUid() == Process.SYSTEM_UID) {
-            /* In normal operation, SYSTEM_UID can only specify a restricted
-             * set of UIDs. In factory test mode, SYSTEM_UID may specify any uid.
-             */
-            boolean uidRestricted = FactoryTest.getMode() == FactoryTest.FACTORY_TEST_OFF;
-
-            if (uidRestricted && args.mUidSpecified && (args.mUid < Process.SYSTEM_UID)) {
-                throw new ZygoteSecurityException(
-                        "System UID may not launch process with UID < "
-                        + Process.SYSTEM_UID);
-            }
+        if (args.mUidSpecified && (args.mUid < minChildUid(peer))) {
+            throw new ZygoteSecurityException(
+                    "System UID may not launch process with UID < "
+                    + Process.SYSTEM_UID);
         }
 
         // If not otherwise specified, uid and gid are inherited from peer
@@ -953,45 +1027,6 @@
     }
 
     /**
-     * Reads an argument list from the provided socket
-     * @return Argument list or null if EOF is reached
-     * @throws IOException passed straight through
-     */
-    static String[] readArgumentList(BufferedReader socketReader) throws IOException {
-        int argc;
-
-        try {
-            String argc_string = socketReader.readLine();
-
-            if (argc_string == null) {
-                // EOF reached.
-                return null;
-            }
-            argc = Integer.parseInt(argc_string);
-
-        } catch (NumberFormatException ex) {
-            Log.e("Zygote", "Invalid Zygote wire format: non-int at argc");
-            throw new IOException("Invalid wire format");
-        }
-
-        // See bug 1092107: large argc can be used for a DOS attack
-        if (argc > MAX_ZYGOTE_ARGC) {
-            throw new IOException("Max arg count exceeded");
-        }
-
-        String[] args = new String[argc];
-        for (int arg_index = 0; arg_index < argc; arg_index++) {
-            args[arg_index] = socketReader.readLine();
-            if (args[arg_index] == null) {
-                // We got an unexpected EOF.
-                throw new IOException("Truncated request");
-            }
-        }
-
-        return args;
-    }
-
-    /**
      * Creates a managed LocalServerSocket object using a file descriptor
      * created by an init.rc script.  The init scripts that specify the
      * sockets name can be found in system/core/rootdir.  The socket is bound
diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java
index 32b808a..65b454d 100644
--- a/core/java/com/android/internal/os/ZygoteArguments.java
+++ b/core/java/com/android/internal/os/ZygoteArguments.java
@@ -16,8 +16,8 @@
 
 package com.android.internal.os;
 
+import java.io.EOFException;
 import java.util.ArrayList;
-import java.util.Arrays;
 
 /**
  * Handles argument parsing for args related to the zygote spawner.
@@ -245,20 +245,34 @@
     /**
      * Constructs instance and parses args
      *
-     * @param args zygote command-line args
+     * @param args zygote command-line args as ZygoteCommandBuffer, positioned after argument count.
      */
-    ZygoteArguments(String[] args) throws IllegalArgumentException {
-        parseArgs(args);
+    private ZygoteArguments(ZygoteCommandBuffer args, int argCount)
+            throws IllegalArgumentException, EOFException {
+        parseArgs(args, argCount);
+    }
+
+    /**
+     * Return a new ZygoteArguments reflecting the contents of the given ZygoteCommandBuffer. Return
+     * null if the ZygoteCommandBuffer was positioned at EOF. Assumes the buffer is initially
+     * positioned at the beginning of the command.
+     */
+    public static ZygoteArguments getInstance(ZygoteCommandBuffer args)
+            throws IllegalArgumentException, EOFException {
+        int argCount = args.getCount();
+        return argCount == 0 ? null : new ZygoteArguments(args, argCount);
     }
 
     /**
      * Parses the commandline arguments intended for the Zygote spawner (such as "--setuid=" and
-     * "--setgid=") and creates an array containing the remaining args.
+     * "--setgid=") and creates an array containing the remaining args. Return false if we were
+     * at EOF.
      *
      * Per security review bug #1112214, duplicate args are disallowed in critical cases to make
      * injection harder.
      */
-    private void parseArgs(String[] args) throws IllegalArgumentException {
+    private void parseArgs(ZygoteCommandBuffer args, int argCount)
+            throws IllegalArgumentException, EOFException {
         /*
          * See android.os.ZygoteProcess.zygoteSendArgsAndGetResult()
          * Presently the wire format to the zygote process is:
@@ -269,13 +283,13 @@
          * the child or -1 on failure.
          */
 
-        int curArg = 0;
-
+        String unprocessedArg = null;
+        int curArg = 0;  // Index of arg
         boolean seenRuntimeArgs = false;
-
         boolean expectRuntimeArgs = true;
-        for ( /* curArg */ ; curArg < args.length; curArg++) {
-            String arg = args[curArg];
+
+        for ( /* curArg */ ; curArg < argCount; ++curArg) {
+            String arg = args.nextArg();
 
             if (arg.equals("--")) {
                 curArg++;
@@ -367,7 +381,8 @@
                         "Duplicate arg specified");
                 }
                 try {
-                    mInvokeWith = args[++curArg];
+                    ++curArg;
+                    mInvokeWith = args.nextArg();
                 } catch (IndexOutOfBoundsException ex) {
                     throw new IllegalArgumentException(
                         "--invoke-with requires argument");
@@ -397,12 +412,14 @@
             } else if (arg.startsWith("--app-data-dir=")) {
                 mAppDataDir = getAssignmentValue(arg);
             } else if (arg.equals("--preload-app")) {
-                mPreloadApp = args[++curArg];
+                ++curArg;
+                mPreloadApp = args.nextArg();
             } else if (arg.equals("--preload-package")) {
-                mPreloadPackage = args[++curArg];
-                mPreloadPackageLibs = args[++curArg];
-                mPreloadPackageLibFileName = args[++curArg];
-                mPreloadPackageCacheKey = args[++curArg];
+                curArg += 4;
+                mPreloadPackage = args.nextArg();
+                mPreloadPackageLibs = args.nextArg();
+                mPreloadPackageLibFileName = args.nextArg();
+                mPreloadPackageCacheKey = args.nextArg();
             } else if (arg.equals("--preload-default")) {
                 mPreloadDefault = true;
                 expectRuntimeArgs = false;
@@ -411,8 +428,11 @@
             } else if (arg.equals("--set-api-denylist-exemptions")) {
                 // consume all remaining args; this is a stand-alone command, never included
                 // with the regular fork command.
-                mApiDenylistExemptions = Arrays.copyOfRange(args, curArg + 1, args.length);
-                curArg = args.length;
+                mApiDenylistExemptions = new String[argCount - curArg - 1];
+                ++curArg;
+                for (int i = 0; curArg < argCount; ++curArg, ++i) {
+                    mApiDenylistExemptions[i] = args.nextArg();
+                }
                 expectRuntimeArgs = false;
             } else if (arg.startsWith("--hidden-api-log-sampling-rate=")) {
                 String rateStr = getAssignmentValue(arg);
@@ -462,35 +482,46 @@
             } else if (arg.equals(Zygote.BIND_MOUNT_APP_DATA_DIRS)) {
                 mBindMountAppDataDirs = true;
             } else {
+                unprocessedArg = arg;
                 break;
             }
         }
+        // curArg is the index of the first unprocessed argument. That argument is either referenced
+        // by unprocessedArg or not read yet.
 
         if (mBootCompleted) {
-            if (args.length - curArg > 0) {
+            if (argCount > curArg) {
                 throw new IllegalArgumentException("Unexpected arguments after --boot-completed");
             }
         } else if (mAbiListQuery || mPidQuery) {
-            if (args.length - curArg > 0) {
+            if (argCount > curArg) {
                 throw new IllegalArgumentException("Unexpected arguments after --query-abi-list.");
             }
         } else if (mPreloadPackage != null) {
-            if (args.length - curArg > 0) {
+            if (argCount > curArg) {
                 throw new IllegalArgumentException(
                     "Unexpected arguments after --preload-package.");
             }
         } else if (mPreloadApp != null) {
-            if (args.length - curArg > 0) {
+            if (argCount > curArg) {
                 throw new IllegalArgumentException(
                     "Unexpected arguments after --preload-app.");
             }
         } else if (expectRuntimeArgs) {
             if (!seenRuntimeArgs) {
-                throw new IllegalArgumentException("Unexpected argument : " + args[curArg]);
+                throw new IllegalArgumentException("Unexpected argument : "
+                    + (unprocessedArg == null ? args.nextArg() : unprocessedArg));
             }
 
-            mRemainingArgs = new String[args.length - curArg];
-            System.arraycopy(args, curArg, mRemainingArgs, 0, mRemainingArgs.length);
+            mRemainingArgs = new String[argCount - curArg];
+            int i = 0;
+            if (unprocessedArg != null) {
+                mRemainingArgs[0] = unprocessedArg;
+                ++i;
+            }
+            for (; i < argCount - curArg; ++i) {
+                mRemainingArgs[i] = args.nextArg();
+            }
         }
 
         if (mStartChildZygote) {
diff --git a/core/java/com/android/internal/os/ZygoteCommandBuffer.java b/core/java/com/android/internal/os/ZygoteCommandBuffer.java
new file mode 100644
index 0000000..b61ae7a
--- /dev/null
+++ b/core/java/com/android/internal/os/ZygoteCommandBuffer.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.LocalSocket;
+
+import java.io.FileDescriptor;
+import java.lang.ref.Reference;  // For reachabilityFence.
+
+/**
+ * A native-accessible buffer for Zygote commands. Designed to support repeated forking
+ * of applications without intervening memory allocation, thus keeping zygote memory
+ * as stable as possible.
+ * A ZygoteCommandBuffer may have an associated socket from which it can be refilled.
+ * Otherwise the contents are explicitly set by getInstance().
+ *
+ * NOT THREAD-SAFE. No methods may be called concurrently from multiple threads.
+ *
+ * Only one ZygoteCommandBuffer can exist at a time.
+ * Must be explicitly closed before being dropped.
+ * @hide
+ */
+class ZygoteCommandBuffer implements AutoCloseable {
+    private long mNativeBuffer;  // Not final so that we can clear it in close().
+
+    /**
+     * The command socket.
+     *
+     * mSocket is retained in the child process in "peer wait" mode, so
+     * that it closes when the child process terminates. In other cases,
+     * it is closed in the peer.
+     */
+    private final LocalSocket mSocket;
+    private final int mNativeSocket;
+
+    /**
+     * Constructs instance from file descriptor from which the command will be read.
+     * Only a single instance may be live in a given process. The native code checks.
+     *
+     * @param fd file descriptor to read from. The setCommand() method may be used if and only if
+     * fd is null.
+     */
+    ZygoteCommandBuffer(@Nullable LocalSocket socket) {
+        mSocket = socket;
+        if (socket == null) {
+            mNativeSocket = -1;
+        } else {
+            mNativeSocket = mSocket.getFileDescriptor().getInt$();
+        }
+        mNativeBuffer = getNativeBuffer(mNativeSocket);
+    }
+
+    /**
+     * Constructs an instance with explicitly supplied arguments and an invalid
+     * file descriptor. Can only be used for a single command.
+     */
+    ZygoteCommandBuffer(@NonNull String[] args) {
+        this((LocalSocket) null);
+        setCommand(args);
+    }
+
+
+    private static native long getNativeBuffer(int fd);
+
+    /**
+     * Deallocate native resources associated with the one and only command buffer, and prevent
+     * reuse. Subsequent calls to getInstance() will yield a new buffer.
+     * We do not close the associated socket, if any.
+     */
+    @Override
+    public void close() {
+        freeNativeBuffer(mNativeBuffer);
+        mNativeBuffer = 0;
+    }
+
+    private static native void freeNativeBuffer(long /* NativeCommandBuffer* */ nbuffer);
+
+    /**
+     * Read at least the first line of the next command into the buffer, return the argument count
+     * from that line. Assumes we are initially positioned at the beginning of the first line of
+     * the command. Leave the buffer positioned at the beginning of the second command line, i.e.
+     * the first argument. If the buffer has no associated file descriptor, we just reposition to
+     * the beginning of the buffer, and reread existing contents.  Returns zero if we started out
+     * at EOF.
+     */
+    int getCount() {
+        try {
+            return nativeGetCount(mNativeBuffer);
+        } finally {
+            // Make sure the mNativeSocket doesn't get closed due to early finalization.
+            Reference.reachabilityFence(mSocket);
+        }
+    }
+
+    private static native int nativeGetCount(long /* NativeCommandBuffer* */ nbuffer);
+
+
+    /*
+     * Set the buffer to contain the supplied sequence of arguments.
+     */
+    private void setCommand(String[] command) {
+        int nArgs = command.length;
+        insert(mNativeBuffer, Integer.toString(nArgs));
+        for (String s: command) {
+            insert(mNativeBuffer, s);
+        }
+        // Native code checks there is no socket; hence no reachabilityFence.
+    }
+
+    private static native void insert(long /* NativeCommandBuffer* */ nbuffer, String s);
+
+    /**
+     * Retrieve the next argument/line from the buffer, filling the buffer as necessary.
+     */
+    String nextArg() {
+        try {
+            return nativeNextArg(mNativeBuffer);
+        } finally {
+            Reference.reachabilityFence(mSocket);
+        }
+    }
+
+    private static native String nativeNextArg(long /* NativeCommandBuffer* */ nbuffer);
+
+    void readFullyAndReset() {
+        try {
+            nativeReadFullyAndReset(mNativeBuffer);
+        } finally {
+            Reference.reachabilityFence(mSocket);
+        }
+    }
+
+    private static native void nativeReadFullyAndReset(long /* NativeCommandBuffer* */ nbuffer);
+
+    /**
+     * Fork a child as specified by the current command in the buffer, and repeat this process
+     * after refilling the buffer, so long as the buffer clearly contains another fork command.
+     *
+     * @param zygoteSocket socket from which to obtain new connections when current one is
+     *         disconnected
+     * @param expectedUid Peer UID for current connection. We refuse to deal with requests from
+     *         a different UID.
+     * @param minUid the smallest uid that may be request for the child process.
+     * @param firstNiceName The name for the initial process to be forked. Used only for error
+     *         reporting.
+     *
+     * @return true in the child, false in the parent. In the parent case, the buffer is positioned
+     * at the beginning of a command that still needs to be processed.
+     */
+    boolean forkRepeatedly(FileDescriptor zygoteSocket, int expectedUid, int minUid,
+                       String firstNiceName) {
+        try {
+            return nativeForkRepeatedly(mNativeBuffer, zygoteSocket.getInt$(),
+                    expectedUid, minUid, firstNiceName);
+        } finally {
+            Reference.reachabilityFence(mSocket);
+            Reference.reachabilityFence(zygoteSocket);
+        }
+    }
+
+    /*
+     * Repeatedly fork children as above. It commonly does not return in the parent, but it may.
+     * @return true in the chaild, false in the parent if we encounter a command we couldn't handle.
+     */
+    private static native boolean nativeForkRepeatedly(long /* NativeCommandBuffer* */ nbuffer,
+                                                   int zygoteSocketRawFd,
+                                                   int expectedUid,
+                                                   int minUid,
+                                                   String firstNiceName);
+
+}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 5a576ebb..37c7590 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -36,16 +36,15 @@
 import android.util.Log;
 
 import dalvik.system.VMRuntime;
+import dalvik.system.ZygoteHooks;
 
 import libcore.io.IoUtils;
 
-import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.FileDescriptor;
 import java.io.IOException;
-import java.io.InputStreamReader;
 import java.nio.charset.StandardCharsets;
 import java.util.Base64;
 import java.util.concurrent.TimeUnit;
@@ -67,7 +66,6 @@
     private final LocalSocket mSocket;
     @UnsupportedAppUsage
     private final DataOutputStream mSocketOutStream;
-    private final BufferedReader mSocketReader;
     @UnsupportedAppUsage
     private final Credentials peer;
     private final String abiList;
@@ -85,9 +83,6 @@
         this.abiList = abiList;
 
         mSocketOutStream = new DataOutputStream(socket.getOutputStream());
-        mSocketReader =
-                new BufferedReader(
-                        new InputStreamReader(socket.getInputStream()), Zygote.SOCKET_BUFFER_SIZE);
 
         mSocket.setSoTimeout(CONNECTION_TIMEOUT_MILLIS);
 
@@ -111,178 +106,216 @@
     }
 
     /**
-     * Reads one start command from the command socket. If successful, a child is forked and a
+     * Reads a command from the command socket. If a child is successfully forked, a
      * {@code Runnable} that calls the childs main method (or equivalent) is returned in the child
      * process. {@code null} is always returned in the parent process (the zygote).
+     * If multipleOK is set, we may keep processing additional fork commands before returning.
      *
      * If the client closes the socket, an {@code EOF} condition is set, which callers can test
      * for by calling {@code ZygoteConnection.isClosedByPeer}.
      */
-    Runnable processOneCommand(ZygoteServer zygoteServer) {
-        String[] args;
+    Runnable processCommand(ZygoteServer zygoteServer, boolean multipleOK) {
+        ZygoteArguments parsedArgs;
 
-        try {
-            args = Zygote.readArgumentList(mSocketReader);
-        } catch (IOException ex) {
-            throw new IllegalStateException("IOException on command socket", ex);
+        try (ZygoteCommandBuffer argBuffer = new ZygoteCommandBuffer(mSocket)) {
+            while (true) {
+                try {
+                    parsedArgs = ZygoteArguments.getInstance(argBuffer);
+                    // Keep argBuffer around, since we need it to fork.
+                } catch (IOException ex) {
+                    throw new IllegalStateException("IOException on command socket", ex);
+                }
+                if (parsedArgs == null) {
+                    isEof = true;
+                    return null;
+                }
+
+                int pid;
+                FileDescriptor childPipeFd = null;
+                FileDescriptor serverPipeFd = null;
+
+                if (parsedArgs.mBootCompleted) {
+                    handleBootCompleted();
+                    return null;
+                }
+
+                if (parsedArgs.mAbiListQuery) {
+                    handleAbiListQuery();
+                    return null;
+                }
+
+                if (parsedArgs.mPidQuery) {
+                    handlePidQuery();
+                    return null;
+                }
+
+                if (parsedArgs.mUsapPoolStatusSpecified) {
+                    // Handle this once we've released the argBuffer, to avoid opening a second one.
+                    break;
+                }
+
+                if (parsedArgs.mPreloadDefault) {
+                    handlePreload();
+                    return null;
+                }
+
+                if (parsedArgs.mPreloadPackage != null) {
+                    handlePreloadPackage(parsedArgs.mPreloadPackage,
+                            parsedArgs.mPreloadPackageLibs,
+                            parsedArgs.mPreloadPackageLibFileName,
+                            parsedArgs.mPreloadPackageCacheKey);
+                    return null;
+                }
+
+                if (canPreloadApp() && parsedArgs.mPreloadApp != null) {
+                    byte[] rawParcelData = Base64.getDecoder().decode(parsedArgs.mPreloadApp);
+                    Parcel appInfoParcel = Parcel.obtain();
+                    appInfoParcel.unmarshall(rawParcelData, 0, rawParcelData.length);
+                    appInfoParcel.setDataPosition(0);
+                    ApplicationInfo appInfo =
+                            ApplicationInfo.CREATOR.createFromParcel(appInfoParcel);
+                    appInfoParcel.recycle();
+                    if (appInfo != null) {
+                        handlePreloadApp(appInfo);
+                    } else {
+                        throw new IllegalArgumentException("Failed to deserialize --preload-app");
+                    }
+                    return null;
+                }
+
+                if (parsedArgs.mApiDenylistExemptions != null) {
+                    return handleApiDenylistExemptions(zygoteServer,
+                            parsedArgs.mApiDenylistExemptions);
+                }
+
+                if (parsedArgs.mHiddenApiAccessLogSampleRate != -1
+                        || parsedArgs.mHiddenApiAccessStatslogSampleRate != -1) {
+                    return handleHiddenApiAccessLogSampleRate(zygoteServer,
+                            parsedArgs.mHiddenApiAccessLogSampleRate,
+                            parsedArgs.mHiddenApiAccessStatslogSampleRate);
+                }
+
+                if (parsedArgs.mPermittedCapabilities != 0
+                        || parsedArgs.mEffectiveCapabilities != 0) {
+                    throw new ZygoteSecurityException("Client may not specify capabilities: "
+                            + "permitted=0x" + Long.toHexString(parsedArgs.mPermittedCapabilities)
+                            + ", effective=0x"
+                            + Long.toHexString(parsedArgs.mEffectiveCapabilities));
+                }
+
+                Zygote.applyUidSecurityPolicy(parsedArgs, peer);
+                Zygote.applyInvokeWithSecurityPolicy(parsedArgs, peer);
+
+                Zygote.applyDebuggerSystemProperty(parsedArgs);
+                Zygote.applyInvokeWithSystemProperty(parsedArgs);
+
+                int[][] rlimits = null;
+
+                if (parsedArgs.mRLimits != null) {
+                    rlimits = parsedArgs.mRLimits.toArray(Zygote.INT_ARRAY_2D);
+                }
+
+                int[] fdsToIgnore = null;
+
+                if (parsedArgs.mInvokeWith != null) {
+                    try {
+                        FileDescriptor[] pipeFds = Os.pipe2(O_CLOEXEC);
+                        childPipeFd = pipeFds[1];
+                        serverPipeFd = pipeFds[0];
+                        Os.fcntlInt(childPipeFd, F_SETFD, 0);
+                        fdsToIgnore = new int[]{childPipeFd.getInt$(), serverPipeFd.getInt$()};
+                    } catch (ErrnoException errnoEx) {
+                        throw new IllegalStateException("Unable to set up pipe for invoke-with",
+                                errnoEx);
+                    }
+                }
+
+                /*
+                 * In order to avoid leaking descriptors to the Zygote child,
+                 * the native code must close the two Zygote socket descriptors
+                 * in the child process before it switches from Zygote-root to
+                 * the UID and privileges of the application being launched.
+                 *
+                 * In order to avoid "bad file descriptor" errors when the
+                 * two LocalSocket objects are closed, the Posix file
+                 * descriptors are released via a dup2() call which closes
+                 * the socket and substitutes an open descriptor to /dev/null.
+                 */
+
+                int [] fdsToClose = { -1, -1 };
+
+                FileDescriptor fd = mSocket.getFileDescriptor();
+
+                if (fd != null) {
+                    fdsToClose[0] = fd.getInt$();
+                }
+
+                FileDescriptor zygoteFd = zygoteServer.getZygoteSocketFileDescriptor();
+
+                if (zygoteFd != null) {
+                    fdsToClose[1] = zygoteFd.getInt$();
+                }
+
+                if (parsedArgs.mInvokeWith != null || parsedArgs.mStartChildZygote
+                        || !multipleOK || peer.getUid() != Process.SYSTEM_UID) {
+                    // Continue using old code for now. TODO: Handle these cases in the other path.
+                    pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid,
+                            parsedArgs.mGids, parsedArgs.mRuntimeFlags, rlimits,
+                            parsedArgs.mMountExternal, parsedArgs.mSeInfo, parsedArgs.mNiceName,
+                            fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
+                            parsedArgs.mInstructionSet, parsedArgs.mAppDataDir,
+                            parsedArgs.mIsTopApp, parsedArgs.mPkgDataInfoList,
+                            parsedArgs.mWhitelistedDataInfoList, parsedArgs.mBindMountAppDataDirs,
+                            parsedArgs.mBindMountAppStorageDirs);
+
+                    try {
+                        if (pid == 0) {
+                            // in child
+                            zygoteServer.setForkChild();
+
+                            zygoteServer.closeServerSocket();
+                            IoUtils.closeQuietly(serverPipeFd);
+                            serverPipeFd = null;
+
+                            return handleChildProc(parsedArgs, childPipeFd,
+                                    parsedArgs.mStartChildZygote);
+                        } else {
+                            // In the parent. A pid < 0 indicates a failure and will be handled in
+                            // handleParentProc.
+                            IoUtils.closeQuietly(childPipeFd);
+                            childPipeFd = null;
+                            handleParentProc(pid, serverPipeFd);
+                            return null;
+                        }
+                    } finally {
+                        IoUtils.closeQuietly(childPipeFd);
+                        IoUtils.closeQuietly(serverPipeFd);
+                    }
+                } else {
+                    ZygoteHooks.preFork();
+                    Runnable result = Zygote.forkSimpleApps(argBuffer,
+                            zygoteServer.getZygoteSocketFileDescriptor(),
+                            peer.getUid(), Zygote.minChildUid(peer), parsedArgs.mNiceName);
+                    if (result == null) {
+                        // parent; we finished some number of forks. Result is Boolean.
+                        // We already did the equivalent of handleParentProc().
+                        ZygoteHooks.postForkCommon();
+                        // argBuffer contains a command not understood by forksimpleApps.
+                        continue;
+                    } else {
+                        // child; result is a Runnable.
+                        zygoteServer.setForkChild();
+                        Zygote.setAppProcessName(parsedArgs, TAG);  // ??? Necessary?
+                        return result;
+                    }
+                }
+            }
         }
-
-        // readArgumentList returns null only when it has reached EOF with no available
-        // data to read. This will only happen when the remote socket has disconnected.
-        if (args == null) {
-            isEof = true;
-            return null;
-        }
-
-        int pid;
-        FileDescriptor childPipeFd = null;
-        FileDescriptor serverPipeFd = null;
-
-        ZygoteArguments parsedArgs = new ZygoteArguments(args);
-
-        if (parsedArgs.mBootCompleted) {
-            handleBootCompleted();
-            return null;
-        }
-
-        if (parsedArgs.mAbiListQuery) {
-            handleAbiListQuery();
-            return null;
-        }
-
-        if (parsedArgs.mPidQuery) {
-            handlePidQuery();
-            return null;
-        }
-
         if (parsedArgs.mUsapPoolStatusSpecified) {
+            // Now that we've released argBuffer:
             return handleUsapPoolStatusChange(zygoteServer, parsedArgs.mUsapPoolEnabled);
         }
-
-        if (parsedArgs.mPreloadDefault) {
-            handlePreload();
-            return null;
-        }
-
-        if (parsedArgs.mPreloadPackage != null) {
-            handlePreloadPackage(parsedArgs.mPreloadPackage, parsedArgs.mPreloadPackageLibs,
-                    parsedArgs.mPreloadPackageLibFileName, parsedArgs.mPreloadPackageCacheKey);
-            return null;
-        }
-
-        if (canPreloadApp() && parsedArgs.mPreloadApp != null) {
-            byte[] rawParcelData = Base64.getDecoder().decode(parsedArgs.mPreloadApp);
-            Parcel appInfoParcel = Parcel.obtain();
-            appInfoParcel.unmarshall(rawParcelData, 0, rawParcelData.length);
-            appInfoParcel.setDataPosition(0);
-            ApplicationInfo appInfo = ApplicationInfo.CREATOR.createFromParcel(appInfoParcel);
-            appInfoParcel.recycle();
-            if (appInfo != null) {
-                handlePreloadApp(appInfo);
-            } else {
-                throw new IllegalArgumentException("Failed to deserialize --preload-app");
-            }
-            return null;
-        }
-
-        if (parsedArgs.mApiDenylistExemptions != null) {
-            return handleApiDenylistExemptions(zygoteServer, parsedArgs.mApiDenylistExemptions);
-        }
-
-        if (parsedArgs.mHiddenApiAccessLogSampleRate != -1
-                || parsedArgs.mHiddenApiAccessStatslogSampleRate != -1) {
-            return handleHiddenApiAccessLogSampleRate(zygoteServer,
-                    parsedArgs.mHiddenApiAccessLogSampleRate,
-                    parsedArgs.mHiddenApiAccessStatslogSampleRate);
-        }
-
-        if (parsedArgs.mPermittedCapabilities != 0 || parsedArgs.mEffectiveCapabilities != 0) {
-            throw new ZygoteSecurityException("Client may not specify capabilities: "
-                    + "permitted=0x" + Long.toHexString(parsedArgs.mPermittedCapabilities)
-                    + ", effective=0x" + Long.toHexString(parsedArgs.mEffectiveCapabilities));
-        }
-
-        Zygote.applyUidSecurityPolicy(parsedArgs, peer);
-        Zygote.applyInvokeWithSecurityPolicy(parsedArgs, peer);
-
-        Zygote.applyDebuggerSystemProperty(parsedArgs);
-        Zygote.applyInvokeWithSystemProperty(parsedArgs);
-
-        int[][] rlimits = null;
-
-        if (parsedArgs.mRLimits != null) {
-            rlimits = parsedArgs.mRLimits.toArray(Zygote.INT_ARRAY_2D);
-        }
-
-        int[] fdsToIgnore = null;
-
-        if (parsedArgs.mInvokeWith != null) {
-            try {
-                FileDescriptor[] pipeFds = Os.pipe2(O_CLOEXEC);
-                childPipeFd = pipeFds[1];
-                serverPipeFd = pipeFds[0];
-                Os.fcntlInt(childPipeFd, F_SETFD, 0);
-                fdsToIgnore = new int[]{childPipeFd.getInt$(), serverPipeFd.getInt$()};
-            } catch (ErrnoException errnoEx) {
-                throw new IllegalStateException("Unable to set up pipe for invoke-with", errnoEx);
-            }
-        }
-
-        /*
-         * In order to avoid leaking descriptors to the Zygote child,
-         * the native code must close the two Zygote socket descriptors
-         * in the child process before it switches from Zygote-root to
-         * the UID and privileges of the application being launched.
-         *
-         * In order to avoid "bad file descriptor" errors when the
-         * two LocalSocket objects are closed, the Posix file
-         * descriptors are released via a dup2() call which closes
-         * the socket and substitutes an open descriptor to /dev/null.
-         */
-
-        int [] fdsToClose = { -1, -1 };
-
-        FileDescriptor fd = mSocket.getFileDescriptor();
-
-        if (fd != null) {
-            fdsToClose[0] = fd.getInt$();
-        }
-
-        fd = zygoteServer.getZygoteSocketFileDescriptor();
-
-        if (fd != null) {
-            fdsToClose[1] = fd.getInt$();
-        }
-
-        pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
-                parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
-                parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
-                parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mIsTopApp,
-                parsedArgs.mPkgDataInfoList, parsedArgs.mWhitelistedDataInfoList,
-                parsedArgs.mBindMountAppDataDirs, parsedArgs.mBindMountAppStorageDirs);
-
-        try {
-            if (pid == 0) {
-                // in child
-                zygoteServer.setForkChild();
-
-                zygoteServer.closeServerSocket();
-                IoUtils.closeQuietly(serverPipeFd);
-                serverPipeFd = null;
-
-                return handleChildProc(parsedArgs, childPipeFd, parsedArgs.mStartChildZygote);
-            } else {
-                // In the parent. A pid < 0 indicates a failure and will be handled in
-                // handleParentProc.
-                IoUtils.closeQuietly(childPipeFd);
-                childPipeFd = null;
-                handleParentProc(pid, serverPipeFd);
-                return null;
-            }
-        } finally {
-            IoUtils.closeQuietly(childPipeFd);
-            IoUtils.closeQuietly(serverPipeFd);
-        }
+        throw new AssertionError("Shouldn't get here");
     }
 
     private void handleAbiListQuery() {
@@ -557,7 +590,7 @@
 
                     if (res > 0) {
                         if ((fds[0].revents & POLLIN) != 0) {
-                            // Only read one byte, so as not to block.
+                            // Only read one byte, so as not to block. Really needed?
                             int readBytes = android.system.Os.read(pipeFd, data, dataIndex, 1);
                             if (readBytes < 0) {
                                 throw new RuntimeException("Some error");
diff --git a/core/java/com/android/internal/os/ZygoteConnectionConstants.java b/core/java/com/android/internal/os/ZygoteConnectionConstants.java
index 506e39f..0c1cd6d 100644
--- a/core/java/com/android/internal/os/ZygoteConnectionConstants.java
+++ b/core/java/com/android/internal/os/ZygoteConnectionConstants.java
@@ -31,9 +31,6 @@
      */
     public static final int CONNECTION_TIMEOUT_MILLIS = 1000;
 
-    /** max number of arguments that a connection can specify */
-    public static final int MAX_ZYGOTE_ARGC = 1024;
-
     /**
      * Wait time for a wrapped app to report back its pid.
      *
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index f2ed50e..d5b778e 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -65,6 +65,7 @@
 import libcore.io.IoUtils;
 
 import java.io.BufferedReader;
+import java.io.EOFException;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -782,7 +783,13 @@
         int pid;
 
         try {
-            parsedArgs = new ZygoteArguments(args);
+            ZygoteCommandBuffer commandBuffer = new ZygoteCommandBuffer(args);
+            try {
+                parsedArgs = ZygoteArguments.getInstance(commandBuffer);
+            } catch (EOFException e) {
+                throw new AssertionError("Unexpected argument error for forking system server", e);
+            }
+            commandBuffer.close();
             Zygote.applyDebuggerSystemProperty(parsedArgs);
             Zygote.applyInvokeWithSystemProperty(parsedArgs);
 
@@ -861,7 +868,7 @@
      * into new processes are required to either set the priority to the default value or terminate
      * before executing any non-system code.  The native side of this occurs in SpecializeCommon,
      * while the Java Language priority is changed in ZygoteInit.handleSystemServerProcess,
-     * ZygoteConnection.handleChildProc, and Zygote.usapMain.
+     * ZygoteConnection.handleChildProc, and Zygote.childMain.
      *
      * @param argv  Command line arguments used to specify the Zygote's configuration.
      */
diff --git a/core/java/com/android/internal/os/ZygoteServer.java b/core/java/com/android/internal/os/ZygoteServer.java
index 585ddf6..f71b314 100644
--- a/core/java/com/android/internal/os/ZygoteServer.java
+++ b/core/java/com/android/internal/os/ZygoteServer.java
@@ -337,7 +337,7 @@
      * @param sessionSocketRawFDs  Anonymous session sockets that are currently open
      * @return In the Zygote process this function will always return null; in unspecialized app
      *         processes this function will return a Runnable object representing the new
-     *         application that is passed up from usapMain.
+     *         application that is passed up from childMain (the usap's main wait loop).
      */
 
     Runnable fillUsapPool(int[] sessionSocketRawFDs, boolean isPriorityRefill) {
@@ -420,6 +420,7 @@
      * Runs the zygote process's select loop. Accepts new connections as
      * they happen, and reads commands from connections one spawn-request's
      * worth at a time.
+     * @param abiList list of ABIs supported by this zygote.
      */
     Runnable runSelectLoop(String abiList) {
         ArrayList<FileDescriptor> socketFDs = new ArrayList<>();
@@ -537,22 +538,23 @@
 
                     if (pollIndex == 0) {
                         // Zygote server socket
-
                         ZygoteConnection newPeer = acceptCommandPeer(abiList);
                         peers.add(newPeer);
                         socketFDs.add(newPeer.getFileDescriptor());
-
                     } else if (pollIndex < usapPoolEventFDIndex) {
                         // Session socket accepted from the Zygote server socket
 
                         try {
                             ZygoteConnection connection = peers.get(pollIndex);
-                            final Runnable command = connection.processOneCommand(this);
+                            boolean multipleForksOK = !isUsapPoolEnabled()
+                                    && ZygoteHooks.indefiniteThreadSuspensionOK();
+                            final Runnable command =
+                                    connection.processCommand(this, multipleForksOK);
 
                             // TODO (chriswailes): Is this extra check necessary?
                             if (mIsForkChild) {
                                 // We're in the child. We should always have a command to run at
-                                // this stage if processOneCommand hasn't called "exec".
+                                // this stage if processCommand hasn't called "exec".
                                 if (command == null) {
                                     throw new IllegalStateException("command == null");
                                 }
@@ -565,7 +567,7 @@
                                 }
 
                                 // We don't know whether the remote side of the socket was closed or
-                                // not until we attempt to read from it from processOneCommand. This
+                                // not until we attempt to read from it from processCommand. This
                                 // shows up as a regular POLLIN event in our regular processing
                                 // loop.
                                 if (connection.isClosedByPeer()) {
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 9840013..9a91d20 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -124,6 +124,7 @@
 import com.android.internal.widget.FloatingToolbar;
 
 import java.util.List;
+import java.util.function.Consumer;
 
 /** @hide */
 public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {
@@ -282,14 +283,19 @@
     private final Paint mLegacyNavigationBarBackgroundPaint = new Paint();
     private Insets mBackgroundInsets = Insets.NONE;
     private Insets mLastBackgroundInsets = Insets.NONE;
-    private int mLastBackgroundBlurRadius = 0;
     private boolean mDrawLegacyNavigationBarBackground;
 
     private PendingInsetsController mPendingInsetsController = new PendingInsetsController();
+
+    private int mOriginalBackgroundBlurRadius = 0;
+    private int mBackgroundBlurRadius = 0;
+    private int mLastBackgroundBlurRadius = 0;
+    private boolean mCrossWindowBlurEnabled;
     private final ViewTreeObserver.OnPreDrawListener mBackgroundBlurOnPreDrawListener = () -> {
-        updateBackgroundBlur();
+        updateBackgroundBlurCorners();
         return true;
     };
+    private Consumer<Boolean> mCrossWindowBlurEnabledListener;
 
     DecorView(Context context, int featureId, PhoneWindow window,
             WindowManager.LayoutParams params) {
@@ -1272,23 +1278,17 @@
         }
 
         if (mBackgroundInsets.equals(mLastBackgroundInsets)
-                && mWindow.mBackgroundBlurRadius == mLastBackgroundBlurRadius
+                && mBackgroundBlurRadius == mLastBackgroundBlurRadius
                 && mLastOriginalBackgroundDrawable == mOriginalBackgroundDrawable) {
             return;
         }
 
         Drawable destDrawable = mOriginalBackgroundDrawable;
-        if (mWindow.mBackgroundBlurRadius > 0 && getViewRootImpl() != null
-                && mWindow.isTranslucent()) {
-            if (mBackgroundBlurDrawable == null) {
-                mBackgroundBlurDrawable = getViewRootImpl().createBackgroundBlurDrawable();
-            }
+        if (mBackgroundBlurRadius > 0) {
             destDrawable = new LayerDrawable(new Drawable[] {mBackgroundBlurDrawable,
                                                              mOriginalBackgroundDrawable});
-            mLastBackgroundBlurRadius = mWindow.mBackgroundBlurRadius;
         }
 
-
         if (destDrawable != null && !mBackgroundInsets.equals(Insets.NONE)) {
             destDrawable = new InsetDrawable(destDrawable,
                     mBackgroundInsets.left, mBackgroundInsets.top,
@@ -1309,23 +1309,60 @@
         super.setBackgroundDrawable(destDrawable);
 
         mLastBackgroundInsets = mBackgroundInsets;
+        mLastBackgroundBlurRadius = mBackgroundBlurRadius;
         mLastOriginalBackgroundDrawable = mOriginalBackgroundDrawable;
     }
 
-    private void updateBackgroundBlur() {
+    private void updateBackgroundBlurCorners() {
         if (mBackgroundBlurDrawable == null) return;
 
+        float cornerRadius = 0;
         // If the blur radius is 0, the blur region won't be sent to surface flinger, so we don't
         // need to calculate the corner radius.
-        if (mWindow.mBackgroundBlurRadius > 0) {
-            if (mOriginalBackgroundDrawable != null) {
-                final Outline outline = new Outline();
-                mOriginalBackgroundDrawable.getOutline(outline);
-                mBackgroundBlurDrawable.setCornerRadius(outline.mMode == Outline.MODE_ROUND_RECT
-                                                           ? outline.getRadius() : 0);
-            }
+        if (mBackgroundBlurRadius != 0 && mOriginalBackgroundDrawable != null) {
+            final Outline outline = new Outline();
+            mOriginalBackgroundDrawable.getOutline(outline);
+            cornerRadius = outline.mMode == Outline.MODE_ROUND_RECT ? outline.getRadius() : 0;
         }
-        mBackgroundBlurDrawable.setBlurRadius(mWindow.mBackgroundBlurRadius);
+        mBackgroundBlurDrawable.setCornerRadius(cornerRadius);
+    }
+
+    private void updateBackgroundBlurRadius() {
+        if (getViewRootImpl() == null) return;
+
+        mBackgroundBlurRadius = mCrossWindowBlurEnabled && mWindow.isTranslucent()
+                ? mOriginalBackgroundBlurRadius : 0;
+        if (mBackgroundBlurDrawable == null && mBackgroundBlurRadius > 0) {
+            mBackgroundBlurDrawable = getViewRootImpl().createBackgroundBlurDrawable();
+        }
+
+        if (mBackgroundBlurDrawable != null) {
+            mBackgroundBlurDrawable.setBlurRadius(mBackgroundBlurRadius);
+            updateBackgroundDrawable();
+        }
+    }
+
+    void setBackgroundBlurRadius(int blurRadius) {
+        mOriginalBackgroundBlurRadius = blurRadius;
+        if (blurRadius > 0) {
+            if (mCrossWindowBlurEnabledListener == null) {
+                mCrossWindowBlurEnabledListener = enabled -> {
+                    mCrossWindowBlurEnabled = enabled;
+                    updateBackgroundBlurRadius();
+                };
+                getContext().getSystemService(WindowManager.class)
+                        .addCrossWindowBlurEnabledListener(mCrossWindowBlurEnabledListener);
+                getViewTreeObserver().addOnPreDrawListener(mBackgroundBlurOnPreDrawListener);
+            } else {
+                updateBackgroundBlurRadius();
+            }
+        } else if (mCrossWindowBlurEnabledListener != null) {
+            mCrossWindowBlurEnabledListener = null;
+            getContext().getSystemService(WindowManager.class)
+                    .removeCrossWindowBlurEnabledListener(mCrossWindowBlurEnabledListener);
+            getViewTreeObserver().removeOnPreDrawListener(mBackgroundBlurOnPreDrawListener);
+            updateBackgroundBlurRadius();
+        }
     }
 
     @Override
@@ -1758,9 +1795,6 @@
             cb.onAttachedToWindow();
         }
 
-        getViewTreeObserver().addOnPreDrawListener(mBackgroundBlurOnPreDrawListener);
-        updateBackgroundDrawable();
-
         if (mFeatureId == -1) {
             /*
              * The main window has been attached, try to restore any panels
@@ -1782,6 +1816,9 @@
             // renderer about it.
             mBackdropFrameRenderer.onConfigurationChange();
         }
+
+        updateBackgroundBlurRadius();
+
         mWindow.onViewRootImplSet(getViewRootImpl());
     }
 
@@ -1794,8 +1831,6 @@
             cb.onDetachedFromWindow();
         }
 
-        getViewTreeObserver().removeOnPreDrawListener(mBackgroundBlurOnPreDrawListener);
-
         if (mWindow.mDecorContentParent != null) {
             mWindow.mDecorContentParent.dismissPopups();
         }
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index d06413c..6049486 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -75,6 +75,7 @@
 import android.util.SparseArray;
 import android.util.TypedValue;
 import android.view.ContextThemeWrapper;
+import android.view.CrossWindowBlurListeners;
 import android.view.Gravity;
 import android.view.IRotationWatcher.Stub;
 import android.view.IScrollCaptureCallbacks;
@@ -258,7 +259,7 @@
     Drawable mBackgroundDrawable = null;
     Drawable mBackgroundFallbackDrawable = null;
 
-    int mBackgroundBlurRadius = 0;
+    private int mBackgroundBlurRadius = 0;
 
     private boolean mLoadElevation = true;
     private float mElevation;
@@ -1527,9 +1528,11 @@
     @Override
     public final void setBackgroundBlurRadius(int blurRadius) {
         super.setBackgroundBlurRadius(blurRadius);
-        if (getContext().getPackageManager().hasSystemFeature(
-                    PackageManager.FEATURE_CROSS_LAYER_BLUR)) {
-            mBackgroundBlurRadius = Math.max(blurRadius, 0);
+        if (CrossWindowBlurListeners.CROSS_WINDOW_BLUR_SUPPORTED) {
+            if (mBackgroundBlurRadius != Math.max(blurRadius, 0)) {
+                mBackgroundBlurRadius = Math.max(blurRadius, 0);
+                mDecor.setBackgroundBlurRadius(mBackgroundBlurRadius);
+            }
         }
     }
 
@@ -2556,8 +2559,8 @@
                 params.flags |= WindowManager.LayoutParams.FLAG_BLUR_BEHIND;
             }
 
-            params.blurBehindRadius = a.getDimensionPixelSize(
-                    android.R.styleable.Window_windowBlurBehindRadius, 0);
+            params.setBlurBehindRadius(a.getDimensionPixelSize(
+                    android.R.styleable.Window_windowBlurBehindRadius, 0));
         }
 
         setBackgroundBlurRadius(a.getDimensionPixelSize(
diff --git a/core/java/com/android/internal/policy/TransitionAnimation.java b/core/java/com/android/internal/policy/TransitionAnimation.java
index 56b25b2..93ba037 100644
--- a/core/java/com/android/internal/policy/TransitionAnimation.java
+++ b/core/java/com/android/internal/policy/TransitionAnimation.java
@@ -180,6 +180,7 @@
                 "android", com.android.internal.R.anim.cross_profile_apps_thumbnail_enter);
     }
 
+    /** Load animation by resource Id from specific LayoutParams. */
     @Nullable
     private Animation loadAnimationRes(LayoutParams lp, int resId) {
         Context context = mContext;
@@ -193,6 +194,7 @@
         return null;
     }
 
+    /** Load animation by resource Id from specific package. */
     @Nullable
     private Animation loadAnimationRes(String packageName, int resId) {
         if (ResourceId.isValid(resId)) {
@@ -204,6 +206,13 @@
         return null;
     }
 
+    /** Load animation by resource Id from android package. */
+    @Nullable
+    public Animation loadDefaultAnimationRes(int resId) {
+        return loadAnimationRes("android", resId);
+    }
+
+    /** Load animation by attribute Id from specific LayoutParams */
     @Nullable
     public Animation loadAnimationAttr(LayoutParams lp, int animAttr, int transit) {
         int resId = Resources.ID_NULL;
@@ -222,6 +231,25 @@
         return null;
     }
 
+    /** Load animation by attribute Id from android package. */
+    @Nullable
+    public Animation loadDefaultAnimationAttr(int animAttr) {
+        int resId = Resources.ID_NULL;
+        Context context = mContext;
+        if (animAttr >= 0) {
+            AttributeCache.Entry ent = getCachedAnimations("android",
+                    mDefaultWindowAnimationStyleResId);
+            if (ent != null) {
+                context = ent.context;
+                resId = ent.array.getResourceId(animAttr, 0);
+            }
+        }
+        if (ResourceId.isValid(resId)) {
+            return loadAnimationSafely(context, resId, mTag);
+        }
+        return null;
+    }
+
     @Nullable
     private AttributeCache.Entry getCachedAnimations(LayoutParams lp) {
         if (mDebug) {
diff --git a/core/java/com/android/internal/power/MeasuredEnergyStats.java b/core/java/com/android/internal/power/MeasuredEnergyStats.java
index d7b4d78..d49203c 100644
--- a/core/java/com/android/internal/power/MeasuredEnergyStats.java
+++ b/core/java/com/android/internal/power/MeasuredEnergyStats.java
@@ -193,34 +193,30 @@
         return mAccumulatedEnergiesMicroJoules.length;
     }
 
-    // TODO: Get rid of the 'accumulate' boolean. It's always true.
     /** Updates the given standard energy bucket with the given energy if accumulate is true. */
-    public void updateStandardBucket(@StandardEnergyBucket int bucket, long energyDeltaUJ,
-            boolean accumulate) {
+    public void updateStandardBucket(@StandardEnergyBucket int bucket, long energyDeltaUJ) {
         checkValidStandardBucket(bucket);
-        updateEntry(bucket, energyDeltaUJ, accumulate);
+        updateEntry(bucket, energyDeltaUJ);
     }
 
     /** Updates the given custom energy bucket with the given energy if accumulate is true. */
-    public void updateCustomBucket(int customBucket, long energyDeltaUJ, boolean accumulate) {
+    public void updateCustomBucket(int customBucket, long energyDeltaUJ) {
         if (!isValidCustomBucket(customBucket)) {
             Slog.e(TAG, "Attempted to update invalid custom bucket " + customBucket);
             return;
         }
         final int index = customBucketToIndex(customBucket);
-        updateEntry(index, energyDeltaUJ, accumulate);
+        updateEntry(index, energyDeltaUJ);
     }
 
     /** Updates the given index with the given energy if accumulate is true. */
-    private void updateEntry(int index, long energyDeltaUJ, boolean accumulate) {
-        if (accumulate) {
-            if (mAccumulatedEnergiesMicroJoules[index] >= 0L) {
-                mAccumulatedEnergiesMicroJoules[index] += energyDeltaUJ;
-            } else {
-                Slog.wtf(TAG, "Attempting to add " + energyDeltaUJ + " to unavailable bucket "
-                        + getBucketName(index) + " whose value was "
-                        + mAccumulatedEnergiesMicroJoules[index]);
-            }
+    private void updateEntry(int index, long energyDeltaUJ) {
+        if (mAccumulatedEnergiesMicroJoules[index] >= 0L) {
+            mAccumulatedEnergiesMicroJoules[index] += energyDeltaUJ;
+        } else {
+            Slog.wtf(TAG, "Attempting to add " + energyDeltaUJ + " to unavailable bucket "
+                    + getBucketName(index) + " whose value was "
+                    + mAccumulatedEnergiesMicroJoules[index]);
         }
     }
 
diff --git a/core/java/com/android/internal/power/TEST_MAPPING b/core/java/com/android/internal/power/TEST_MAPPING
new file mode 100644
index 0000000..96f31bc
--- /dev/null
+++ b/core/java/com/android/internal/power/TEST_MAPPING
@@ -0,0 +1,19 @@
+{
+  "presubmit": [
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        { "include-filter": "com.android.internal.os.BatteryStatsTests" },
+        { "exclude-annotation": "com.android.internal.os.SkipPresubmit" }
+      ]
+    },
+    {
+      "name": "FrameworksServicesTests",
+      "options": [
+        { "include-filter": "com.android.server.am.BatteryStatsServiceTest" },
+        { "include-filter": "com.android.server.am.MeasuredEnergySnapshotTest" },
+        { "include-filter": "com.android.server.am.BatteryExternalStatsWorkerTest" }
+      ]
+    }
+  ]
+}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index bb0fd7f..fde48e8 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -22,6 +22,7 @@
 import android.hardware.biometrics.IBiometricSysuiReceiver;
 import android.hardware.biometrics.PromptInfo;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
 
@@ -66,7 +67,7 @@
     void onNotificationError(String pkg, String tag, int id,
             int uid, int initialPid, String message, int userId);
     void onClearAllNotifications(int userId);
-    void onNotificationClear(String pkg, String tag, int id, int userId, String key,
+    void onNotificationClear(String pkg, int userId, String key,
             int dismissalSurface, int dismissalSentiment, in NotificationVisibility nv);
     void onNotificationVisibilityChanged( in NotificationVisibility[] newlyVisibleKeys,
             in NotificationVisibility[] noLongerVisibleKeys);
@@ -82,6 +83,7 @@
     void hideCurrentInputMethodForBubbles();
     void grantInlineReplyUriPermission(String key, in Uri uri, in UserHandle user, String packageName);
     void clearInlineReplyUriPermissions(String key);
+    void onNotificationFeedbackReceived(String key, in Bundle feedback);
 
     void onGlobalActionsShown();
     void onGlobalActionsHidden();
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index f7d440d..95e0a3b 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -94,6 +94,6 @@
     void notifyBarringInfoChanged(int slotIndex, int subId, in BarringInfo barringInfo);
     void notifyPhysicalChannelConfigForSubscriber(in int subId,
             in List<PhysicalChannelConfig> configs);
-    void notifyDataEnabled(boolean enabled, int reason);
+    void notifyDataEnabled(in int phoneId, int subId, boolean enabled, int reason);
     void notifyAllowedNetworkTypesChanged(in int phoneId, in int subId, in Map allowedNetworkTypeList);
 }
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index ef2275d..ab0149f 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.ScrollCaptureResponse;
 import android.view.WindowInsets.Type.InsetsType;
 import android.window.ClientWindowFrames;
 
@@ -160,7 +161,9 @@
     @Override
     public void requestScrollCapture(IScrollCaptureCallbacks callbacks) {
         try {
-            callbacks.onUnavailable();
+            callbacks.onScrollCaptureResponse(
+                    new ScrollCaptureResponse.Builder().setDescription("Not Implemented").build());
+
         } catch (RemoteException ex) {
             // ignore
         }
diff --git a/core/java/com/android/internal/view/ScrollCaptureViewSupport.java b/core/java/com/android/internal/view/ScrollCaptureViewSupport.java
index 85fa791..a41511b 100644
--- a/core/java/com/android/internal/view/ScrollCaptureViewSupport.java
+++ b/core/java/com/android/internal/view/ScrollCaptureViewSupport.java
@@ -16,15 +16,19 @@
 
 package com.android.internal.view;
 
+import android.annotation.UiThread;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
 import android.graphics.HardwareRenderer;
 import android.graphics.Matrix;
 import android.graphics.RecordingCanvas;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.RenderNode;
-import android.os.Handler;
+import android.os.CancellationSignal;
 import android.util.DisplayMetrics;
 import android.util.Log;
+import android.view.Display.ColorMode;
 import android.view.ScrollCaptureCallback;
 import android.view.ScrollCaptureSession;
 import android.view.Surface;
@@ -44,32 +48,42 @@
  * @param <V> the specific View subclass handled
  * @see ScrollCaptureViewHelper
  */
+@UiThread
 public class ScrollCaptureViewSupport<V extends View> implements ScrollCaptureCallback {
 
-    public static final long NO_FRAME_PRODUCED = -1;
-
     private static final String TAG = "ScrollCaptureViewSupport";
 
     private static final boolean WAIT_FOR_ANIMATION = true;
 
     private final WeakReference<V> mWeakView;
     private final ScrollCaptureViewHelper<V> mViewHelper;
-    private ViewRenderer mRenderer;
-    private Handler mUiHandler;
+    private final ViewRenderer mRenderer;
     private boolean mStarted;
     private boolean mEnded;
 
     ScrollCaptureViewSupport(V containingView, ScrollCaptureViewHelper<V> viewHelper) {
         mWeakView = new WeakReference<>(containingView);
         mRenderer = new ViewRenderer();
-        mUiHandler = containingView.getHandler();
+        // TODO(b/177649144): provide access to color space from android.media.Image
         mViewHelper = viewHelper;
     }
 
-    // Base implementation of ScrollCaptureCallback
+    /** Based on ViewRootImpl#updateColorModeIfNeeded */
+    @ColorMode
+    private static int getColorMode(View containingView) {
+        Context context = containingView.getContext();
+        int colorMode = containingView.getViewRootImpl().mWindowAttributes.getColorMode();
+        if (!context.getResources().getConfiguration().isScreenWideColorGamut()) {
+            colorMode = ActivityInfo.COLOR_MODE_DEFAULT;
+        }
+        return colorMode;
+    }
 
     @Override
-    public final void onScrollCaptureSearch(Consumer<Rect> onReady) {
+    public final void onScrollCaptureSearch(CancellationSignal signal, Consumer<Rect> onReady) {
+        if (signal.isCanceled()) {
+            return;
+        }
         V view = mWeakView.get();
         mStarted = false;
         mEnded = false;
@@ -82,7 +96,11 @@
     }
 
     @Override
-    public final void onScrollCaptureStart(ScrollCaptureSession session, Runnable onReady) {
+    public final void onScrollCaptureStart(ScrollCaptureSession session, CancellationSignal signal,
+            Runnable onReady) {
+        if (signal.isCanceled()) {
+            return;
+        }
         V view = mWeakView.get();
 
         mEnded = false;
@@ -99,18 +117,22 @@
     }
 
     @Override
-    public final void onScrollCaptureImageRequest(ScrollCaptureSession session, Rect requestRect) {
+    public final void onScrollCaptureImageRequest(ScrollCaptureSession session,
+            CancellationSignal signal, Rect requestRect, Consumer<Rect> onComplete) {
+        if (signal.isCanceled()) {
+            return;
+        }
         V view = mWeakView.get();
         if (view == null || !view.isVisibleToUser()) {
             // Signal to the controller that we have a problem and can't continue.
-            session.notifyBufferSent(NO_FRAME_PRODUCED, new Rect());
+            onComplete.accept(new Rect());
             return;
         }
         // Ask the view to scroll as needed to bring this area into view.
         ScrollResult scrollResult = mViewHelper.onScrollRequested(view, session.getScrollBounds(),
                 requestRect);
         if (scrollResult.availableArea.isEmpty()) {
-            session.notifyBufferSent(NO_FRAME_PRODUCED, scrollResult.availableArea);
+            onComplete.accept(scrollResult.availableArea);
             return;
         }
         view.invalidate(); // don't wait for vsync
@@ -121,17 +143,13 @@
         viewCaptureArea.offset(0, -scrollResult.scrollDelta);
 
         if (WAIT_FOR_ANIMATION) {
-            Log.d(TAG, "render: delaying until animation");
             view.postOnAnimation(() ->  {
-                Log.d(TAG, "postOnAnimation(): rendering now");
-                long resultFrame = mRenderer.renderView(view, viewCaptureArea);
-                Log.d(TAG, "notifyBufferSent: " + scrollResult.availableArea);
-
-                session.notifyBufferSent(resultFrame, new Rect(scrollResult.availableArea));
+                mRenderer.renderView(view, viewCaptureArea);
+                onComplete.accept(new Rect(scrollResult.availableArea));
             });
         } else {
-            long resultFrame = mRenderer.renderView(view, viewCaptureArea);
-            session.notifyBufferSent(resultFrame, new Rect(scrollResult.availableArea));
+            mRenderer.renderView(view, viewCaptureArea);
+            onComplete.accept(new Rect(scrollResult.availableArea));
         }
     }
 
@@ -239,7 +257,7 @@
             mCaptureRenderNode.endRecording();
         }
 
-        public long renderView(View view, Rect sourceRect) {
+        public void renderView(View view, Rect sourceRect) {
             if (updateForView(view)) {
                 setupLighting(view);
             }
@@ -258,7 +276,7 @@
             switch (request.syncAndDraw()) {
                 case HardwareRenderer.SYNC_OK:
                 case HardwareRenderer.SYNC_REDRAW_REQUESTED:
-                    return frameNumber;
+                    return;
 
                 case HardwareRenderer.SYNC_FRAME_DROPPED:
                     Log.e(TAG, "syncAndDraw(): SYNC_FRAME_DROPPED !");
@@ -270,7 +288,6 @@
                     Log.e(TAG, "syncAndDraw(): SYNC_CONTEXT_IS_STOPPED !");
                     break;
             }
-            return NO_FRAME_PRODUCED;
         }
 
         public void trimMemory() {
@@ -289,5 +306,17 @@
             mTempMatrix.mapRect(mTempRectF);
             mTempRectF.round(outRect);
         }
+
+        public void setColorMode(@ColorMode int colorMode) {
+            mRenderer.setColorMode(colorMode);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "ScrollCaptureViewSupport{"
+                + "view=" + mWeakView.get()
+                + ", helper=" + mViewHelper
+                + '}';
     }
 }
diff --git a/core/java/com/android/internal/widget/NotificationVanishingFrameLayout.java b/core/java/com/android/internal/widget/NotificationVanishingFrameLayout.java
new file mode 100644
index 0000000..742bdfd
--- /dev/null
+++ b/core/java/com/android/internal/widget/NotificationVanishingFrameLayout.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.RemoteViews;
+
+/**
+ * This view will measure itself as having 0 size if all of its children are {@link #GONE}.
+ * Otherwise it acts like a normal {@link FrameLayout}.
+ */
+@RemoteViews.RemoteView
+public class NotificationVanishingFrameLayout extends FrameLayout {
+    public NotificationVanishingFrameLayout(Context context) {
+        this(context, null, 0, 0);
+    }
+
+    public NotificationVanishingFrameLayout(Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0, 0);
+    }
+
+    public NotificationVanishingFrameLayout(Context context, @Nullable AttributeSet attrs,
+            int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public NotificationVanishingFrameLayout(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        if (allChildrenGone()) {
+            int zeroSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.EXACTLY);
+            super.onMeasure(zeroSpec, zeroSpec);
+        } else {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        }
+    }
+
+    private boolean allChildrenGone() {
+        final int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            final View child =  getChildAt(i);
+            if (child != null && child.getVisibility() != GONE) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index a2de0af..fd6038f 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -399,7 +399,10 @@
             if (mCurDown && ps.mCurDown) {
                 // Draw crosshairs.
                 canvas.drawLine(0, ps.mCoords.y, getWidth(), ps.mCoords.y, mTargetPaint);
-                canvas.drawLine(ps.mCoords.x, 0, ps.mCoords.x, getHeight(), mTargetPaint);
+                // Extend crosshairs to cover screen regardless of rotation (ie. since the rotated
+                // canvas can "expose" content past 0 and up-to the largest screen dimension).
+                canvas.drawLine(ps.mCoords.x, -getHeight(), ps.mCoords.x,
+                        Math.max(getHeight(), getWidth()), mTargetPaint);
 
                 // Draw current point.
                 int pressureLevel = (int)(ps.mCoords.pressure * 255);
diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java
index 95999a7..fe3042d 100644
--- a/core/java/com/android/server/BootReceiver.java
+++ b/core/java/com/android/server/BootReceiver.java
@@ -74,6 +74,7 @@
     private static final int GMSCORE_LASTK_LOG_SIZE = 196608;
 
     private static final String TAG_TOMBSTONE = "SYSTEM_TOMBSTONE";
+    private static final String TAG_TOMBSTONE_PROTO = "SYSTEM_TOMBSTONE_PROTO";
 
     // The pre-froyo package and class of the system updater, which
     // ran in the system process.  We need to remove its packages here
@@ -251,14 +252,14 @@
      * @param ctx Context
      * @param tombstone path to the tombstone
      */
-    public static void addTombstoneToDropBox(Context ctx, File tombstone) {
+    public static void addTombstoneToDropBox(Context ctx, File tombstone, boolean proto) {
         final DropBoxManager db = ctx.getSystemService(DropBoxManager.class);
         final String bootReason = SystemProperties.get("ro.boot.bootreason", null);
         HashMap<String, Long> timestamps = readTimestamps();
         try {
             final String headers = getBootHeadersToLogAndUpdate();
             addFileToDropBox(db, timestamps, headers, tombstone.getPath(), LOG_SIZE,
-                    TAG_TOMBSTONE);
+                    proto ? TAG_TOMBSTONE_PROTO : TAG_TOMBSTONE);
         } catch (IOException e) {
             Slog.e(TAG, "Can't log tombstone", e);
         }
diff --git a/core/java/com/android/server/OWNERS b/core/java/com/android/server/OWNERS
new file mode 100644
index 0000000..12629254
--- /dev/null
+++ b/core/java/com/android/server/OWNERS
@@ -0,0 +1 @@
+per-file SystemConfig.java = toddke@google.com
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 8982519..58df2be 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -24,6 +24,7 @@
 import android.content.ComponentName;
 import android.content.pm.FeatureInfo;
 import android.content.pm.PackageManager;
+import android.hardware.SensorPrivacyManager;
 import android.os.Build;
 import android.os.CarrierAssociatedAppEntry;
 import android.os.Environment;
@@ -94,9 +95,6 @@
     // property for runtime configuration differentiation in vendor
     private static final String VENDOR_SKU_PROPERTY = "ro.boot.product.vendor.sku";
 
-    // property for background blur support in surface flinger
-    private static final String BLUR_PROPERTY = "ro.surface_flinger.supports_background_blur";
-
     // Group-ids that are given to all packages as read from etc/permissions/*.xml.
     int[] mGlobalGids = EmptyArray.INT;
 
@@ -1234,10 +1232,10 @@
             addFeature(PackageManager.FEATURE_RAM_NORMAL, 0);
         }
 
-        if (IncrementalManager.isFeatureEnabled()) {
+        final int incrementalVersion = IncrementalManager.getVersion();
+        if (incrementalVersion > 0) {
             addFeature(PackageManager.FEATURE_INCREMENTAL_DELIVERY, 0);
-            addFeature(PackageManager.FEATURE_INCREMENTAL_DELIVERY_VERSION,
-                    IncrementalManager.isV2Available() ? 2 : 1);
+            addFeature(PackageManager.FEATURE_INCREMENTAL_DELIVERY_VERSION, incrementalVersion);
         }
 
         if (PackageManager.APP_ENUMERATION_ENABLED_BY_DEFAULT) {
@@ -1248,8 +1246,12 @@
             addFeature(PackageManager.FEATURE_IPSEC_TUNNELS, 0);
         }
 
-        if (SystemProperties.get(BLUR_PROPERTY, "default").equals("1")) {
-            addFeature(PackageManager.FEATURE_CROSS_LAYER_BLUR, 0);
+        if (SensorPrivacyManager.USE_MICROPHONE_TOGGLE) {
+            addFeature(PackageManager.FEATURE_MICROPHONE_TOGGLE, 0);
+        }
+
+        if (SensorPrivacyManager.USE_CAMERA_TOGGLE) {
+            addFeature(PackageManager.FEATURE_CAMERA_TOGGLE, 0);
         }
 
         for (String featureName : mUnavailableFeatures) {
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index d72a0ec..e6fb5ae 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -1,3 +1,21 @@
+
+package {
+    default_applicable_licenses: ["frameworks_base_core_jni_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_core_jni_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_library_shared {
     name: "libandroid_runtime",
     host_supported: true,
@@ -33,6 +51,7 @@
         "android_util_XmlBlock.cpp",
         "android_util_jar_StrictJarFile.cpp",
         "com_android_internal_util_VirtualRefBasePtr.cpp",
+        ":deviceproductinfoconstants_aidl",
     ],
 
     include_dirs: [
@@ -103,6 +122,7 @@
                 "android_view_PointerIcon.cpp",
                 "android_view_Surface.cpp",
                 "android_view_SurfaceControl.cpp",
+                "android_view_SurfaceControlFpsListener.cpp",
                 "android_graphics_BLASTBufferQueue.cpp",
                 "android_view_SurfaceSession.cpp",
                 "android_view_TextureView.cpp",
@@ -157,6 +177,7 @@
                 "android_hardware_Camera.cpp",
                 "android_hardware_camera2_CameraMetadata.cpp",
                 "android_hardware_camera2_DngCreator.cpp",
+                "android_hardware_camera2_impl_CameraExtensionJpegProcessor.cpp",
                 "android_hardware_camera2_utils_SurfaceUtils.cpp",
                 "android_hardware_display_DisplayManagerGlobal.cpp",
                 "android_hardware_display_DisplayViewport.cpp",
@@ -191,6 +212,7 @@
                 "com_android_internal_os_KernelSingleProcessCpuThreadReader.cpp",
                 "com_android_internal_os_KernelSingleUidTimeReader.cpp",
                 "com_android_internal_os_Zygote.cpp",
+                "com_android_internal_os_ZygoteCommandBuffer.cpp",
                 "com_android_internal_os_ZygoteInit.cpp",
                 "hwbinder/EphemeralStorage.cpp",
                 "fd_utils.cpp",
@@ -209,10 +231,11 @@
             ],
 
             shared_libs: [
-                "android.hardware.memtrack-unstable-ndk_platform",
+                "android.hardware.memtrack-V1-ndk_platform",
                 "audioclient-types-aidl-cpp",
                 "audioflinger-aidl-cpp",
                 "av-types-aidl-cpp",
+                "android.hardware.camera.device@3.2",
                 "libandroidicu",
                 "libbpf_android",
                 "libnetdbpf",
@@ -242,6 +265,7 @@
                 "libdataloader",
                 "libvulkan",
                 "libETC1",
+                "libjpeg",
                 "libhardware",
                 "libhardware_legacy",
                 "libselinux",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 38bcc0f..ddd8613 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -74,6 +74,7 @@
 extern int register_android_hardware_Camera(JNIEnv *env);
 extern int register_android_hardware_camera2_CameraMetadata(JNIEnv *env);
 extern int register_android_hardware_camera2_DngCreator(JNIEnv *env);
+extern int register_android_hardware_camera2_impl_CameraExtensionJpegProcessor(JNIEnv* env);
 extern int register_android_hardware_camera2_utils_SurfaceUtils(JNIEnv* env);
 extern int register_android_hardware_display_DisplayManagerGlobal(JNIEnv* env);
 extern int register_android_hardware_HardwareBuffer(JNIEnv *env);
@@ -119,6 +120,7 @@
 extern int register_android_view_InputWindowHandle(JNIEnv* env);
 extern int register_android_view_Surface(JNIEnv* env);
 extern int register_android_view_SurfaceControl(JNIEnv* env);
+extern int register_android_view_SurfaceControlFpsListener(JNIEnv* env);
 extern int register_android_view_SurfaceSession(JNIEnv* env);
 extern int register_android_view_CompositionSamplingListener(JNIEnv* env);
 extern int register_android_view_TextureView(JNIEnv* env);
@@ -196,6 +198,7 @@
 extern int register_com_android_internal_os_KernelSingleProcessCpuThreadReader(JNIEnv* env);
 extern int register_com_android_internal_os_KernelSingleUidTimeReader(JNIEnv *env);
 extern int register_com_android_internal_os_Zygote(JNIEnv *env);
+extern int register_com_android_internal_os_ZygoteCommandBuffer(JNIEnv *env);
 extern int register_com_android_internal_os_ZygoteInit(JNIEnv *env);
 extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env);
 
@@ -1487,6 +1490,7 @@
         REG_JNI(register_android_view_InputWindowHandle),
         REG_JNI(register_android_view_Surface),
         REG_JNI(register_android_view_SurfaceControl),
+        REG_JNI(register_android_view_SurfaceControlFpsListener),
         REG_JNI(register_android_view_SurfaceSession),
         REG_JNI(register_android_view_CompositionSamplingListener),
         REG_JNI(register_android_view_TextureView),
@@ -1528,11 +1532,13 @@
         REG_JNI(register_com_android_internal_net_NetworkUtilsInternal),
         REG_JNI(register_com_android_internal_os_ClassLoaderFactory),
         REG_JNI(register_com_android_internal_os_Zygote),
+        REG_JNI(register_com_android_internal_os_ZygoteCommandBuffer),
         REG_JNI(register_com_android_internal_os_ZygoteInit),
         REG_JNI(register_com_android_internal_util_VirtualRefBasePtr),
         REG_JNI(register_android_hardware_Camera),
         REG_JNI(register_android_hardware_camera2_CameraMetadata),
         REG_JNI(register_android_hardware_camera2_DngCreator),
+        REG_JNI(register_android_hardware_camera2_impl_CameraExtensionJpegProcessor),
         REG_JNI(register_android_hardware_camera2_utils_SurfaceUtils),
         REG_JNI(register_android_hardware_display_DisplayManagerGlobal),
         REG_JNI(register_android_hardware_HardwareBuffer),
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 5b327d4..d0504fb 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -421,11 +421,18 @@
 };
 
 static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jlong sensorManager,
-        jobject eventQWeak, jobject msgQ, jstring packageName, jint mode) {
+                                        jobject eventQWeak, jobject msgQ, jstring packageName,
+                                        jint mode, jstring opPackageName, jstring attributionTag) {
     SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
     ScopedUtfChars packageUtf(env, packageName);
     String8 clientName(packageUtf.c_str());
-    sp<SensorEventQueue> queue(mgr->createEventQueue(clientName, mode));
+
+    String16 attributionTagName("");
+    if (attributionTag != nullptr) {
+        ScopedUtfChars attrUtf(env, attributionTag);
+        attributionTagName = String16(attrUtf.c_str());
+    }
+    sp<SensorEventQueue> queue(mgr->createEventQueue(clientName, mode, attributionTagName));
 
     if (queue == NULL) {
         jniThrowRuntimeException(env, "Cannot construct native SensorEventQueue.");
@@ -517,29 +524,20 @@
 };
 
 static const JNINativeMethod gBaseEventQueueMethods[] = {
-    {"nativeInitBaseEventQueue",
-             "(JLjava/lang/ref/WeakReference;Landroid/os/MessageQueue;Ljava/lang/String;ILjava/lang/String;)J",
-             (void*)nativeInitSensorEventQueue },
+        {"nativeInitBaseEventQueue",
+         "(JLjava/lang/ref/WeakReference;Landroid/os/MessageQueue;Ljava/lang/String;ILjava/lang/"
+         "String;Ljava/lang/String;)J",
+         (void *)nativeInitSensorEventQueue},
 
-    {"nativeEnableSensor",
-            "(JIII)I",
-            (void*)nativeEnableSensor },
+        {"nativeEnableSensor", "(JIII)I", (void *)nativeEnableSensor},
 
-    {"nativeDisableSensor",
-            "(JI)I",
-            (void*)nativeDisableSensor },
+        {"nativeDisableSensor", "(JI)I", (void *)nativeDisableSensor},
 
-    {"nativeDestroySensorEventQueue",
-            "(J)V",
-            (void*)nativeDestroySensorEventQueue },
+        {"nativeDestroySensorEventQueue", "(J)V", (void *)nativeDestroySensorEventQueue},
 
-    {"nativeFlushSensor",
-            "(J)I",
-            (void*)nativeFlushSensor },
+        {"nativeFlushSensor", "(J)I", (void *)nativeFlushSensor},
 
-    {"nativeInjectSensorData",
-            "(JI[FIJ)I",
-            (void*)nativeInjectSensorData },
+        {"nativeInjectSensorData", "(JI[FIJ)I", (void *)nativeInjectSensorData},
 };
 
 } //unnamed namespace
diff --git a/core/jni/android_hardware_camera2_impl_CameraExtensionJpegProcessor.cpp b/core/jni/android_hardware_camera2_impl_CameraExtensionJpegProcessor.cpp
new file mode 100644
index 0000000..1390759
--- /dev/null
+++ b/core/jni/android_hardware_camera2_impl_CameraExtensionJpegProcessor.cpp
@@ -0,0 +1,629 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <array>
+#include <cstring>
+#include <cstdio>
+#include <inttypes.h>
+#include <memory.h>
+#include <vector>
+
+#include <setjmp.h>
+
+#include <android/hardware/camera/device/3.2/types.h>
+
+#include "core_jni_helpers.h"
+#include "jni.h"
+#include <nativehelper/JNIHelp.h>
+
+#define CAMERA_PROCESSOR_CLASS_NAME "android/hardware/camera2/impl/CameraExtensionJpegProcessor"
+
+extern "C" {
+#include "jpeglib.h"
+}
+
+using namespace std;
+using namespace android;
+
+using android::hardware::camera::device::V3_2::CameraBlob;
+using android::hardware::camera::device::V3_2::CameraBlobId;
+
+class Transform;
+struct Plane;
+
+inline int sgn(int val) { return (0 < val) - (val < 0); }
+
+inline int min(int a, int b) { return a < b ? a : b; }
+
+inline int max(int a, int b) { return a > b ? a : b; }
+
+/**
+ * Represents a combined cropping and rotation transformation.
+ *
+ * The transformation maps the coordinates (mOrigX, mOrigY) and (mOneX, mOneY)
+ * in the input image to the origin and (mOutputWidth, mOutputHeight)
+ * respectively.
+ */
+class Transform {
+    public:
+        Transform(int origX, int origY, int oneX, int oneY);
+
+        static Transform forCropFollowedByRotation(int cropLeft, int cropTop,
+                int cropRight, int cropBottom, int rot90);
+
+        inline int getOutputWidth() const { return mOutputWidth; }
+
+        inline int getOutputHeight() const { return mOutputHeight; }
+
+        bool operator==(const Transform& other) const;
+
+        /**
+         * Transforms the input coordinates.  Coordinates outside the cropped region
+         * are clamped to valid values.
+         */
+        void map(int x, int y, int* outX, int* outY) const;
+
+    private:
+        int mOutputWidth;
+        int mOutputHeight;
+
+        // The coordinates of the point to map the origin to.
+        const int mOrigX, mOrigY;
+        // The coordinates of the point to map the point (getOutputWidth(),
+        // getOutputHeight()) to.
+        const int mOneX, mOneY;
+
+        // A matrix for the rotational component.
+        int mMat00, mMat01;
+        int mMat10, mMat11;
+};
+
+/**
+ * Represents a model for accessing pixel data for a single plane of an image.
+ * Note that the actual data is not owned by this class, and the underlying
+ * data does not need to be stored in separate planes.
+ */
+struct Plane {
+    // The dimensions of this plane of the image
+    int width;
+    int height;
+
+    // A pointer to raw pixel data
+    const unsigned char* data;
+    // The difference in address between consecutive pixels in the same row
+    int pixelStride;
+    // The difference in address between the start of consecutive rows
+    int rowStride;
+};
+
+/**
+ * Provides an interface for simultaneously reading a certain number of rows of
+ * an image plane as contiguous arrays, suitable for use with libjpeg.
+ */
+template <unsigned int ROWS>
+class RowIterator {
+    public:
+        /**
+         * Creates a new RowIterator which will crop and rotate with the given
+         * transform.
+         *
+         * @param plane the plane to iterate over
+         * @param transform the transformation to map output values into the
+         * coordinate space of the plane
+         * @param rowLength the length of the rows returned via LoadAt().  If this is
+         * longer than the width of the output (after applying the transform), then
+         * the right-most value is repeated.
+         */
+        inline RowIterator(Plane plane, Transform transform, int rowLength);
+
+        /**
+         * Returns an array of pointers into consecutive rows of contiguous image
+         * data starting at y.  That is, samples within each row are contiguous.
+         * However, the individual arrays pointed-to may be separate.
+         * When the end of the image is reached, the last row of the image is
+         * repeated.
+         * The returned pointers are valid until the next call to loadAt().
+         */
+        inline const std::array<unsigned char*, ROWS> loadAt(int baseY);
+
+    private:
+        Plane mPlane;
+        Transform mTransform;
+        // The length of a row, with padding to the next multiple of 64.
+        int mPaddedRowLength;
+        std::vector<unsigned char> mBuffer;
+};
+
+template <unsigned int ROWS>
+RowIterator<ROWS>::RowIterator(Plane plane, Transform transform,
+                                         int rowLength)
+        : mPlane(plane), mTransform(transform) {
+    mPaddedRowLength = rowLength;
+    mBuffer = std::vector<unsigned char>(rowLength * ROWS);
+}
+
+template <unsigned int ROWS>
+const std::array<unsigned char*, ROWS> RowIterator<ROWS>::loadAt(int baseY) {
+    std::array<unsigned char*, ROWS> bufPtrs;
+    for (unsigned int i = 0; i < ROWS; i++) {
+        bufPtrs[i] = &mBuffer[mPaddedRowLength * i];
+    }
+
+    if (mPlane.width == 0 || mPlane.height == 0) {
+        return bufPtrs;
+    }
+
+    for (unsigned int i = 0; i < ROWS; i++) {
+        int y = i + baseY;
+        y = min(y, mTransform.getOutputHeight() - 1);
+
+        int output_width = mPaddedRowLength;
+        output_width = min(output_width, mTransform.getOutputWidth());
+        output_width = min(output_width, mPlane.width);
+
+        // Each row in the output image will be copied into buf_ by gathering pixels
+        // along an axis-aligned line in the plane.
+        // The line is defined by (startX, startY) -> (endX, endY), computed via the
+        // current Transform.
+        int startX;
+        int startY;
+        mTransform.map(0, y, &startX, &startY);
+
+        int endX;
+        int endY;
+        mTransform.map(output_width - 1, y, &endX, &endY);
+
+        // Clamp (startX, startY) and (endX, endY) to the valid bounds of the plane.
+        startX = min(startX, mPlane.width - 1);
+        startY = min(startY, mPlane.height - 1);
+        endX = min(endX, mPlane.width - 1);
+        endY = min(endY, mPlane.height - 1);
+        startX = max(startX, 0);
+        startY = max(startY, 0);
+        endX = max(endX, 0);
+        endY = max(endY, 0);
+
+        // To reduce work inside the copy-loop, precompute the start, end, and
+        // stride relating the values to be gathered from mPlane into buf
+        // for this particular scan-line.
+        int dx = sgn(endX - startX);
+        int dy = sgn(endY - startY);
+        if (!(dx == 0 || dy == 0)) {
+            ALOGE("%s: Unexpected bounds: %dx%d %dx%d!", __FUNCTION__, startX, endX, startY, endY);
+            return bufPtrs;
+        }
+
+        // The index into mPlane.data of (startX, startY)
+        int plane_start = startX * mPlane.pixelStride + startY * mPlane.rowStride;
+        // The index into mPlane.data of (endX, endY)
+        int plane_end = endX * mPlane.pixelStride + endY * mPlane.rowStride;
+        // The stride, in terms of indices in plane_data, required to enumerate the
+        // samples between the start and end points.
+        int stride = dx * mPlane.pixelStride + dy * mPlane.rowStride;
+        // In the degenerate-case of a 1x1 plane, startX and endX are equal, so
+        // stride would be 0, resulting in an infinite-loop.  To avoid this case,
+        // use a stride of at-least 1.
+        if (stride == 0) {
+            stride = 1;
+        }
+
+        int outX = 0;
+        for (int idx = plane_start; idx >= min(plane_start, plane_end) &&
+                idx <= max(plane_start, plane_end); idx += stride) {
+            bufPtrs[i][outX] = mPlane.data[idx];
+            outX++;
+        }
+
+        // Fill the remaining right-edge of the buffer by extending the last
+        // value.
+        unsigned char right_padding_value = bufPtrs[i][outX - 1];
+        for (; outX < mPaddedRowLength; outX++) {
+            bufPtrs[i][outX] = right_padding_value;
+        }
+    }
+
+    return bufPtrs;
+}
+
+template <typename T>
+void safeDelete(T& t) {
+    delete t;
+    t = nullptr;
+}
+
+template <typename T>
+void safeDeleteArray(T& t) {
+    delete[] t;
+    t = nullptr;
+}
+
+Transform::Transform(int origX, int origY, int oneX, int oneY)
+    : mOrigX(origX), mOrigY(origY), mOneX(oneX), mOneY(oneY) {
+    if (origX == oneX || origY == oneY) {
+        // Handle the degenerate case of cropping to a 0x0 rectangle.
+        mMat00 = 0;
+        mMat01 = 0;
+        mMat10 = 0;
+        mMat11 = 0;
+        return;
+    }
+
+    if (oneX > origX && oneY > origY) {
+        // 0-degree rotation
+        mMat00 = 1;
+        mMat01 = 0;
+        mMat10 = 0;
+        mMat11 = 1;
+        mOutputWidth = abs(oneX - origX);
+        mOutputHeight = abs(oneY - origY);
+    } else if (oneX < origX && oneY > origY) {
+        // 90-degree CCW rotation
+        mMat00 = 0;
+        mMat01 = -1;
+        mMat10 = 1;
+        mMat11 = 0;
+        mOutputWidth = abs(oneY - origY);
+        mOutputHeight = abs(oneX - origX);
+    } else if (oneX > origX && oneY < origY) {
+        // 270-degree CCW rotation
+        mMat00 = 0;
+        mMat01 = 1;
+        mMat10 = -1;
+        mMat11 = 0;
+        mOutputWidth = abs(oneY - origY);
+        mOutputHeight = abs(oneX - origX);;
+    } else if (oneX < origX && oneY < origY) {
+        // 180-degree CCW rotation
+        mMat00 = -1;
+        mMat01 = 0;
+        mMat10 = 0;
+        mMat11 = -1;
+        mOutputWidth = abs(oneX - origX);
+        mOutputHeight = abs(oneY - origY);
+    }
+}
+
+Transform Transform::forCropFollowedByRotation(int cropLeft, int cropTop, int cropRight,
+        int cropBottom, int rot90) {
+    // The input crop-region excludes cropRight and cropBottom, so transform the
+    // crop rect such that it defines the entire valid region of pixels
+    // inclusively.
+    cropRight -= 1;
+    cropBottom -= 1;
+
+    int cropXLow = min(cropLeft, cropRight);
+    int cropYLow = min(cropTop, cropBottom);
+    int cropXHigh = max(cropLeft, cropRight);
+    int cropYHigh = max(cropTop, cropBottom);
+    rot90 %= 4;
+    if (rot90 == 0) {
+        return Transform(cropXLow, cropYLow, cropXHigh + 1, cropYHigh + 1);
+    } else if (rot90 == 1) {
+        return Transform(cropXHigh, cropYLow, cropXLow - 1, cropYHigh + 1);
+    } else if (rot90 == 2) {
+        return Transform(cropXHigh, cropYHigh, cropXLow - 1, cropYLow - 1);
+    } else if (rot90 == 3) {
+        return Transform(cropXLow, cropYHigh, cropXHigh + 1, cropYLow - 1);
+    }
+    // Impossible case.
+    return Transform(cropXLow, cropYLow, cropXHigh + 1, cropYHigh + 1);
+}
+
+bool Transform::operator==(const Transform& other) const {
+    return other.mOrigX == mOrigX &&  //
+           other.mOrigY == mOrigY &&  //
+           other.mOneX == mOneX &&    //
+           other.mOneY == mOneY;
+}
+
+/**
+ * Transforms the input coordinates.  Coordinates outside the cropped region
+ * are clamped to valid values.
+ */
+void Transform::map(int x, int y, int* outX, int* outY) const {
+    x = max(x, 0);
+    y = max(y, 0);
+    x = min(x, getOutputWidth() - 1);
+    y = min(y, getOutputHeight() - 1);
+    *outX = x * mMat00 + y * mMat01 + mOrigX;
+    *outY = x * mMat10 + y * mMat11 + mOrigY;
+}
+
+int compress(int img_width, int img_height, RowIterator<16>& y_row_generator,
+        RowIterator<8>& cb_row_generator, RowIterator<8>& cr_row_generator,
+        unsigned char* out_buf, size_t out_buf_capacity, std::function<void(size_t)> flush,
+        int quality) {
+    // libjpeg requires the use of setjmp/longjmp to recover from errors.  Since
+    // this doesn't play well with RAII, we must use pointers and manually call
+    // delete. See POSIX documentation for longjmp() for details on why the
+    // volatile keyword is necessary.
+    volatile jpeg_compress_struct cinfov;
+
+    jpeg_compress_struct& cinfo =
+            *const_cast<struct jpeg_compress_struct*>(&cinfov);
+
+    JSAMPROW* volatile yArr = nullptr;
+    JSAMPROW* volatile cbArr = nullptr;
+    JSAMPROW* volatile crArr = nullptr;
+
+    JSAMPARRAY imgArr[3];
+
+    // Error handling
+
+    struct my_error_mgr {
+        struct jpeg_error_mgr pub;
+        jmp_buf setjmp_buffer;
+    } err;
+
+    cinfo.err = jpeg_std_error(&err.pub);
+
+    // Default error_exit will call exit(), so override
+    // to return control via setjmp/longjmp.
+    err.pub.error_exit = [](j_common_ptr cinfo) {
+        my_error_mgr* myerr = reinterpret_cast<my_error_mgr*>(cinfo->err);
+
+        (*cinfo->err->output_message)(cinfo);
+
+        // Return control to the setjmp point (see call to setjmp()).
+        longjmp(myerr->setjmp_buffer, 1);
+    };
+
+    cinfo.err = (struct jpeg_error_mgr*)&err;
+
+    // Set the setjmp point to return to in case of error.
+    if (setjmp(err.setjmp_buffer)) {
+        // If libjpeg hits an error, control will jump to this point (see call to
+        // longjmp()).
+        jpeg_destroy_compress(&cinfo);
+
+        safeDeleteArray(yArr);
+        safeDeleteArray(cbArr);
+        safeDeleteArray(crArr);
+
+        return -1;
+    }
+
+    // Create jpeg compression context
+    jpeg_create_compress(&cinfo);
+
+    // Stores data needed by our c-style callbacks into libjpeg
+    struct ClientData {
+        unsigned char* out_buf;
+        size_t out_buf_capacity;
+        std::function<void(size_t)> flush;
+        int totalOutputBytes;
+    } clientData{out_buf, out_buf_capacity, flush, 0};
+
+    cinfo.client_data = &clientData;
+
+    // Initialize destination manager
+    jpeg_destination_mgr dest;
+
+    dest.init_destination = [](j_compress_ptr cinfo) {
+        ClientData& cdata = *reinterpret_cast<ClientData*>(cinfo->client_data);
+
+        cinfo->dest->next_output_byte = cdata.out_buf;
+        cinfo->dest->free_in_buffer = cdata.out_buf_capacity;
+    };
+
+    dest.empty_output_buffer = [](j_compress_ptr cinfo) -> boolean {
+        ClientData& cdata = *reinterpret_cast<ClientData*>(cinfo->client_data);
+
+        size_t numBytesInBuffer = cdata.out_buf_capacity;
+        cdata.flush(numBytesInBuffer);
+        cdata.totalOutputBytes += numBytesInBuffer;
+
+        // Reset the buffer
+        cinfo->dest->next_output_byte = cdata.out_buf;
+        cinfo->dest->free_in_buffer = cdata.out_buf_capacity;
+
+        return true;
+    };
+
+    dest.term_destination = [](j_compress_ptr cinfo __unused) {
+        // do nothing to terminate the output buffer
+    };
+
+    cinfo.dest = &dest;
+
+    // Set jpeg parameters
+    cinfo.image_width = img_width;
+    cinfo.image_height = img_height;
+    cinfo.input_components = 3;
+
+    // Set defaults based on the above values
+    jpeg_set_defaults(&cinfo);
+
+    jpeg_set_quality(&cinfo, quality, true);
+
+    cinfo.dct_method = JDCT_IFAST;
+
+    cinfo.raw_data_in = true;
+
+    jpeg_set_colorspace(&cinfo, JCS_YCbCr);
+
+    cinfo.comp_info[0].h_samp_factor = 2;
+    cinfo.comp_info[0].v_samp_factor = 2;
+    cinfo.comp_info[1].h_samp_factor = 1;
+    cinfo.comp_info[1].v_samp_factor = 1;
+    cinfo.comp_info[2].h_samp_factor = 1;
+    cinfo.comp_info[2].v_samp_factor = 1;
+
+    jpeg_start_compress(&cinfo, true);
+
+    yArr = new JSAMPROW[cinfo.comp_info[0].v_samp_factor * DCTSIZE];
+    cbArr = new JSAMPROW[cinfo.comp_info[1].v_samp_factor * DCTSIZE];
+    crArr = new JSAMPROW[cinfo.comp_info[2].v_samp_factor * DCTSIZE];
+
+    imgArr[0] = const_cast<JSAMPARRAY>(yArr);
+    imgArr[1] = const_cast<JSAMPARRAY>(cbArr);
+    imgArr[2] = const_cast<JSAMPARRAY>(crArr);
+
+    for (int y = 0; y < img_height; y += DCTSIZE * 2) {
+        std::array<unsigned char*, 16> yData = y_row_generator.loadAt(y);
+        std::array<unsigned char*, 8> cbData = cb_row_generator.loadAt(y / 2);
+        std::array<unsigned char*, 8> crData = cr_row_generator.loadAt(y / 2);
+
+        for (int row = 0; row < DCTSIZE * 2; row++) {
+            yArr[row] = yData[row];
+        }
+        for (int row = 0; row < DCTSIZE; row++) {
+            cbArr[row] = cbData[row];
+            crArr[row] = crData[row];
+        }
+
+        jpeg_write_raw_data(&cinfo, imgArr, DCTSIZE * 2);
+    }
+
+    jpeg_finish_compress(&cinfo);
+
+    int numBytesInBuffer = cinfo.dest->next_output_byte - out_buf;
+
+    flush(numBytesInBuffer);
+
+    clientData.totalOutputBytes += numBytesInBuffer;
+
+    safeDeleteArray(yArr);
+    safeDeleteArray(cbArr);
+    safeDeleteArray(crArr);
+
+    jpeg_destroy_compress(&cinfo);
+
+    return clientData.totalOutputBytes;
+}
+
+int compress(
+        /** Input image dimensions */
+        int width, int height,
+        /** Y Plane */
+        unsigned char* yBuf, int yPStride, int yRStride,
+        /** Cb Plane */
+        unsigned char* cbBuf, int cbPStride, int cbRStride,
+        /** Cr Plane */
+        unsigned char* crBuf, int crPStride, int crRStride,
+        /** Output */
+        unsigned char* outBuf, size_t outBufCapacity,
+        /** Jpeg compression parameters */
+        int quality,
+        /** Crop */
+        int cropLeft, int cropTop, int cropRight, int cropBottom,
+        /** Rotation (multiple of 90).  For example, rot90 = 1 implies a 90 degree
+         * rotation. */
+        int rot90) {
+    int finalWidth;
+    int finalHeight;
+    finalWidth = cropRight - cropLeft;
+    finalHeight = cropBottom - cropTop;
+
+    rot90 %= 4;
+    // for 90 and 270-degree rotations, flip the final width and height
+    if (rot90 == 1) {
+        finalWidth = cropBottom - cropTop;
+        finalHeight = cropRight - cropLeft;
+    } else if (rot90 == 3) {
+        finalWidth = cropBottom - cropTop;
+        finalHeight = cropRight - cropLeft;
+    }
+
+    const Plane yP = {width, height, yBuf, yPStride, yRStride};
+    const Plane cbP = {width / 2, height / 2, cbBuf, cbPStride, cbRStride};
+    const Plane crP = {width / 2, height / 2, crBuf, crPStride, crRStride};
+
+    auto flush = [](size_t numBytes __unused) {
+        // do nothing
+    };
+
+    // Round up to the nearest multiple of 64.
+    int y_row_length = (finalWidth + 16 + 63) & ~63;
+    int cb_row_length = (finalWidth / 2 + 16 + 63) & ~63;
+    int cr_row_length = (finalWidth / 2 + 16 + 63) & ~63;
+
+    Transform yTrans = Transform::forCropFollowedByRotation(
+            cropLeft, cropTop, cropRight, cropBottom, rot90);
+
+    Transform chromaTrans = Transform::forCropFollowedByRotation(
+            cropLeft / 2, cropTop / 2, cropRight / 2, cropBottom / 2, rot90);
+
+    RowIterator<16> yIter(yP, yTrans, y_row_length);
+    RowIterator<8> cbIter(cbP, chromaTrans, cb_row_length);
+    RowIterator<8> crIter(crP, chromaTrans, cr_row_length);
+
+    return compress(finalWidth, finalHeight, yIter, cbIter, crIter, outBuf, outBufCapacity, flush,
+            quality);
+}
+
+extern "C" {
+
+static jint CameraExtensionJpegProcessor_compressJpegFromYUV420p(
+        JNIEnv* env, jclass clazz __unused,
+        /** Input image dimensions */
+        jint width, jint height,
+        /** Y Plane */
+        jobject yBuf, jint yPStride, jint yRStride,
+        /** Cb Plane */
+        jobject cbBuf, jint cbPStride, jint cbRStride,
+        /** Cr Plane */
+        jobject crBuf, jint crPStride, jint crRStride,
+        /** Output */
+        jobject outBuf, jint outBufCapacity,
+        /** Jpeg compression parameters */
+        jint quality,
+        /** Crop */
+        jint cropLeft, jint cropTop, jint cropRight, jint cropBottom,
+        /** Rotation (multiple of 90).  For example, rot90 = 1 implies a 90 degree
+         * rotation. */
+        jint rot90) {
+    jbyte* y = (jbyte*)env->GetDirectBufferAddress(yBuf);
+    jbyte* cb = (jbyte*)env->GetDirectBufferAddress(cbBuf);
+    jbyte* cr = (jbyte*)env->GetDirectBufferAddress(crBuf);
+    jbyte* out = (jbyte*)env->GetDirectBufferAddress(outBuf);
+
+    size_t actualJpegSize = compress(width, height,
+            (unsigned char*)y, yPStride, yRStride,
+            (unsigned char*)cb, cbPStride, cbRStride,
+            (unsigned char*)cr, crPStride, crRStride,
+            (unsigned char*)out, (size_t)outBufCapacity,
+            quality, cropLeft, cropTop, cropRight, cropBottom, rot90);
+
+    size_t finalJpegSize = actualJpegSize + sizeof(CameraBlob);
+    if (finalJpegSize > outBufCapacity) {
+        ALOGE("%s: Final jpeg buffer %zu not large enough for the jpeg blob header with "\
+                "capacity %d", __FUNCTION__, finalJpegSize, outBufCapacity);
+        return actualJpegSize;
+    }
+
+    int8_t* header = static_cast<int8_t *> (out) +
+            (outBufCapacity - sizeof(CameraBlob));
+    CameraBlob *blob = reinterpret_cast<CameraBlob *> (header);
+    blob->blobId = CameraBlobId::JPEG;
+    blob->blobSize = actualJpegSize;
+
+    return actualJpegSize;
+}
+
+} // extern "C"
+
+static const JNINativeMethod gCameraExtensionJpegProcessorMethods[] = {
+    {"compressJpegFromYUV420pNative",
+    "(IILjava/nio/ByteBuffer;IILjava/nio/ByteBuffer;IILjava/nio/ByteBuffer;IILjava/nio/ByteBuffer;IIIIIII)I",
+    (void*)CameraExtensionJpegProcessor_compressJpegFromYUV420p}};
+
+// Get all the required offsets in java class and register native functions
+int register_android_hardware_camera2_impl_CameraExtensionJpegProcessor(JNIEnv* env) {
+    // Register native functions
+    return RegisterMethodsOrDie(env, CAMERA_PROCESSOR_CLASS_NAME,
+            gCameraExtensionJpegProcessorMethods, NELEM(gCameraExtensionJpegProcessorMethods));
+}
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 8d193bf..0e0f98e 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -861,6 +861,23 @@
     return jStatus;
 }
 
+static void android_media_AudioRecord_setLogSessionId(JNIEnv *env, jobject thiz,
+                                                      jstring jlogSessionId) {
+    sp<AudioRecord> record = getAudioRecord(env, thiz);
+    if (record == nullptr) {
+        jniThrowException(env, "java/lang/IllegalStateException",
+                          "Unable to retrieve AudioRecord pointer for setLogSessionId()");
+    }
+    if (jlogSessionId == nullptr) {
+        ALOGV("%s: logSessionId nullptr", __func__);
+        record->setLogSessionId(nullptr);
+        return;
+    }
+    ScopedUtfChars logSessionId(env, jlogSessionId);
+    ALOGV("%s: logSessionId '%s'", __func__, logSessionId.c_str());
+    record->setLogSessionId(logSessionId.c_str());
+}
+
 // ----------------------------------------------------------------------------
 static jint android_media_AudioRecord_get_port_id(JNIEnv *env,  jobject thiz) {
     sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
@@ -876,50 +893,48 @@
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 static const JNINativeMethod gMethods[] = {
-    // name,               signature,  funcPtr
-    {"native_start",         "(II)I",    (void *)android_media_AudioRecord_start},
-    {"native_stop",          "()V",    (void *)android_media_AudioRecord_stop},
-    {"native_setup",         "(Ljava/lang/Object;Ljava/lang/Object;[IIIII[ILjava/lang/String;J)I",
-                                      (void *)android_media_AudioRecord_setup},
-    {"native_finalize",      "()V",    (void *)android_media_AudioRecord_finalize},
-    {"native_release",       "()V",    (void *)android_media_AudioRecord_release},
-    {"native_read_in_byte_array",
-                             "([BIIZ)I",
-                                     (void *)android_media_AudioRecord_readInArray<jbyteArray>},
-    {"native_read_in_short_array",
-                             "([SIIZ)I",
-                                     (void *)android_media_AudioRecord_readInArray<jshortArray>},
-    {"native_read_in_float_array",
-                             "([FIIZ)I",
-                                     (void *)android_media_AudioRecord_readInArray<jfloatArray>},
-    {"native_read_in_direct_buffer","(Ljava/lang/Object;IZ)I",
-                                       (void *)android_media_AudioRecord_readInDirectBuffer},
-    {"native_get_buffer_size_in_frames",
-                             "()I", (void *)android_media_AudioRecord_get_buffer_size_in_frames},
-    {"native_set_marker_pos","(I)I",   (void *)android_media_AudioRecord_set_marker_pos},
-    {"native_get_marker_pos","()I",    (void *)android_media_AudioRecord_get_marker_pos},
-    {"native_set_pos_update_period",
-                             "(I)I",   (void *)android_media_AudioRecord_set_pos_update_period},
-    {"native_get_pos_update_period",
-                             "()I",    (void *)android_media_AudioRecord_get_pos_update_period},
-    {"native_get_min_buff_size",
-                             "(III)I",   (void *)android_media_AudioRecord_get_min_buff_size},
-    {"native_getMetrics",    "()Landroid/os/PersistableBundle;",
-                                         (void *)android_media_AudioRecord_native_getMetrics},
-    {"native_setInputDevice", "(I)Z", (void *)android_media_AudioRecord_setInputDevice},
-    {"native_getRoutedDeviceId", "()I", (void *)android_media_AudioRecord_getRoutedDeviceId},
-    {"native_enableDeviceCallback", "()V", (void *)android_media_AudioRecord_enableDeviceCallback},
-    {"native_disableDeviceCallback", "()V",
-                                        (void *)android_media_AudioRecord_disableDeviceCallback},
-    {"native_get_timestamp", "(Landroid/media/AudioTimestamp;I)I",
-                                       (void *)android_media_AudioRecord_get_timestamp},
-    {"native_get_active_microphones", "(Ljava/util/ArrayList;)I",
-                                        (void *)android_media_AudioRecord_get_active_microphones},
-    {"native_getPortId", "()I", (void *)android_media_AudioRecord_get_port_id},
-    {"native_set_preferred_microphone_direction", "(I)I",
-                        (void *)android_media_AudioRecord_set_preferred_microphone_direction},
-    {"native_set_preferred_microphone_field_dimension", "(F)I",
-                        (void *)android_media_AudioRecord_set_preferred_microphone_field_dimension},
+        {"native_start", "(II)I", (void *)android_media_AudioRecord_start},
+        {"native_stop", "()V", (void *)android_media_AudioRecord_stop},
+        {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;[IIIII[ILjava/lang/String;J)I",
+         (void *)android_media_AudioRecord_setup},
+        {"native_finalize", "()V", (void *)android_media_AudioRecord_finalize},
+        {"native_release", "()V", (void *)android_media_AudioRecord_release},
+        {"native_read_in_byte_array", "([BIIZ)I",
+         (void *)android_media_AudioRecord_readInArray<jbyteArray>},
+        {"native_read_in_short_array", "([SIIZ)I",
+         (void *)android_media_AudioRecord_readInArray<jshortArray>},
+        {"native_read_in_float_array", "([FIIZ)I",
+         (void *)android_media_AudioRecord_readInArray<jfloatArray>},
+        {"native_read_in_direct_buffer", "(Ljava/lang/Object;IZ)I",
+         (void *)android_media_AudioRecord_readInDirectBuffer},
+        {"native_get_buffer_size_in_frames", "()I",
+         (void *)android_media_AudioRecord_get_buffer_size_in_frames},
+        {"native_set_marker_pos", "(I)I", (void *)android_media_AudioRecord_set_marker_pos},
+        {"native_get_marker_pos", "()I", (void *)android_media_AudioRecord_get_marker_pos},
+        {"native_set_pos_update_period", "(I)I",
+         (void *)android_media_AudioRecord_set_pos_update_period},
+        {"native_get_pos_update_period", "()I",
+         (void *)android_media_AudioRecord_get_pos_update_period},
+        {"native_get_min_buff_size", "(III)I", (void *)android_media_AudioRecord_get_min_buff_size},
+        {"native_getMetrics", "()Landroid/os/PersistableBundle;",
+         (void *)android_media_AudioRecord_native_getMetrics},
+        {"native_setInputDevice", "(I)Z", (void *)android_media_AudioRecord_setInputDevice},
+        {"native_getRoutedDeviceId", "()I", (void *)android_media_AudioRecord_getRoutedDeviceId},
+        {"native_enableDeviceCallback", "()V",
+         (void *)android_media_AudioRecord_enableDeviceCallback},
+        {"native_disableDeviceCallback", "()V",
+         (void *)android_media_AudioRecord_disableDeviceCallback},
+        {"native_get_timestamp", "(Landroid/media/AudioTimestamp;I)I",
+         (void *)android_media_AudioRecord_get_timestamp},
+        {"native_get_active_microphones", "(Ljava/util/ArrayList;)I",
+         (void *)android_media_AudioRecord_get_active_microphones},
+        {"native_getPortId", "()I", (void *)android_media_AudioRecord_get_port_id},
+        {"native_set_preferred_microphone_direction", "(I)I",
+         (void *)android_media_AudioRecord_set_preferred_microphone_direction},
+        {"native_set_preferred_microphone_field_dimension", "(F)I",
+         (void *)android_media_AudioRecord_set_preferred_microphone_field_dimension},
+        {"native_setLogSessionId", "(Ljava/lang/String;)V",
+         (void *)android_media_AudioRecord_setLogSessionId},
 };
 
 // field names found in android/media/AudioRecord.java
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 065c79b..cae6db5 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -1419,6 +1419,33 @@
     return nativeToJavaStatus(status);
 }
 
+static void android_media_AudioTrack_setLogSessionId(JNIEnv *env, jobject thiz,
+                                                     jstring jlogSessionId) {
+    sp<AudioTrack> track = getAudioTrack(env, thiz);
+    if (track == nullptr) {
+        jniThrowException(env, "java/lang/IllegalStateException",
+                          "Unable to retrieve AudioTrack pointer for setLogSessionId()");
+    }
+    if (jlogSessionId == nullptr) {
+        ALOGV("%s: logSessionId nullptr", __func__);
+        track->setLogSessionId(nullptr);
+        return;
+    }
+    ScopedUtfChars logSessionId(env, jlogSessionId);
+    ALOGV("%s: logSessionId '%s'", __func__, logSessionId.c_str());
+    track->setLogSessionId(logSessionId.c_str());
+}
+
+static void android_media_AudioTrack_setPlayerIId(JNIEnv *env, jobject thiz, jint playerIId) {
+    sp<AudioTrack> track = getAudioTrack(env, thiz);
+    if (track == nullptr) {
+        jniThrowException(env, "java/lang/IllegalStateException",
+                          "Unable to retrieve AudioTrack pointer for setPlayerIId()");
+    }
+    ALOGV("%s: playerIId %d", __func__, playerIId);
+    track->setPlayerIId(playerIId);
+}
+
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 static const JNINativeMethod gMethods[] = {
@@ -1496,6 +1523,9 @@
          (void *)android_media_AudioTrack_getAudioDescriptionMixLeveldB},
         {"native_set_dual_mono_mode", "(I)I", (void *)android_media_AudioTrack_setDualMonoMode},
         {"native_get_dual_mono_mode", "([I)I", (void *)android_media_AudioTrack_getDualMonoMode},
+        {"native_setLogSessionId", "(Ljava/lang/String;)V",
+         (void *)android_media_AudioTrack_setLogSessionId},
+        {"native_setPlayerIId", "(I)V", (void *)android_media_AudioTrack_setPlayerIId},
 };
 
 // field names found in android/media/AudioTrack.java
diff --git a/core/jni/android_os_Trace.cpp b/core/jni/android_os_Trace.cpp
index 0f7611a..f67007c 100644
--- a/core/jni/android_os_Trace.cpp
+++ b/core/jni/android_os_Trace.cpp
@@ -83,7 +83,7 @@
 }
 
 static void android_os_Trace_nativeSetAppTracingAllowed(JNIEnv*, jclass, jboolean allowed) {
-    atrace_set_debuggable(allowed);
+    atrace_update_tags();
 }
 
 static void android_os_Trace_nativeSetTracingEnabled(JNIEnv*, jclass, jboolean enabled) {
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 7a3366a..cbf4481 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -27,6 +27,7 @@
 #include <android-base/chrono_utils.h>
 #include <android/graphics/region.h>
 #include <android/gui/BnScreenCaptureListener.h>
+#include <android/hardware/display/IDeviceProductInfoConstants.h>
 #include <android/os/IInputConstants.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/android_hardware_HardwareBuffer.h>
@@ -44,14 +45,15 @@
 #include <ui/BlurRegion.h>
 #include <ui/ConfigStoreTypes.h>
 #include <ui/DeviceProductInfo.h>
-#include <ui/DisplayInfo.h>
 #include <ui/DisplayMode.h>
 #include <ui/DisplayedFrameStats.h>
+#include <ui/DynamicDisplayInfo.h>
 #include <ui/FrameStats.h>
 #include <ui/GraphicTypes.h>
 #include <ui/HdrCapabilities.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
+#include <ui/StaticDisplayInfo.h>
 #include <utils/LightRefBase.h>
 #include <utils/Log.h>
 
@@ -86,11 +88,24 @@
     jfieldID density;
     jfieldID secure;
     jfieldID deviceProductInfo;
-} gDisplayInfoClassInfo;
+} gStaticDisplayInfoClassInfo;
 
 static struct {
     jclass clazz;
     jmethodID ctor;
+    jfieldID supportedDisplayModes;
+    jfieldID activeDisplayModeId;
+    jfieldID supportedColorModes;
+    jfieldID activeColorMode;
+    jfieldID hdrCapabilities;
+    jfieldID autoLowLatencyModeSupported;
+    jfieldID gameContentTypeSupported;
+} gDynamicDisplayInfoClassInfo;
+
+static struct {
+    jclass clazz;
+    jmethodID ctor;
+    jfieldID id;
     jfieldID width;
     jfieldID height;
     jfieldID xDpi;
@@ -580,6 +595,15 @@
     transaction->setBlurRegions(ctrl, blurRegionVector);
 }
 
+static void nativeSetStretchEffect(JNIEnv* env, jclass clazz, jlong transactionObj,
+                                   jlong nativeObject, jfloat left, jfloat top, jfloat right,
+                                   jfloat bottom, jfloat vecX, jfloat vecY,
+                                   jfloat maxStretchAmount) {
+    auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
+    transaction->setStretchEffect(ctrl, left, top, right, bottom, vecX, vecY, maxStretchAmount);
+}
+
 static void nativeSetSize(JNIEnv* env, jclass clazz, jlong transactionObj,
         jlong nativeObject, jint w, jint h) {
     auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
@@ -999,63 +1023,125 @@
     } else {
         LOG_FATAL("Unknown alternative for variant DeviceProductInfo::ManufactureOrModelDate");
     }
-    auto relativeAddress = env->NewIntArray(info->relativeAddress.size());
-    auto relativeAddressData = env->GetIntArrayElements(relativeAddress, nullptr);
-    for (int i = 0; i < info->relativeAddress.size(); i++) {
-        relativeAddressData[i] = info->relativeAddress[i];
+    jint connectionToSinkType;
+    // Relative address maps to HDMI physical address. All addresses are 4 digits long allowing
+    // for a 5–device-deep hierarchy. For more information, refer:
+    // Section 8.7 - Physical Address of HDMI Specification Version 1.3a
+    using android::hardware::display::IDeviceProductInfoConstants;
+    if (info->relativeAddress.size() != 4) {
+        connectionToSinkType = IDeviceProductInfoConstants::CONNECTION_TO_SINK_UNKNOWN;
+    } else if (info->relativeAddress[0] == 0) {
+        connectionToSinkType = IDeviceProductInfoConstants::CONNECTION_TO_SINK_BUILT_IN;
+    } else if (info->relativeAddress[1] == 0) {
+        connectionToSinkType = IDeviceProductInfoConstants::CONNECTION_TO_SINK_DIRECT;
+    } else {
+        connectionToSinkType = IDeviceProductInfoConstants::CONNECTION_TO_SINK_TRANSITIVE;
     }
-    env->ReleaseIntArrayElements(relativeAddress, relativeAddressData, 0);
 
     return env->NewObject(gDeviceProductInfoClassInfo.clazz, gDeviceProductInfoClassInfo.ctor, name,
                           manufacturerPnpId, productId, modelYear, manufactureDate,
-                          relativeAddress);
+                          connectionToSinkType);
 }
 
-static jobject nativeGetDisplayInfo(JNIEnv* env, jclass clazz, jobject tokenObj) {
-    DisplayInfo info;
+static jobject nativeGetStaticDisplayInfo(JNIEnv* env, jclass clazz, jobject tokenObj) {
+    ui::StaticDisplayInfo info;
     if (const auto token = ibinderForJavaObject(env, tokenObj);
-        !token || SurfaceComposerClient::getDisplayInfo(token, &info) != NO_ERROR) {
+        !token || SurfaceComposerClient::getStaticDisplayInfo(token, &info) != NO_ERROR) {
         return nullptr;
     }
 
-    jobject object = env->NewObject(gDisplayInfoClassInfo.clazz, gDisplayInfoClassInfo.ctor);
-    env->SetBooleanField(object, gDisplayInfoClassInfo.isInternal,
-                         info.connectionType == DisplayConnectionType::Internal);
-    env->SetFloatField(object, gDisplayInfoClassInfo.density, info.density);
-    env->SetBooleanField(object, gDisplayInfoClassInfo.secure, info.secure);
-    env->SetObjectField(object, gDisplayInfoClassInfo.deviceProductInfo,
+    jobject object =
+            env->NewObject(gStaticDisplayInfoClassInfo.clazz, gStaticDisplayInfoClassInfo.ctor);
+    env->SetBooleanField(object, gStaticDisplayInfoClassInfo.isInternal,
+                         info.connectionType == ui::DisplayConnectionType::Internal);
+    env->SetFloatField(object, gStaticDisplayInfoClassInfo.density, info.density);
+    env->SetBooleanField(object, gStaticDisplayInfoClassInfo.secure, info.secure);
+    env->SetObjectField(object, gStaticDisplayInfoClassInfo.deviceProductInfo,
                         convertDeviceProductInfoToJavaObject(env, info.deviceProductInfo));
     return object;
 }
 
-static jobjectArray nativeGetDisplayModes(JNIEnv* env, jclass clazz, jobject tokenObj) {
-    Vector<ui::DisplayMode> modes;
-    if (const auto token = ibinderForJavaObject(env, tokenObj); !token ||
-        SurfaceComposerClient::getDisplayModes(token, &modes) != NO_ERROR || modes.isEmpty()) {
+static jobject convertDisplayModeToJavaObject(JNIEnv* env, const ui::DisplayMode& config) {
+    jobject object = env->NewObject(gDisplayModeClassInfo.clazz, gDisplayModeClassInfo.ctor);
+    env->SetIntField(object, gDisplayModeClassInfo.id, config.id);
+    env->SetIntField(object, gDisplayModeClassInfo.width, config.resolution.getWidth());
+    env->SetIntField(object, gDisplayModeClassInfo.height, config.resolution.getHeight());
+    env->SetFloatField(object, gDisplayModeClassInfo.xDpi, config.xDpi);
+    env->SetFloatField(object, gDisplayModeClassInfo.yDpi, config.yDpi);
+
+    env->SetFloatField(object, gDisplayModeClassInfo.refreshRate, config.refreshRate);
+    env->SetLongField(object, gDisplayModeClassInfo.appVsyncOffsetNanos, config.appVsyncOffset);
+    env->SetLongField(object, gDisplayModeClassInfo.presentationDeadlineNanos,
+                      config.presentationDeadline);
+    env->SetIntField(object, gDisplayModeClassInfo.group, config.group);
+    return object;
+}
+
+jobject convertDeviceProductInfoToJavaObject(JNIEnv* env, const HdrCapabilities& capabilities) {
+    const auto& types = capabilities.getSupportedHdrTypes();
+    std::vector<int32_t> intTypes;
+    for (auto type : types) {
+        intTypes.push_back(static_cast<int32_t>(type));
+    }
+    auto typesArray = env->NewIntArray(types.size());
+    env->SetIntArrayRegion(typesArray, 0, intTypes.size(), intTypes.data());
+
+    return env->NewObject(gHdrCapabilitiesClassInfo.clazz, gHdrCapabilitiesClassInfo.ctor,
+                          typesArray, capabilities.getDesiredMaxLuminance(),
+                          capabilities.getDesiredMaxAverageLuminance(),
+                          capabilities.getDesiredMinLuminance());
+}
+
+static jobject nativeGetDynamicDisplayInfo(JNIEnv* env, jclass clazz, jobject tokenObj) {
+    ui::DynamicDisplayInfo info;
+    if (const auto token = ibinderForJavaObject(env, tokenObj);
+        !token || SurfaceComposerClient::getDynamicDisplayInfo(token, &info) != NO_ERROR) {
         return nullptr;
     }
 
-    jobjectArray modesArray =
-            env->NewObjectArray(modes.size(), gDisplayModeClassInfo.clazz, nullptr);
-
-    for (size_t c = 0; c < modes.size(); ++c) {
-        const ui::DisplayMode& mode = modes[c];
-        jobject object = env->NewObject(gDisplayModeClassInfo.clazz, gDisplayModeClassInfo.ctor);
-        env->SetIntField(object, gDisplayModeClassInfo.width, mode.resolution.getWidth());
-        env->SetIntField(object, gDisplayModeClassInfo.height, mode.resolution.getHeight());
-        env->SetFloatField(object, gDisplayModeClassInfo.xDpi, mode.xDpi);
-        env->SetFloatField(object, gDisplayModeClassInfo.yDpi, mode.yDpi);
-
-        env->SetFloatField(object, gDisplayModeClassInfo.refreshRate, mode.refreshRate);
-        env->SetLongField(object, gDisplayModeClassInfo.appVsyncOffsetNanos, mode.appVsyncOffset);
-        env->SetLongField(object, gDisplayModeClassInfo.presentationDeadlineNanos,
-                          mode.presentationDeadline);
-        env->SetIntField(object, gDisplayModeClassInfo.group, mode.group);
-        env->SetObjectArrayElement(modesArray, static_cast<jsize>(c), object);
-        env->DeleteLocalRef(object);
+    jobject object =
+            env->NewObject(gDynamicDisplayInfoClassInfo.clazz, gDynamicDisplayInfoClassInfo.ctor);
+    if (object == NULL) {
+        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+        return NULL;
     }
 
-    return modesArray;
+    const auto numModes = info.supportedDisplayModes.size();
+    jobjectArray modesArray = env->NewObjectArray(numModes, gDisplayModeClassInfo.clazz, nullptr);
+    for (size_t i = 0; i < numModes; i++) {
+        const ui::DisplayMode& mode = info.supportedDisplayModes[i];
+        jobject displayModeObj = convertDisplayModeToJavaObject(env, mode);
+        env->SetObjectArrayElement(modesArray, static_cast<jsize>(i), displayModeObj);
+        env->DeleteLocalRef(displayModeObj);
+    }
+    env->SetObjectField(object, gDynamicDisplayInfoClassInfo.supportedDisplayModes, modesArray);
+    env->SetIntField(object, gDynamicDisplayInfoClassInfo.activeDisplayModeId,
+                     info.activeDisplayModeId);
+
+    jintArray colorModesArray = env->NewIntArray(info.supportedColorModes.size());
+    if (colorModesArray == NULL) {
+        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+        return NULL;
+    }
+    jint* colorModesArrayValues = env->GetIntArrayElements(colorModesArray, 0);
+    for (size_t i = 0; i < info.supportedColorModes.size(); i++) {
+        colorModesArrayValues[i] = static_cast<jint>(info.supportedColorModes[i]);
+    }
+    env->ReleaseIntArrayElements(colorModesArray, colorModesArrayValues, 0);
+    env->SetObjectField(object, gDynamicDisplayInfoClassInfo.supportedColorModes, colorModesArray);
+
+    env->SetIntField(object, gDynamicDisplayInfoClassInfo.activeColorMode,
+                     static_cast<jint>(info.activeColorMode));
+
+    env->SetObjectField(object, gDynamicDisplayInfoClassInfo.hdrCapabilities,
+                        convertDeviceProductInfoToJavaObject(env, info.hdrCapabilities));
+
+    env->SetBooleanField(object, gDynamicDisplayInfoClassInfo.autoLowLatencyModeSupported,
+                         info.autoLowLatencyModeSupported);
+
+    env->SetBooleanField(object, gDynamicDisplayInfoClassInfo.gameContentTypeSupported,
+                         info.gameContentTypeSupported);
+    return object;
 }
 
 static jboolean nativeSetDesiredDisplayModeSpecs(JNIEnv* env, jclass clazz, jobject tokenObj,
@@ -1063,9 +1149,8 @@
     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
     if (token == nullptr) return JNI_FALSE;
 
-    size_t defaultMode =
-            static_cast<size_t>(env->GetIntField(DesiredDisplayModeSpecs,
-                                                 gDesiredDisplayModeSpecsClassInfo.defaultMode));
+    ui::DisplayModeId defaultMode = env->GetIntField(DesiredDisplayModeSpecs,
+                                                     gDesiredDisplayModeSpecsClassInfo.defaultMode);
     jboolean allowGroupSwitching =
             env->GetBooleanField(DesiredDisplayModeSpecs,
                                  gDesiredDisplayModeSpecsClassInfo.allowGroupSwitching);
@@ -1095,7 +1180,7 @@
     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
     if (token == nullptr) return nullptr;
 
-    size_t defaultMode;
+    ui::DisplayModeId defaultMode;
     bool allowGroupSwitching;
     float primaryRefreshRateMin;
     float primaryRefreshRateMax;
@@ -1115,34 +1200,6 @@
                           appRequestRefreshRateMax);
 }
 
-static jint nativeGetActiveDisplayMode(JNIEnv* env, jclass clazz, jobject tokenObj) {
-    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
-    if (token == NULL) return -1;
-    return static_cast<jint>(SurfaceComposerClient::getActiveDisplayModeId(token));
-}
-
-static jintArray nativeGetDisplayColorModes(JNIEnv* env, jclass, jobject tokenObj) {
-    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
-    if (token == NULL) return NULL;
-    Vector<ui::ColorMode> colorModes;
-    if (SurfaceComposerClient::getDisplayColorModes(token, &colorModes) != NO_ERROR ||
-            colorModes.isEmpty()) {
-        return NULL;
-    }
-
-    jintArray colorModesArray = env->NewIntArray(colorModes.size());
-    if (colorModesArray == NULL) {
-        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
-        return NULL;
-    }
-    jint* colorModesArrayValues = env->GetIntArrayElements(colorModesArray, 0);
-    for (size_t i = 0; i < colorModes.size(); i++) {
-        colorModesArrayValues[i] = static_cast<jint>(colorModes[i]);
-    }
-    env->ReleaseIntArrayElements(colorModesArray, colorModesArrayValues, 0);
-    return colorModesArray;
-}
-
 static jobject nativeGetDisplayNativePrimaries(JNIEnv* env, jclass, jobject tokenObj) {
     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
     if (token == NULL) return NULL;
@@ -1203,12 +1260,6 @@
     return jprimaries;
 }
 
-static jint nativeGetActiveColorMode(JNIEnv* env, jclass, jobject tokenObj) {
-    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
-    if (token == NULL) return -1;
-    return static_cast<jint>(SurfaceComposerClient::getActiveColorMode(token));
-}
-
 static jintArray nativeGetCompositionDataspaces(JNIEnv* env, jclass) {
     ui::Dataspace defaultDataspace, wcgDataspace;
     ui::PixelFormat defaultPixelFormat, wcgPixelFormat;
@@ -1414,40 +1465,6 @@
     transaction->reparent(ctrl, newParent);
 }
 
-static jobject nativeGetHdrCapabilities(JNIEnv* env, jclass clazz, jobject tokenObject) {
-    sp<IBinder> token(ibinderForJavaObject(env, tokenObject));
-    if (token == NULL) return NULL;
-
-    HdrCapabilities capabilities;
-    SurfaceComposerClient::getHdrCapabilities(token, &capabilities);
-
-    const auto& types = capabilities.getSupportedHdrTypes();
-    std::vector<int32_t> intTypes;
-    for (auto type : types) {
-        intTypes.push_back(static_cast<int32_t>(type));
-    }
-    auto typesArray = env->NewIntArray(types.size());
-    env->SetIntArrayRegion(typesArray, 0, intTypes.size(), intTypes.data());
-
-    return env->NewObject(gHdrCapabilitiesClassInfo.clazz, gHdrCapabilitiesClassInfo.ctor,
-            typesArray, capabilities.getDesiredMaxLuminance(),
-            capabilities.getDesiredMaxAverageLuminance(), capabilities.getDesiredMinLuminance());
-}
-
-static jboolean nativeGetAutoLowLatencyModeSupport(JNIEnv* env, jclass clazz, jobject tokenObject) {
-    sp<IBinder> token(ibinderForJavaObject(env, tokenObject));
-    if (token == NULL) return NULL;
-
-    return SurfaceComposerClient::getAutoLowLatencyModeSupport(token);
-}
-
-static jboolean nativeGetGameContentTypeSupport(JNIEnv* env, jclass clazz, jobject tokenObject) {
-    sp<IBinder> token(ibinderForJavaObject(env, tokenObject));
-    if (token == NULL) return NULL;
-
-    return SurfaceComposerClient::getGameContentTypeSupport(token);
-}
-
 static void nativeSetAutoLowLatencyMode(JNIEnv* env, jclass clazz, jobject tokenObject, jboolean on) {
     sp<IBinder> token(ibinderForJavaObject(env, tokenObject));
     if (token == NULL) return;
@@ -1754,6 +1771,8 @@
             (void*)nativeSetLayerStack },
     {"nativeSetBlurRegions", "(JJ[[FI)V",
             (void*)nativeSetBlurRegions },
+    {"nativeSetStretchEffect", "(JJFFFFFFF)V",
+            (void*) nativeSetStretchEffect },
     {"nativeSetShadowRadius", "(JJF)V",
             (void*)nativeSetShadowRadius },
     {"nativeSetFrameRate", "(JJFIZ)V",
@@ -1778,38 +1797,29 @@
             (void*)nativeSetDisplayProjection },
     {"nativeSetDisplaySize", "(JLandroid/os/IBinder;II)V",
             (void*)nativeSetDisplaySize },
-    {"nativeGetDisplayInfo", "(Landroid/os/IBinder;)Landroid/view/SurfaceControl$DisplayInfo;",
-            (void*)nativeGetDisplayInfo },
-    {"nativeGetDisplayModes", "(Landroid/os/IBinder;)[Landroid/view/SurfaceControl$DisplayMode;",
-            (void*)nativeGetDisplayModes },
-    {"nativeGetActiveDisplayMode", "(Landroid/os/IBinder;)I",
-            (void*)nativeGetActiveDisplayMode },
+    {"nativeGetStaticDisplayInfo",
+            "(Landroid/os/IBinder;)Landroid/view/SurfaceControl$StaticDisplayInfo;",
+            (void*)nativeGetStaticDisplayInfo },
+    {"nativeGetDynamicDisplayInfo",
+            "(Landroid/os/IBinder;)Landroid/view/SurfaceControl$DynamicDisplayInfo;",
+            (void*)nativeGetDynamicDisplayInfo },
     {"nativeSetDesiredDisplayModeSpecs",
             "(Landroid/os/IBinder;Landroid/view/SurfaceControl$DesiredDisplayModeSpecs;)Z",
             (void*)nativeSetDesiredDisplayModeSpecs },
     {"nativeGetDesiredDisplayModeSpecs",
             "(Landroid/os/IBinder;)Landroid/view/SurfaceControl$DesiredDisplayModeSpecs;",
             (void*)nativeGetDesiredDisplayModeSpecs },
-    {"nativeGetDisplayColorModes", "(Landroid/os/IBinder;)[I",
-            (void*)nativeGetDisplayColorModes},
-    {"nativeGetDisplayNativePrimaries", "(Landroid/os/IBinder;)Landroid/view/SurfaceControl$DisplayPrimaries;",
+    {"nativeGetDisplayNativePrimaries",
+            "(Landroid/os/IBinder;)Landroid/view/SurfaceControl$DisplayPrimaries;",
             (void*)nativeGetDisplayNativePrimaries },
-    {"nativeGetActiveColorMode", "(Landroid/os/IBinder;)I",
-            (void*)nativeGetActiveColorMode},
     {"nativeSetActiveColorMode", "(Landroid/os/IBinder;I)Z",
             (void*)nativeSetActiveColorMode},
-    {"nativeGetAutoLowLatencyModeSupport", "(Landroid/os/IBinder;)Z",
-            (void*)nativeGetAutoLowLatencyModeSupport },
     {"nativeSetAutoLowLatencyMode", "(Landroid/os/IBinder;Z)V",
             (void*)nativeSetAutoLowLatencyMode },
-    {"nativeGetGameContentTypeSupport", "(Landroid/os/IBinder;)Z",
-            (void*)nativeGetGameContentTypeSupport },
     {"nativeSetGameContentType", "(Landroid/os/IBinder;Z)V",
             (void*)nativeSetGameContentType },
     {"nativeGetCompositionDataspaces", "()[I",
             (void*)nativeGetCompositionDataspaces},
-    {"nativeGetHdrCapabilities", "(Landroid/os/IBinder;)Landroid/view/Display$HdrCapabilities;",
-            (void*)nativeGetHdrCapabilities },
     {"nativeClearContentFrameStats", "(J)Z",
             (void*)nativeClearContentFrameStats },
     {"nativeGetContentFrameStats", "(JLandroid/view/WindowContentFrameStats;)Z",
@@ -1888,19 +1898,40 @@
     gIntegerClassInfo.clazz = MakeGlobalRefOrDie(env, integerClass);
     gIntegerClassInfo.ctor = GetMethodIDOrDie(env, gIntegerClassInfo.clazz, "<init>", "(I)V");
 
-    jclass infoClazz = FindClassOrDie(env, "android/view/SurfaceControl$DisplayInfo");
-    gDisplayInfoClassInfo.clazz = MakeGlobalRefOrDie(env, infoClazz);
-    gDisplayInfoClassInfo.ctor = GetMethodIDOrDie(env, infoClazz, "<init>", "()V");
-    gDisplayInfoClassInfo.isInternal = GetFieldIDOrDie(env, infoClazz, "isInternal", "Z");
-    gDisplayInfoClassInfo.density = GetFieldIDOrDie(env, infoClazz, "density", "F");
-    gDisplayInfoClassInfo.secure = GetFieldIDOrDie(env, infoClazz, "secure", "Z");
-    gDisplayInfoClassInfo.deviceProductInfo =
+    jclass infoClazz = FindClassOrDie(env, "android/view/SurfaceControl$StaticDisplayInfo");
+    gStaticDisplayInfoClassInfo.clazz = MakeGlobalRefOrDie(env, infoClazz);
+    gStaticDisplayInfoClassInfo.ctor = GetMethodIDOrDie(env, infoClazz, "<init>", "()V");
+    gStaticDisplayInfoClassInfo.isInternal = GetFieldIDOrDie(env, infoClazz, "isInternal", "Z");
+    gStaticDisplayInfoClassInfo.density = GetFieldIDOrDie(env, infoClazz, "density", "F");
+    gStaticDisplayInfoClassInfo.secure = GetFieldIDOrDie(env, infoClazz, "secure", "Z");
+    gStaticDisplayInfoClassInfo.deviceProductInfo =
             GetFieldIDOrDie(env, infoClazz, "deviceProductInfo",
                             "Landroid/hardware/display/DeviceProductInfo;");
 
+    jclass dynamicInfoClazz = FindClassOrDie(env, "android/view/SurfaceControl$DynamicDisplayInfo");
+    gDynamicDisplayInfoClassInfo.clazz = MakeGlobalRefOrDie(env, dynamicInfoClazz);
+    gDynamicDisplayInfoClassInfo.ctor = GetMethodIDOrDie(env, dynamicInfoClazz, "<init>", "()V");
+    gDynamicDisplayInfoClassInfo.supportedDisplayModes =
+            GetFieldIDOrDie(env, dynamicInfoClazz, "supportedDisplayModes",
+                            "[Landroid/view/SurfaceControl$DisplayMode;");
+    gDynamicDisplayInfoClassInfo.activeDisplayModeId =
+            GetFieldIDOrDie(env, dynamicInfoClazz, "activeDisplayModeId", "I");
+    gDynamicDisplayInfoClassInfo.supportedColorModes =
+            GetFieldIDOrDie(env, dynamicInfoClazz, "supportedColorModes", "[I");
+    gDynamicDisplayInfoClassInfo.activeColorMode =
+            GetFieldIDOrDie(env, dynamicInfoClazz, "activeColorMode", "I");
+    gDynamicDisplayInfoClassInfo.hdrCapabilities =
+            GetFieldIDOrDie(env, dynamicInfoClazz, "hdrCapabilities",
+                            "Landroid/view/Display$HdrCapabilities;");
+    gDynamicDisplayInfoClassInfo.autoLowLatencyModeSupported =
+            GetFieldIDOrDie(env, dynamicInfoClazz, "autoLowLatencyModeSupported", "Z");
+    gDynamicDisplayInfoClassInfo.gameContentTypeSupported =
+            GetFieldIDOrDie(env, dynamicInfoClazz, "gameContentTypeSupported", "Z");
+
     jclass modeClazz = FindClassOrDie(env, "android/view/SurfaceControl$DisplayMode");
     gDisplayModeClassInfo.clazz = MakeGlobalRefOrDie(env, modeClazz);
     gDisplayModeClassInfo.ctor = GetMethodIDOrDie(env, modeClazz, "<init>", "()V");
+    gDisplayModeClassInfo.id = GetFieldIDOrDie(env, modeClazz, "id", "I");
     gDisplayModeClassInfo.width = GetFieldIDOrDie(env, modeClazz, "width", "I");
     gDisplayModeClassInfo.height = GetFieldIDOrDie(env, modeClazz, "height", "I");
     gDisplayModeClassInfo.xDpi = GetFieldIDOrDie(env, modeClazz, "xDpi", "F");
@@ -1948,7 +1979,7 @@
                              "Ljava/lang/String;"
                              "Ljava/lang/Integer;"
                              "Landroid/hardware/display/DeviceProductInfo$ManufactureDate;"
-                             "[I)V");
+                             "I)V");
 
     jclass deviceProductInfoManufactureDateClazz =
             FindClassOrDie(env, "android/hardware/display/DeviceProductInfo$ManufactureDate");
diff --git a/core/jni/android_view_SurfaceControlFpsListener.cpp b/core/jni/android_view_SurfaceControlFpsListener.cpp
new file mode 100644
index 0000000..6fa12e5
--- /dev/null
+++ b/core/jni/android_view_SurfaceControlFpsListener.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SurfaceControlFpsListener"
+
+#include <android/gui/BnFpsListener.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/Log.h>
+#include <gui/ISurfaceComposer.h>
+#include <gui/SurfaceComposerClient.h>
+#include <nativehelper/JNIHelp.h>
+#include <utils/Log.h>
+#include <utils/RefBase.h>
+
+#include "android_util_Binder.h"
+#include "core_jni_helpers.h"
+
+namespace android {
+
+namespace {
+
+struct {
+    jclass mClass;
+    jmethodID mDispatchOnFpsReported;
+} gListenerClassInfo;
+
+struct SurfaceControlFpsListener : public gui::BnFpsListener {
+    SurfaceControlFpsListener(JNIEnv* env, jobject listener)
+          : mListener(env->NewWeakGlobalRef(listener)) {}
+
+    binder::Status onFpsReported(float fps) override {
+        JNIEnv* env = AndroidRuntime::getJNIEnv();
+        LOG_ALWAYS_FATAL_IF(env == nullptr, "Unable to retrieve JNIEnv in onFpsReported.");
+
+        jobject listener = env->NewGlobalRef(mListener);
+        if (listener == NULL) {
+            // Weak reference went out of scope
+            return binder::Status::ok();
+        }
+        env->CallStaticVoidMethod(gListenerClassInfo.mClass,
+                                  gListenerClassInfo.mDispatchOnFpsReported, listener,
+                                  static_cast<jfloat>(fps));
+        env->DeleteGlobalRef(listener);
+
+        if (env->ExceptionCheck()) {
+            ALOGE("SurfaceControlFpsListener.onFpsReported() failed.");
+            LOGE_EX(env);
+            env->ExceptionClear();
+        }
+        return binder::Status::ok();
+    }
+
+protected:
+    virtual ~SurfaceControlFpsListener() {
+        JNIEnv* env = AndroidRuntime::getJNIEnv();
+        env->DeleteWeakGlobalRef(mListener);
+    }
+
+private:
+    jweak mListener;
+};
+
+jlong nativeCreate(JNIEnv* env, jclass clazz, jobject obj) {
+    SurfaceControlFpsListener* listener = new SurfaceControlFpsListener(env, obj);
+    listener->incStrong((void*)nativeCreate);
+    return reinterpret_cast<jlong>(listener);
+}
+
+void nativeDestroy(JNIEnv* env, jclass clazz, jlong ptr) {
+    SurfaceControlFpsListener* listener = reinterpret_cast<SurfaceControlFpsListener*>(ptr);
+    listener->decStrong((void*)nativeCreate);
+}
+
+void nativeRegister(JNIEnv* env, jclass clazz, jlong ptr, jlong layerObj) {
+    sp<SurfaceControlFpsListener> listener = reinterpret_cast<SurfaceControlFpsListener*>(ptr);
+    auto layer = reinterpret_cast<SurfaceControl*>(layerObj);
+    sp<IBinder> layerHandle = layer != nullptr ? layer->getHandle() : nullptr;
+    if (SurfaceComposerClient::addFpsListener(layerHandle, listener) != OK) {
+        constexpr auto error_msg = "Couldn't addFpsListener";
+        ALOGE(error_msg);
+        jniThrowRuntimeException(env, error_msg);
+    }
+}
+
+void nativeUnregister(JNIEnv* env, jclass clazz, jlong ptr) {
+    sp<SurfaceControlFpsListener> listener = reinterpret_cast<SurfaceControlFpsListener*>(ptr);
+
+    if (SurfaceComposerClient::removeFpsListener(listener) != OK) {
+        constexpr auto error_msg = "Couldn't removeFpsListener";
+        ALOGE(error_msg);
+        jniThrowRuntimeException(env, error_msg);
+    }
+}
+
+const JNINativeMethod gMethods[] = {
+        /* name, signature, funcPtr */
+        {"nativeCreate", "(Landroid/view/SurfaceControlFpsListener;)J", (void*)nativeCreate},
+        {"nativeDestroy", "(J)V", (void*)nativeDestroy},
+        {"nativeRegister", "(JJ)V", (void*)nativeRegister},
+        {"nativeUnregister", "(J)V", (void*)nativeUnregister}};
+
+} // namespace
+
+int register_android_view_SurfaceControlFpsListener(JNIEnv* env) {
+    int res = jniRegisterNativeMethods(env, "android/view/SurfaceControlFpsListener", gMethods,
+                                       NELEM(gMethods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
+
+    jclass clazz = env->FindClass("android/view/SurfaceControlFpsListener");
+    gListenerClassInfo.mClass = MakeGlobalRefOrDie(env, clazz);
+    gListenerClassInfo.mDispatchOnFpsReported =
+            env->GetStaticMethodID(clazz, "dispatchOnFpsReported",
+                                   "(Landroid/view/SurfaceControlFpsListener;F)V");
+    return 0;
+}
+
+} // namespace android
diff --git a/core/jni/com_android_internal_os_KernelCpuBpfTracking.cpp b/core/jni/com_android_internal_os_KernelCpuBpfTracking.cpp
index e6a82f6..6b41b2e 100644
--- a/core/jni/com_android_internal_os_KernelCpuBpfTracking.cpp
+++ b/core/jni/com_android_internal_os_KernelCpuBpfTracking.cpp
@@ -24,8 +24,48 @@
     return android::bpf::isTrackingUidTimesSupported() ? JNI_TRUE : JNI_FALSE;
 }
 
+static jboolean KernelCpuBpfTracking_startTrackingInternal(JNIEnv *, jobject) {
+    return android::bpf::startTrackingUidTimes();
+}
+
+static jlongArray KernelCpuBpfTracking_getFreqsInternal(JNIEnv *env, jobject) {
+    auto freqs = android::bpf::getCpuFreqs();
+    if (!freqs) return NULL;
+
+    std::vector<uint64_t> allFreqs;
+    for (const auto &vec : *freqs) std::copy(vec.begin(), vec.end(), std::back_inserter(allFreqs));
+
+    auto ar = env->NewLongArray(allFreqs.size());
+    if (ar != NULL) {
+        env->SetLongArrayRegion(ar, 0, allFreqs.size(),
+                                reinterpret_cast<const jlong *>(allFreqs.data()));
+    }
+    return ar;
+}
+
+static jintArray KernelCpuBpfTracking_getFreqsClustersInternal(JNIEnv *env, jobject) {
+    auto freqs = android::bpf::getCpuFreqs();
+    if (!freqs) return NULL;
+
+    std::vector<uint32_t> freqsClusters;
+    uint32_t clusters = freqs->size();
+    for (uint32_t c = 0; c < clusters; ++c) {
+        freqsClusters.insert(freqsClusters.end(), (*freqs)[c].size(), c);
+    }
+
+    auto ar = env->NewIntArray(freqsClusters.size());
+    if (ar != NULL) {
+        env->SetIntArrayRegion(ar, 0, freqsClusters.size(),
+                               reinterpret_cast<const jint *>(freqsClusters.data()));
+    }
+    return ar;
+}
+
 static const JNINativeMethod methods[] = {
         {"isSupported", "()Z", (void *)KernelCpuBpfTracking_isSupported},
+        {"startTrackingInternal", "()Z", (void *)KernelCpuBpfTracking_startTrackingInternal},
+        {"getFreqsInternal", "()[J", (void *)KernelCpuBpfTracking_getFreqsInternal},
+        {"getFreqsClustersInternal", "()[I", (void *)KernelCpuBpfTracking_getFreqsClustersInternal},
 };
 
 int register_com_android_internal_os_KernelCpuBpfTracking(JNIEnv *env) {
diff --git a/core/jni/com_android_internal_os_KernelCpuTotalBpfMapReader.cpp b/core/jni/com_android_internal_os_KernelCpuTotalBpfMapReader.cpp
index 7249238..ad43014 100644
--- a/core/jni/com_android_internal_os_KernelCpuTotalBpfMapReader.cpp
+++ b/core/jni/com_android_internal_os_KernelCpuTotalBpfMapReader.cpp
@@ -20,33 +20,27 @@
 
 namespace android {
 
-static jboolean KernelCpuTotalBpfMapReader_read(JNIEnv *env, jobject, jobject callback) {
-    jclass callbackClass = env->GetObjectClass(callback);
-    jmethodID callbackMethod = env->GetMethodID(callbackClass, "accept", "(IIJ)V");
-    if (callbackMethod == 0) {
-        return JNI_FALSE;
-    }
-
-    auto freqs = android::bpf::getCpuFreqs();
-    if (!freqs) return JNI_FALSE;
+static jlongArray KernelCpuTotalBpfMapReader_readInternal(JNIEnv *env, jobject) {
     auto freqTimes = android::bpf::getTotalCpuFreqTimes();
     if (!freqTimes) return JNI_FALSE;
 
-    auto freqsClusterSize = (*freqs).size();
-    for (uint32_t clusterIndex = 0; clusterIndex < freqsClusterSize; ++clusterIndex) {
-        auto freqsSize = (*freqs)[clusterIndex].size();
-        for (uint32_t freqIndex = 0; freqIndex < freqsSize; ++freqIndex) {
-            env->CallVoidMethod(callback, callbackMethod, clusterIndex,
-                                (*freqs)[clusterIndex][freqIndex],
-                                (*freqTimes)[clusterIndex][freqIndex] / 1000000);
+    std::vector<uint64_t> allTimes;
+    for (const auto &vec : *freqTimes) {
+        for (const auto &timeNs : vec) {
+            allTimes.push_back(timeNs / 1000000);
         }
     }
-    return JNI_TRUE;
+
+    auto ar = env->NewLongArray(allTimes.size());
+    if (ar != NULL) {
+        env->SetLongArrayRegion(ar, 0, allTimes.size(),
+                                reinterpret_cast<const jlong *>(allTimes.data()));
+    }
+    return ar;
 }
 
 static const JNINativeMethod methods[] = {
-        {"read", "(Lcom/android/internal/os/KernelCpuTotalBpfMapReader$Callback;)Z",
-         (void *)KernelCpuTotalBpfMapReader_read},
+        {"readInternal", "()[J", (void *)KernelCpuTotalBpfMapReader_readInternal},
 };
 
 int register_com_android_internal_os_KernelCpuTotalBpfMapReader(JNIEnv *env) {
diff --git a/core/jni/com_android_internal_os_KernelCpuUidBpfMapReader.cpp b/core/jni/com_android_internal_os_KernelCpuUidBpfMapReader.cpp
index 7c68de5..7900d30 100644
--- a/core/jni/com_android_internal_os_KernelCpuUidBpfMapReader.cpp
+++ b/core/jni/com_android_internal_os_KernelCpuUidBpfMapReader.cpp
@@ -82,25 +82,9 @@
     return true;
 }
 
-static jlongArray KernelCpuUidFreqTimeBpfMapReader_getDataDimensions(JNIEnv *env, jobject) {
-    auto freqs = android::bpf::getCpuFreqs();
-    if (!freqs) return NULL;
-
-    std::vector<uint64_t> allFreqs;
-    for (const auto &vec : *freqs) std::copy(vec.begin(), vec.end(), std::back_inserter(allFreqs));
-
-    auto ar = env->NewLongArray(allFreqs.size());
-    if (ar != NULL) {
-        env->SetLongArrayRegion(ar, 0, allFreqs.size(),
-                                reinterpret_cast<const jlong *>(allFreqs.data()));
-    }
-    return ar;
-}
-
 static const JNINativeMethod gFreqTimeMethods[] = {
         {"removeUidRange", "(II)Z", (void *)KernelCpuUidFreqTimeBpfMapReader_removeUidRange},
         {"readBpfData", "()Z", (void *)KernelCpuUidFreqTimeBpfMapReader_readBpfData},
-        {"getDataDimensions", "()[J", (void *)KernelCpuUidFreqTimeBpfMapReader_getDataDimensions},
 };
 
 static jboolean KernelCpuUidActiveTimeBpfMapReader_readBpfData(JNIEnv *env, jobject thiz) {
@@ -186,10 +170,6 @@
         {"KernelCpuUidClusterTimeBpfMapReader", gClusterTimeMethods, NELEM(gClusterTimeMethods)},
 };
 
-static jboolean KernelCpuUidBpfMapReader_startTrackingBpfTimes(JNIEnv *, jobject) {
-    return android::bpf::startTrackingUidTimes();
-}
-
 int register_com_android_internal_os_KernelCpuUidBpfMapReader(JNIEnv *env) {
     gSparseArrayClassInfo.clazz = FindClassOrDie(env, "android/util/SparseArray");
     gSparseArrayClassInfo.clazz = MakeGlobalRefOrDie(env, gSparseArrayClassInfo.clazz);
@@ -198,14 +178,10 @@
     gSparseArrayClassInfo.get =
             GetMethodIDOrDie(env, gSparseArrayClassInfo.clazz, "get", "(I)Ljava/lang/Object;");
     constexpr auto readerName = "com/android/internal/os/KernelCpuUidBpfMapReader";
-    constexpr JNINativeMethod method = {"startTrackingBpfTimes", "()Z",
-                                        (void *)KernelCpuUidBpfMapReader_startTrackingBpfTimes};
-
-    int ret = RegisterMethodsOrDie(env, readerName, &method, 1);
-    if (ret < 0) return ret;
     auto c = FindClassOrDie(env, readerName);
     gmData = GetFieldIDOrDie(env, c, "mData", "Landroid/util/SparseArray;");
 
+    int ret = 0;
     for (const auto &m : gAllMethods) {
         auto fullName = android::base::StringPrintf("%s$%s", readerName, m.name);
         ret = RegisterMethodsOrDie(env, fullName.c_str(), m.methods, m.numMethods);
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index e801725..c9062d8 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -17,6 +17,8 @@
 #define LOG_TAG "Zygote"
 #define ATRACE_TAG ATRACE_TAG_DALVIK
 
+#include "com_android_internal_os_Zygote.h"
+
 #include <async_safe/log.h>
 
 // sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc
@@ -91,19 +93,6 @@
 
 #include "nativebridge/native_bridge.h"
 
-/* Functions in the callchain during the fork shall not be protected with
-   Armv8.3-A Pointer Authentication, otherwise child will not be able to return. */
-#ifdef __ARM_FEATURE_PAC_DEFAULT
-#ifdef __ARM_FEATURE_BTI_DEFAULT
-#define NO_PAC_FUNC __attribute__((target("branch-protection=bti")))
-#else
-#define NO_PAC_FUNC __attribute__((target("branch-protection=none")))
-#endif /* __ARM_FEATURE_BTI_DEFAULT */
-#else /* !__ARM_FEATURE_PAC_DEFAULT */
-#define NO_PAC_FUNC
-#endif /* __ARM_FEATURE_PAC_DEFAULT */
-
-
 namespace {
 
 // TODO (chriswailes): Add a function to initialize native Zygote data.
@@ -118,8 +107,7 @@
 using android::base::WriteStringToFile;
 using android::base::GetBoolProperty;
 
-#define CREATE_ERROR(...) StringPrintf("%s:%d: ", __FILE__, __LINE__). \
-                              append(StringPrintf(__VA_ARGS__))
+using android::zygote::ZygoteFailure;
 
 // This type is duplicated in fd_utils.h
 typedef const std::function<void(std::string)>& fail_fn_t;
@@ -214,7 +202,7 @@
   static constexpr EntryStorage INVALID_ENTRY_VALUE = {-1, -1};
 
   std::atomic<EntryStorage> mStorage;
-  static_assert(decltype(mStorage)::is_always_lock_free);
+  static_assert(decltype(mStorage)::is_always_lock_free);  // Accessed from signal handler.
 
  public:
   constexpr UsapTableEntry() : mStorage(INVALID_ENTRY_VALUE) {}
@@ -917,36 +905,6 @@
 }
 
 /**
- * A failure function used to report fatal errors to the managed runtime.  This
- * function is often curried with the process name information and then passed
- * to called functions.
- *
- * @param env  Managed runtime environment
- * @param process_name  A native representation of the process name
- * @param managed_process_name  A managed representation of the process name
- * @param msg  The error message to be reported
- */
-[[noreturn]]
-static void ZygoteFailure(JNIEnv* env,
-                          const char* process_name,
-                          jstring managed_process_name,
-                          const std::string& msg) {
-  std::unique_ptr<ScopedUtfChars> scoped_managed_process_name_ptr = nullptr;
-  if (managed_process_name != nullptr) {
-    scoped_managed_process_name_ptr.reset(new ScopedUtfChars(env, managed_process_name));
-    if (scoped_managed_process_name_ptr->c_str() != nullptr) {
-      process_name = scoped_managed_process_name_ptr->c_str();
-    }
-  }
-
-  const std::string& error_msg =
-      (process_name == nullptr) ? msg : StringPrintf("(%s) %s", process_name, msg.c_str());
-
-  env->FatalError(error_msg.c_str());
-  __builtin_unreachable();
-}
-
-/**
  * A helper method for converting managed strings to native strings.  A fatal
  * error is generated if a problem is encountered in extracting a non-null
  * string.
@@ -1073,86 +1031,6 @@
 #endif
 }
 
-// Utility routine to fork a process from the zygote.
-NO_PAC_FUNC
-static pid_t ForkCommon(JNIEnv* env, bool is_system_server,
-                        const std::vector<int>& fds_to_close,
-                        const std::vector<int>& fds_to_ignore,
-                        bool is_priority_fork) {
-  SetSignalHandlers();
-
-  // Curry a failure function.
-  auto fail_fn = std::bind(ZygoteFailure, env, is_system_server ? "system_server" : "zygote",
-                           nullptr, _1);
-
-  // Temporarily block SIGCHLD during forks. The SIGCHLD handler might
-  // log, which would result in the logging FDs we close being reopened.
-  // This would cause failures because the FDs are not allowlisted.
-  //
-  // Note that the zygote process is single threaded at this point.
-  BlockSignal(SIGCHLD, fail_fn);
-
-  // Close any logging related FDs before we start evaluating the list of
-  // file descriptors.
-  __android_log_close();
-  AStatsSocket_close();
-
-  // If this is the first fork for this zygote, create the open FD table.  If
-  // it isn't, we just need to check whether the list of open files has changed
-  // (and it shouldn't in the normal case).
-  if (gOpenFdTable == nullptr) {
-    gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, fail_fn);
-  } else {
-    gOpenFdTable->Restat(fds_to_ignore, fail_fn);
-  }
-
-  android_fdsan_error_level fdsan_error_level = android_fdsan_get_error_level();
-
-  // Purge unused native memory in an attempt to reduce the amount of false
-  // sharing with the child process.  By reducing the size of the libc_malloc
-  // region shared with the child process we reduce the number of pages that
-  // transition to the private-dirty state when malloc adjusts the meta-data
-  // on each of the pages it is managing after the fork.
-  mallopt(M_PURGE, 0);
-
-  pid_t pid = fork();
-
-  if (pid == 0) {
-    if (is_priority_fork) {
-      setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX);
-    } else {
-      setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MIN);
-    }
-
-    // The child process.
-    PAuthKeyChange(env);
-    PreApplicationInit();
-
-    // Clean up any descriptors which must be closed immediately
-    DetachDescriptors(env, fds_to_close, fail_fn);
-
-    // Invalidate the entries in the USAP table.
-    ClearUsapTable();
-
-    // Re-open all remaining open file descriptors so that they aren't shared
-    // with the zygote across a fork.
-    gOpenFdTable->ReopenOrDetach(fail_fn);
-
-    // Turn fdsan back on.
-    android_fdsan_set_error_level(fdsan_error_level);
-
-    // Reset the fd to the unsolicited zygote socket
-    gSystemServerSocketFd = -1;
-  } else {
-    ALOGD("Forked child process %d", pid);
-  }
-
-  // We blocked SIGCHLD prior to a fork, we unblock it here.
-  UnblockSignal(SIGCHLD, fail_fn);
-
-  return pid;
-}
-
 // Create an app data directory over tmpfs overlayed CE / DE storage, and bind mount it
 // from the actual app data directory in data mirror.
 static bool createAndMountAppData(std::string_view package_name,
@@ -1973,9 +1851,10 @@
   static int sUsapTableInsertIndex = 0;
 
   int search_index = sUsapTableInsertIndex;
-
   do {
     if (gUsapTable[search_index].SetIfInvalid(usap_pid, read_pipe_fd)) {
+      ++gUsapPoolCount;
+
       // Start our next search right after where we finished this one.
       sUsapTableInsertIndex = (search_index + 1) % gUsapTable.size();
 
@@ -1993,7 +1872,7 @@
 /**
  * Invalidates the entry in the USAPTable corresponding to the provided
  * process ID if it is present.  If an entry was removed the USAP pool
- * count is decremented.
+ * count is decremented. May be called from signal handler.
  *
  * @param usap_pid  Process ID of the USAP entry to invalidate
  * @return True if an entry was invalidated; false otherwise
@@ -2069,6 +1948,121 @@
 
 namespace android {
 
+/**
+ * A failure function used to report fatal errors to the managed runtime.  This
+ * function is often curried with the process name information and then passed
+ * to called functions.
+ *
+ * @param env  Managed runtime environment
+ * @param process_name  A native representation of the process name
+ * @param managed_process_name  A managed representation of the process name
+ * @param msg  The error message to be reported
+ */
+[[noreturn]]
+void zygote::ZygoteFailure(JNIEnv* env,
+                           const char* process_name,
+                           jstring managed_process_name,
+                           const std::string& msg) {
+  std::unique_ptr<ScopedUtfChars> scoped_managed_process_name_ptr = nullptr;
+  if (managed_process_name != nullptr) {
+    scoped_managed_process_name_ptr.reset(new ScopedUtfChars(env, managed_process_name));
+    if (scoped_managed_process_name_ptr->c_str() != nullptr) {
+      process_name = scoped_managed_process_name_ptr->c_str();
+    }
+  }
+
+  const std::string& error_msg =
+      (process_name == nullptr || process_name[0] == '\0') ?
+      msg : StringPrintf("(%s) %s", process_name, msg.c_str());
+
+  env->FatalError(error_msg.c_str());
+  __builtin_unreachable();
+}
+
+// Utility routine to fork a process from the zygote.
+NO_PAC_FUNC
+pid_t zygote::ForkCommon(JNIEnv* env, bool is_system_server,
+                         const std::vector<int>& fds_to_close,
+                         const std::vector<int>& fds_to_ignore,
+                         bool is_priority_fork,
+                         bool purge) {
+  SetSignalHandlers();
+
+  // Curry a failure function.
+  auto fail_fn = std::bind(zygote::ZygoteFailure, env,
+                           is_system_server ? "system_server" : "zygote",
+                           nullptr, _1);
+
+  // Temporarily block SIGCHLD during forks. The SIGCHLD handler might
+  // log, which would result in the logging FDs we close being reopened.
+  // This would cause failures because the FDs are not allowlisted.
+  //
+  // Note that the zygote process is single threaded at this point.
+  BlockSignal(SIGCHLD, fail_fn);
+
+  // Close any logging related FDs before we start evaluating the list of
+  // file descriptors.
+  __android_log_close();
+  AStatsSocket_close();
+
+  // If this is the first fork for this zygote, create the open FD table.  If
+  // it isn't, we just need to check whether the list of open files has changed
+  // (and it shouldn't in the normal case).
+  if (gOpenFdTable == nullptr) {
+    gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, fail_fn);
+  } else {
+    gOpenFdTable->Restat(fds_to_ignore, fail_fn);
+  }
+
+  android_fdsan_error_level fdsan_error_level = android_fdsan_get_error_level();
+
+  if (purge) {
+    // Purge unused native memory in an attempt to reduce the amount of false
+    // sharing with the child process.  By reducing the size of the libc_malloc
+    // region shared with the child process we reduce the number of pages that
+    // transition to the private-dirty state when malloc adjusts the meta-data
+    // on each of the pages it is managing after the fork.
+    mallopt(M_PURGE, 0);
+  }
+
+  pid_t pid = fork();
+
+  if (pid == 0) {
+    if (is_priority_fork) {
+      setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX);
+    } else {
+      setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MIN);
+    }
+
+    // The child process.
+    PAuthKeyChange(env);
+    PreApplicationInit();
+
+    // Clean up any descriptors which must be closed immediately
+    DetachDescriptors(env, fds_to_close, fail_fn);
+
+    // Invalidate the entries in the USAP table.
+    ClearUsapTable();
+
+    // Re-open all remaining open file descriptors so that they aren't shared
+    // with the zygote across a fork.
+    gOpenFdTable->ReopenOrDetach(fail_fn);
+
+    // Turn fdsan back on.
+    android_fdsan_set_error_level(fdsan_error_level);
+
+    // Reset the fd to the unsolicited zygote socket
+    gSystemServerSocketFd = -1;
+  } else {
+    ALOGD("Forked child process %d", pid);
+  }
+
+  // We blocked SIGCHLD prior to a fork, we unblock it here.
+  UnblockSignal(SIGCHLD, fail_fn);
+
+  return pid;
+}
+
 static void com_android_internal_os_Zygote_nativePreApplicationInit(JNIEnv*, jclass) {
   PreApplicationInit();
 }
@@ -2085,7 +2079,8 @@
     jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
 
     if (UNLIKELY(managed_fds_to_close == nullptr)) {
-      ZygoteFailure(env, "zygote", nice_name, "Zygote received a null fds_to_close vector.");
+      zygote::ZygoteFailure(env, "zygote", nice_name,
+                            "Zygote received a null fds_to_close vector.");
     }
 
     std::vector<int> fds_to_close =
@@ -2111,7 +2106,7 @@
         fds_to_ignore.push_back(gSystemServerSocketFd);
     }
 
-    pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore, true);
+    pid_t pid = zygote::ForkCommon(env, false, fds_to_close, fds_to_ignore, true);
 
     if (pid == 0) {
       SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
@@ -2146,10 +2141,10 @@
       fds_to_ignore.push_back(gSystemServerSocketFd);
   }
 
-  pid_t pid = ForkCommon(env, true,
-                         fds_to_close,
-                         fds_to_ignore,
-                         true);
+  pid_t pid = zygote::ForkCommon(env, true,
+                                 fds_to_close,
+                                 fds_to_ignore,
+                                 true);
   if (pid == 0) {
       // System server prcoess does not need data isolation so no need to
       // know pkg_data_info_list.
@@ -2189,58 +2184,74 @@
  * ensuring proper file descriptor hygiene.
  *
  * @param env  Managed runtime environment
- * @param read_pipe_fd  The read FD for the USAP reporting pipe.  Manually closed by blastlas
- * in managed code.
+ * @param read_pipe_fd  The read FD for the USAP reporting pipe.  Manually closed by the child
+ * in managed code. -1 indicates none.
  * @param write_pipe_fd  The write FD for the USAP reporting pipe.  Manually closed by the
- * zygote in managed code.
+ * zygote in managed code. -1 indicates none.
  * @param managed_session_socket_fds  A list of anonymous session sockets that must be ignored by
  * the FD hygiene code and automatically "closed" in the new USAP.
+ * @param args_known Arguments for specialization are available; no need to read from a socket
  * @param is_priority_fork  Controls the nice level assigned to the newly created process
- * @return
+ * @return child pid in the parent, 0 in the child
  */
 NO_PAC_FUNC
-static jint com_android_internal_os_Zygote_nativeForkUsap(JNIEnv* env,
-                                                          jclass,
-                                                          jint read_pipe_fd,
-                                                          jint write_pipe_fd,
-                                                          jintArray managed_session_socket_fds,
-                                                          jboolean is_priority_fork) {
-  std::vector<int> fds_to_close(MakeUsapPipeReadFDVector()),
-                   fds_to_ignore(fds_to_close);
-
+static jint com_android_internal_os_Zygote_nativeForkApp(JNIEnv* env,
+                                                         jclass,
+                                                         jint read_pipe_fd,
+                                                         jint write_pipe_fd,
+                                                         jintArray managed_session_socket_fds,
+                                                         jboolean args_known,
+                                                         jboolean is_priority_fork) {
   std::vector<int> session_socket_fds =
       ExtractJIntArray(env, "USAP", nullptr, managed_session_socket_fds)
           .value_or(std::vector<int>());
+  return zygote::forkApp(env, read_pipe_fd, write_pipe_fd, session_socket_fds,
+                            args_known == JNI_TRUE, is_priority_fork == JNI_TRUE, true);
+}
 
-  // The USAP Pool Event FD is created during the initialization of the
-  // USAP pool and should always be valid here.
+NO_PAC_FUNC
+int zygote::forkApp(JNIEnv* env,
+                    int read_pipe_fd,
+                    int write_pipe_fd,
+                    const std::vector<int>& session_socket_fds,
+                    bool args_known,
+                    bool is_priority_fork,
+                    bool purge) {
+
+  std::vector<int> fds_to_close(MakeUsapPipeReadFDVector()),
+                   fds_to_ignore(fds_to_close);
 
   fds_to_close.push_back(gZygoteSocketFD);
-  fds_to_close.push_back(gUsapPoolEventFD);
-  fds_to_close.insert(fds_to_close.end(), session_socket_fds.begin(), session_socket_fds.end());
   if (gSystemServerSocketFd != -1) {
       fds_to_close.push_back(gSystemServerSocketFd);
   }
+  if (args_known) {
+      fds_to_close.push_back(gUsapPoolSocketFD);
+  }
+  fds_to_close.insert(fds_to_close.end(), session_socket_fds.begin(), session_socket_fds.end());
 
-  fds_to_ignore.push_back(gZygoteSocketFD);
   fds_to_ignore.push_back(gUsapPoolSocketFD);
-  fds_to_ignore.push_back(gUsapPoolEventFD);
-  fds_to_ignore.push_back(read_pipe_fd);
-  fds_to_ignore.push_back(write_pipe_fd);
+  fds_to_ignore.push_back(gZygoteSocketFD);
+  if (read_pipe_fd != -1) {
+      fds_to_ignore.push_back(read_pipe_fd);
+  }
+  if (write_pipe_fd != -1) {
+      fds_to_ignore.push_back(write_pipe_fd);
+  }
   fds_to_ignore.insert(fds_to_ignore.end(), session_socket_fds.begin(), session_socket_fds.end());
+
+  if (gUsapPoolEventFD != -1) {
+      fds_to_close.push_back(gUsapPoolEventFD);
+      fds_to_ignore.push_back(gUsapPoolEventFD);
+  }
   if (gSystemServerSocketFd != -1) {
+      if (args_known) {
+          fds_to_close.push_back(gSystemServerSocketFd);
+      }
       fds_to_ignore.push_back(gSystemServerSocketFd);
   }
-
-  pid_t usap_pid = ForkCommon(env, /* is_system_server= */ false, fds_to_close, fds_to_ignore,
-                              is_priority_fork == JNI_TRUE);
-
-  if (usap_pid != 0) {
-    ++gUsapPoolCount;
-    AddUsapTableEntry(usap_pid, read_pipe_fd);
-  }
-
-  return usap_pid;
+  return zygote::ForkCommon(env, /* is_system_server= */ false, fds_to_close,
+                            fds_to_ignore, is_priority_fork == JNI_TRUE, purge);
 }
 
 static void com_android_internal_os_Zygote_nativeAllowFileAcrossFork(
@@ -2354,7 +2365,7 @@
    */
 
   if (!SetTaskProfiles(0, {})) {
-    ZygoteFailure(env, "zygote", nullptr, "Zygote SetTaskProfiles failed");
+    zygote::ZygoteFailure(env, "zygote", nullptr, "Zygote SetTaskProfiles failed");
   }
 }
 
@@ -2372,15 +2383,21 @@
   return managed_usap_fds;
 }
 
+/*
+ * Add the given pid and file descriptor to the Usap table. CriticalNative method.
+ */
+static void com_android_internal_os_Zygote_nativeAddUsapTableEntry(jint pid, jint read_pipe_fd) {
+  AddUsapTableEntry(pid, read_pipe_fd);
+}
+
 /**
- * A JNI wrapper around RemoveUsapTableEntry.
+ * A JNI wrapper around RemoveUsapTableEntry. CriticalNative method.
  *
  * @param env  Managed runtime environment
  * @param usap_pid  Process ID of the USAP entry to invalidate
  * @return  True if an entry was invalidated; false otherwise.
  */
-static jboolean com_android_internal_os_Zygote_nativeRemoveUsapTableEntry(JNIEnv* env, jclass,
-                                                                          jint usap_pid) {
+static jboolean com_android_internal_os_Zygote_nativeRemoveUsapTableEntry(jint usap_pid) {
   return RemoveUsapTableEntry(usap_pid);
 }
 
@@ -2395,7 +2412,8 @@
 static jint com_android_internal_os_Zygote_nativeGetUsapPoolEventFD(JNIEnv* env, jclass) {
   if (gUsapPoolEventFD == -1) {
     if ((gUsapPoolEventFD = eventfd(0, 0)) == -1) {
-      ZygoteFailure(env, "zygote", nullptr, StringPrintf("Unable to create eventfd: %s", strerror(errno)));
+      zygote::ZygoteFailure(env, "zygote", nullptr,
+                            StringPrintf("Unable to create eventfd: %s", strerror(errno)));
     }
   }
 
@@ -2438,12 +2456,12 @@
 }
 
 static void com_android_internal_os_Zygote_nativeBlockSigTerm(JNIEnv* env, jclass) {
-  auto fail_fn = std::bind(ZygoteFailure, env, "usap", nullptr, _1);
+  auto fail_fn = std::bind(zygote::ZygoteFailure, env, "usap", nullptr, _1);
   BlockSignal(SIGTERM, fail_fn);
 }
 
 static void com_android_internal_os_Zygote_nativeUnblockSigTerm(JNIEnv* env, jclass) {
-  auto fail_fn = std::bind(ZygoteFailure, env, "usap", nullptr, _1);
+  auto fail_fn = std::bind(zygote::ZygoteFailure, env, "usap", nullptr, _1);
   UnblockSignal(SIGTERM, fail_fn);
 }
 
@@ -2549,7 +2567,10 @@
          (void*)com_android_internal_os_Zygote_nativePreApplicationInit},
         {"nativeInstallSeccompUidGidFilter", "(II)V",
          (void*)com_android_internal_os_Zygote_nativeInstallSeccompUidGidFilter},
-        {"nativeForkUsap", "(II[IZ)I", (void*)com_android_internal_os_Zygote_nativeForkUsap},
+        {"nativeForkApp", "(II[IZZ)I", (void*)com_android_internal_os_Zygote_nativeForkApp},
+        // @CriticalNative
+        {"nativeAddUsapTableEntry", "(II)V",
+         (void*)com_android_internal_os_Zygote_nativeAddUsapTableEntry},
         {"nativeSpecializeAppProcess",
          "(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/"
          "String;Z[Ljava/lang/String;[Ljava/lang/String;ZZ)V",
@@ -2558,6 +2579,10 @@
          (void*)com_android_internal_os_Zygote_nativeInitNativeState},
         {"nativeGetUsapPipeFDs", "()[I",
          (void*)com_android_internal_os_Zygote_nativeGetUsapPipeFDs},
+        // @CriticalNative
+        {"nativeAddUsapTableEntry", "(II)V",
+         (void*)com_android_internal_os_Zygote_nativeAddUsapTableEntry},
+        // @CriticalNative
         {"nativeRemoveUsapTableEntry", "(I)Z",
          (void*)com_android_internal_os_Zygote_nativeRemoveUsapTableEntry},
         {"nativeGetUsapPoolEventFD", "()I",
diff --git a/core/jni/com_android_internal_os_Zygote.h b/core/jni/com_android_internal_os_Zygote.h
new file mode 100644
index 0000000..d2da914
--- /dev/null
+++ b/core/jni/com_android_internal_os_Zygote.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _COM_ANDROID_INTERNAL_OS_ZYGOTE_H
+#define _COM_ANDROID_INTERNAL_OS_ZYGOTE_H
+
+#define LOG_TAG "Zygote"
+#define ATRACE_TAG ATRACE_TAG_DALVIK
+
+/* Functions in the callchain during the fork shall not be protected with
+   Armv8.3-A Pointer Authentication, otherwise child will not be able to return. */
+#ifdef __ARM_FEATURE_PAC_DEFAULT
+#ifdef __ARM_FEATURE_BTI_DEFAULT
+#define NO_PAC_FUNC __attribute__((target("branch-protection=bti")))
+#else
+#define NO_PAC_FUNC __attribute__((target("branch-protection=none")))
+#endif /* __ARM_FEATURE_BTI_DEFAULT */
+#else /* !__ARM_FEATURE_PAC_DEFAULT */
+#define NO_PAC_FUNC
+#endif /* __ARM_FEATURE_PAC_DEFAULT */
+
+#include <jni.h>
+#include <vector>
+#include <android-base/stringprintf.h>
+
+#define CREATE_ERROR(...) StringPrintf("%s:%d: ", __FILE__, __LINE__). \
+                              append(StringPrintf(__VA_ARGS__))
+
+namespace android {
+namespace zygote {
+
+NO_PAC_FUNC
+pid_t ForkCommon(JNIEnv* env,bool is_system_server,
+                 const std::vector<int>& fds_to_close,
+                 const std::vector<int>& fds_to_ignore,
+                 bool is_priority_fork,
+                 bool purge = true);
+
+/**
+ * Fork a process. The pipe fds are used for usap communication, or -1 in
+ * other cases. Session_socket_fds are FDs used for zygote communication that must be dealt
+ * with hygienically, but are not otherwise used here. Args_known indicates that the process
+ * will be immediately specialized with arguments that are already known, so no usap
+ * communication is required. Is_priority_fork should be true if this is on the app startup
+ * critical path. Purge specifies that unused pages should be purged before the fork.
+ */
+NO_PAC_FUNC
+int forkApp(JNIEnv* env,
+            int read_pipe_fd,
+            int write_pipe_fd,
+            const std::vector<int>& session_socket_fds,
+            bool args_known,
+            bool is_priority_fork,
+            bool purge);
+
+[[noreturn]]
+void ZygoteFailure(JNIEnv* env,
+                   const char* process_name,
+                   jstring managed_process_name,
+                   const std::string& msg);
+
+}  // namespace zygote
+}  // namespace android
+
+#endif // _COM_ANDROID_INTERNAL_OS_ZYGOTE_
diff --git a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
new file mode 100644
index 0000000..011e8f8
--- /dev/null
+++ b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
@@ -0,0 +1,512 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "com_android_internal_os_Zygote.h"
+
+#include <algorithm>
+#include <android-base/logging.h>
+#include <async_safe/log.h>
+#include <cctype>
+#include <chrono>
+#include <core_jni_helpers.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+#include <optional>
+#include <poll.h>
+#include <unistd.h>
+#include <utility>
+#include <utils/misc.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <vector>
+
+namespace android {
+
+using namespace std::placeholders;
+using android::base::StringPrintf;
+using android::zygote::ZygoteFailure;
+
+// WARNING: Knows a little about the wire protocol used to communicate with Zygote.
+// TODO: Fix error handling.
+
+constexpr size_t MAX_COMMAND_BYTES = 12200;
+constexpr size_t NICE_NAME_BYTES = 50;
+
+// A buffer optionally bundled with a file descriptor from which we can fill it.
+// Does not own the file descriptor; destroying a NativeCommandBuffer does not
+// close the descriptor.
+class NativeCommandBuffer {
+ public:
+  NativeCommandBuffer(int sourceFd): mEnd(0), mNext(0), mLinesLeft(0), mFd(sourceFd) {}
+
+  // Read mNext line from mFd, filling mBuffer from file descriptor, as needed.
+  // Return a pair of pointers pointing to the first character, and one past the
+  // mEnd of the line, i.e. at the newline. Returns nothing on failure.
+  template<class FailFn>
+  std::optional<std::pair<char*, char*>> readLine(FailFn fail_fn) {
+    char* result = mBuffer + mNext;
+    while (true) {
+      if (mNext == mEnd) {
+        if (mEnd == MAX_COMMAND_BYTES) {
+          return {};
+        }
+        if (mFd == -1) {
+          fail_fn("ZygoteCommandBuffer.readLine attempted to read from mFd -1");
+        }
+        ssize_t nread = TEMP_FAILURE_RETRY(read(mFd, mBuffer + mEnd, MAX_COMMAND_BYTES - mEnd));
+        if (nread <= 0) {
+          if (nread == 0) {
+            return {};
+          }
+          fail_fn(CREATE_ERROR("session socket read failed: %s", strerror(errno)));
+        } else if (nread == MAX_COMMAND_BYTES - mEnd) {
+          // This is pessimistic by one character, but close enough.
+          fail_fn("ZygoteCommandBuffer overflowed: command too long");
+        }
+        mEnd += nread;
+      }
+      // UTF-8 does not allow newline to occur as part of a multibyte character.
+      char* nl = static_cast<char *>(memchr(mBuffer + mNext, '\n', mEnd - mNext));
+      if (nl == nullptr) {
+        mNext = mEnd;
+      } else {
+        mNext = nl - mBuffer + 1;
+        if (--mLinesLeft < 0) {
+          fail_fn("ZygoteCommandBuffer.readLine attempted to read past mEnd of command");
+        }
+        return std::make_pair(result, nl);
+      }
+    }
+  }
+
+  void reset() {
+    mNext = 0;
+  }
+
+  // Make sure the current command is fully buffered, without reading past the current command.
+  template<class FailFn>
+  void readAllLines(FailFn fail_fn) {
+     while (mLinesLeft > 0) {
+       readLine(fail_fn);
+    }
+  }
+
+  void clear() {
+    // Don't bother to actually clear the buffer; it'll be unmapped in the child anyway.
+    reset();
+    mNiceName[0] = '\0';
+    mEnd = 0;
+  }
+
+  // Insert line into the mBuffer. Checks that the mBuffer is not associated with an mFd.
+  // Implicitly adds newline separators. Allows mBuffer contents to be explicitly set.
+  void insert(const char* line, size_t lineLen) {
+    DCHECK(mFd == -1);
+    CHECK(mEnd + lineLen < MAX_COMMAND_BYTES);
+    strncpy(mBuffer + mEnd, line, lineLen);
+    mBuffer[mEnd + lineLen] = '\n';
+    mEnd += lineLen + 1;
+  }
+
+  // Clear mBuffer, start reading new command, return the number of arguments, leaving mBuffer
+  // positioned at the beginning of first argument. Return 0 on EOF.
+  template<class FailFn>
+  int getCount(FailFn fail_fn) {
+    mLinesLeft = 1;
+    auto line = readLine(fail_fn);
+    if (!line.has_value()) {
+      return 0;
+    }
+    char* countString = line.value().first;  // Newline terminated.
+    long nArgs = atol(countString);
+    if (nArgs <= 0 || nArgs >= MAX_COMMAND_BYTES / 2) {
+      fail_fn(CREATE_ERROR("Unreasonable argument count %ld", nArgs));
+    }
+    mLinesLeft = nArgs;
+    return static_cast<int>(nArgs);
+  }
+
+  // Is the mBuffer a simple fork command?
+  // We disallow request to wrap the child process, child zygotes, anything that
+  // mentions capabilities or requests uid < minUid.
+  // We insist that --setuid and --setgid arguments are explicitly included and that the
+  // command starts with --runtime-args.
+  // Assumes we are positioned at the beginning of the command after the argument count,
+  // and leaves the position at some indeterminate position in the buffer.
+  // As a side effect, this sets mNiceName to a non-empty string, if possible.
+  template<class FailFn>
+  bool isSimpleForkCommand(int minUid, FailFn fail_fn) {
+    if (mLinesLeft <= 0 || mLinesLeft  >= MAX_COMMAND_BYTES / 2) {
+      return false;
+    }
+    static const char* RUNTIME_ARGS = "--runtime-args";
+    static const char* INVOKE_WITH = "--invoke-with";
+    static const char* CHILD_ZYGOTE = "--start-child-zygote";
+    static const char* SETUID = "--setuid=";
+    static const char* SETGID = "--setgid=";
+    static const char* CAPABILITIES = "--capabilities";
+    static const char* NICE_NAME = "--nice-name=";
+    static const size_t RA_LENGTH = strlen(RUNTIME_ARGS);
+    static const size_t IW_LENGTH = strlen(INVOKE_WITH);
+    static const size_t CZ_LENGTH = strlen(CHILD_ZYGOTE);
+    static const size_t SU_LENGTH = strlen(SETUID);
+    static const size_t SG_LENGTH = strlen(SETGID);
+    static const size_t CA_LENGTH = strlen(CAPABILITIES);
+    static const size_t NN_LENGTH = strlen(NICE_NAME);
+
+    bool saw_setuid = false, saw_setgid = false;
+    bool saw_runtime_args = false;
+
+    while (mLinesLeft > 0) {
+      auto read_result = readLine(fail_fn);
+      if (!read_result.has_value()) {
+        return false;
+      }
+      auto [arg_start, arg_end] = read_result.value();
+      if (arg_end - arg_start == RA_LENGTH
+          && strncmp(arg_start, RUNTIME_ARGS, RA_LENGTH) == 0) {
+        saw_runtime_args = true;
+        continue;
+      }
+      if (arg_end - arg_start >= NN_LENGTH
+          && strncmp(arg_start, NICE_NAME, NN_LENGTH) == 0) {
+        size_t name_len = arg_end - (arg_start + NN_LENGTH);
+        size_t copy_len = std::min(name_len, NICE_NAME_BYTES - 1);
+        memcpy(mNiceName, arg_start + NN_LENGTH, copy_len);
+        mNiceName[copy_len] = '\0';
+        continue;
+      }
+      if (arg_end - arg_start == IW_LENGTH
+          && strncmp(arg_start, INVOKE_WITH, IW_LENGTH) == 0) {
+        // This also removes the need for invoke-with security checks here.
+        return false;
+      }
+      if (arg_end - arg_start == CZ_LENGTH
+          && strncmp(arg_start, CHILD_ZYGOTE, CZ_LENGTH) == 0) {
+        return false;
+      }
+      if (arg_end - arg_start >= CA_LENGTH
+          && strncmp(arg_start, CAPABILITIES, CA_LENGTH) == 0) {
+        return false;
+      }
+      if (arg_end - arg_start >= SU_LENGTH
+          && strncmp(arg_start, SETUID, SU_LENGTH) == 0) {
+        int uid = digitsVal(arg_start + SU_LENGTH, arg_end);
+        if (uid < minUid) {
+          return false;
+        }
+        saw_setuid = true;
+        continue;
+      }
+      if (arg_end - arg_start >= SG_LENGTH
+          && strncmp(arg_start, SETGID, SG_LENGTH) == 0) {
+        int gid = digitsVal(arg_start + SG_LENGTH, arg_end);
+        if (gid == -1) {
+          return false;
+        }
+        saw_setgid = true;
+      }
+    }
+    return saw_runtime_args && saw_setuid && saw_setgid;
+  }
+
+  void setFd(int new_fd) {
+    mFd = new_fd;
+  }
+
+  int getFd() const {
+    return mFd;
+  }
+
+  const char* niceNameAddr() const {
+    return mNiceName;
+  }
+
+  // Debug only:
+  void logState() const {
+    ALOGD("mbuffer starts with %c%c, nice name is %s, "
+          "mEnd = %u, mNext = %u, mLinesLeft = %d, mFd = %d",
+          mBuffer[0], (mBuffer[1] == '\n' ? ' ' : mBuffer[1]),
+          niceNameAddr(),
+          static_cast<unsigned>(mEnd), static_cast<unsigned>(mNext),
+          static_cast<int>(mLinesLeft), mFd);
+  }
+
+ private:
+  // Picky version of atoi(). No sign or unexpected characters allowed. Return -1 on failure.
+  static int digitsVal(char* start, char* end) {
+    int result = 0;
+    if (end - start > 6) {
+      return -1;
+    }
+    for (char* dp = start; dp < end; ++dp) {
+      if (*dp < '0' || *dp > '9') {
+        ALOGW("Argument failed integer format check");
+        return -1;
+      }
+      result = 10 * result + (*dp - '0');
+    }
+    return result;
+  }
+
+  uint32_t mEnd;  // Index of first empty byte in the mBuffer.
+  uint32_t mNext;  // Index of first character past last line returned by readLine.
+  int32_t mLinesLeft;  // Lines in current command that haven't yet been read.
+  int mFd;  // Open file descriptor from which we can read more. -1 if none.
+  char mNiceName[NICE_NAME_BYTES];
+  char mBuffer[MAX_COMMAND_BYTES];
+};
+
+static_assert(sizeof(NativeCommandBuffer) < 3 * 4096);
+
+static int buffersAllocd(0);
+
+// Get a new NativeCommandBuffer. Can only be called once between freeNativeBuffer calls,
+// so that only one buffer exists at a time.
+jlong com_android_internal_os_ZygoteCommandBuffer_getNativeBuffer(JNIEnv* env, jclass, jint fd) {
+  CHECK(buffersAllocd == 0);
+  ++buffersAllocd;
+  // MMap explicitly to get it page aligned.
+  void *bufferMem = mmap(NULL, sizeof(NativeCommandBuffer), PROT_READ | PROT_WRITE,
+                         MAP_ANONYMOUS | MAP_PRIVATE | MAP_POPULATE, -1, 0);
+  // Currently we mmap and unmap one for every request handled by the Java code.
+  // That could be improved, but unclear it matters.
+  if (bufferMem == MAP_FAILED) {
+    ZygoteFailure(env, nullptr, nullptr, "Failed to map argument buffer");
+  }
+  return (jlong) new(bufferMem) NativeCommandBuffer(fd);
+}
+
+// Delete native command buffer.
+void com_android_internal_os_ZygoteCommandBuffer_freeNativeBuffer(JNIEnv* env, jclass,
+                                                                  jlong j_buffer) {
+  CHECK(buffersAllocd == 1);
+  NativeCommandBuffer* n_buffer = reinterpret_cast<NativeCommandBuffer*>(j_buffer);
+  n_buffer->~NativeCommandBuffer();
+  if (munmap(n_buffer, sizeof(NativeCommandBuffer)) != 0) {
+    ZygoteFailure(env, nullptr, nullptr, "Failed to unmap argument buffer");
+  }
+  --buffersAllocd;
+}
+
+// Clear the buffer, read the line containing the count, and return the count.
+jint com_android_internal_os_ZygoteCommandBuffer_nativeGetCount(JNIEnv* env, jclass,
+                                                                jlong j_buffer) {
+  NativeCommandBuffer* n_buffer = reinterpret_cast<NativeCommandBuffer*>(j_buffer);
+  auto fail_fn = std::bind(ZygoteFailure, env, nullptr, nullptr, _1);
+  return n_buffer->getCount(fail_fn);
+}
+
+// Explicitly insert a string as the last line (argument) of the buffer.
+void com_android_internal_os_ZygoteCommandBuffer_insert(JNIEnv* env, jclass, jlong j_buffer,
+                                                        jstring line) {
+  NativeCommandBuffer* n_buffer = reinterpret_cast<NativeCommandBuffer*>(j_buffer);
+  size_t lineLen = static_cast<size_t>(env->GetStringUTFLength(line));
+  const char* cstring = env->GetStringUTFChars(line, NULL);
+  n_buffer->insert(cstring, lineLen);
+  env->ReleaseStringUTFChars(line, cstring);
+}
+
+// Read a line from the buffer, refilling as necessary.
+jstring com_android_internal_os_ZygoteCommandBuffer_nativeNextArg(JNIEnv* env, jclass,
+                                                                  jlong j_buffer) {
+  NativeCommandBuffer* n_buffer = reinterpret_cast<NativeCommandBuffer*>(j_buffer);
+  auto fail_fn = std::bind(ZygoteFailure, env, n_buffer->niceNameAddr(), nullptr, _1);
+  auto line = n_buffer->readLine(fail_fn);
+  if (!line.has_value()) {
+    fail_fn("Incomplete zygote command");
+  }
+  auto [cresult, endp] = line.value();
+  // OK to temporarily clobber the buffer, since this is not thread safe, and we're modifying
+  // the buffer anyway.
+  *endp = '\0';
+  jstring result = env->NewStringUTF(cresult);
+  *endp = '\n';
+  return result;
+}
+
+// Read all lines from the current command into the buffer, and then reset the buffer, so
+// we will start reading again at the beginning of the command, starting with the argument
+// count. And we don't need access to the fd to do so.
+void com_android_internal_os_ZygoteCommandBuffer_nativeReadFullyAndReset(JNIEnv* env, jclass,
+                                                                         jlong j_buffer) {
+  NativeCommandBuffer* n_buffer = reinterpret_cast<NativeCommandBuffer*>(j_buffer);
+  auto fail_fn = std::bind(ZygoteFailure, env, n_buffer->niceNameAddr(), nullptr, _1);
+  n_buffer->readAllLines(fail_fn);
+  n_buffer->reset();
+}
+
+// Fork a child as specified by the current command buffer, and refill the command
+// buffer from the given socket. So long as the result is another simple fork command,
+// repeat this process.
+// It must contain a fork command, which is currently restricted not to fork another
+// zygote or involve a wrapper process.
+// The initial buffer should be partially or entirely read; we read it fully and reset it.
+// When we return, the buffer contains the command we couldn't handle, and has been reset().
+// We return false in the parent when we see a command we didn't understand, and thus the
+// command in the buffer still needs to be executed.
+// We return true in each child.
+// We only process fork commands if the peer uid matches expected_uid.
+// For every fork command after the first, we check that the requested uid is at
+// least minUid.
+NO_PAC_FUNC
+jboolean com_android_internal_os_ZygoteCommandBuffer_nativeForkRepeatedly(
+            JNIEnv* env,
+            jclass,
+            jlong j_buffer,
+            jint zygote_socket_fd,
+            jint expected_uid,
+            jint minUid,
+            jstring managed_nice_name) {
+
+  NativeCommandBuffer* n_buffer = reinterpret_cast<NativeCommandBuffer*>(j_buffer);
+  int session_socket = n_buffer->getFd();
+  std::vector<int> session_socket_fds {session_socket};
+  auto fail_fn_1 = std::bind(ZygoteFailure, env, static_cast<const char*>(nullptr),
+                             static_cast<jstring>(managed_nice_name), _1);
+  // This binds to the nice name address; the actual names are updated by isSimpleForkCommand:
+  auto fail_fn_n = std::bind(ZygoteFailure, env, n_buffer->niceNameAddr(),
+                             static_cast<jstring>(nullptr), _1);
+  auto fail_fn_z = std::bind(ZygoteFailure, env, "zygote", nullptr, _1);
+
+  struct pollfd fd_structs[2];
+  static const int ZYGOTE_IDX = 0;
+  static const int SESSION_IDX = 1;
+  fd_structs[ZYGOTE_IDX].fd = zygote_socket_fd;
+  fd_structs[ZYGOTE_IDX].events = POLLIN;
+  fd_structs[SESSION_IDX].fd = session_socket;
+  fd_structs[SESSION_IDX].events = POLLIN;
+
+  struct timeval timeout;
+  socklen_t timeout_size = sizeof timeout;
+  if (getsockopt(session_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, &timeout_size) != 0) {
+    fail_fn_z("Failed to retrieve session socket timeout");
+  }
+
+  struct ucred credentials;
+  socklen_t cred_size = sizeof credentials;
+  if (getsockopt(n_buffer->getFd(), SOL_SOCKET, SO_PEERCRED, &credentials, &cred_size) == -1
+      || cred_size != sizeof credentials) {
+    fail_fn_1("ForkMany failed to get initial credentials, %s", strerror(errno));
+  }
+
+  bool first_time = true;
+  do {
+    if (credentials.uid != expected_uid) {
+      return JNI_FALSE;
+    }
+    n_buffer->readAllLines(first_time ? fail_fn_1 : fail_fn_n);
+    n_buffer->reset();
+    int pid = zygote::forkApp(env, /* no pipe FDs */ -1, -1, session_socket_fds,
+                              /*args_known=*/ true, /*is_priority_fork=*/ true,
+                              /*purge=*/ first_time);
+    if (pid == 0) {
+      return JNI_TRUE;
+    }
+    // We're in the parent. Write big-endian pid, followed by a boolean.
+    char pid_buf[5];
+    int tmp_pid = pid;
+    for (int i = 3; i >= 0; --i) {
+      pid_buf[i] = tmp_pid & 0xff;
+      tmp_pid >>= 8;
+    }
+    pid_buf[4] = 0;  // Process is not wrapped.
+    int res = write(session_socket, pid_buf, 5);
+    if (res != 5) {
+      if (res == -1) {
+        (first_time ? fail_fn_1 : fail_fn_n)
+            (CREATE_ERROR("Pid write error %d: %s", errno, strerror(errno)));
+      } else {
+        (first_time ? fail_fn_1 : fail_fn_n)
+            (CREATE_ERROR("Write unexpectedly returned short: %d < 5", res));
+      }
+    }
+    // Clear buffer and get count from next command.
+    n_buffer->clear();
+    for (;;) {
+      // Poll isn't strictly necessary for now. But without it, disconnect is hard to detect.
+      int poll_res = TEMP_FAILURE_RETRY(poll(fd_structs, 2, -1 /* infinite timeout */));
+      if ((fd_structs[SESSION_IDX].revents & POLLIN) != 0) {
+        if (n_buffer->getCount(fail_fn_z) != 0) {
+          break;
+        }  // else disconnected;
+      } else if (poll_res == 0 || (fd_structs[ZYGOTE_IDX].revents & POLLIN) == 0) {
+        fail_fn_z(
+            CREATE_ERROR("Poll returned with no descriptors ready! Poll returned %d", poll_res));
+      }
+      // We've now seen either a disconnect or connect request.
+      close(session_socket);
+      int new_fd = accept(zygote_socket_fd, nullptr, nullptr);
+      if (new_fd == -1) {
+        fail_fn_z("Accept(%d) failed: %s", zygote_socket_fd, strerror(errno));
+      }
+      if (new_fd != session_socket) {
+          // Move new_fd back to the old value, so that we don't have to change Java-level data
+          // structures to reflect a change. This implicitly closes the old one.
+          if (dup2(new_fd, session_socket) != session_socket) {
+            fail_fn_z(CREATE_ERROR("Failed to move fd %d to %d: %s",
+                                   new_fd, session_socket, strerror(errno)));
+          }
+          close(new_fd);
+      }
+      // If we ever return, we effectively reuse the old Java ZygoteConnection.
+      // None of its state needs to change.
+      if (setsockopt(session_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, timeout_size) != 0) {
+        fail_fn_z(CREATE_ERROR("Failed to set receive timeout for socket %d: %s",
+                               session_socket, strerror(errno)));
+      }
+      if (setsockopt(session_socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, timeout_size) != 0) {
+        fail_fn_z(CREATE_ERROR("Failed to set send timeout for socket %d: %s",
+                               session_socket, strerror(errno)));
+      }
+      if (getsockopt(session_socket, SOL_SOCKET, SO_PEERCRED, &credentials, &cred_size) == -1) {
+        fail_fn_z(CREATE_ERROR("ForkMany failed to get credentials: %s", strerror(errno)));
+      }
+      if (cred_size != sizeof credentials) {
+        fail_fn_z(CREATE_ERROR("ForkMany credential size = %d, should be %d",
+                               cred_size, static_cast<int>(sizeof credentials)));
+      }
+    }
+    first_time = false;
+  } while (n_buffer->isSimpleForkCommand(minUid, fail_fn_n));
+  ALOGW("forkRepeatedly terminated due to non-simple command");
+  n_buffer->logState();
+  n_buffer->reset();
+  return JNI_FALSE;
+}
+
+#define METHOD_NAME(m) com_android_internal_os_ZygoteCommandBuffer_ ## m
+
+static const JNINativeMethod gMethods[] = {
+        {"getNativeBuffer", "(I)J", (void *) METHOD_NAME(getNativeBuffer)},
+        {"freeNativeBuffer", "(J)V", (void *) METHOD_NAME(freeNativeBuffer)},
+        {"insert", "(JLjava/lang/String;)V", (void *) METHOD_NAME(insert)},
+        {"nativeNextArg", "(J)Ljava/lang/String;", (void *) METHOD_NAME(nativeNextArg)},
+        {"nativeReadFullyAndReset", "(J)V", (void *) METHOD_NAME(nativeReadFullyAndReset)},
+        {"nativeGetCount", "(J)I", (void *) METHOD_NAME(nativeGetCount)},
+        {"nativeForkRepeatedly", "(JIIILjava/lang/String;)Z",
+          (void *) METHOD_NAME(nativeForkRepeatedly)},
+};
+
+int register_com_android_internal_os_ZygoteCommandBuffer(JNIEnv* env) {
+  return RegisterMethodsOrDie(env, "com/android/internal/os/ZygoteCommandBuffer", gMethods,
+                              NELEM(gMethods));
+}
+
+}  // namespace android
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index c580b34..ad1d252 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -282,7 +282,8 @@
         optional SettingProto force_rtl = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto emulate_display_cutout = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto force_desktop_mode_on_external_displays = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
-        optional SettingProto enable_sizecompat_freeform = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        // Deprecated, use enable_non_resizable_multi_window
+        optional SettingProto enable_sizecompat_freeform = 7 [ (android.privacy).dest = DEST_AUTOMATIC, deprecated = true ];
         optional SettingProto enable_non_resizable_multi_window = 8 [ (android.privacy).dest = DEST_AUTOMATIC ];
     }
     optional Development development = 39;
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index d3c2d31..ec41a47 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -627,6 +627,7 @@
         optional int64 duration_ms = 2;
         optional string tag = 3;
         optional int32 type = 4;
+        optional int32 reason_code = 5;
     }
     repeated PendingTempWhitelist pending_temp_whitelist = 26;
 
diff --git a/core/proto/android/server/powerstatsservice.proto b/core/proto/android/server/powerstatsservice.proto
index 4b1ee02..f64e146 100644
--- a/core/proto/android/server/powerstatsservice.proto
+++ b/core/proto/android/server/powerstatsservice.proto
@@ -144,7 +144,7 @@
      */
     optional int64 total_state_entry_count = 3;
     /**
-     * Last time this state was entered. Time in milliseconds since boot
+     * Last time this state was entered. Walltime in milliseconds since Unix epoch.
      */
     optional int64 last_entry_timestamp_ms = 4;
 }
@@ -208,7 +208,7 @@
     /** Unique index identifying the energy consumer. */
     optional int32 id = 1;
 
-    /** Time since device boot(CLOCK_BOOTTIME) in milli-seconds */
+    /** Walltime in milliseconds since Unix epoch */
     optional int64 timestamp_ms = 2;
 
     /** Accumulated energy since device boot in microwatt-seconds (uWs) */
@@ -247,7 +247,7 @@
      */
     optional int32 id = 1;
 
-    /** Time since device boot(CLOCK_BOOTTIME) in milli-seconds */
+    /** Walltime in milliseconds since Unix epoch */
     optional int64 timestamp_ms = 2;
 
     /** Accumulated energy since device boot in microwatt-seconds (uWs) */
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index c882431..ec502c3 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -174,10 +174,10 @@
     // Use root_display_area instead
     optional WindowContainerProto window_container = 1 [deprecated=true];
     optional int32 id = 2;
-    reserved 3; // stacks
-    optional DockedStackDividerControllerProto docked_stack_divider_controller = 4 [deprecated=true];
+    reserved 3; // RootTasks
+    optional DockedTaskDividerControllerProto docked_task_divider_controller = 4 [deprecated=true];
     // Will be removed soon.
-    optional PinnedStackControllerProto pinned_stack_controller = 5 [deprecated=true];
+    optional PinnedTaskControllerProto pinned_task_controller = 5 [deprecated=true];
     /* non app windows */
     repeated WindowTokenProto above_app_windows = 6 [deprecated=true];
     repeated WindowTokenProto below_app_windows = 7 [deprecated=true];
@@ -256,15 +256,15 @@
     optional int32 last_orientation = 5 [(.android.typedef) = "android.content.pm.ActivityInfo.ScreenOrientation"];
 }
 
-/* represents DockedStackDividerController */
-message DockedStackDividerControllerProto {
+/* represents DockedTaskDividerController */
+message DockedTaskDividerControllerProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
     optional bool minimized_dock = 1 [deprecated=true];
 }
 
-/* represents PinnedStackController */
-message PinnedStackControllerProto {
+/* represents PinnedTaskController */
+message PinnedTaskControllerProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
     optional .android.graphics.RectProto default_bounds = 1 [deprecated=true];
@@ -406,6 +406,8 @@
     optional int64 finished_seamless_rotation_frame = 40;
     optional WindowFramesProto window_frames = 41;
     optional bool force_seamless_rotation = 42;
+    optional bool in_size_compat_mode = 43;
+    optional float global_scale = 44;
 }
 
 message IdentifierProto {
@@ -516,6 +518,7 @@
     optional .android.graphics.RectProto visible_insets = 13 [deprecated=true];
     optional .android.graphics.RectProto stable_insets = 14 [deprecated=true];
     optional .android.graphics.RectProto outsets = 15;
+    optional .android.graphics.RectProto compat_frame = 16;
 }
 
 message InsetsSourceProviderProto {
diff --git a/core/proto/android/service/netstats.proto b/core/proto/android/service/netstats.proto
index 8ebb4a9..c8cdfdd 100644
--- a/core/proto/android/service/netstats.proto
+++ b/core/proto/android/service/netstats.proto
@@ -80,6 +80,8 @@
     optional bool metered = 5;
 
     optional bool default_network = 6;
+
+    optional int32 oem_managed_network = 7;
 }
 
 // Corresponds to NetworkStatsRecorder.
diff --git a/core/res/Android.bp b/core/res/Android.bp
index 9ee5e5e1..b988b5a 100644
--- a/core/res/Android.bp
+++ b/core/res/Android.bp
@@ -14,11 +14,103 @@
 // limitations under the License.
 //
 
+package {
+    default_applicable_licenses: ["frameworks_base_core_res_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_core_res_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+        "SPDX-license-identifier-GPL",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
+genrule {
+    name: "remote-color-resources-compile-public",
+    tools: ["aapt2"],
+    srcs: [
+        "remote_color_resources_res/values/public.xml",
+    ],
+    out: ["values_public.arsc.flat"],
+    cmd: "$(location aapt2) compile $(in) -o $(genDir)",
+}
+
+genrule {
+    name: "remote-color-resources-compile-colors",
+    tools: ["aapt2"],
+    srcs: [
+        "remote_color_resources_res/values/colors.xml",
+    ],
+    out: ["values_colors.arsc.flat"],
+    cmd: "$(location aapt2) compile $(in) -o $(genDir)",
+}
+
+genrule {
+    name: "remote-color-resources-apk",
+    tools: ["aapt2"],
+    // The first input file in the list must be the manifest
+    srcs: [
+        "RemoteThemeColorsAndroidManifest.xml",
+        ":remote-color-resources-compile-public",
+        ":remote-color-resources-compile-colors",
+    ],
+    out: ["remote-color-resources.apk"],
+    cmd: "$(location aapt2) link -o $(out) --manifest $(in)"
+}
+
+genrule {
+    name: "remote-color-resources-arsc",
+    srcs: [":remote-color-resources-apk"],
+    out: ["res/raw/remote_views_color_resources.arsc"],
+    cmd: "mkdir -p $(genDir)/remote-color-resources-arsc && "
+        + "unzip -x $(in) resources.arsc -d $(genDir)/remote-color-resources-arsc && "
+        + "mkdir -p $$(dirname $(out)) && "
+        + "mv $(genDir)/remote-color-resources-arsc/resources.arsc $(out) && "
+        + "echo 'Created $(out)'"
+}
+
+genrule {
+    name: "remote-color-resources-arsc-zip",
+    tools: ["soong_zip"],
+    srcs: [
+        ":remote-color-resources-arsc",
+        "remote_color_resources_res/symbols.xml",
+    ],
+    out: ["remote_views_color_resources.zip"],
+    cmd: "INPUTS=($(in)) && "
+        + "RES_DIR=$$(dirname $$(dirname $${INPUTS[0]})) && "
+        + "mkdir -p $$RES_DIR/values && "
+        + "cp $${INPUTS[1]} $$RES_DIR/values && "
+        + "$(location soong_zip) -o $(out) -C $$RES_DIR -D $$RES_DIR && "
+        + "cp $(out) ."
+}
+
 android_app {
     name: "framework-res",
     sdk_version: "core_platform",
     certificate: "platform",
 
+    srcs: [":remote-color-resources-arsc"],
+
     // Disable dexpreopt and verify_uses_libraries check as the app
     // contains no Java code to be dexpreopted.
     enforce_uses_libs: false,
@@ -42,6 +134,10 @@
         "--auto-add-overlay",
     ],
 
+    resource_zips: [
+        ":remote-color-resources-arsc-zip",
+    ],
+
     // Create package-export.apk, which other packages can use to get
     // PRODUCT-agnostic resource data like IDs and type definitions.
     export_package_resources: true,
@@ -66,6 +162,7 @@
     srcs: [
         "assets/**/*",
         "res/**/*",
+        ":remote-color-resources-arsc",
     ],
 }
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 18cc3ac..d5f5d28 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -690,6 +690,9 @@
     <!-- Made protected in S (was added in R) -->
     <protected-broadcast android:name="com.android.internal.intent.action.BUGREPORT_REQUESTED" />
 
+    <!-- Added in S -->
+    <protected-broadcast android:name="android.intent.action.REBOOT_READY" />
+
     <!-- ====================================================================== -->
     <!--                          RUNTIME PERMISSIONS                           -->
     <!-- ====================================================================== -->
@@ -1281,15 +1284,15 @@
         android:backgroundPermission="android.permission.RECORD_BACKGROUND_AUDIO"
         android:protectionLevel="dangerous|instant" />
 
-    <!-- Allows an application to record audio while in the background.
-         <p>Protection level: dangerous
-    -->
+    <!-- @SystemApi @TestApi Allows an application to record audio while in the background.
+         This permission is not intended to be held by apps.
+         <p>Protection level: internal
+        @hide -->
     <permission android:name="android.permission.RECORD_BACKGROUND_AUDIO"
         android:permissionGroup="android.permission-group.UNDEFINED"
         android:label="@string/permlab_recordBackgroundAudio"
         android:description="@string/permdesc_recordBackgroundAudio"
-        android:permissionFlags="hardRestricted|installerExemptIgnored"
-        android:protectionLevel="dangerous" />
+        android:protectionLevel="internal" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for activity recognition                        -->
@@ -1365,15 +1368,15 @@
         android:backgroundPermission="android.permission.BACKGROUND_CAMERA"
         android:protectionLevel="dangerous|instant" />
 
-    <!-- Required to be able to access the camera device in the background.
-         <p>Protection level: dangerous
-    -->
+    <!-- @SystemApi @TestApi Required to be able to access the camera device in the background.
+         This permission is not intended to be held by apps.
+         <p>Protection level: internal
+        @hide -->
     <permission android:name="android.permission.BACKGROUND_CAMERA"
             android:permissionGroup="android.permission-group.UNDEFINED"
             android:label="@string/permlab_backgroundCamera"
             android:description="@string/permdesc_backgroundCamera"
-            android:permissionFlags="hardRestricted|installerExemptIgnored"
-            android:protectionLevel="dangerous" />
+            android:protectionLevel="internal" />
 
     <!-- @SystemApi Required in addition to android.permission.CAMERA to be able to access
            system only camera devices.
@@ -2638,6 +2641,16 @@
         android:label="@string/permlab_manageProfileAndDeviceOwners"
         android:description="@string/permdesc_manageProfileAndDeviceOwners" />
 
+    <!-- @TestApi @hide Allows an application to reset the record of previous system update freeze
+         periods. -->
+    <permission android:name="android.permission.CLEAR_FREEZE_PERIOD"
+                android:protectionLevel="signature" />
+
+    <!-- @TestApi @hide Allows an application to force available DevicePolicyManager logs to
+         DPC. -->
+    <permission android:name="android.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS"
+                android:protectionLevel="signature" />
+
     <!-- Allows an application to get full detailed information about
          recently running tasks, with full fidelity to the real state.
          @hide -->
@@ -3905,6 +3918,12 @@
     <permission android:name="android.permission.SET_KEYBOARD_LAYOUT"
         android:protectionLevel="signature" />
 
+    <!-- Allows an app to use exact alarm scheduling APIs to perform timing
+         sensitive background work.
+     -->
+    <permission android:name="android.permission.SCHEDULE_EXACT_ALARM"
+        android:protectionLevel="normal|appop"/>
+
     <!-- Allows an application to query tablet mode state and monitor changes
          in it.
          <p>Not for use by third-party applications.
@@ -3963,16 +3982,12 @@
     <permission android:name="com.android.permission.INSTALL_EXISTING_PACKAGES"
         android:protectionLevel="signature|privileged" />
 
-    <!-- Allows an application to use the package installer v2 APIs.
-         <p>The package installer v2 APIs are still a work in progress and we're
-         currently validating they work in all scenarios.
+    <!-- Allows an application to use System Data Loaders.
          <p>Not for use by third-party applications.
-         TODO(b/152310230): use this permission to protect only Incremental installations
-         once the APIs are confirmed to be sufficient.
          @hide
     -->
-    <permission android:name="com.android.permission.USE_INSTALLER_V2"
-        android:protectionLevel="signature|verifier" />
+    <permission android:name="com.android.permission.USE_SYSTEM_DATA_LOADERS"
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi @TestApi Allows an application to clear user data.
          <p>Not for use by third-party applications
@@ -5405,6 +5420,12 @@
          @hide -->
     <permission android:name="android.permission.MANAGE_SENSOR_PRIVACY"
                 android:protectionLevel="signature" />
+
+    <!-- @SystemApi Allows sensor privacy changes to be observed.
+         @hide -->
+    <permission android:name="android.permission.OBSERVE_SENSOR_PRIVACY"
+                android:protectionLevel="signature|installer" />
+
     <!-- @SystemApi Permission that protects the {@link Intent#ACTION_REVIEW_ACCESSIBILITY_SERVICES}
          intent.
          @hide -->
@@ -5492,11 +5513,11 @@
                 android:protectionLevel="signature" />
 
     <!-- Must be required by a
-        {@link android.service.screenshot.ScreenshotHasherService}
+        {@link android.service.displayhash.DisplayHasherService}
         to ensure that only the system can bind to it.
         @hide This is not a third-party API (intended for OEMs and system apps).
     -->
-    <permission android:name="android.permission.BIND_SCREENSHOT_HASHER_SERVICE"
+    <permission android:name="android.permission.BIND_DISPLAY_HASHER_SERVICE"
         android:protectionLevel="signature" />
 
     <!-- @hide @TestApi Allows an application to enable/disable toast rate limiting.
diff --git a/core/res/RemoteThemeColorsAndroidManifest.xml b/core/res/RemoteThemeColorsAndroidManifest.xml
new file mode 100644
index 0000000..11970fd
--- /dev/null
+++ b/core/res/RemoteThemeColorsAndroidManifest.xml
@@ -0,0 +1,5 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+  package="android">
+<application/>
+</manifest>
+
diff --git a/core/res/remote_color_resources_res/symbols.xml b/core/res/remote_color_resources_res/symbols.xml
new file mode 100644
index 0000000..82d5e3e
--- /dev/null
+++ b/core/res/remote_color_resources_res/symbols.xml
@@ -0,0 +1,4 @@
+<resources>
+  <!-- ARSC file used to overlay local colors when rendering a RemoteViews -->
+  <java-symbol type="raw" name="remote_views_color_resources" />
+</resources>
diff --git a/core/res/remote_color_resources_res/values/colors.xml b/core/res/remote_color_resources_res/values/colors.xml
new file mode 100644
index 0000000..295f16e
--- /dev/null
+++ b/core/res/remote_color_resources_res/values/colors.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+  <!-- Note: the values of the colors doesn't really matter (they will always be overwritten before used), but they help a lot debugging, to find out which color is where in the ARSC file. -->
+  <color name="system_primary_0">#01010101</color>
+  <color name="system_primary_50">#02020202</color>
+  <color name="system_primary_100">#03030303</color>
+  <color name="system_primary_200">#04040404</color>
+  <color name="system_primary_300">#05050505</color>
+  <color name="system_primary_400">#06060606</color>
+  <color name="system_primary_500">#07070707</color>
+  <color name="system_primary_600">#08080808</color>
+  <color name="system_primary_700">#09090909</color>
+  <color name="system_primary_800">#0a0a0a0a</color>
+  <color name="system_primary_900">#0b0b0b0b</color>
+  <color name="system_primary_1000">#0c0c0c0c</color>
+  <color name="system_secondary_0">#10101010</color>
+  <color name="system_secondary_50">#20202020</color>
+  <color name="system_secondary_100">#30303030</color>
+  <color name="system_secondary_200">#40404040</color>
+  <color name="system_secondary_300">#50505050</color>
+  <color name="system_secondary_400">#60606060</color>
+  <color name="system_secondary_500">#70707070</color>
+  <color name="system_secondary_600">#80808080</color>
+  <color name="system_secondary_700">#90909090</color>
+  <color name="system_secondary_800">#a0a0a0a0</color>
+  <color name="system_secondary_900">#b0b0b0b0</color>
+  <color name="system_secondary_1000">#c0c0c0c0</color>
+  <color name="system_neutral_0">#1f1f1f1f</color>
+  <color name="system_neutral_50">#2f2f2f2f</color>
+  <color name="system_neutral_100">#3f3f3f3f</color>
+  <color name="system_neutral_200">#4f4f4f4f</color>
+  <color name="system_neutral_300">#5f5f5f5f</color>
+  <color name="system_neutral_400">#6f6f6f6f</color>
+  <color name="system_neutral_500">#7f7f7f7f</color>
+  <color name="system_neutral_600">#8f8f8f8f</color>
+  <color name="system_neutral_700">#9f9f9f9f</color>
+  <color name="system_neutral_800">#afafafaf</color>
+  <color name="system_neutral_900">#bfbfbfbf</color>
+  <color name="system_neutral_1000">#cfcfcfcf</color>
+</resources>
diff --git a/core/res/remote_color_resources_res/values/public.xml b/core/res/remote_color_resources_res/values/public.xml
new file mode 100644
index 0000000..e628f09
--- /dev/null
+++ b/core/res/remote_color_resources_res/values/public.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+  <public-group type="color" first-id="0x0106001d">
+    <public name="system_primary_0" />
+    <public name="system_primary_50" />
+    <public name="system_primary_100" />
+    <public name="system_primary_200" />
+    <public name="system_primary_300" />
+    <public name="system_primary_400" />
+    <public name="system_primary_500" />
+    <public name="system_primary_600" />
+    <public name="system_primary_700" />
+    <public name="system_primary_800" />
+    <public name="system_primary_900" />
+    <public name="system_primary_1000" />
+    <public name="system_secondary_0" />
+    <public name="system_secondary_50" />
+    <public name="system_secondary_100" />
+    <public name="system_secondary_200" />
+    <public name="system_secondary_300" />
+    <public name="system_secondary_400" />
+    <public name="system_secondary_500" />
+    <public name="system_secondary_600" />
+    <public name="system_secondary_700" />
+    <public name="system_secondary_800" />
+    <public name="system_secondary_900" />
+    <public name="system_secondary_1000" />
+    <public name="system_neutral_0" />
+    <public name="system_neutral_50" />
+    <public name="system_neutral_100" />
+    <public name="system_neutral_200" />
+    <public name="system_neutral_300" />
+    <public name="system_neutral_400" />
+    <public name="system_neutral_500" />
+    <public name="system_neutral_600" />
+    <public name="system_neutral_700" />
+    <public name="system_neutral_800" />
+    <public name="system_neutral_900" />
+    <public name="system_neutral_1000" />
+  </public-group>
+</resources>
diff --git a/core/res/res/drawable/toast_frame.xml b/core/res/res/drawable/toast_frame.xml
index d57bd6a..44c00c0 100644
--- a/core/res/res/drawable/toast_frame.xml
+++ b/core/res/res/drawable/toast_frame.xml
@@ -17,8 +17,7 @@
 -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
-    <!-- background is material_grey_200 with .9 alpha -->
-    <solid android:color="#E6EEEEEE" />
-    <corners android:radius="22dp" />
+    <solid android:color="?android:attr/colorBackground" />
+    <corners android:radius="28dp" />
 </shape>
 
diff --git a/core/res/res/layout/notification_template_conversation_header.xml b/core/res/res/layout/notification_template_conversation_header.xml
index b018676..e01d803 100644
--- a/core/res/res/layout/notification_template_conversation_header.xml
+++ b/core/res/res/layout/notification_template_conversation_header.xml
@@ -99,13 +99,26 @@
         android:visibility="gone"
         />
 
+    <TextView
+        android:id="@+id/verification_divider"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Info"
+        android:layout_marginStart="@dimen/notification_conversation_header_separating_margin"
+        android:layout_marginEnd="@dimen/notification_conversation_header_separating_margin"
+        android:text="@string/notification_header_divider_symbol"
+        android:layout_gravity="center"
+        android:paddingTop="1sp"
+        android:singleLine="true"
+        android:visibility="gone"
+        />
+
     <ImageView
         android:id="@+id/verification_icon"
-        android:layout_width="@dimen/notification_badge_size"
-        android:layout_height="@dimen/notification_badge_size"
+        android:layout_width="@dimen/notification_verification_icon_size"
+        android:layout_height="@dimen/notification_verification_icon_size"
         android:layout_gravity="center"
         android:layout_marginStart="4dp"
-        android:contentDescription="@string/notification_alerted_content_description"
         android:paddingTop="2dp"
         android:scaleType="fitCenter"
         android:src="@drawable/ic_notifications_alerted"
@@ -140,6 +153,19 @@
         />
 
     <ImageView
+        android:id="@+id/phishing_alert"
+        android:layout_width="@dimen/notification_phishing_alert_size"
+        android:layout_height="@dimen/notification_phishing_alert_size"
+        android:layout_marginStart="4dp"
+        android:paddingTop="2dp"
+        android:scaleType="fitCenter"
+        android:src="@drawable/ic_dialog_alert_material"
+        android:visibility="gone"
+        android:contentDescription="@string/notification_phishing_alert_content_description"
+        />
+
+
+    <ImageView
         android:id="@+id/profile_badge"
         android:layout_width="@dimen/notification_badge_size"
         android:layout_height="@dimen/notification_badge_size"
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index 88998f2..1de1d04 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -17,8 +17,8 @@
 <NotificationHeaderView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/notification_header"
-    android:layout_width="wrap_content"
-    android:layout_height="@dimen/notification_header_solo_height"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/notification_header_height"
     android:layout_marginBottom="@dimen/notification_header_margin_bottom"
     android:clipChildren="false"
     android:gravity="center_vertical"
@@ -33,6 +33,7 @@
         android:layout_gravity="center_vertical|start"
         android:layout_marginStart="@dimen/notification_left_icon_start"
         android:background="@drawable/notification_large_icon_outline"
+        android:clipToOutline="true"
         android:importantForAccessibility="no"
         android:scaleType="centerCrop"
         android:visibility="gone"
diff --git a/core/res/res/layout/notification_template_material_base.xml b/core/res/res/layout/notification_template_material_base.xml
index 41be36b..b83611bc 100644
--- a/core/res/res/layout/notification_template_material_base.xml
+++ b/core/res/res/layout/notification_template_material_base.xml
@@ -30,6 +30,7 @@
         android:layout_gravity="center_vertical|start"
         android:layout_marginStart="@dimen/notification_left_icon_start"
         android:background="@drawable/notification_large_icon_outline"
+        android:clipToOutline="true"
         android:importantForAccessibility="no"
         android:scaleType="centerCrop"
         android:visibility="gone"
@@ -54,6 +55,7 @@
         android:layout_marginBottom="@dimen/notification_right_icon_headerless_margin"
         android:layout_marginEnd="@dimen/notification_header_expand_icon_size"
         android:background="@drawable/notification_large_icon_outline"
+        android:clipToOutline="true"
         android:importantForAccessibility="no"
         android:scaleType="centerCrop"
         />
@@ -89,26 +91,11 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
-        android:layout_marginBottom="@dimen/notification_headerless_margin_minimum"
-        android:layout_marginTop="@dimen/notification_headerless_margin_minimum"
+        android:layout_marginBottom="@dimen/notification_headerless_margin_twoline"
+        android:layout_marginTop="@dimen/notification_headerless_margin_twoline"
         android:orientation="vertical"
         >
 
-        <!--
-        This invisible FrameLayout is here as a collapsible padding.  Having a layout_weight=1 is
-        what causes this view (and it's counterpart at the opposite end) to collapse before the
-        actual content views do.
-        This pair of 10dp collapsible paddings (plus the 16dp fixed margins) allow us to support
-        headerless notifications of 1-3 lines (where each line is 20dp tall) where the 1-line
-        variant is 56dp and the 2- and 3-line variants are both 76dp.
-        -->
-        <FrameLayout
-            android:id="@+id/notification_headerless_margin_extra_top"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/notification_headerless_margin_extra"
-            android:layout_weight="1"
-            />
-
         <!-- extends ViewGroup -->
         <NotificationTopLineView
             android:id="@+id/notification_top_line"
@@ -151,12 +138,20 @@
             android:orientation="vertical"
             >
 
-            <include
-                layout="@layout/notification_template_text"
+            <com.android.internal.widget.NotificationVanishingFrameLayout
                 android:layout_width="match_parent"
                 android:layout_height="@dimen/notification_headerless_line_height"
-                android:layout_marginTop="0dp"
-                />
+                >
+                <!-- This is the simplest way to keep this text vertically centered without using
+                 gravity="center_vertical" which causes jumpiness in expansion animations. -->
+                <include
+                    layout="@layout/notification_template_text"
+                    android:layout_width="match_parent"
+                    android:layout_height="@dimen/notification_text_height"
+                    android:layout_gravity="center_vertical"
+                    android:layout_marginTop="0dp"
+                    />
+            </com.android.internal.widget.NotificationVanishingFrameLayout>
 
             <include
                 layout="@layout/notification_template_progress"
@@ -166,21 +161,6 @@
 
         </LinearLayout>
 
-        <!--
-        This invisible FrameLayout is here as a collapsible padding.  Having a layout_weight=1 is
-        what causes this view (and it's counterpart at the opposite end) to collapse before the
-        actual content views do.
-        This pair of 10dp collapsible paddings (plus the 16dp fixed margins) allow us to support
-        headerless notifications of 1-3 lines (where each line is 20dp tall) where the 1-line
-        variant is 56dp and the 2- and 3-line variants are both 76dp.
-        -->
-        <FrameLayout
-            android:id="@+id/notification_headerless_margin_extra_bottom"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/notification_headerless_margin_extra"
-            android:layout_weight="1"
-            />
-
     </LinearLayout>
 
 </com.android.internal.widget.NotificationMaxHeightFrameLayout>
diff --git a/core/res/res/layout/notification_template_material_big_base.xml b/core/res/res/layout/notification_template_material_big_base.xml
index de537b2..2d1c342 100644
--- a/core/res/res/layout/notification_template_material_big_base.xml
+++ b/core/res/res/layout/notification_template_material_big_base.xml
@@ -38,11 +38,7 @@
             android:layout_gravity="top"
             >
 
-            <include
-                layout="@layout/notification_template_header"
-                android:layout_width="match_parent"
-                android:layout_height="@dimen/notification_header_big_height"
-                />
+            <include layout="@layout/notification_template_header" />
 
             <LinearLayout
                 android:id="@+id/notification_main_column"
diff --git a/core/res/res/layout/notification_template_material_big_media.xml b/core/res/res/layout/notification_template_material_big_media.xml
index 696cb65..bdd4430 100644
--- a/core/res/res/layout/notification_template_material_big_media.xml
+++ b/core/res/res/layout/notification_template_material_big_media.xml
@@ -36,7 +36,6 @@
         layout="@layout/notification_template_header"
         android:layout_width="match_parent"
         android:layout_height="@dimen/media_notification_header_height"
-        android:layout_gravity="start"
         />
 
     <LinearLayout
diff --git a/core/res/res/layout/notification_template_material_big_picture.xml b/core/res/res/layout/notification_template_material_big_picture.xml
index 25d396f..6f3c77f 100644
--- a/core/res/res/layout/notification_template_material_big_picture.xml
+++ b/core/res/res/layout/notification_template_material_big_picture.xml
@@ -23,11 +23,7 @@
     android:clipChildren="false"
     >
 
-    <include
-        layout="@layout/notification_template_header"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/notification_header_big_height"
-        />
+    <include layout="@layout/notification_template_header" />
 
     <include layout="@layout/notification_template_right_icon" />
 
@@ -72,6 +68,7 @@
             android:layout_marginStart="@dimen/notification_content_margin_start"
             android:layout_marginEnd="@dimen/notification_content_margin_end"
             android:background="@drawable/notification_big_picture_outline"
+            android:clipToOutline="true"
             android:scaleType="centerCrop"
             />
 
diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml
index 2452a32..2954ba2 100644
--- a/core/res/res/layout/notification_template_material_big_text.xml
+++ b/core/res/res/layout/notification_template_material_big_text.xml
@@ -23,11 +23,7 @@
     android:tag="bigText"
     >
 
-    <include
-        layout="@layout/notification_template_header"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/notification_header_big_height"
-        />
+    <include layout="@layout/notification_template_header" />
 
     <com.android.internal.widget.RemeasuringLinearLayout
         android:id="@+id/notification_action_list_margin_target"
diff --git a/core/res/res/layout/notification_template_material_media.xml b/core/res/res/layout/notification_template_material_media.xml
index 7daccd2..baffdd5 100644
--- a/core/res/res/layout/notification_template_material_media.xml
+++ b/core/res/res/layout/notification_template_material_media.xml
@@ -32,7 +32,8 @@
     />
     <include layout="@layout/notification_template_header"
         android:layout_width="match_parent"
-        android:layout_height="@dimen/media_notification_header_height" />
+        android:layout_height="@dimen/media_notification_header_height"
+        />
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/core/res/res/layout/notification_template_right_icon.xml b/core/res/res/layout/notification_template_right_icon.xml
index d22d4c2..f163ed5 100644
--- a/core/res/res/layout/notification_template_right_icon.xml
+++ b/core/res/res/layout/notification_template_right_icon.xml
@@ -22,6 +22,7 @@
     android:layout_marginEnd="@dimen/notification_header_expand_icon_size"
     android:layout_marginTop="@dimen/notification_right_icon_big_margin_top"
     android:background="@drawable/notification_large_icon_outline"
+    android:clipToOutline="true"
     android:importantForAccessibility="no"
     android:scaleType="centerCrop"
     />
diff --git a/core/res/res/layout/notification_top_line_views.xml b/core/res/res/layout/notification_top_line_views.xml
index 7656dd5..88bcc4d 100644
--- a/core/res/res/layout/notification_top_line_views.xml
+++ b/core/res/res/layout/notification_top_line_views.xml
@@ -123,6 +123,18 @@
         />
 
     <ImageView
+        android:id="@+id/phishing_alert"
+        android:layout_width="@dimen/notification_phishing_alert_size"
+        android:layout_height="@dimen/notification_phishing_alert_size"
+        android:layout_marginStart="4dp"
+        android:baseline="10dp"
+        android:scaleType="fitCenter"
+        android:src="@drawable/ic_dialog_alert_material"
+        android:visibility="gone"
+        android:contentDescription="@string/notification_phishing_alert_content_description"
+        />
+
+    <ImageView
         android:id="@+id/profile_badge"
         android:layout_width="@dimen/notification_badge_size"
         android:layout_height="@dimen/notification_badge_size"
diff --git a/core/res/res/layout/splash_screen_view.xml b/core/res/res/layout/splash_screen_view.xml
index 513da5e..e6d724f 100644
--- a/core/res/res/layout/splash_screen_view.xml
+++ b/core/res/res/layout/splash_screen_view.xml
@@ -21,14 +21,16 @@
     android:orientation="vertical">
 
     <View android:id="@+id/splashscreen_icon_view"
-    android:layout_height="wrap_content"
-    android:layout_width="wrap_content"
-    android:layout_gravity="center"/>
+          android:layout_height="wrap_content"
+          android:layout_width="wrap_content"
+          android:layout_gravity="center"
+          android:contentDescription="@string/splash_screen_view_icon_description"/>
 
     <View android:id="@+id/splashscreen_branding_view"
           android:layout_height="wrap_content"
           android:layout_width="wrap_content"
           android:layout_gravity="center_horizontal|bottom"
-          android:layout_marginBottom="60dp"/>
+          android:layout_marginBottom="60dp"
+          android:contentDescription="@string/splash_screen_view_branding_description"/>
 
 </android.window.SplashScreenView>
\ No newline at end of file
diff --git a/core/res/res/layout/transient_notification.xml b/core/res/res/layout/transient_notification.xml
index db586ec..8fcb77f 100644
--- a/core/res/res/layout/transient_notification.xml
+++ b/core/res/res/layout/transient_notification.xml
@@ -18,24 +18,27 @@
 */
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical"
-    android:background="?android:attr/toastFrameBackground">
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:gravity="center_vertical"
+    android:maxWidth="@dimen/toast_width"
+    android:background="?android:attr/toastFrameBackground"
+    android:layout_marginEnd="16dp"
+    android:layout_marginStart="16dp"
+    android:paddingStart="16dp"
+    android:paddingEnd="16dp">
 
     <TextView
         android:id="@android:id/message"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_weight="1"
-        android:layout_marginHorizontal="24dp"
-        android:layout_marginVertical="15dp"
-        android:layout_gravity="center_horizontal"
-        android:textAppearance="@style/TextAppearance.Toast"
-        android:textColor="@color/primary_text_default_material_light"
-        />
-
+        android:ellipsize="end"
+        android:maxLines="2"
+        android:paddingTop="12dp"
+        android:paddingBottom="12dp"
+        android:lineHeight="20sp"
+        android:textAppearance="@style/TextAppearance.Toast"/>
 </LinearLayout>
-
-
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 55eaaf6..4b591bf 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Hierdie toetstel het nie \'n vingerafdruksensor nie."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor is tydelik gedeaktiveer."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Vinger <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Gebruik jou vingerafdruk om voort te gaan"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Vingerafdrukikoon"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Kan nie meer gesig herken nie. Probeer weer."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Te eenders. Verander asseblief jou pose."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Draai jou kop \'n bietjie minder."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Draai jou kop \'n bietjie minder."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Draai jou kop \'n bietjie minder."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Verwyder enigiets wat jou gesig versteek."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Maak die bokant van jou skerm skoon, insluitend die swart balk"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Laat die program toe om Moenie Steur Nie-opstelling te lees en skryf."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"begin kyk van toestemminggebruik"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Laat die houer toe om die toestemminggebruik vir \'n program te begin. Behoort nooit vir normale programme nodig te wees nie."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"kry toegang tot sensordata teen \'n hoë monsternemingkoers"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Laat die program toe om monsters van sensordata teen \'n hoër koers as 200 Hz te neem"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Stel wagwoordreëls"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Beheer die lengte en die karakters wat in skermslotwagwoorde en -PIN\'e toegelaat word."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitor pogings om skerm te ontsluit"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Gebruik kortpad"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Kleuromkering"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Kleurkorreksie"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Het volumesleutels ingehou. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aangeskakel."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Het volumesleutels ingehou. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> is afgeskakel"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Druk en hou albei volumesleutels drie sekondes lank om <xliff:g id="SERVICE_NAME">%1$s</xliff:g> te gebruik"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-versoek is na video-oproep toe verander"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-versoek is na USSD-versoek toe verander"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Na nuwe SS-versoek toe verander"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Uitvissingwaarskuwing"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Werkprofiel"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Kennisgewing gegee"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Vou uit"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maksimeer"</string>
     <string name="close_button_text" msgid="10603510034455258">"Maak toe"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Antwoord"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Wys af"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Lui af"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Inkomende oproep"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Oproep aan die gang"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Keur tans \'n inkomende oproep"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> gekies</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> gekies</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Om voort te gaan, moet &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; toegang tot jou toestel se kamera hê."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Skakel aan"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Sensorprivaatheid"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 3161226..a43b29a 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ይህ መሣሪያ የጣት አሻራ ዳሳሽ የለውም።"</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"ዳሳሽ ለጊዜው ተሰናክሏል።"</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"ጣት <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"ለመቀጠል የእርስዎን የጣት አሻራ ይጠቀሙ"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"የጣት አሻራ አዶ"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"ከእንግዲህ ፊትን ለይቶ ማወቅ አይችልም። እንደገና ይሞክሩ።"</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"በጣም ይመሳሰላል፣ እባክዎ የእርስዎን ፎቶ አነሳስ ይለውጡ"</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"ጭንቅላትዎን ትንሽ ብቻ ያዙሩት።"</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"ጭንቅላትዎን ትንሽ ብቻ ያዙሩት።"</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"ጭንቅላትዎን ትንሽ ብቻ ያዙሩት።"</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"የእርስዎን ፊት የሚደብቀውን ሁሉንም ነገር በማስወገድ ላይ"</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"የማያ ገጽዎን አናት ያጽዱት፣ ጥቁር አሞሌውን ጨምሮ"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"መተግበሪያው የአትረብሽ ውቅረትን እንዲያነብብ እና እንዲጸፍ ይፈቅዳል።"</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"የእይታ ፈቃድ መጠቀምን መጀመር"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"ያዢው ለአንድ መተግበሪያ የፈቃድ አጠቃቀሙን እንዲያስጀምር ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ ሊያስፈልግ አይገባም።"</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"የዳሳሽ ውሂቡን በከፍተኛ የናሙና ብዛት ላይ ይድረሱበት"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"መተግበሪያው የዳሳሽ ውሂቡን ከ200 ኸ በሚበልጥ ፍጥነት ናሙና እንዲያደርግ ይፈቅድለታል"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"የይለፍ ቃል ደንቦች አዘጋጅ"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"በማያ ገጽ መቆለፊያ የይለፍ ቃሎች እና ፒኖች ውስጥ የሚፈቀዱ ቁምፊዎችን እና ርዝመታቸውን ተቆጣጠር።"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"የማሳያ-ክፈት ሙከራዎችን ክትትል ያድርጉባቸው"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"አቋራጭ ይጠቀሙ"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"ተቃራኒ ቀለም"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"የቀለም ማስተካከያ"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"የድምፅ ቁልፎችን ይዟል። <xliff:g id="SERVICE_NAME">%1$s</xliff:g> በርቷል።"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"የድምፅ ቁልፎችን ይዟል። <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ጠፍተዋል።"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>ን ለመጠቀም ለሦስት ሰከንዶች ሁለቱንም የድምፅ ቁልፎች ተጭነው ይያዙ"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"የSS ጥያቄ ወደ የቪዲዮ ጥሪ ተለውጧል"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"የSS ጥያቄ ወደ የUSSD ጥያቄ ተለውጧል"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"ወደ አዲስ የSS ጥያቄ ተለውጧል"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"የማስገር ማንቂያ"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"የስራ መገለጫ"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"ነቅተዋል"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"ዘርጋ"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"አስፋ"</string>
     <string name="close_button_text" msgid="10603510034455258">"ዝጋ"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>፦ <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"መልስ"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"አትቀበል"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"ስልኩን ዝጋ"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"ገቢ ጥሪ"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"እየተካሄደ ያለ ጥሪ"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"ገቢ ጥሪ ማጣራት"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ተመርጧል</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ተመርጠዋል</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"ለመቀጠል፣ &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; የመሣሪያዎን ካሜራ መድረስ ይፈልጋል።"</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"አብራ"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"ዳሳሽ ግላዊነት"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index a2d3671..3990bab 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -152,8 +152,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"‏Wi-Fi فقط"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <!-- no translation found for crossSimFormat_spn_cross_sim_calling (5620807020002879057) -->
-    <skip />
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"<xliff:g id="SPN">%s</xliff:g> الاتصال الاحتياطي"</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: لم تتم إعادة التوجيه"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> بعد <xliff:g id="TIME_DELAY">{2}</xliff:g> ثانية"</string>
@@ -592,6 +591,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"لا يحتوي هذا الجهاز على مستشعِر بصمات إصبع."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"تم إيقاف جهاز الاستشعار مؤقتًا."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"الإصبع <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"يمكنك استخدام بصمة الإصبع للمتابعة."</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"رمز بصمة الإصبع"</string>
@@ -618,7 +618,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"لم يعُد يمكن التعرّف على الوجه. حاول مرة أخرى."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"الوجه مشابه جدًا، يُرجى تغيير وضعيتك."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"حرّك رأسك قليلاً نحو الأمام مباشرة."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"حرّك رأسك قليلاً نحو الأمام مباشرة."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"حرّك رأسك قليلاً نحو الوسط."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"عليك بإزالة أي شيء يُخفي وجهك."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"يُرجى تنظيف الجزء العلوي من الشاشة، بما في ذلك الشريط الأسود."</string>
@@ -697,6 +698,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"للسماح للتطبيق بقراءة إعداد \"عدم الإزعاج\" وكتابتها."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"بدء استخدام إذن العرض"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"للسماح للمالك ببدء استخدام الإذن لأحد التطبيقات. ولن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"الوصول إلى بيانات جهاز الاستشعار بمعدّل مرتفع للبيانات في الملف الصوتي"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"يسمح هذا الأذن للتطبيق بزيادة بيانات جهاز الاستشعار بمعدّل بيانات في الملف الصوتي أكبر من 200 هرتز."</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"تعيين قواعد كلمة المرور"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"للتحكم في الطول والأحرف المسموح بها في كلمات المرور وأرقام التعريف الشخصي في قفل الشاشة."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"مراقبة محاولات فتح قفل الشاشة"</string>
@@ -1753,6 +1756,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"استخدام الاختصار"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"قلب الألوان"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"تصحيح الألوان"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"تم الضغط مع الاستمرار على مفتاحَي التحكّم في مستوى الصوت. تم تفعيل <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"تم الضغط مع الاستمرار على مفتاحَي التحكّم في مستوى الصوت. تم إيقاف <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"اضغط مع الاستمرار على مفتاحي مستوى الصوت لمدة 3 ثوانٍ لاستخدام <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
@@ -1992,6 +1997,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"‏تم تغيير طلب SS إلى مكالمة فيديو."</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"‏تم تغيير طلب SS إلى طلب USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"‏تم التغيير إلى طلب SS الجديد."</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"تنبيه بشأن تصيّد احتيالي"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"الملف الشخصي للعمل"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"تمّ تفعيل التنبيه"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"توسيع"</string>
@@ -2005,6 +2011,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"تكبير"</string>
     <string name="close_button_text" msgid="10603510034455258">"إغلاق"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"ردّ"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"رفض"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"قطع الاتصال"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"مكالمة واردة"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"مكالمة جارية"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"رصد مكالمة واردة"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="zero">تم اختيار <xliff:g id="COUNT_1">%1$d</xliff:g> عنصر</item>
       <item quantity="two">تم اختيار عنصرين (<xliff:g id="COUNT_1">%1$d</xliff:g>)</item>
@@ -2345,4 +2357,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"‏للمتابعة، يحتاج تطبيق &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; إلى الوصول إلى كاميرا الجهاز."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"تفعيل"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"الخصوصية في جهاز الاستشعار"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 0a9ef97..28af8a3 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -148,8 +148,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"কোৱল ৱাই-ফাই"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <!-- no translation found for crossSimFormat_spn_cross_sim_calling (5620807020002879057) -->
-    <skip />
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"<xliff:g id="SPN">%s</xliff:g> বেকআপ কলিং"</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ফৰৱাৰ্ড কৰা নহ\'ল"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> ছেকেণ্ডৰ পাছত"</string>
@@ -580,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"এই ডিভাইচটোত ফিংগাৰপ্ৰিণ্ট ছেন্সৰ নাই।"</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"ছেন্সৰটো সাময়িকভাৱে অক্ষম হৈ আছে।"</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"<xliff:g id="FINGERID">%d</xliff:g> আঙুলি"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"অব্যাহত ৰাখিবলৈ আপোনাৰ ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰক"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ফিংগাৰপ্ৰিণ্ট আইকন"</string>
@@ -606,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"মুখমণ্ডল আৰু চিনাক্ত কৰিব নোৱাৰি। আকৌ চেষ্টা কৰক।"</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"একে ধৰণৰ হৈছে, অনুগ্ৰহ কৰি আপোনাৰ প’জটো সলনি কৰক।"</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"আপোনাৰ মূৰটো সামান্য কমকৈ ঘূৰাওক।"</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"আপোনাৰ মূৰটো সামান্য কমকৈ ঘূৰাওক।"</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"আপোনাৰ মূৰটো সামান্য কমকৈ ঘূৰাওক।"</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"আপোনাৰ মুখখন ঢাকি ৰখা বস্তুবোৰ আঁতৰাওক।"</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"ক’লা বাৰডালকে ধৰি আপোনাৰ স্ক্রীণৰ ওপৰৰ অংশ চাফা কৰক"</string>
@@ -685,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"অসুবিধা নিদিবৰ কনফিগাৰেশ্বনক পঢ়িবলৈ আৰু সালসলনি কৰিবলৈ এপটোক অনুমতি দিয়ে।"</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"চোৱাৰ অনুমতিৰ ব্যৱহাৰ আৰম্ভ কৰক"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"ধাৰকক কোনো এপৰ বাবে অনুমতিৰ ব্যৱহাৰ আৰম্ভ কৰিবলৈ দিয়ে। সাধাৰণ এপ্‌সমূহৰ বাবে কেতিয়াও প্ৰয়োজন হ’ব নালাগে।"</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"এটা উচ্চ ছেম্পলিঙৰ হাৰত ছেন্সৰৰ ডেটা এক্সেছ কৰে"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"এপ্‌টোক ২০০ হাৰ্টজতকৈ অধিক হাৰত ছেন্সৰৰ ডেটাৰ নমুনা ল’বলৈ অনুমতি দিয়ে"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"পাছৱর্ডৰ নিয়ম ছেট কৰক"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"স্ক্ৰীণ লক পাছৱৰ্ড আৰু পিনৰ দৈর্ঘ্য আৰু কি কি আখৰ ব্যৱহাৰ কৰিব পাৰে তাক নিয়ন্ত্ৰণ কৰক।"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"স্ক্ৰীণ আনলক কৰা প্ৰয়াসবোৰ পৰ্যবেক্ষণ কৰিব পাৰে"</string>
@@ -1665,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"শ্বৰ্টকাট ব্যৱহাৰ কৰক"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"ৰং বিপৰীতকৰণ"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"ৰং শুধৰণী"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ভলিউম কীসমূহ ধৰি ৰাখক। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> অন কৰা হ\'ল।"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ভলিউম কী ধৰি ৰাখিছিল। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> অফ কৰা হ\'ল।"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ব্যৱহাৰ কৰিবলৈ দুয়োটা ভলিউম বুটাম তিনি ছেকেণ্ডৰ বাবে হেঁচি ৰাখক"</string>
@@ -1868,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS অনুৰোধ ভিডিঅ\' কললৈ সলনি কৰা হ’ল"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS অনুৰোধ USSD অনুৰোধলৈ সলনি কৰা হ’ল"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"নতুন SS অনুৰোধলৈ সলনি কৰা হ’ল"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"ফিশ্বিঙৰ সতৰ্কবাৰ্তা"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"কৰ্মস্থানৰ প্ৰ\'ফাইল"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"সতৰ্ক কৰা হ’ল"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"বিস্তাৰ কৰক"</string>
@@ -1881,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"সৰ্বাধিক মাত্ৰালৈ বঢ়াওক"</string>
     <string name="close_button_text" msgid="10603510034455258">"বন্ধ কৰক"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"উত্তৰ দিয়ক"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"প্ৰত্যাখ্যান কৰক"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"কল কাটি দিয়ক"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"অন্তৰ্গামী কল"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"চলি থকা কল"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"এটা অন্তৰ্গামী কলৰ পৰীক্ষা কৰি থকা হৈছে"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g>টা বাছনি কৰা হ’ল</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>টা বাছনি কৰা হ’ল</item>
@@ -2209,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"অব্যাহত ৰাখিবলৈ &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt;এ আপোনাৰ ডিভাইচৰ কেমেৰা এক্সেছ কৰাৰ আৱশ্যক।"</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"অন কৰক"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"ছেন্সৰ সম্পৰ্কীয় গোপনীয়তাৰ নীতি"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index e91e2b7..8459403 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -325,7 +325,7 @@
     <string name="permgroupdesc_sensors" msgid="2610631290633747752">"Həyati əlamətlər haqqında sensor dataya daxil olun"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Pəncərənin məzmununu əldə edin"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Əlaqədə olduğunuz pəncərənin məzmununu nəzərdən keçirin."</string>
-    <string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Toxunaraq Kəşf et funksiyasını yandırın"</string>
+    <string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Toxunuşla öyrənmə funksiyasını aktiv edin"</string>
     <string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"Tıklanan hissələr səsləndiriləcək və ekran jestlərlə idarə oluna biləcək."</string>
     <string name="capability_title_canRequestFilterKeyEvents" msgid="2772371671541753254">"Yazdığınız mətni izləyin"</string>
     <string name="capability_desc_canRequestFilterKeyEvents" msgid="2381315802405773092">"Kredit kartı nömrələri və parollar kimi şəxsi məlumatlar daxildir."</string>
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Bu cihazda barmaq izi sensoru yoxdur."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor müvəqqəti deaktivdir."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Barmaq <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Davam etmək üçün barmaq izinizi istifadə edin"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Barmaq izi ikonası"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Üzü artıq tanımaq olmur. Yenidən cəhd edin."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Digəri ilə oxşardır, pozanızı dəyişin."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Başınızı bir az döndərin."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Başınızı bir az döndərin."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Başınızı bir az döndərin."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Üzünüzü gizlədən maneələri kənarlaşdırın."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Qara panel daxil olmaqla, ekranın yuxarısını təmizləyin"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Tətbiqə \"Narahat Etməyin\" konfiqurasiyasını oxumağa və yazmağa icazə verin."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"Baxış icazəsinin istifadəsinə başlayın"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Sahibinə tətbiqin icazədən istifadəsinə başlamağa imkan verir. Adi tətbiqlər üçün heç vaxt tələb edilmir."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"sensor datasına yüksək ölçmə sürəti ilə giriş etmək"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Tətbiqə sensor datasını 200 Hz-dən yüksək sürətlə ölçməyə imkan verir"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Parol qaydalarını təyin edin"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Ekran kilidinin parolu və PINlərində icazə verilən uzunluq və simvollara nəzarət edin."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Ekranı kiliddən çıxarmaq üçün edilən cəhdlərə nəzarət edin"</string>
@@ -1629,7 +1633,7 @@
     <string name="kg_failed_attempts_now_wiping" product="tv" msgid="5045460916106267585">"Android TV cihazını kiliddən çıxarmaq üçün <xliff:g id="NUMBER">%d</xliff:g> dəfə yanlış cəhd etdiniz. Android TV cihazınız defolt fabrik dəyərlərinə sıfırlanacaq."</string>
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="5043730590446071189">"Siz telefonun kilidini açmaq üçün <xliff:g id="NUMBER">%d</xliff:g> yanlış cəhd etmisiniz. Telefon artıq defolt zavod halına sıfırlanacaq."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="7086799295109717623">"Siz kilidi açmaq üçün şablonu <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə səhv çəkdiniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> daha uğursuz cəhddən sonra planşetinizin kilidini e-poçt hesabınızla açmaq tələb olunacaq.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniyə ərzində bir daha yoxlayın."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4670840383567106114">"Kiliddən çıxarma modelini <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış çəkdiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> yanlış cəhddən sonra Android TV cihazını e-poçt hesabınızla kiliddən çıxarmağınız tələb olunacaq.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniyə sonra yenidən cəhd edin."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4670840383567106114">"Kiliddən çıxarma modelini <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış çəkdiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> yanlış cəhddən sonra Android TV cihazını e-poçt hesabınızla kiliddən çıxarmağınız tələb olunacaq.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniyə sonra cəhd edin."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Siz artıq modeli <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış daxil etmisiniz.<xliff:g id="NUMBER_1">%2$d</xliff:g> dəfə də yanlış daxil etsəniz, telefonun kilidinin açılması üçün elektron poçt ünvanınız tələb olunacaq.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniyə ərzində yenidən cəhd edin."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" - "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Yığışdır"</string>
@@ -1637,10 +1641,10 @@
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Əlçatımlılıq Qısayolu istifadə edilsin?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Qısayol aktiv olduqda, hər iki səs düyməsinə 3 saniyə basıb saxlamaqla əlçatımlılıq funksiyası başladılacaq."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Əlçatımlılıq funksiyaları üçün qısayol aktiv edilsin?"</string>
-    <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Hər iki səs səviyyəsi düyməsinə bir neçə saniyə basıb saxladıqda əlçatımlılıq funksiyaları aktiv olur. Bu, cihazınızın işləmə qaydasını dəyişə bilər.\n\nCari funksiyalar:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nAyarlar və Əlçatımlılıq bölməsində seçilmiş funksiyaları dəyişə bilərsiniz."</string>
+    <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Hər iki səs səviyyəsi düyməsinə bir neçə saniyə basıb saxladıqda əlçatımlılıq funksiyaları aktiv olur. Cihazınızın işləmə qaydasını dəyişə bilər.\n\nCari funksiyalar:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nAyarlar və Əlçatımlılıq bölməsində seçilmiş funksiyaları dəyişə bilərsiniz."</string>
     <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> qısayolu aktiv edilsin?"</string>
-    <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Hər iki səs səviyyəsi düyməsinə bir neçə saniyə basıb saxladıqda əlçatımlılıq funksiyası olan <xliff:g id="SERVICE">%1$s</xliff:g> aktiv olur. Bu, cihazınızın işləmə qaydasını dəyişə bilər.\n\nAyarlar və Əlçatımlılıq bölməsində bu qısayolu başqa bir funksiyata dəyişə bilərsiniz."</string>
+    <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Hər iki səs səviyyəsi düyməsinə bir neçə saniyə basıb saxladıqda əlçatımlılıq funksiyası olan <xliff:g id="SERVICE">%1$s</xliff:g> aktiv olur. Cihazınızın işləmə qaydasını dəyişə bilər.\n\nAyarlar və Əlçatımlılıq bölməsində bu qısayolu başqa bir funksiyaya dəyişə bilərsiniz."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Aktiv edin"</string>
     <string name="accessibility_shortcut_off" msgid="3651336255403648739">"Aktiv etməyin"</string>
     <string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"AKTİV"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Qısayol İstifadə edin"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Rəng İnversiyası"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Rəng korreksiyası"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Səs səviyyəsi düymələrinə basıb saxlayın. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aktiv edildi."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Səs səviyyəsi düymələrinə basılaraq saxlanıb. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> deaktiv edilib."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> istifadə etmək üçün hər iki səs düyməsini üç saniyə basıb saxlayın"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS sorğusu video zəngə dəyişdirildi"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS sorğusu USSD sorğusuna dəyişdirildi"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Yeni SS sorğusuna dəyişdirildi"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Fişinq siqnalı"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"İş profili"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Xəbərdarlıq edildi"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Genişləndirin"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Böyüdün"</string>
     <string name="close_button_text" msgid="10603510034455258">"Qapadın"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Cavab verin"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"İmtina edin"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Dəstəyi asın"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Gələn zəng"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Davam edən zəng"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Gələn zəng göstərilir"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> seçilib</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> seçilib</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Davam etmək üçün &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; tətbiqi cihazın kamerasına giriş tələb edir."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Aktiv edin"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Sensor Məxfiliyi"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index a490a6c..a7f6433 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -582,6 +582,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Ovaj uređaj nema senzor za otisak prsta."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Senzor je privremeno onemogućen."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Nastavite pomoću otiska prsta"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona otiska prsta"</string>
@@ -608,7 +609,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Više ne može da se prepozna lice. Probajte ponovo."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Previše je slično, promenite pozu."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Malo manje pomerite glavu."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Malo manje pomerite glavu."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Malo manje pomerite glavu."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Uklonite sve što vam zaklanja lice."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Očistite gornji deo ekrana, uključujući crnu traku"</string>
@@ -687,6 +689,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Dozvoljava aplikaciji da čita i upisuje konfiguraciju podešavanja Ne uznemiravaj."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"početak korišćenja dozvole za pregled"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Dozvoljava vlasniku da započne korišćenje dozvole za aplikaciju. Nikada ne bi trebalo da bude potrebna za uobičajene aplikacije."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"pristup podacima senzora pri velikoj brzini uzorkovanja"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Dozvoljava aplikaciji da uzima uzorak podataka senzora pri brzini većoj od 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Podešavanje pravila za lozinku"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Kontroliše dužinu i znakove dozvoljene u lozinkama i PIN-ovima za zaključavanje ekrana."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Nadgledajte pokušaje otključavanja ekrana"</string>
@@ -1686,6 +1690,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Koristi prečicu"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inverzija boja"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Korekcija boja"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Držali ste tastere za jačinu zvuka. Usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je uključena."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Držali ste tastere za jačinu zvuka. Usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je isključena."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pritisnite i zadržite oba tastera za jačinu zvuka tri sekunde da biste koristili <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1898,6 +1904,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS zahtev je promenjen u video poziv"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS zahtev je promenjen u USSD zahtev"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Promenjeno je u novi SS zahtev"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Upozorenje o „pecanju“"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Poslovni profil"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Obavešteno"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Proširi"</string>
@@ -1911,6 +1918,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Uvećaj"</string>
     <string name="close_button_text" msgid="10603510034455258">"Zatvori"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Odgovori"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Odbij"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Prekini vezu"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Dolazni poziv"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Poziv je u toku"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Proverava se dolazni poziv"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one">Izabrana je <xliff:g id="COUNT_1">%1$d</xliff:g> stavka</item>
       <item quantity="few">Izabrane su <xliff:g id="COUNT_1">%1$d</xliff:g> stavke</item>
@@ -2242,4 +2255,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"&lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; zahteva pristup kameri uređaja radi nastavljanja."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Uključi"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Privatnost senzora"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 80f67d0..1022cef 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -150,8 +150,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Толькі Wi-Fi"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <!-- no translation found for crossSimFormat_spn_cross_sim_calling (5620807020002879057) -->
-    <skip />
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"Рэзервовае капіраванне выклікаў праз аператара \"<xliff:g id="SPN">%s</xliff:g>\""</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: не пераадрасоўваецца"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> праз <xliff:g id="TIME_DELAY">{2}</xliff:g> с."</string>
@@ -586,6 +585,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"На гэтай прыладзе няма сканера адбіткаў пальцаў."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Датчык часова выключаны."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Палец <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Каб працягнуць, выкарыстоўвайце свой адбітак пальца"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Значок адбіткаў пальцаў"</string>
@@ -612,7 +612,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Не ўдаецца распазнаць твар. Паўтарыце спробу."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Не бачна розніцы. Памяняйце позу."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Вы занадта моцна павярнулі галаву."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Галава не ў цэнтры."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Вы занадта моцна павярнулі галаву."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Прыміце ўсё, што закрывае ваш твар."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Ачысціце ад бруду верхнюю частку экрана, у тым ліку чорную панэль"</string>
@@ -691,6 +692,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Дазваляе праграме чытаць і выконваць запіс у канфігурацыю рэжыму «Не турбаваць»."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"запусціць выкарыстанне дазволаў на прагляд"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Дазваляе трымальніку запусціць выкарыстанне дазволаў праграмай. Не патрэбна для звычайных праграм."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"атрымліваць даныя датчыка з высокай частатой дыскрэтызацыі"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Праграма зможа распазнаваць даныя датчыка з частатой звыш 200 Гц"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Устанавіць правілы паролю"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Кіраваць даўжынёй і сімваламі, дазволенымі пры ўводзе пароляў і PIN-кодаў блакіроўкі экрана."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Сачыць за спробамі разблакіроўкі экрана"</string>
@@ -791,7 +794,7 @@
     <string name="eventTypeAnniversary" msgid="4684702412407916888">"Гадавіна"</string>
     <string name="eventTypeOther" msgid="530671238533887997">"Іншае"</string>
     <string name="emailTypeCustom" msgid="1809435350482181786">"Карыстальніцкая"</string>
-    <string name="emailTypeHome" msgid="1597116303154775999">"Хатні"</string>
+    <string name="emailTypeHome" msgid="1597116303154775999">"Асабістая"</string>
     <string name="emailTypeWork" msgid="2020095414401882111">"Працоўная"</string>
     <string name="emailTypeOther" msgid="5131130857030897465">"Іншая"</string>
     <string name="emailTypeMobile" msgid="787155077375364230">"Мабільны"</string>
@@ -1709,6 +1712,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Выкарыстоўваць камбінацыю хуткага доступу"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Інверсія колеру"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Карэкцыя колеру"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Клавішы гучнасці ўтрымліваліся націснутымі. Уключана служба \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\"."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Клавішы гучнасці ўтрымліваліся націснутымі. Служба \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\" выключана."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Каб карыстацца сэрвісам \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\", націсніце і ўтрымлівайце на працягу трох секунд абедзве клавішы гучнасці"</string>
@@ -1930,6 +1935,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-запыт заменены на відэавыклік"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-запыт заменены на USSD-запыт"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Зроблена замена на новы SS-запыт"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Абвестка пра фішынг"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Працоўны профіль"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"З гукам"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Разгарнуць"</string>
@@ -1943,6 +1949,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Разгарнуць"</string>
     <string name="close_button_text" msgid="10603510034455258">"Закрыць"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Адказаць"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Адхіліць"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Завяршыць"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Уваходны выклік"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Бягучы выклік"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Фільтраванне ўваходнага выкліку"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> выбраны</item>
       <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> выбрана</item>
@@ -2277,4 +2289,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Каб працягнуць, дайце праграме &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; доступ да камеры прылады."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Уключыць"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Прыватнасць інфармацыі з датчыка"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 20342e0..ef20bad 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Това устройство няма сензор за отпечатъци."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Сензорът е временно деактивиран."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Пръст <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Използвайте отпечатъка си, за да продължите"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Икона за отпечатък"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Лицето не бе разпознато. Опитайте отново."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Позата ви е сходна с предишна. Моля, променете я."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Не завъртайте главата си толкова много."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Не завъртайте главата си толкова много."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Не завъртайте главата си толкова много."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Премахнете всичко, което закрива лицето ви."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Почистете горната част на екрана си, включително черната лента"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Предоставя на приложението достъп за четене и запис до конфигурацията на „Не безпокойте“."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"стартиране на прегледа на използваните разрешения"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Разрешава на притежателя да стартира прегледа на използваните разрешения за дадено приложение. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"осъществяване на достъп до данните от сензорите при висока скорост на семплиране"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Разрешава на приложението да семплира данните от сензорите със скорост, по-висока от 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Задаване на правила за паролата"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Контролира дължината и разрешените знаци за паролите и ПИН кодовете за заключване на екрана."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Наблюдаване на опитите за отключване на екрана"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Използване на пряк път"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Инвертиране на цветовете"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Коригиране на цветовете"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Задържахте бутоните за силата на звука. Услугата <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е включена."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Задържахте бутоните за силата на звука. Услугата <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е изключена."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"За да използвате <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, натиснете двата бутона за силата на звука и ги задръжте за 3 секунди"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS заявката е променена на видеообаждане"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS заявката е променена на USSD заявка"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Променено на нова SS заявка"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Сигнал за фишинг"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Служебен потребителски профил"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Сигналът е изпратен"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Разгъване"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Увеличаване"</string>
     <string name="close_button_text" msgid="10603510034455258">"Затваряне"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"„<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>“: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Отговор"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Отхвърляне"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Затваряне"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Входящо обаждане"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Текущо обаждане"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Преглежда се входящо обаждане"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other">Избрахте <xliff:g id="COUNT_1">%1$d</xliff:g></item>
       <item quantity="one">Избрахте <xliff:g id="COUNT_0">%1$d</xliff:g></item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"За да продължите, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; се нуждае от достъп до камерата на устройството ви."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Включване"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Поверителност на сензорните данни"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 51d09b2..0e30c04 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -148,8 +148,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"শুধুমাত্র ওয়াই-ফাই"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <!-- no translation found for crossSimFormat_spn_cross_sim_calling (5620807020002879057) -->
-    <skip />
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"<xliff:g id="SPN">%s</xliff:g> ব্যাক-আপ কলিং"</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ফরওয়ার্ড করা হয়নি"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> সেকেন্ড পরে"</string>
@@ -580,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"এই ডিভাইসে আঙ্গুলের ছাপ নেওয়ার সেন্সর নেই।"</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"সেন্সর অস্থায়ীভাবে বন্ধ করা আছে।"</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"আঙ্গুল <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"চালিয়ে যেতে আঙ্গুলের ছাপ ব্যবহার করুন"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"আঙ্গুলের ছাপ আইকন"</string>
@@ -606,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"আর মুখ চিনতে পারবেন না। আবার চেষ্টা করুন।"</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"একই ধরনের দেখতে, একটু অন্যদিকে ঘুরে দাঁড়ান।"</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"আপনার মাথাটি নিচের দিকে সামান্য নামান।"</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"আপনার মাথাটি নিচের দিকে সামান্য নামান।"</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"আপনার মাথাটি সামান্য ঘোরান।"</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"আপনার ফেসকে আড়াল করে এমন সব কিছু সরিয়ে দিন।"</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"ব্ল্যাক বার সহ আপনার স্ক্রিনের উপরের অংশ মুছে ফেলুন"</string>
@@ -685,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"অ্যাপটিকে \'বিরক্ত করবে না\' কনফিগারেশন পড়া এবং লেখার অনুমতি দেয়।"</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"দেখার অনুমতি কাজে লাগানো শুরু করুন"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"কোনও অ্যাপের কোনও নির্দিষ্ট অনুমতির ব্যবহার শুরু করার ক্ষেত্রে হোল্ডারকে সাহায্য করে। সাধারণ অ্যাপের জন্য এটির পরিবর্তন হওয়ার কথা নয়।"</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"হাই স্যাম্পলিং রেটে সেন্সর ডেটা অ্যাক্সেস করুন"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"200 Hz-এর বেশি রেটে অ্যাপকে স্যাম্পল সেন্সর ডেটার জন্য অনুমতি দিন"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"পাসওয়ার্ড নিয়মগুলি সেট করে"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"স্ক্রিন লক করার পাসওয়ার্ডগুলিতে অনুমতিপ্রাপ্ত অক্ষর এবং দৈর্ঘ্য নিয়ন্ত্রণ করে৷"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"স্ক্রিন আনলক করার প্রচেষ্টাগুলির উপরে নজর রাখুন"</string>
@@ -1665,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"শর্টকাট ব্যবহার করুন"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"রঙ উল্টানো"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"রঙ সংশোধন"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ভলিউম কী ধরে ছিলেন। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> চালু করা হয়েছে।"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ভলিউম কী ধরে ছিলেন। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> বন্ধ করা হয়েছে।"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ব্যবহার করতে ভলিউম কী বোতাম ৩ সেকেন্ডের জন্য চেপে ধরে রাখুন"</string>
@@ -1868,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS অনুরোধ ভিডিও কলে পরিবর্তন করা হয়েছে"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS অনুরোধ USSD অনুরোধে পরিবর্তন করা হয়েছে"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"নতুন SS অনুরোধে পরিবর্তন করা হয়েছে"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"ফিশিংয়ের সতর্কতা"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"কর্মস্থলের প্রোফাইল"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"সতর্ক করা হয়েছে"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"বড় করুন"</string>
@@ -1881,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"বড় করুন"</string>
     <string name="close_button_text" msgid="10603510034455258">"বন্ধ করুন"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"উত্তর"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"বাতিল করুন"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"কল কেটে দেওয়া"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"ইনকামিং কল"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"চালু থাকা কল"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"ইনকামিং কল স্ক্রিনিং করা হচ্ছে"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g>টি নির্বাচন করা হয়েছে</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>টি নির্বাচন করা হয়েছে</item>
@@ -2209,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"চালিয়ে যেতে, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; আপনার ডিভাইসের ক্যামেরা অ্যাক্সেস করতে চায়।"</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"চালু করুন"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"সেন্সর গোপনীয়তা"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 989e2bb..77b64b5 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -582,6 +582,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Ovaj uređaj nema senzor za otisak prsta."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Senzor je privremeno onemogućen."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Nastavite pomoću otiska prsta"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona za otisak prsta"</string>
@@ -608,7 +609,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Više nije moguće prepoznati lice. Pokušajte opet."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Previše slično, promijenite položaj."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Malo manje zakrenite glavu."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Malo manje zakrenite glavu."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Malo manje zakrenite glavu."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Uklonite prepreke koje blokiraju vaše lice."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Očistite vrh ekrana, uključujući crnu traku"</string>
@@ -687,6 +689,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Omogućava aplikaciji da čita i upisuje konfiguraciju načina rada Ne ometaj."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"pokrenuti korištenje odobrenja za pregled"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Dozvoljava vlasniku da pokrene korištenje odobrenja za aplikaciju. Ne bi trebalo biti potrebno za obične aplikacije."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"pristup podacima senzora velikom brzinom uzorkovanja"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Dozvoljava aplikaciji da uzorkuje podatke senzora brzinom većom od 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Postavljanje pravila za lozinke"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Kontrolira dužinu i znakove koji su dozvoljeni u lozinkama za zaključavanje ekrana i PIN-ovima."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Prati pokušaje otključavanja ekrana"</string>
@@ -1686,6 +1690,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Koristi prečicu"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inverzija boja"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Ispravka boja"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Držali ste tipke za jačinu zvuka. Usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je uključena."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Držali ste tipke za jačinu zvuka. Usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je isključena."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pritisnite obje tipke za podešavanje jačine zvuka i držite ih pritisnutim tri sekunde da koristite uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1898,6 +1904,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS zahtjev je promijenjen u video poziv"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS zahtjev je promijenjen u USSD zahtjev"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Promijenjeno u novi SS zahtjev"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Upozorenje o krađi identiteta"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Profil za posao"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Upozoreni"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Proširi"</string>
@@ -1911,6 +1918,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Povećaj maksimalno"</string>
     <string name="close_button_text" msgid="10603510034455258">"Zatvori"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Odgovori"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Odbaci"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Prekini vezu"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Dolazni poziv"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Poziv u toku"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Filtriranje dolaznog poziva"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> stavka je odabrana</item>
       <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> stavke su odabrane</item>
@@ -2242,4 +2255,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Da nastavite, aplikaciji &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; je potreban pristup kameri vašeg uređaja."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Uključi"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Privatnost senzora"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index e9c55d7..a226ac3 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -538,10 +538,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"Permet que l\'aplicació conegui el nivell de complexitat del bloqueig de pantalla (alt, mitjà, baix o cap), que indica la llargària i el tipus de bloqueig de pantalla possibles. L\'aplicació també pot suggerir que els usuaris actualitzin el bloqueig de pantalla a un nivell determinat, però els usuaris poden ignorar aquestes recomanacions. Tingues en compte que el bloqueig de pantalla no s\'emmagatzema com a text sense format, de manera que l\'aplicació no coneix la contrasenya exacta."</string>
     <string name="permlab_useBiometric" msgid="6314741124749633786">"utilitza maquinari biomètric"</string>
     <string name="permdesc_useBiometric" msgid="7502858732677143410">"Permet que l\'aplicació faci servir maquinari biomètric per a l\'autenticació"</string>
-    <string name="permlab_manageFingerprint" msgid="7432667156322821178">"Gestionar el maquinari d\'empremtes dactilars"</string>
+    <string name="permlab_manageFingerprint" msgid="7432667156322821178">"Gestionar el maquinari d\'empremtes digitals"</string>
     <string name="permdesc_manageFingerprint" msgid="2025616816437339865">"Permet que l\'aplicació invoqui mètodes per afegir i suprimir plantilles d\'empremtes dactilars que es puguin fer servir."</string>
-    <string name="permlab_useFingerprint" msgid="1001421069766751922">"Utilitzar el maquinari d\'empremtes dactilars"</string>
-    <string name="permdesc_useFingerprint" msgid="412463055059323742">"Permet que l\'aplicació faci servir maquinari d\'empremtes dactilars per a l\'autenticació"</string>
+    <string name="permlab_useFingerprint" msgid="1001421069766751922">"Utilitzar el maquinari d\'empremtes digitals"</string>
+    <string name="permdesc_useFingerprint" msgid="412463055059323742">"Permet que l\'aplicació faci servir maquinari d\'empremtes digitals per a l\'autenticació"</string>
     <string name="permlab_audioWrite" msgid="8501705294265669405">"modificar la teva col·lecció de música"</string>
     <string name="permdesc_audioWrite" msgid="8057399517013412431">"Permet que l\'aplicació modifiqui la teva col·lecció de música."</string>
     <string name="permlab_videoWrite" msgid="5940738769586451318">"modificar la teva col·lecció de vídeos"</string>
@@ -567,7 +567,7 @@
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"L\'empremta digital s\'ha autenticat"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Cara autenticada"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Cara autenticada; prem el botó per confirmar"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"El maquinari per a empremtes dactilars no està disponible."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"El maquinari d\'empremtes digitals no està disponible."</string>
     <string name="fingerprint_error_no_space" msgid="6126456006769817485">"L\'empremta digital no es pot desar. Suprimeix-ne una."</string>
     <string name="fingerprint_error_timeout" msgid="2946635815726054226">"S\'ha esgotat el temps d\'espera per a l\'empremta digital. Torna-ho a provar."</string>
     <string name="fingerprint_error_canceled" msgid="540026881380070750">"S\'ha cancel·lat l\'operació d\'empremta digital."</string>
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Aquest dispositiu no té sensor d\'empremtes dactilars."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"El sensor està desactivat temporalment."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Dit <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Fes servir l\'empremta digital per continuar"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icona d\'empremta digital"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Ja no es reconeix la teva cara. Torna-ho a provar."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"És massa semblant; canvia de postura."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"No giris tant el cap."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"No inclinis tant el cap."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"No giris tant el cap."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Suprimeix qualsevol cosa que amagui la teva cara."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Neteja la part superior de la pantalla, inclosa la barra negra"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Permet que l\'aplicació llegeixi la configuració No molestis i hi escrigui."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"comença a utilitzar el permís de visualització"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Permet que un propietari comenci a utilitzar el permís amb una aplicació. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"accedir a les dades del sensor a una freqüència de mostratge alta"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Permet que l\'aplicació dugui a terme un mostratge de les dades del sensor a una freqüència superior a 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Definir les normes de contrasenya"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Permet controlar la longitud i el nombre de caràcters permesos a les contrasenyes i als PIN del bloqueig de pantalla."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Supervisar els intents de desbloqueig de la pantalla"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilitza la drecera"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversió de colors"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Correcció de color"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"S\'han mantingut premudes les tecles de volum. S\'ha activat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"S\'han mantingut premudes les tecles de volum. S\'ha desactivat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Mantén premudes les dues tecles de volum durant 3 segons per fer servir <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"La sol·licitud SS s\'ha canviat per una videotrucada"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"La sol·licitud SS s\'ha canviat per una sol·licitud USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"S\'ha canviat a una nova sol·licitud SS"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Alerta de pesca de credencials"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Perfil de treball"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"S\'ha enviat una alerta"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Desplega"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maximitza"</string>
     <string name="close_button_text" msgid="10603510034455258">"Tanca"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Respon"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Rebutja"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Penja"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Trucada entrant"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Trucada en curs"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"S\'està filtrant una trucada entrant"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other">Seleccionats: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
       <item quantity="one">Seleccionats: <xliff:g id="COUNT_0">%1$d</xliff:g></item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Per continuar, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; necessita accedir a la càmera del dispositiu."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Activa"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Privadesa dels sensors"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 071bbfd..fdb2ff1 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -585,6 +585,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Toto zařízení nemá snímač otisků prstů."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Senzor je dočasně deaktivován."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Pokračujte přiložením prstu"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona otisku prstů"</string>
@@ -611,7 +612,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Obličej už nelze rozpoznat. Zkuste to znovu."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Příliš podobné, změňte výraz."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Natočte hlavu o něco méně."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Natočte hlavu o něco méně."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Natočte hlavu o něco méně."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Odstraňte vše, co vám zakrývá obličej."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Očistěte horní část obrazovky včetně černé části"</string>
@@ -690,6 +692,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Umožňuje aplikaci číst a zapisovat konfiguraci režimu Nerušit."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"zahájení zobrazení využití oprávnění"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Umožňuje přístup zahájit využití oprávnění jiné aplikace. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"přístup k datům ze senzorů s vyšší vzorkovací frekvencí"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Umožňuje aplikaci vzorkovat data ze senzorů s frekvencí vyšší než 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Nastavit pravidla pro heslo"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Ovládání délky a znaků povolených v heslech a kódech PIN zámku obrazovky."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Sledovat pokusy o odemknutí obrazovky"</string>
@@ -1708,6 +1712,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Použít zkratku"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Převrácení barev"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Oprava barev"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Byla podržena tlačítka hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je zapnutá."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Byla podržena tlačítka hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> byla vypnuta."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Chcete-li používat službu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, tři sekundy podržte stisknutá obě tlačítka hlasitosti"</string>
@@ -1929,6 +1935,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Požadavek SS byl změněn na videohovor"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Požadavek SS byl změněn na požadavek USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Změněno na nový požadavek SS"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Upozornění na phishing"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Pracovní profil"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Upozorněno"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Rozbalit"</string>
@@ -1942,6 +1949,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maximalizovat"</string>
     <string name="close_button_text" msgid="10603510034455258">"Zavřít"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Přijmout"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Odmítnout"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Zavěsit"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Příchozí hovor"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Probíhající hovor"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Prověřování příchozího hovoru"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> položky</item>
       <item quantity="many"><xliff:g id="COUNT_1">%1$d</xliff:g> položky</item>
@@ -2276,4 +2289,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Než budete pokračovat, udělte aplikaci &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; přístup k fotoaparátu na zařízení."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Zapnout"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Ochrana soukromí – senzor"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index b760f5b..dddc070 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -148,7 +148,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Kun Wi-Fi"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"Alternativ løsning til opkald leveret af <xliff:g id="SPN">%s</xliff:g>"</string>
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"<xliff:g id="SPN">%s</xliff:g>-opkald via alternativt SIM"</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Ikke viderestillet"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> efter <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunder"</string>
@@ -581,6 +581,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Denne enhed har ingen fingeraftrykslæser."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensoren er midlertidigt deaktiveret."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Fingeraftryk <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Brug dit fingeraftryk for at fortsætte"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon for fingeraftryk"</string>
@@ -607,7 +608,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Ansigtet kan ikke længere genkendes. Prøv igen."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Det minder for meget om et andet. Skift stilling."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Du skal ikke dreje hovedet så meget."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Du skal ikke dreje hovedet så meget."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Du skal ikke dreje hovedet så meget."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Hvis noget skjuler dit ansigt, skal du fjerne det."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Rengør toppen af din skærm, inkl. den sorte bjælke"</string>
@@ -686,6 +688,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Giver appen tilladelse til at læse og redigere konfigurationen af Forstyr ikke."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"start brugen at tilladelsesvisning"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Tillader, at brugeren kan bruge en tilladelse for en app. Dette bør aldrig være nødvendigt for almindelige apps."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"få adgang til sensordata ved høj samplingfrekvens"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Tillader, at appen kan sample sensordata ved en højere frekvens end 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Angiv regler for adgangskoder"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Tjek længden samt tilladte tegn i adgangskoder og pinkoder til skærmlåsen."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Overvåg forsøg på oplåsning af skærm"</string>
@@ -1666,6 +1670,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Brug genvej"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Ombytning af farver"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Korriger farve"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Lydstyrkeknapperne blev holdt nede. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er aktiveret."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Lydstyrkeknapperne blev holdt nede. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er deaktiveret."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Hold begge lydstyrkeknapper nede i tre sekunder for at bruge <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1869,6 +1875,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-anmodningen blev ændret til et videoopkald"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-anmodningen blev ændret til en USSD-anmodning"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Ændret til en SS-anmodning"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Phishingadvarsel"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Arbejdsprofil"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Underrettet"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Udvid"</string>
@@ -1882,6 +1889,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maksimér"</string>
     <string name="close_button_text" msgid="10603510034455258">"Luk"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Besvar"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Afvis"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Læg på"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Indgående opkald"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Igangværende opkald"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Et indgående opkald screenes"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g>valgt</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> valgt</item>
@@ -2210,4 +2223,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"&lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; skal have adgang til din enheds kamera, før den kan fortsætte."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Aktivér"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Beskyttelse af sensoroplysninger"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index f8066e2..472f1d2 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -148,8 +148,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Nur WLAN"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <!-- no translation found for crossSimFormat_spn_cross_sim_calling (5620807020002879057) -->
-    <skip />
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"<xliff:g id="SPN">%s</xliff:g>-Anruf über Ersatz-SIM"</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nicht weitergeleitet"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g><xliff:g id="DIALING_NUMBER">{1}</xliff:g> nach <xliff:g id="TIME_DELAY">{2}</xliff:g> Sekunden."</string>
@@ -580,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Dieses Gerät hat keinen Fingerabdrucksensor."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Der Sensor ist vorübergehend deaktiviert."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Mithilfe deines Fingerabdrucks fortfahren"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerabdruck-Symbol"</string>
@@ -606,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Gesicht wird nicht mehr erkannt. Erneut versuchen."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Zu ähnlich. Bitte dreh deinen Kopf etwas."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Dreh den Kopf etwas weniger zur Seite."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Neig den Kopf etwas weniger stark."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Neig den Kopf etwas weniger stark."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Entferne alles, was dein Gesicht verdeckt."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Reinige den oberen Teil deines Bildschirms, einschließlich der schwarzen Leiste"</string>
@@ -685,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Ermöglicht der App Lese- und Schreibzugriff auf die \"Bitte nicht stören\"-Konfiguration"</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"Mit der Verwendung der Anzeigeberechtigung beginnen"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Ermöglicht dem Inhaber, die Berechtigungsnutzung für eine App zu beginnen. Sollte für normale Apps nie benötigt werden."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"Sensordaten mit hoher Frequenz auslesen"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Erlaubt der App, Sensordaten mit einer Frequenz von mehr als 200 Hz auszulesen"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Passwortregeln festlegen"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Zulässige Länge und Zeichen für Passwörter für die Displaysperre festlegen"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Versuche zum Entsperren des Displays überwachen"</string>
@@ -1665,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Verknüpfung verwenden"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Farbumkehr"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Farbkorrektur"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Lautstärketasten wurden gedrückt gehalten. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ist aktiviert."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Lautstärketasten wurden gedrückt gehalten. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ist deaktiviert."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Halten Sie beide Lautstärketasten drei Sekunden lang gedrückt, um <xliff:g id="SERVICE_NAME">%1$s</xliff:g> zu verwenden"</string>
@@ -1868,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-Anfrage wurde in Videoanruf geändert"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-Anfrage wurde in USSD-Anfrage geändert"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"In neue SS-Anfrage geändert"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Phishing-Warnung"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Arbeitsprofil"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Gewarnt"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Maximieren"</string>
@@ -1881,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maximieren"</string>
     <string name="close_button_text" msgid="10603510034455258">"Schließen"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Annehmen"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Ablehnen"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Auflegen"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Eingehender Anruf"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Aktueller Anruf"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Screening für eingehenden Anruf"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ausgewählt</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ausgewählt</item>
@@ -2209,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Zum Fortfahren benötigt &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; Zugriff auf die Kamera deines Geräts."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Aktivieren"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Datenschutz für Sensoren"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 4f3c8a9..22b3401 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Αυτή η συσκευή δεν διαθέτει αισθητήρα δακτυλικού αποτυπώματος."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Ο αισθητήρας απενεργοποιήθηκε προσωρινά."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Δάχτυλο <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Χρησιμοποιήστε το δακτυλικό αποτύπωμά σας για να συνεχίσετε"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Εικονίδιο δακτυλικών αποτυπωμάτων"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Αδύνατη η αναγνώριση του προσώπου. Επανάληψη."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Πολύ παρόμοιο, αλλάξτε την πόζα σας."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Στρέψτε λιγότερο το κεφάλι σας."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Στρέψτε λιγότερο το κεφάλι σας."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Στρέψτε λιγότερο το κεφάλι σας."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Απομακρύνετε οτιδήποτε κρύβει το πρόσωπό σας."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Καθαρίστε το επάνω μέρος της οθόνης σας, συμπεριλαμβανομένης της μαύρης γραμμής"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Επιτρέπει στην εφαρμογή την εγγραφή και τη σύνταξη διαμόρφωσης για τη λειτουργία \"Μην ενοχλείτε\"."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"έναρξη χρήσης άδειας προβολής"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Επιτρέπει στον κάτοχο να ξεκινήσει τη χρήση της άδειας για μια εφαρμογή. Δεν απαιτείται ποτέ για κανονικές εφαρμογές."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"πρόσβαση σε δεδομένα αισθητήρα με υψηλό ρυθμό δειγματοληψίας"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Επιτρέπει στην εφαρμογή τη δειγματοληψία των δεδομένων αισθητήρα με ρυθμό μεγαλύτερο από 200 Hz."</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Ορισμός κανόνων κωδικού πρόσβασης"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Ελέγξτε την έκταση και τους επιτρεπόμενους χαρακτήρες σε κωδικούς πρόσβασης κλειδώματος οθόνης και PIN."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Παρακολούθηση προσπαθειών ξεκλειδώματος οθόνης"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Χρήση συντόμευσης"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Αντιστροφή χρωμάτων"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Διόρθωση χρωμάτων"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Τα πλήκτρα έντασης είναι πατημένα. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ενεργοποιήθηκε."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Τα πλήκτρα έντασης είναι πατημένα. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>: απενεργοποιημένο"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Πατήστε παρατεταμένα και τα δύο κουμπιά έντασης ήχου για τρία δευτερόλεπτα, ώστε να χρησιμοποιήσετε την υπηρεσία <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Το αίτημα SS τροποποιήθηκε σε βιντεοκλήση"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Το αίτημα SS τροποποιήθηκε σε αίτημα USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Τροποποιήθηκε σε νέο αίτημα SS"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Ειδοποίηση ηλεκτρονικού ψαρέματος (phishing)"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Προφίλ εργασίας"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Ειδοποιήθηκε"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Ανάπτυξη"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Μεγιστοποίηση"</string>
     <string name="close_button_text" msgid="10603510034455258">"Κλείσιμο"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Απάντηση"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Απόρριψη"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Τερματισμός"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Εισερχόμενη κλήση"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Κλήση σε εξέλιξη"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Διαλογή εισερχόμενης κλήσης"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other">Επιλέχτηκαν <xliff:g id="COUNT_1">%1$d</xliff:g></item>
       <item quantity="one">Επιλέχτηκε <xliff:g id="COUNT_0">%1$d</xliff:g></item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Για να συνεχίσετε, η εφαρμογή &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; χρειάζεται πρόσβαση στην κάμερα της συσκευής σας."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Ενεργοποίηση"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Απόρρητο αισθητήρα"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 9f3bc7d..f2cbb75 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"This device does not have a fingerprint sensor."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor temporarily disabled."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Use your fingerprint to continue"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerprint icon"</string>
@@ -605,7 +606,7 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"No longer able to recognise face. Try again."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Too similar, please change your pose."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Turn your head a little less."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Turn your head a little less."</string>
+    <string name="face_acquired_tilt_too_extreme" msgid="8618210742620248049">"Tilt your head a little less."</string>
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Turn your head a little less."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Remove anything hiding your face."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Clean the top of your screen, including the black bar"</string>
@@ -684,6 +685,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Allows the app to read and write Do Not Disturb configuration."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"start view permission usage"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Allows the holder to start the permission usage for an app. Should never be needed for normal apps."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"access sensor data at a high sampling rate"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Allows the app to sample sensor data at a rate greater than 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Set password rules"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Control the length and the characters allowed in screen lock passwords and PINs."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitor screen unlock attempts"</string>
@@ -1664,6 +1667,7 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Use Shortcut"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Colour Inversion"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Colour correction"</string>
+    <string name="reduce_bright_colors_feature_name" msgid="8978255324027479398">"Reduce brightness"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1871,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS request changed to video call"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS request changed to USSD request"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Changed to new SS request"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Phishing alert"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Work profile"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Alerted"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Expand"</string>
@@ -1880,6 +1885,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maximise"</string>
     <string name="close_button_text" msgid="10603510034455258">"Close"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Answer"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Decline"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Hang up"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Incoming call"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"On-going call"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Screening an incoming call"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selected</item>
@@ -2208,4 +2219,6 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"To continue, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; needs access to your device’s camera."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Turn on"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Sensor privacy"</string>
+    <string name="splash_screen_view_icon_description" msgid="180638751260598187">"Application icon"</string>
+    <string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Application branding image"</string>
 </resources>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 766e372..f440c8a 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"This device does not have a fingerprint sensor."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor temporarily disabled."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Use your fingerprint to continue"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerprint icon"</string>
@@ -605,7 +606,7 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"No longer able to recognise face. Try again."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Too similar, please change your pose."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Turn your head a little less."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Turn your head a little less."</string>
+    <string name="face_acquired_tilt_too_extreme" msgid="8618210742620248049">"Tilt your head a little less."</string>
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Turn your head a little less."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Remove anything hiding your face."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Clean the top of your screen, including the black bar"</string>
@@ -684,6 +685,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Allows the app to read and write Do Not Disturb configuration."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"start view permission usage"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Allows the holder to start the permission usage for an app. Should never be needed for normal apps."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"access sensor data at a high sampling rate"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Allows the app to sample sensor data at a rate greater than 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Set password rules"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Control the length and the characters allowed in screen lock passwords and PINs."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitor screen unlock attempts"</string>
@@ -1664,6 +1667,7 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Use Shortcut"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Colour inversion"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Colour correction"</string>
+    <string name="reduce_bright_colors_feature_name" msgid="8978255324027479398">"Reduce brightness"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1871,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS request changed to video call"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS request changed to USSD request"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Changed to new SS request"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Phishing alert"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Work profile"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Alerted"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Expand"</string>
@@ -1880,6 +1885,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maximise"</string>
     <string name="close_button_text" msgid="10603510034455258">"Close"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Answer"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Decline"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Hang up"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Incoming call"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"On-going call"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Screening an incoming call"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selected</item>
@@ -2208,4 +2219,6 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"To continue, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; needs access to your device’s camera."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Turn on"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Sensor privacy"</string>
+    <string name="splash_screen_view_icon_description" msgid="180638751260598187">"Application icon"</string>
+    <string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Application branding image"</string>
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 16da211..93881e9 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"This device does not have a fingerprint sensor."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor temporarily disabled."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Use your fingerprint to continue"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerprint icon"</string>
@@ -605,7 +606,7 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"No longer able to recognise face. Try again."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Too similar, please change your pose."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Turn your head a little less."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Turn your head a little less."</string>
+    <string name="face_acquired_tilt_too_extreme" msgid="8618210742620248049">"Tilt your head a little less."</string>
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Turn your head a little less."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Remove anything hiding your face."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Clean the top of your screen, including the black bar"</string>
@@ -684,6 +685,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Allows the app to read and write Do Not Disturb configuration."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"start view permission usage"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Allows the holder to start the permission usage for an app. Should never be needed for normal apps."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"access sensor data at a high sampling rate"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Allows the app to sample sensor data at a rate greater than 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Set password rules"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Control the length and the characters allowed in screen lock passwords and PINs."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitor screen unlock attempts"</string>
@@ -1664,6 +1667,7 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Use Shortcut"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Colour Inversion"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Colour correction"</string>
+    <string name="reduce_bright_colors_feature_name" msgid="8978255324027479398">"Reduce brightness"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1871,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS request changed to video call"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS request changed to USSD request"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Changed to new SS request"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Phishing alert"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Work profile"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Alerted"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Expand"</string>
@@ -1880,6 +1885,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maximise"</string>
     <string name="close_button_text" msgid="10603510034455258">"Close"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Answer"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Decline"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Hang up"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Incoming call"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"On-going call"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Screening an incoming call"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selected</item>
@@ -2208,4 +2219,6 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"To continue, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; needs access to your device’s camera."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Turn on"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Sensor privacy"</string>
+    <string name="splash_screen_view_icon_description" msgid="180638751260598187">"Application icon"</string>
+    <string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Application branding image"</string>
 </resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 150830e..a7fa30e 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"This device does not have a fingerprint sensor."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor temporarily disabled."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Use your fingerprint to continue"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerprint icon"</string>
@@ -605,7 +606,7 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"No longer able to recognise face. Try again."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Too similar, please change your pose."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Turn your head a little less."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Turn your head a little less."</string>
+    <string name="face_acquired_tilt_too_extreme" msgid="8618210742620248049">"Tilt your head a little less."</string>
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Turn your head a little less."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Remove anything hiding your face."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Clean the top of your screen, including the black bar"</string>
@@ -684,6 +685,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Allows the app to read and write Do Not Disturb configuration."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"start view permission usage"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Allows the holder to start the permission usage for an app. Should never be needed for normal apps."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"access sensor data at a high sampling rate"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Allows the app to sample sensor data at a rate greater than 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Set password rules"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Control the length and the characters allowed in screen lock passwords and PINs."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitor screen unlock attempts"</string>
@@ -1664,6 +1667,7 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Use Shortcut"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Colour Inversion"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Color correction"</string>
+    <string name="reduce_bright_colors_feature_name" msgid="8978255324027479398">"Reduce brightness"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1871,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS request changed to video call"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS request changed to USSD request"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Changed to new SS request"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Phishing alert"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Work profile"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Alerted"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Expand"</string>
@@ -1880,6 +1885,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maximise"</string>
     <string name="close_button_text" msgid="10603510034455258">"Close"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Answer"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Decline"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Hang up"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Incoming call"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"On-going call"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Screening an incoming call"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selected</item>
@@ -2208,4 +2219,6 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"To continue, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; needs access to your device’s camera."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Turn on"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Sensor privacy"</string>
+    <string name="splash_screen_view_icon_description" msgid="180638751260598187">"Application icon"</string>
+    <string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Application branding image"</string>
 </resources>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index e952cac..ce9a915 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎‏‎‎‎‏‎‏‏‎‏‏‏‏‎‎‎‏‎‎‎‏‏‏‏‎‏‎‎‏‏‎‎‏‎‏‎‎‎‎‎‎‎‎‏‏‎‎‏‎‏‏‎‎This device does not have a fingerprint sensor.‎‏‎‎‏‎"</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‏‏‏‎‎‎‏‏‎‎‏‎‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎‏‏‎‎‎‏‎‎‎‏‏‏‎‎‎‎‏‎‏‏‏‎‎‎‏‎Sensor temporarily disabled.‎‏‎‎‏‎"</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎‏‎‎‏‎‎‏‎‏‏‎‏‎‏‎‎‏‎‎‏‎‏‏‏‏‏‎‎‏‎‎‎‏‏‏‏‏‏‎‎‏‎‎Finger ‎‏‎‎‏‏‎<xliff:g id="FINGERID">%d</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‏‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‎‏‎‏‎‏‎‏‏‏‏‎‎‏‎‎‎‏‎‏‏‎‎‏‎‎‎‏‏‎‎‎‎‎‏‎Use your fingerprint to continue‎‏‎‎‏‎"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‎‎‏‎‏‎‎‏‎‏‏‏‏‎‎‎‏‏‎‏‏‎‎‎‎‎‎‏‎‎‏‏‏‎‏‎‎‏‎‎‎‏‎Fingerprint icon‎‏‎‎‏‎"</string>
@@ -605,7 +606,7 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‎‏‏‏‎‎‎‏‎‎‎‏‎‎‏‎‏‏‏‎‎‏‏‎‎‏‎‎‎‏‎‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‏‏‏‏‎‏‏‏‎‎No longer able to recognize face. Try again.‎‏‎‎‏‎"</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‎‎‏‎‏‎‏‎‏‏‏‎‏‎‎‏‎‏‏‎‎‏‎‎‎‏‏‎‏‎‏‎‏‎‎‎‎‎‎‎‏‎‏‎‏‎‎‎‎‏‎‏‎‎Too similar, please change your pose.‎‏‎‎‏‎"</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‏‏‏‎‎‎‎‎‎‎‎‏‏‎‎‎‎‎‏‎‎‏‏‎‎‎‏‎‏‎‎‎‎‎‎‏‎‏‏‎‎‎‎‎‏‎‎‎‏‏‏‏‎Turn your head a little less.‎‏‎‎‏‎"</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‏‏‏‎‏‎‏‎‎‏‏‎‎‏‏‎‎‎‎‏‏‏‎‎‏‏‎‎‏‏‏‎‏‏‎Turn your head a little less.‎‏‎‎‏‎"</string>
+    <string name="face_acquired_tilt_too_extreme" msgid="8618210742620248049">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‎‏‎‎‏‎‏‏‎‎‏‎‏‎‏‎‏‎‏‏‏‎‏‎‏‏‏‏‏‏‏‎‎‎‏‎Tilt your head a little less.‎‏‎‎‏‎"</string>
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‏‎‏‏‎‏‎‏‎‎‏‎‎‎‏‎‏‏‏‎‎‎‎‏‎‎‏‎‎‏‏‎‎‏‎Turn your head a little less.‎‏‎‎‏‎"</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‏‏‎‎‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‎‏‎‎‎‎‎‏‎‏‏‏‏‎Remove anything hiding your face.‎‏‎‎‏‎"</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‎‎‎‏‎‎‎‎‎‏‏‏‎‏‎‎‎‏‎‎‎‏‎‏‎‏‎‏‏‎‏‏‏‏‏‎‎‎‎‏‎‏‎‎‎‏‏‏‎‎Clean the top of your screen, including the black bar‎‏‎‎‏‎"</string>
@@ -684,6 +685,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‏‎‎‏‏‎‎‏‏‎‎‎‎‎‎‏‎‎‎‏‎‏‏‎‎‏‎‎‏‏‏‎‎‎‏‏‏‎‏‏‏‏‏‎‎‏‎‏‎‏‎Allows the app to read and write Do Not Disturb configuration.‎‏‎‎‏‎"</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‏‏‎‎‎‎‏‎‏‎‎‏‎‎‏‎‏‎‎‏‎‎‏‎‎‎‎‏‏‏‎‎‏‏‎‎‎‎‎‏‎‏‎‏‎‎‏‎‎‎‏‎‏‎‏‎start view permission usage‎‏‎‎‏‎"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‏‎‎‎‏‏‏‏‎‎‏‏‏‏‎‎‏‏‎‎‏‎‎‎‏‎‎‏‏‎‎‎‏‎‏‎‎‎‏‏‎‏‎‎‏‎‏‏‏‎‏‎‏‎‎Allows the holder to start the permission usage for an app. Should never be needed for normal apps.‎‏‎‎‏‎"</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‎‏‏‎‏‏‏‎‎‏‎‎‏‎‎‏‎‏‏‏‏‏‎‎‎‏‎‏‏‎‏‏‎‎‎‎‎‏‏‏‎‎access sensor data at a high sampling rate‎‏‎‎‏‎"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‎‏‏‎‎‎‏‎‏‏‎‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‏‎‏‏‎Allows the app to sample sensor data at a rate greater than 200 Hz‎‏‎‎‏‎"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‎‏‎‏‎‏‎‎‏‎‏‎‎‏‏‎‎‏‏‎‏‎‏‏‏‎‎‏‎‏‏‎‎‎‏‎‏‏‏‏‎‎‎‏‎‎‏‎‏‏‎‏‏‏‎Set password rules‎‏‎‎‏‎"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‎‎‏‎‏‎‏‎‎‏‏‏‏‎‏‏‎‎‎‏‎‏‎‎‏‏‎‏‎‎‎‎‏‏‎‎‎‎‎‎‏‎Control the length and the characters allowed in screen lock passwords and PINs.‎‏‎‎‏‎"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‏‎‏‏‏‎‏‏‏‎‎‏‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‎‏‎‏‎‏‏‎‎‏‎‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎Monitor screen unlock attempts‎‏‎‎‏‎"</string>
@@ -1664,6 +1667,7 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‏‏‏‎‏‎‏‏‎‎‎‏‎‎‏‎‎‎‎‎‏‎‏‎‎‎‏‎‎‏‎‏‏‏‎‏‎‎‎‏‏‏‏‎‎‏‎‏‏‏‏‎‎Use Shortcut‎‏‎‎‏‎"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‎‎‎‎‏‏‎‎‏‎‏‏‏‎‎‏‏‎‎‏‎‏‎‏‏‎‎‎‎‎‏‎‏‎‏‎‏‏‎‏‏‏‎‏‏‏‏‏‏‎‏‎‏‎‎‎Color Inversion‎‏‎‎‏‎"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‏‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‎‎‎‏‏‏‏‎‎‎‏‎‎‎‎‎‎‎‏‎‎‎‎‏‏‎‎‎‎‎‎‎‎‏‎‏‎Color Correction‎‏‎‎‏‎"</string>
+    <string name="reduce_bright_colors_feature_name" msgid="8978255324027479398">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‎‏‎‎‏‎‏‎‏‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‎‏‏‏‎‎‏‎‏‎‏‏‎‎‏‏‎‎Reduce brightness‎‏‎‎‏‎"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‎‎‎‏‏‎‏‎‏‎‎‏‏‏‏‏‎‏‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‎‏‏‏‎Held volume keys. ‎‏‎‎‏‏‎<xliff:g id="SERVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ turned on.‎‏‎‎‏‎"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‏‎‎‏‏‎‏‎‏‏‎‎‏‏‏‎‎‏‎‏‎‏‏‏‏‎‏‎‏‏‏‎‎‏‎‎‏‎‏‏‎Held volume keys. ‎‏‎‎‏‏‎<xliff:g id="SERVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ turned off.‎‏‎‎‏‎"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‏‎‎‎‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‏‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‎‏‎‎Press and hold both volume keys for three seconds to use ‎‏‎‎‏‏‎<xliff:g id="SERVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
@@ -1867,6 +1871,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‎‎‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‏‏‏‎‏‎‎‎‏‎‏‎‎‏‎‏‎‏‎‏‏‎‎‎‎SS request changed to video call‎‏‎‎‏‎"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‏‎‎‏‏‎‏‎‎‎‎‎‏‎‏‏‎‎‎‏‎‏‎‏‎‎‎‏‏‎‏‎‎‏‏‏‎‎‎‎‎‎‎‏‏‏‏‎‎‎‎SS request changed to USSD request‎‏‎‎‏‎"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎‏‎‏‎‏‎‎‎‏‏‎‏‎‎‏‎‎‎‏‎‎‎‏‏‎‏‎‎‏‎‏‏‏‎‎‏‎‏‎‎‏‏‎‏‏‎‎‎‏‎‎‏‎‎Changed to new SS request‎‏‎‎‏‎"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‎‏‏‎‎‏‎‎‎‏‏‏‎‏‏‎‎‏‏‏‏‎‎‎‎‎‏‎‏‎‎‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‎Phishing alert‎‏‎‎‏‎"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‎‎‎‎‎‎‏‏‎‏‏‏‏‎‏‎‏‎‎‎‏‏‏‎‎‎‎‏‎‎‏‏‎‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‏‎‎‏‏‏‎Work profile‎‏‎‎‏‎"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‏‎‏‎‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‏‎‎‏‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎Alerted‎‏‎‎‏‎"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‎‎‎‏‏‏‏‏‎‎‎‏‎‎‎‎‏‏‎‎‏‏‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‎‏‏‏‎‎‏‏‏‎Expand‎‏‎‎‏‎"</string>
@@ -1880,6 +1885,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‎‎‎‏‏‎‏‎‏‎‏‏‏‎‏‏‎‏‏‏‎‏‏‏‏‎‎‏‎‏‎‏‎‏‏‎‏‏‎‏‏‏‎‏‏‏‎‎‎‏‏‎‎‏‎‏‎Maximize‎‏‎‎‏‎"</string>
     <string name="close_button_text" msgid="10603510034455258">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‏‏‎‏‎‎‏‎‏‏‎‏‎‏‎‏‏‏‏‎‏‎‏‏‎‎‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‏‏‎‏‏‎‏‎‎Close‎‏‎‎‏‎"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‎‏‏‏‎‎‏‏‎‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‏‏‎‏‎‎‏‎‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‏‎‏‎‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>‎‏‎‎‏‏‏‎: ‎‏‎‎‏‏‎<xliff:g id="SENDER_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‎‎‎‏‏‎‎‏‏‎‏‏‎‎‏‏‎‏‏‎‎‏‎‏‎‎‏‎‎‏‏‎‎‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎‏‎‎‏‎Answer‎‏‎‎‏‎"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‏‎‏‎‎‏‎‎‎‏‎‏‎‎‎‎‏‎‎‎‎‎‏‎‏‎‏‎‏‎‎‎‏‎‎‏‏‎‎‏‏‏‏‎‎‏‎‏‎‏‏‎‎Decline‎‏‎‎‏‎"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‎‏‏‎‏‎‏‏‎‎‎‎‎‎‎‎‎‎‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‎‎‏‎‎‎‎‏‎‏‎‎‎‏‏‎Hang Up‎‏‎‎‏‎"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‎‎‎‎‎‎‏‎‏‏‎‏‎‏‏‏‎‏‎‏‏‎‏‎‏‎‏‏‏‏‏‎‎‏‎‎‏‏‎‎‎‏‏‎‎‎‎‏‏‏‏‎‎‏‎Incoming call‎‏‎‎‏‎"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‏‏‎‏‏‎‏‏‏‏‏‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‏‎‎‏‎‏‏‎Ongoing call‎‏‎‎‏‎"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‎‏‎‎‏‎‏‎‎‎‎‎‏‎‎‎‎‎‎‏‎‎‏‏‎‎‎‎‏‏‎‏‎‎‏‏‏‎‏‏‎‎‎‎‎Screening an incoming call‎‏‎‎‏‎"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‎‎‎‏‏‏‏‎‎‎‎‏‏‎‎‎‎‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‎‏‎‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="COUNT_1">%1$d</xliff:g>‎‏‎‎‏‏‏‎ selected‎‏‎‎‏‎</item>
       <item quantity="one">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‎‎‎‏‏‏‏‎‎‎‎‏‏‎‎‎‎‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‎‏‎‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="COUNT_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ selected‎‏‎‎‏‎</item>
@@ -2208,4 +2219,6 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‎‎‎‎‎‎‏‏‎‎‎‏‏‏‎‎‎‎‎‏‏‏‏‎‎‏‎‎‎‏‏‎‏‎‎‎‏‏‎‏‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎To continue, &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP">%s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; needs access to your device’s camera.‎‏‎‎‏‎"</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‏‎‎‏‎‎‎‏‎‎‏‏‏‎‏‏‎‎‎‎‏‎‎‎‎‏‏‏‏‏‎‏‎‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‎Turn on‎‏‎‎‏‎"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‏‎‏‎‏‏‎‎‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎Sensor Privacy‎‏‎‎‏‎"</string>
+    <string name="splash_screen_view_icon_description" msgid="180638751260598187">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎‎‏‏‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‎‏‏‎‎‎‏‏‏‎‏‏‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎Application icon‎‏‎‎‏‎"</string>
+    <string name="splash_screen_view_branding_description" msgid="7911129347402728216">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‏‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‏‎‎‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‏‏‏‎‎‎‎‎‏‏‎‎‎‏‏‎‎‎‎Application branding image‎‏‎‎‏‎"</string>
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index c5ff193..01d0c7e 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Este dispositivo no tiene sensor de huellas digitales."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Se inhabilitó temporalmente el sensor."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Utiliza tu huella digital para continuar"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ícono de huella digital"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Ya no se reconoce el rostro. Vuelve a intentarlo."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Es muy similar a la anterior. Haz otra pose."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Gira la cabeza un poco menos."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Gira la cabeza un poco menos."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Gira la cabeza un poco menos."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Quítate cualquier objeto que te cubra el rostro."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Limpia la parte superior de la pantalla, incluida la barra negra"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Permite que la aplicación lea y modifique la configuración de la función No interrumpir."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"iniciar uso de permiso de vista"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Permite que el propietario inicie el uso de permisos para una app. No debería requerirse para apps normales."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"Acceder a los datos del sensor a una tasa de muestreo alta"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Permite que la app tome una muestra de los datos del sensor a una tasa superior a 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Establecer reglas de contraseña"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Controlar la longitud y los caracteres permitidos en las contraseñas y los PIN para el bloqueo de pantalla."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Supervisa los intentos para desbloquear la pantalla"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usar acceso directo"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversión de color"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Corrección de color"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Como mantuviste presionadas las teclas de volumen, se activó <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Se presionaron las teclas de volumen. Se desactivó <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Mantén presionadas ambas teclas de volumen durante tres segundos para usar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Se cambió la solicitud SS por una videollamada"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Se cambió la solicitud SS por una solicitud USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Se cambió a una nueva solicitud SS"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Alerta de suplantación de identidad (phishing)"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Perfil de trabajo"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Alerta enviada"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Expandir"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maximizar"</string>
     <string name="close_button_text" msgid="10603510034455258">"Cerrar"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Responder"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Rechazar"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Colgar"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Llamada entrante"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Llamada en curso"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Filtrando una llamada entrante"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elementos seleccionados</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> elemento seleccionado</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Para continuar, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&amp;gt necesita acceso a la cámara del dispositivo."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Activar"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Privacidad del sensor"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 108c3db..28ff5fb 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Este dispositivo no tiene sensor de huellas digitales."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"El sensor está inhabilitado en estos momentos."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Usa tu huella digital para continuar"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icono de huella digital"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"No puede reconocer tu cara. Vuelve a intentarlo."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Se parece mucha a la anterior. Pon otra cara."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Gira la cabeza un poco menos."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Gira la cabeza un poco menos."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"No gires tanto la cabeza."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Retira cualquier objeto que te tape la cara."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Limpia la parte superior de la pantalla, incluida la barra de color negro"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Permite que la aplicación lea y modifique la configuración de No molestar."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"iniciar uso de permiso de visualización"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Permite que el titular inicie el uso de permisos de una aplicación. Las aplicaciones normales no deberían necesitar nunca este permiso."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"acceder a datos de sensores a una frecuencia de muestreo alta"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Permite que la aplicación consulte datos de sensores a una frecuencia superior a 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Establecimiento de reglas de contraseña"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Controla la longitud y los caracteres permitidos en los PIN y en las contraseñas de bloqueo de pantalla."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Supervisar los intentos de desbloqueo de pantalla"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilizar acceso directo"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversión de color"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Corrección de color"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Al mantener pulsadas las teclas de volumen, se ha activado <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Se han mantenido pulsadas las teclas de volumen. Se ha desactivado <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Para utilizar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, mantén pulsadas ambas teclas de volumen durante 3 segundos"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Se ha cambiado la solicitud de SS a una videollamada"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Se ha cambiado la solicitud de SS a una solicitud de USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Se ha cambiado a una nueva solicitud de SS"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Alerta de phishing"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Perfil de trabajo"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Con sonido"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Mostrar"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maximizar"</string>
     <string name="close_button_text" msgid="10603510034455258">"Cerrar"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Responder"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Rechazar"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Colgar"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Llamada entrante"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Llamada en curso"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Filtrando una llamada entrante"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> seleccionados</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> seleccionado</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Para continuar, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; necesita tener acceso a la cámara del dispositivo."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Activar"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Privacidad del sensor"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 70862d4..cb2bcdc 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Selles seadmes pole sõrmejäljeandurit."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Andur on ajutiselt keelatud."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Sõrmejälg <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Jätkamiseks kasutage sõrmejälge"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Sõrmejälje ikoon"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Nägu ei õnnestu enam tuvastada. Proovige uuesti."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Liiga sarnane, palun muutke oma asendit."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Pöörake oma pead veidi vähem."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Pöörake oma pead veidi vähem."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Pöörake oma pead veidi vähem."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Eemaldage kõik, mis varjab teie nägu."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Puhastage ekraani ülaosa, sh musta värvi riba"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Võimaldab rakendusel lugeda ja kirjutada funktsiooni Mitte segada seadistusi."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"vaatamisloa kasutamise alustamine"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Võimaldab omanikul rakenduse puhul alustada loa kasutamist. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"juurdepääs anduri andmetele kõrgel diskreetimissagedusel"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Võimaldab rakendusel anduri andmeid diskreetida sagedusel, mis on suurem kui 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Parooli reeglite määramine"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Juhitakse ekraaniluku paroolide ja PIN-koodide pikkusi ning lubatud tähemärkide seadeid."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Ekraani avamiskatsete jälgimine"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Kasuta otseteed"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Värvide ümberpööramine"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Värvide korrigeerimine"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Helitugevuse klahve hoiti all. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> lülitati sisse."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Helitugevuse klahve hoiti all. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> lülitati välja."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Teenuse <xliff:g id="SERVICE_NAME">%1$s</xliff:g> kasutamiseks hoidke kolm sekundit all mõlemat helitugevuse klahvi"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-taotlus muudeti videokõneks"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-taotlus muudeti USSD-taotluseks"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Muudeti uueks SS-taotluseks"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Andmepüügihoiatus"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Tööprofiil"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Teavitatud"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Laienda"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maksimeeri"</string>
     <string name="close_button_text" msgid="10603510034455258">"Sule"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Vasta"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Keeldu"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Lõpeta kõne"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Sissetulev kõne"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Käimasolev kõne"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Sissetuleva kõne filtreerimine"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> on valitud</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> on valitud</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Jätkamiseks vajab rakendus &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; juurdepääsu teie seadme kaamerale."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Lülita sisse"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Anduri privaatsus"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index bc691a5..f95c279 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -93,7 +93,7 @@
     <string name="notification_channel_mobile_data_status" msgid="1941911162076442474">"Datu-konexioaren egoera"</string>
     <string name="notification_channel_sms" msgid="1243384981025535724">"SMS mezuak"</string>
     <string name="notification_channel_voice_mail" msgid="8457433203106654172">"Erantzungailuko mezuak"</string>
-    <string name="notification_channel_wfc" msgid="9048240466765169038">"Wi-Fi bidezko deiak"</string>
+    <string name="notification_channel_wfc" msgid="9048240466765169038">"Wifi bidezko deiak"</string>
     <string name="notification_channel_sim" msgid="5098802350325677490">"SIMaren egoera"</string>
     <string name="notification_channel_sim_high_prio" msgid="642361929452850928">"SIM txartelaren lehentasun handiko jakinarazpenak"</string>
     <string name="peerTtyModeFull" msgid="337553730440832160">"Beste gailuak TTY osagarria FULL moduan erabiltzea eskatu du"</string>
@@ -122,23 +122,23 @@
     <string name="roamingText11" msgid="5245687407203281407">"Ibiltaritzari buruzko jakinarazpena aktibatuta"</string>
     <string name="roamingText12" msgid="673537506362152640">"Ibiltaritzari buruzko jakinarazpena desaktibatuta"</string>
     <string name="roamingTextSearching" msgid="5323235489657753486">"Zerbitzu bila"</string>
-    <string name="wfcRegErrorTitle" msgid="3193072971584858020">"Ezin izan dira konfiguratu Wi‑Fi bidezko deiak"</string>
+    <string name="wfcRegErrorTitle" msgid="3193072971584858020">"Ezin izan dira konfiguratu wifi bidezko deiak"</string>
   <string-array name="wfcOperatorErrorAlertMessages">
-    <item msgid="468830943567116703">"Wi-Fi bidez deiak egiteko eta mezuak bidaltzeko, eskatu operadoreari zerbitzu hori gaitzeko. Ondoren, aktibatu Wi-Fi bidezko deiak Ezarpenak atalean. (Errore-kodea: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+    <item msgid="468830943567116703">"Wifi bidez deiak egiteko eta mezuak bidaltzeko, eskatu operadoreari zerbitzu hori gaitzeko. Ondoren, aktibatu Wifi bidezko deiak Ezarpenak atalean. (Errore-kodea: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
   </string-array>
   <string-array name="wfcOperatorErrorNotificationMessages">
-    <item msgid="4795145070505729156">"Arazo bat izan da Wi‑Fi bidezko deiak zure operadorearekin erregistratzean: <xliff:g id="CODE">%1$s</xliff:g>"</item>
+    <item msgid="4795145070505729156">"Arazo bat izan da wifi bidezko deiak zure operadorearekin erregistratzean: <xliff:g id="CODE">%1$s</xliff:g>"</item>
   </string-array>
     <!-- no translation found for wfcSpnFormat_spn (2982505428519096311) -->
     <skip />
-    <string name="wfcSpnFormat_spn_wifi_calling" msgid="3165949348000906194">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi bidezko deiak"</string>
+    <string name="wfcSpnFormat_spn_wifi_calling" msgid="3165949348000906194">"<xliff:g id="SPN">%s</xliff:g> operadorearen wifi bidezko deiak"</string>
     <string name="wfcSpnFormat_spn_wifi_calling_vo_hyphen" msgid="3836827895369365298">"<xliff:g id="SPN">%s</xliff:g> operadorearen wifi bidezko deiak"</string>
     <string name="wfcSpnFormat_wlan_call" msgid="4895315549916165700">"WLAN bidezko deia"</string>
     <string name="wfcSpnFormat_spn_wlan_call" msgid="255919245825481510">"<xliff:g id="SPN">%s</xliff:g> WLAN bidezko deia"</string>
     <string name="wfcSpnFormat_spn_wifi" msgid="7232899594327126970">"<xliff:g id="SPN">%s</xliff:g> wifia"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="8383917598312067365">"Wi-Fi bidezko deiak | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="6865214948822061486">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
-    <string name="wfcSpnFormat_wifi_calling" msgid="6178935388378661755">"Wi-Fi bidezko deiak"</string>
+    <string name="wfcSpnFormat_wifi_calling" msgid="6178935388378661755">"Wifi bidezko deiak"</string>
     <string name="wfcSpnFormat_wifi" msgid="1376356951297043426">"Wifia"</string>
     <string name="wfcSpnFormat_wifi_calling_wo_hyphen" msgid="7178561009225028264">"Wi-Fi bidezko deiak"</string>
     <string name="wfcSpnFormat_vowifi" msgid="8371335230890725606">"VoWifi"</string>
@@ -148,8 +148,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wifi-sarea soilik"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <!-- no translation found for crossSimFormat_spn_cross_sim_calling (5620807020002879057) -->
-    <skip />
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"<xliff:g id="SPN">%s</xliff:g> operadorearen deietarako ordezko aukera"</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ez da desbideratu"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> zenbakira <xliff:g id="TIME_DELAY">{2}</xliff:g> segundotan"</string>
@@ -252,7 +251,7 @@
     <string name="global_action_logout" msgid="6093581310002476511">"Amaitu saioa"</string>
     <string name="global_action_screenshot" msgid="2610053466156478564">"Pantaila-argazkia"</string>
     <string name="bugreport_title" msgid="8549990811777373050">"Akatsen txostena"</string>
-    <string name="bugreport_message" msgid="5212529146119624326">"Gailuaren uneko egoerari buruzko informazioa bilduko da, mezu elektroniko gisa bidaltzeko. Minutu batzuk igaroko dira akatsen txostena sortzen hasten denetik bidaltzeko prest egon arte. Itxaron, mesedez."</string>
+    <string name="bugreport_message" msgid="5212529146119624326">"Gailuaren oraingo egoerari buruzko informazioa bilduko da, mezu elektroniko gisa bidaltzeko. Minutu batzuk igaroko dira akatsen txostena sortzen hasten denetik bidaltzeko prest egon arte. Itxaron, mesedez."</string>
     <string name="bugreport_option_interactive_title" msgid="7968287837902871289">"Txosten dinamikoa"</string>
     <string name="bugreport_option_interactive_summary" msgid="8493795476325339542">"Aukera hau erabili beharko zenuke ia beti. Txostenaren jarraipena egin ahal izango duzu eta arazoari buruzko xehetasunak eman ahal izango dituzu. Baliteke gutxitan erabili behar izaten diren atalak ez agertzea, denbora aurrezteko."</string>
     <string name="bugreport_option_full_title" msgid="7681035745950045690">"Txosten osoa"</string>
@@ -452,7 +451,7 @@
     <string name="permdesc_camera" msgid="5240801376168647151">"Aplikazioak abian den bitartean erabil dezake kamera argazkiak ateratzeko eta bideoak grabatzeko."</string>
     <string name="permlab_backgroundCamera" msgid="7549917926079731681">"Argazkiak atera eta bideoak grabatu atzeko planoan."</string>
     <string name="permdesc_backgroundCamera" msgid="1615291686191138250">"Aplikazioak edonoiz erabil dezake kamera argazkiak ateratzeko eta bideoak grabatzeko."</string>
-    <string name="permlab_systemCamera" msgid="3642917457796210580">"onartu aplikazio edo zerbitzu bati sistemako kamerak atzitzea argazkiak eta bideoak ateratzeko"</string>
+    <string name="permlab_systemCamera" msgid="3642917457796210580">"eman sistemako kamerak atzitzeko baimena aplikazio edo zerbitzu bati argazkiak ateratzeko eta bideoak grabatzeko"</string>
     <string name="permdesc_systemCamera" msgid="5938360914419175986">"Pribilegioa duen edo sistemakoa den aplikazio honek edonoiz erabil dezake kamera argazkiak ateratzeko eta bideoak grabatzeko. Halaber, android.permission.CAMERA baimena izan behar du aplikazioak."</string>
     <string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"eman jakinarazpenak jasotzeko baimena aplikazioari edo zerbitzuari kamerak ireki edo ixten direnean."</string>
     <string name="permdesc_cameraOpenCloseListener" msgid="2002636131008772908">"Kamera ireki edo itxi dela (eta zer aplikaziorekin) dioten jakinarazpenak jaso ditzake aplikazio honek."</string>
@@ -580,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Gailu honek ez du hatz-marken sentsorerik."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sentsorea aldi baterako desgaitu da."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"<xliff:g id="FINGERID">%d</xliff:g> hatza"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Aurrera egiteko, erabili hatz-marka"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Hatz-markaren ikonoa"</string>
@@ -606,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Ez dugu ezagutzen aurpegi hori. Saiatu berriro."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Jarrera berdintsuegia da. Alda ezazu."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Biratu burua pixka bat gutxiago."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Biratu burua pixka bat gutxiago."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Biratu burua pixka bat gutxiago."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Kendu aurpegia estaltzen dizuten gauzak."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Garbitu pantailaren goialdea, barra beltza barne"</string>
@@ -674,7 +675,7 @@
     <string name="permlab_accessDrmCertificates" msgid="6473765454472436597">"atzitu DRM ziurtagiriak"</string>
     <string name="permdesc_accessDrmCertificates" msgid="6983139753493781941">"DRM ziurtagiriak hornitzea eta erabiltzeko baimena ematen die aplikazioei. Aplikazio normalek ez lukete beharko."</string>
     <string name="permlab_handoverStatus" msgid="7620438488137057281">"Jaso Android Beam transferentzien egoera"</string>
-    <string name="permdesc_handoverStatus" msgid="3842269451732571070">"Uneko Android Beam transferentziei buruzko informazioa jasotzeko baimena ematen die aplikazioei"</string>
+    <string name="permdesc_handoverStatus" msgid="3842269451732571070">"Oraingo Android Beam transferentziei buruzko informazioa jasotzeko baimena ematen die aplikazioei"</string>
     <string name="permlab_removeDrmCertificates" msgid="710576248717404416">"kendu DRM ziurtagiriak"</string>
     <string name="permdesc_removeDrmCertificates" msgid="4068445390318355716">"DRM ziurtagiriak kentzea baimentzen die aplikazioei. Aplikazio normalek ez lukete beharko."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"lotu operadorearen mezularitza-zerbitzuari"</string>
@@ -685,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Ez molestatzeko moduaren konfigurazioa irakurtzeko eta bertan idazteko baimena ematen die aplikazioei."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"hasi ikusteko baimena erabiltzen"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Aplikazioaren baimena erabiltzen hasteko baimena ematen die titularrei. Aplikazio normalek ez lukete beharko."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"atzitu sentsoreen datuen laginak abiadura handian"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Aplikazioak 200 Hz-tik gorako abiaduran hartu ahal izango ditu sentsoreen datuen laginak"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Ezarri pasahitzen arauak"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Kontrolatu pantaila blokeoaren pasahitzen eta PINen luzera eta onartutako karaktereak."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Gainbegiratu pantaila desblokeatzeko saiakerak"</string>
@@ -1197,7 +1200,7 @@
     <string name="screen_compat_mode_scale" msgid="8627359598437527726">"Eskala"</string>
     <string name="screen_compat_mode_show" msgid="5080361367584709857">"Erakutsi beti"</string>
     <string name="screen_compat_mode_hint" msgid="4032272159093750908">"Gaitu hori berriro Sistemaren ezarpenak &gt; Aplikazioak &gt; Deskargatutakoak."</string>
-    <string name="unsupported_display_size_message" msgid="7265211375269394699">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioak ez du onartzen uneko pantailaren tamaina eta espero ez bezala joka lezake."</string>
+    <string name="unsupported_display_size_message" msgid="7265211375269394699">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioak ez du onartzen pantailaren tamaina, eta baliteke espero ez bezala jokatzea."</string>
     <string name="unsupported_display_size_show" msgid="980129850974919375">"Erakutsi beti"</string>
     <string name="unsupported_compile_sdk_message" msgid="7326293500707890537">"Android sistema eragilearen bertsio bateraezin baterako dago egina <xliff:g id="APP_NAME">%1$s</xliff:g>; beraz, espero ez bezala funtziona lezake. Baliteke aplikazioaren bertsio eguneratuago bat eskuragarri egotea."</string>
     <string name="unsupported_compile_sdk_show" msgid="1601210057960312248">"Erakutsi beti"</string>
@@ -1227,9 +1230,9 @@
     <string name="new_app_description" msgid="1958903080400806644">"Gorde gabe itxiko da <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
     <string name="dump_heap_notification" msgid="5316644945404825032">"<xliff:g id="PROC">%1$s</xliff:g> prozesuak memoria-muga gainditu du"</string>
     <string name="dump_heap_ready_notification" msgid="2302452262927390268">"Prest dago <xliff:g id="PROC">%1$s</xliff:g> memoria-iraulketaren txostena"</string>
-    <string name="dump_heap_notification_detail" msgid="8431586843001054050">"Sortu da uneko memoria-iraulketaren txostena. Sakatu partekatzeko."</string>
-    <string name="dump_heap_title" msgid="4367128917229233901">"Uneko memoria-iraulketaren txostena partekatu nahi duzu?"</string>
-    <string name="dump_heap_text" msgid="1692649033835719336">"<xliff:g id="PROC">%1$s</xliff:g> prozesuak memoria-muga (<xliff:g id="SIZE">%2$s</xliff:g>) gainditu du. Uneko memoria-iraulketaren txostena sortu da, garatzailearekin parteka dezazun. Kontuz: baliteke txosten horrek aplikazioak atzi dezakeen informazio pertsonala izatea."</string>
+    <string name="dump_heap_notification_detail" msgid="8431586843001054050">"Sortu da memoria-iraulketaren txostena. Sakatu partekatzeko."</string>
+    <string name="dump_heap_title" msgid="4367128917229233901">"Memoria-iraulketaren txostena partekatu nahi duzu?"</string>
+    <string name="dump_heap_text" msgid="1692649033835719336">"<xliff:g id="PROC">%1$s</xliff:g> prozesuak memoria-muga (<xliff:g id="SIZE">%2$s</xliff:g>) gainditu du. Memoria-iraulketaren txostena sortu da, garatzailearekin parteka dezazun. Kontuz: baliteke txosten horrek aplikazioak atzi dezakeen informazio pertsonala izatea."</string>
     <string name="dump_heap_system_text" msgid="6805155514925350849">"<xliff:g id="PROC">%1$s</xliff:g> prozesuak bere memoria-muga (<xliff:g id="SIZE">%2$s</xliff:g>) gainditu du. Memoria-iraulketaren txosten bat duzu erabilgarri, hura partekatu nahi baduzu ere. Kontuz: baliteke txosten horrek prozesuak atzi dezakeen kontuzko informazio pertsonala izatea eta datu horien barnean zuk idatzitakoak egotea, besteak beste."</string>
     <string name="dump_heap_ready_text" msgid="5849618132123045516">"<xliff:g id="PROC">%1$s</xliff:g> prozesuaren memoria-iraulketaren txosten bat duzu erabilgarri, hura partekatu nahi baduzu ere. Kontuz: baliteke txosten horrek prozesuak atzi dezakeen kontuzko informazio pertsonala izatea eta datu horien barnean zuk idatzitakoak egotea, besteak beste."</string>
     <string name="sendText" msgid="493003724401350724">"Aukeratu testurako ekintza"</string>
@@ -1357,7 +1360,7 @@
     <string name="alert_windows_notification_message" msgid="6538171456970725333">"Ez baduzu nahi <xliff:g id="NAME">%s</xliff:g> zerbitzuak eginbide hori erabiltzea, sakatu hau ezarpenak ireki eta aukera desaktibatzeko."</string>
     <string name="alert_windows_notification_turn_off_action" msgid="7805857234839123780">"Desaktibatu"</string>
     <string name="ext_media_checking_notification_title" msgid="8299199995416510094">"<xliff:g id="NAME">%s</xliff:g> egiaztatzen…"</string>
-    <string name="ext_media_checking_notification_message" msgid="2231566971425375542">"Uneko edukia berrikusten"</string>
+    <string name="ext_media_checking_notification_message" msgid="2231566971425375542">"Edukia berrikusten"</string>
     <string name="ext_media_new_notification_title" msgid="3517407571407687677">"Euskarri berria: <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_new_notification_title" product="automotive" msgid="9085349544984742727">"<xliff:g id="NAME">%s</xliff:g> ez da funtzionatzen ari"</string>
     <string name="ext_media_new_notification_message" msgid="6095403121990786986">"Sakatu konfiguratzeko"</string>
@@ -1638,7 +1641,7 @@
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Erabilerraztasun-lasterbidea erabili nahi duzu?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Lasterbidea aktibatuta dagoenean, bi bolumen-botoiak hiru segundoz sakatuta abiaraziko da erabilerraztasun-eginbidea."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Erabilerraztasun-eginbideetarako lasterbidea aktibatu nahi duzu?"</string>
-    <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Eduki sakatuta bolumen-botoiak segundo batzuez erabilerraztasun-eginbideak aktibatzeko. Hori eginez gero, baliteke zure mugikorraren funtzionamendua aldatzea.\n\nUneko eginbideak:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nHautatutako eginbideak aldatzeko, joan Ezarpenak &gt; Erabilerraztasuna atalera."</string>
+    <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Eduki sakatuta bolumen-botoiak segundo batzuez erabilerraztasun-eginbideak aktibatzeko. Hori eginez gero, baliteke zure mugikorraren funtzionamendua aldatzea.\n\nEginbideak:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nHautatutako eginbideak aldatzeko, joan Ezarpenak &gt; Erabilerraztasuna atalera."</string>
     <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> zerbitzuaren lasterbidea aktibatu nahi duzu?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Eduki sakatuta bolumen-botoiak segundo batzuez <xliff:g id="SERVICE">%1$s</xliff:g> izeneko erabilerraztasun-eginbidea aktibatzeko. Honen bidez, baliteke zure mugikorraren funtzionamendua aldatzea.\n\nLasterbide hau beste eginbide batengatik aldatzeko, joan Ezarpenak &gt; Erabilerraztasuna atalera."</string>
@@ -1665,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Erabili lasterbidea"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Koloreen alderantzikatzea"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Koloreen zuzenketa"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Bolumen-botoiak sakatuta eduki direnez, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aktibatu egin da."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Bolumen-botoiak sakatuta eduki direnez, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desaktibatu egin da."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> erabiltzeko, eduki sakatuta bi bolumen-botoiak hiru segundoz"</string>
@@ -1675,7 +1680,7 @@
     <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"Eginbide batetik bestera aldatzeko, pasatu bi hatz pantailaren behealdetik gora eta eduki sakatuta une batez."</string>
     <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"Eginbide batetik bestera aldatzeko, pasatu hiru hatz pantailaren behealdetik gora eta eduki sakatuta une batez."</string>
     <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Lupa"</string>
-    <string name="user_switched" msgid="7249833311585228097">"Uneko erabiltzailea: <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="user_switched" msgid="7249833311585228097">"Erabiltzailea: <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="user_switching_message" msgid="1912993630661332336">"<xliff:g id="NAME">%1$s</xliff:g> erabiltzailera aldatzen…"</string>
     <string name="user_logging_out_message" msgid="7216437629179710359">"<xliff:g id="NAME">%1$s</xliff:g> erabiltzailearen saioa amaitzen…"</string>
     <string name="owner_name" msgid="8713560351570795743">"Jabea"</string>
@@ -1775,7 +1780,7 @@
     <string name="restr_pin_enter_admin_pin" msgid="1199419462726962697">"Idatzi administratzailearen PIN kodea"</string>
     <string name="restr_pin_enter_pin" msgid="373139384161304555">"Idatzi PINa"</string>
     <string name="restr_pin_incorrect" msgid="3861383632940852496">"Okerra"</string>
-    <string name="restr_pin_enter_old_pin" msgid="7537079094090650967">"Uneko PINa"</string>
+    <string name="restr_pin_enter_old_pin" msgid="7537079094090650967">"Oraingo PINa"</string>
     <string name="restr_pin_enter_new_pin" msgid="3267614461844565431">"PIN berria"</string>
     <string name="restr_pin_confirm_pin" msgid="7143161971614944989">"Berretsi PIN berria"</string>
     <string name="restr_pin_create_pin" msgid="917067613896366033">"Konfiguratu debekuak aldatu ahal izateko idatzi beharko den PIN kodea"</string>
@@ -1868,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS eskaera bideo-deira aldatu da"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS eskaera USSD eskaerara aldatu da"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"SS eskaera berrira aldatu da"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Phishing-alerta"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Work profila"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Egin du soinua"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Zabaldu"</string>
@@ -1881,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maximizatu"</string>
     <string name="close_button_text" msgid="10603510034455258">"Itxi"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Erantzun"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Baztertu"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Amaitu deia"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Jasotako deia"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Deia abian da"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Jasotako dei bat bistaratzen"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> hautatuta</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> hautatuta</item>
@@ -2209,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Aurrera egiteko, gailuaren kamera atzitzeko baimena behar du &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; aplikazioak."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Aktibatu"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Sentsoreen pribatutasuna"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 6a0e454..714b5e4 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"این دستگاه حسگر اثر انگشت ندارد."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"حسگر به‌طور موقت غیرفعال است."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"انگشت <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"برای ادامه، از اثر انگشتتان استفاده کنید"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"نماد اثر انگشت"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"دیگر چهره را تشخیص نمی‌دهد. دوباره امتحان کنید."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"بسیار شبیه قبلی است، لطفاً قیافه دیگری بگیرید."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"سرتان را کمی صاف بگیرید."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"سرتان را کمی صاف بگیرید."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"سرتان را کمی صاف بگیرید."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"هرچیزی را که حائل چهره‌تان است بردارید."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"بالای صفحه و همچنین نوار مشکی را تمیز کنید."</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"به برنامه امکان می‌دهد پیکربندی «مزاحم نشوید» را بخواند و بنویسد."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"شروع مشاهده استفاده از مجوز"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"به دارنده اجازه شروع استفاده از مجوز را برای برنامه می‌دهد. هرگز برای برنامه‌های معمول نیاز نیست."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"دسترسی به داده‌های حسگر با نرخ نمونه‌برداری بالا"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"به برنامه اجازه می‌دهد داده‌های حسگر را با نرخ بیش‌از ۲۰۰ هرتز نمونه‌برداری کند"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"تنظیم قوانین گذرواژه"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"کنترل طول و نوع نویسه‌هایی که در گذرواژه و پین قفل صفحه مجاز است."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"پایش تلاش‌های باز کردن قفل صفحه"</string>
@@ -1440,7 +1444,7 @@
     <string name="notification_listener_binding_label" msgid="2702165274471499713">"شنونده اعلان"</string>
     <string name="vr_listener_binding_label" msgid="8013112996671206429">"‏شنونده VR"</string>
     <string name="condition_provider_service_binding_label" msgid="8490641013951857673">"ارائه‌دهنده وضعیت"</string>
-    <string name="notification_ranker_binding_label" msgid="432708245635563763">"سرویس رتبه‌بندی اعلان"</string>
+    <string name="notification_ranker_binding_label" msgid="432708245635563763">"سرویس رده‌بندی اعلان"</string>
     <string name="vpn_title" msgid="5906991595291514182">"‏VPN فعال شد"</string>
     <string name="vpn_title_long" msgid="6834144390504619998">"‏VPN را <xliff:g id="APP">%s</xliff:g> فعال کرده است"</string>
     <string name="vpn_text" msgid="2275388920267251078">"برای مدیریت شبکه ضربه بزنید."</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"استفاده از میان‌بر"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"وارونگی رنگ"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"تصحیح رنگ"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"کلیدهای میزان صدا پایین نگه داشته شد. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> روشن شد."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"کلیدهای میزان صدا پایین نگه داشته شد. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> خاموش شد."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"برای استفاده از <xliff:g id="SERVICE_NAME">%1$s</xliff:g>، هر دو کلید صدا را فشار دهید و سه ثانیه نگه دارید"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"‏درخواست SS به تماس تصویری تغییر کرد"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"‏درخواست SS به‌ درخواست USSD تغییر کرد"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"‏به‌ درخواست SS جدید تغییر کرد"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"هشدار رمزگیری"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"نمایه کاری"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"هشدار ارسال شد"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"بزرگ کردن"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"بزرگ کردن"</string>
     <string name="close_button_text" msgid="10603510034455258">"بستن"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>:‏ <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"پاسخ"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"رد کردن"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"قطع تماس"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"تماس ورودی"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"تماس درحال انجام"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"درحال غربال کردن تماس ورودی"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one">‏<xliff:g id="COUNT_1">%1$d</xliff:g> انتخاب شد</item>
       <item quantity="other">‏<xliff:g id="COUNT_1">%1$d</xliff:g> انتخاب شد</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"‏برای ادامه دادن، &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; باید به دوربین دستگاه دسترسی داشته باشد."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"روشن کردن"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"حریم‌خصوصی حسگر"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 8e5d9b4..ef872e9 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Laitteessa ei ole sormenjälkitunnistinta."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Tunnistin poistettu väliaikaisesti käytöstä."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Sormi <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Jatka sormenjäljen avulla"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Sormenjälkikuvake"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Ei enää tunnista kasvoja. Yritä uudelleen."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Liian samanlainen, vaihda asentoa."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Käännä päätä vähän vähemmän."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Käännä päätä vähän vähemmän."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Käännä päätä vähän vähemmän."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Poista esteet kasvojesi edestä."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Puhdista näytön yläreuna, mukaan lukien musta palkki"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Sallii sovelluksen lukea ja muokata Älä häiritse -tilan asetuksia."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"aloita katseluoikeuksien käyttö"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Antaa luvanhaltijan käynnistää sovelluksen käyttöoikeuksien käytön. Ei tavallisten sovelluksien käyttöön."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"saada pääsyn anturidataan suuremmalla näytteenottotaajuudella"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Sallii sovelluksen ottaa anturidatasta näytteitä yli 200 Hz:n taajuudella"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Asentaa salasanasäännöt"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Hallinnoida ruudun lukituksen salasanoissa ja PIN-koodeissa sallittuja merkkejä ja niiden pituutta."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Tarkkailla näytön avaamisyrityksiä"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Käytä pikanäppäintä"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Käänteiset värit"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Värinkorjaus"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Äänenvoimakkuuspainikkeita painettiin pitkään. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> laitettiin päälle."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Äänenvoimakkuuspainikkeita painettiin pitkään. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> laitettiin pois päältä."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Voit käyttää palvelua <xliff:g id="SERVICE_NAME">%1$s</xliff:g> painamalla molempia äänenvoimakkuuspainikkeita kolmen sekunnin ajan"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-pyyntö vaihdettu videopuheluksi"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-pyyntö vaihdettu USSD-pyynnöksi"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Vaihdettu uudeksi SS-pyynnöksi"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Varoitus tietojenkalastelusta"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Työprofiili"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Hälytti"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Laajenna"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Suurenna"</string>
     <string name="close_button_text" msgid="10603510034455258">"Sulje"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Vastaa"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Hylkää"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Lopeta puhelu"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Saapuva puhelu"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Käynnissä oleva puhelu"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Seulotaan saapuvaa puhelua"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> valittu</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> valittu</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Jotta voit jatkaa, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; tarvitsee pääsyn laitteesi kameraan."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Laita päälle"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Anturin tietosuoja"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 849f9594..7cc3160 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -148,8 +148,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi seulement"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <!-- no translation found for crossSimFormat_spn_cross_sim_calling (5620807020002879057) -->
-    <skip />
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"Méthode d\'appel secondaire avec <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : non transféré"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : <xliff:g id="DIALING_NUMBER">{1}</xliff:g> au bout de <xliff:g id="TIME_DELAY">{2}</xliff:g> secondes"</string>
@@ -580,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Cet appareil ne possède pas de capteur d\'empreintes digitales."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Le capteur a été désactivé temporairement."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Doigt <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Utilisez votre empreinte digitale pour continuer"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icône d\'empreinte digitale"</string>
@@ -606,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Ce visage ne sera plus reconnu. Réessayez."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Trop similaire. Changez de pose."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Tournez un peu moins votre tête."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Tournez un peu moins votre tête."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Tournez un peu moins votre tête."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Retirez tout ce qui pourrait couvrir votre visage."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Nettoyez le haut de l\'écran, y compris la barre noire"</string>
@@ -685,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Permet à l\'application de consulter et de modifier la configuration du mode Ne pas déranger."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"démarrer l\'affichage de l\'usage des autorisations"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Permet au détenteur de démarrer l\'usage des autorisations pour une application. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"accéder aux données des capteurs à un taux d’échantillonnage élevé"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Permet à l’application d’échantillonner les données des capteurs à une fréquence supérieure à 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Définir les règles du mot de passe"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Gérer le nombre et le type de caractères autorisés dans les mots de passe et les NIP de verrouillage de l\'écran."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Gérer les tentatives de déverrouillage de l\'écran"</string>
@@ -1665,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utiliser le raccourci"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversion des couleurs"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Correction des couleurs"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Touches de volume maintenues enfoncées. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> activé."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Touches de volume maintenues enfoncées. Service <xliff:g id="SERVICE_NAME">%1$s</xliff:g> désactivé."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Maintenez enfoncées les deux touches de volume pendant trois secondes pour utiliser <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1868,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"La demande SS a été remplacée par une demande d\'appel vidéo"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"La demande SS a été remplacée par une demande USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"La demande a été remplacée par une nouvelle demande SS"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Alerte d\'hameçonnage"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Profil professionnel"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Alerté"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Développer"</string>
@@ -1881,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Agrandir"</string>
     <string name="close_button_text" msgid="10603510034455258">"Fermer"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g> : <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Répondre"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Refuser"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Raccrocher"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Appel entrant"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Appel en cours"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Filtrer un appel entrant"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> élément sélectionné</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> éléments sélectionnés</item>
@@ -2209,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Pour continuer, vous devez accorder l\'accès à l\'appareil photo de votre appareil à l\'application &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt;."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Activer"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Confidentialité des capteurs"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 60138c4..a3c0bad 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -148,8 +148,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi uniquement"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <!-- no translation found for crossSimFormat_spn_cross_sim_calling (5620807020002879057) -->
-    <skip />
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"Appels de secours via <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : non transféré"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : <xliff:g id="DIALING_NUMBER">{1}</xliff:g> au bout de <xliff:g id="TIME_DELAY">{2}</xliff:g> secondes"</string>
@@ -580,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Aucun lecteur d\'empreinte digitale n\'est installé sur cet appareil."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Capteur temporairement désactivé."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Doigt <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Utilisez votre empreinte digitale pour continuer"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icône d\'empreinte digitale"</string>
@@ -606,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Impossible de reconnaître le visage. Réessayez."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Ressemble à un visage existant, changez de pose."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Tournez un peu moins la tête."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Tournez un peu moins la tête."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Tournez un peu moins la tête."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Retirez tout ce qui cache votre visage."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Nettoyez la partie supérieure de l\'écran, y compris la barre noire"</string>
@@ -685,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Permet à l\'application de consulter et de modifier la configuration du mode Ne pas déranger."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"activer l\'utilisation de l\'autorisation d\'affichage"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Permet à l\'application autorisée d\'activer l\'utilisation de l\'autorisation pour une application. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"accéder aux données des capteurs à un taux d\'échantillonnage élevé"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Autorise l\'appli à échantillonner les données des capteurs à un taux supérieur à 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Définir les règles du mot de passe"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Gérer le nombre et le type de caractères autorisés dans les mots de passe et les codes d\'accès de verrouillage de l\'écran"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Gérer les tentatives de déverrouillage de l\'écran"</string>
@@ -1665,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utiliser le raccourci"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversion des couleurs"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Correction des couleurs"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Touches de volume appuyées de manière prolongée. Service <xliff:g id="SERVICE_NAME">%1$s</xliff:g> activé."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Touches de volume appuyées de manière prolongée. Service <xliff:g id="SERVICE_NAME">%1$s</xliff:g> désactivé."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Appuyez de manière prolongée sur les deux touches de volume pendant trois secondes pour utiliser <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1868,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Requête SS transformée en appel vidéo"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Requête SS transformée en requête USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Remplacement par une nouvelle requête SS"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Alerte de hameçonnage"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Profil professionnel"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Alerte envoyée"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Développer"</string>
@@ -1881,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Agrandir"</string>
     <string name="close_button_text" msgid="10603510034455258">"Fermer"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g> : <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Répondre"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Refuser"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Raccrocher"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Appel entrant"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Appel en cours"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Filtrer un appel entrant"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> élément sélectionné</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> éléments sélectionnés</item>
@@ -2057,7 +2069,7 @@
     <string name="accessibility_system_action_back_label" msgid="4205361367345537608">"Retour"</string>
     <string name="accessibility_system_action_recents_label" msgid="4782875610281649728">"Applications récentes"</string>
     <string name="accessibility_system_action_notifications_label" msgid="6083767351772162010">"Notifications"</string>
-    <string name="accessibility_system_action_quick_settings_label" msgid="4583900123506773783">"Configuration rapide"</string>
+    <string name="accessibility_system_action_quick_settings_label" msgid="4583900123506773783">"Réglages rapides"</string>
     <string name="accessibility_system_action_power_dialog_label" msgid="8095341821683910781">"Boîte de dialogue Marche/Arrêt"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Verrouiller l\'écran"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Capture d\'écran"</string>
@@ -2209,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Pour continuer, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; a besoin d\'accéder à l\'appareil photo de votre appareil."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Activer"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Confidentialité du capteur"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index eadac9e..72a799e 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Este dispositivo non ten sensor de impresión dixital."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Desactivouse o sensor temporalmente."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Utiliza a túa impresión dixital para continuar"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icona de impresión dixital"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Xa non se pode recoñecer a cara. Téntao de novo."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"É moi similar. Cambia a pose."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Xira a cabeza un pouco menos."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Xira a cabeza un pouco menos."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Xira a cabeza un pouco menos."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Quita todo o que oculte a túa cara."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Limpa a parte superior da pantalla, incluída a barra de cor negra"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Permite á aplicación ler e escribir a configuración do modo Non molestar."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"iniciar uso de permiso de vista"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Permite ao propietario iniciar o uso de permisos dunha aplicación. As aplicacións normais non deberían precisalo nunca."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"acceder aos datos dos sensores usando unha taxa de mostraxe alta"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Permite que a aplicación recompile mostras dos datos dos sensores cunha taxa superior a 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Establecer as normas de contrasinal"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Controla a lonxitude e os caracteres permitidos nos contrasinais e nos PIN de bloqueo da pantalla."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Controlar os intentos de desbloqueo da pantalla"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilizar atallo"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversión de cor"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Corrección de cor"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume premidas. Activouse o servizo <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume premidas. Desactivouse <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Mantén premidas as teclas do volume durante tres segudos para usar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"A solicitude SS transformouse nunha videochamada"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"A solicitude SS transformouse nunha solicitude USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Transformouse nunha nova solicitude SS"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Alerta de phishing"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Perfil de traballo"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Con son"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Despregar"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maximizar"</string>
     <string name="close_button_text" msgid="10603510034455258">"Pechar"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Resposta"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Rexeitar"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Colgar"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Chamada entrante"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Chamada en curso"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Filtrando chamada entrante"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other">Seleccionáronse <xliff:g id="COUNT_1">%1$d</xliff:g></item>
       <item quantity="one">Seleccionouse <xliff:g id="COUNT_0">%1$d</xliff:g></item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Para continuar, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; precisa acceder á cámara do dispositivo."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Activar"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Privacidade do sensor"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 86416bc..7a2527f 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -148,8 +148,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"ફક્ત વાઇ-ફાઇ"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <!-- no translation found for crossSimFormat_spn_cross_sim_calling (5620807020002879057) -->
-    <skip />
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"<xliff:g id="SPN">%s</xliff:g> બૅકઅપ કૉલિંગ"</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ફોરવર્ડ કર્યો નથી"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="TIME_DELAY">{2}</xliff:g> સેકન્ડ પછી <xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -580,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"આ ડિવાઇસમાં કોઈ ફિંગરપ્રિન્ટ સેન્સર નથી."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"સેન્સર હંગામી રૂપે બંધ કર્યું છે."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"આંગળી <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"ચાલુ રાખવા માટે તમારી ફિંગરપ્રિન્ટનો ઉપયોગ કરો"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ફિંગરપ્રિન્ટ આયકન"</string>
@@ -606,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"ચહેરો ઓળખી શકાતો નથી. ફરી પ્રયાસ કરો."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"ઘણી સમાનતા ધરાવે છે, કૃપા કરીને તમારો પોઝ બદલો."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"તમારું માથું થોડું ફેરવો."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"તમારું માથું થોડું ફેરવો."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"તમારું માથું થોડું ઓછું ફેરવો."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"તમારા ચહેરાને છુપાવતી કંઈપણ વસ્તુ દૂર કરો."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"કાળી પટ્ટી સહિત, તમારી સ્ક્રીનની ટોચ સાફ કરો"</string>
@@ -685,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"એપ્લિકેશનને ખલેલ પાડશો નહીં ગોઠવણી વાંચવા અને લખવાની મંજૂરી આપે છે."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"પરવાનગી વપરાશ જુઓને શરૂ કરો"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"કોઈ ઍપ માટે પરવાનગી વપરાશ શરૂ કરવાની ધારકને મંજૂરી આપે છે. સામાન્ય ઍપ માટે ક્યારેય જરૂર પડી ન શકે."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"ઉચ્ચ સેમ્પ્લિંગ રેટ પર સેન્સરનો ડેટા ઍક્સેસ કરો"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"ઍપને 200 Hzથી વધુના દરે સેન્સરના ડેટાના નમૂનાની મંજૂરી આપે છે"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"પાસવર્ડ નિયમો સેટ કરો"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"સ્ક્રીન લૉક પાસવર્ડ અને પિનમાં મંજૂર લંબાઈ અને અક્ષરોને નિયંત્રિત કરો."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"સ્ક્રીનને અનલૉક કરવાના પ્રયત્નોનું નિયમન કરો"</string>
@@ -1665,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"શૉર્ટકટનો ઉપયોગ કરો"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"વિપરીત રંગમાં બદલવું"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"રંગ સુધારણા"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"વૉલ્યૂમ કી દબાવી રાખો. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ચાલુ કરી."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"વૉલ્યૂમ કી દબાવી રાખો. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> બંધ કરી."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>નો ઉપયોગ કરવા માટે બન્ને વૉલ્યૂમ કીને ત્રણ સેકન્ડ સુધી દબાવી રાખો"</string>
@@ -1868,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS વિનંતીને વીડિઓ કૉલમાં બદલવામાં આવી છે"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS વિનંતીને USSD વિનંતીમાં બદલવામાં આવી છે"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"નવી SS વિનંતીમાં બદલવામાં આવી છે"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"ફિશિંગ અલર્ટ"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"ઑફિસની પ્રોફાઇલ"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"અલર્ટ કરેલ"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"વિસ્તૃત કરો"</string>
@@ -1881,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"મહત્તમ કરો"</string>
     <string name="close_button_text" msgid="10603510034455258">"બંધ કરો"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"જવાબ"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"નકારો"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"સમાપ્ત કરો"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"ઇનકમિંગ કૉલ"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"ચાલુ કૉલ"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"ઇનકમિંગ કૉલનું સ્ક્રીનિંગ થાય છે"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> પસંદ કરી</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> પસંદ કરી</item>
@@ -2209,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"ચાલુ રાખવા માટે, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt;ને તમારા ડિવાઇસના કૅમેરાના ઍક્સેસની જરૂર છે."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"ચાલુ કરો"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"સેન્સર પ્રાઇવસી સંબંધિત નોટિફિકેશન"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 5f0a8f8..f108aa7 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -303,7 +303,7 @@
     <string name="managed_profile_label" msgid="7316778766973512382">"प्रोफ़ाइल बदलकर वर्क प्रोफ़ाइल पर जाएं"</string>
     <string name="permgrouplab_contacts" msgid="4254143639307316920">"संपर्क"</string>
     <string name="permgroupdesc_contacts" msgid="9163927941244182567">"अपने संपर्कों को ऐक्सेस करने की"</string>
-    <string name="permgrouplab_location" msgid="1858277002233964394">"जगह"</string>
+    <string name="permgrouplab_location" msgid="1858277002233964394">"जगह की जानकारी"</string>
     <string name="permgroupdesc_location" msgid="1995955142118450685">"इस डिवाइस की जगह तक पहुंचने दें"</string>
     <string name="permgrouplab_calendar" msgid="6426860926123033230">"कैलेंडर"</string>
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"अपने कैलेंडर को ऐक्सेस करने"</string>
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"इस डिवाइस में फ़िंगरप्रिंट सेंसर नहीं है."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"सेंसर कुछ समय के लिए बंद कर दिया गया है."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"फ़िंगरप्रिंट <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"जारी रखने के लिए फ़िंगरप्रिंट का इस्तेमाल करें"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"फ़िंगरप्रिंट आइकॉन"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"अब चेहरे की पहचान नहीं कर पा रहा. फिर से कोशिश करें."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"चेहरा काफ़ी मिलता-जुलता है, कृपया अपना पोज़ बदलें."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"अपना सिर थोड़ा कम घुमाएं."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"अपना सिर थोड़ा कम घुमाएं."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"अपना सिर थोड़ा कम घुमाएं."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"आपके चेहरे को छिपाने वाली सभी चीज़ों को हटाएं."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"अपनी स्क्रीन के सबसे ऊपरी हिस्से को साफ़ करें, जिसमें काले रंग वाला बार भी शामिल है"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"ऐप को परेशान न करें कॉन्फ़िगरेशन पढ़ने और लिखने देती है."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"देखने की अनुमतियां चालू करें"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"इस्तेमाल करने वाले को किसी ऐप्लिकेशन के लिए अनुमतियों का इस्तेमाल शुरू करने देता है. सामान्य ऐप्लिकेशन के लिए इसकी ज़रूरत कभी नहीं पड़ती."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"सेंसर डेटा को, नमूने लेने की तेज़ दर पर ऐक्सेस करें"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"यह अनुमति मिलने पर ऐप्लिकेशन, 200 हर्ट्ज़ से ज़्यादा की दर पर सेंसर डेटा का नमूना ले पाएगा"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"पासवर्ड नियम सेट करना"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"स्‍क्रीन लॉक पासवर्ड और पिन की लंबाई और उनमें स्वीकृत वर्णों को नियंत्रित करना."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"स्‍क्रीन अनलॉक करने के की कोशिशों पर नज़र रखना"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"शॉर्टकट का उपयोग करें"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"रंग बदलने की सुविधा"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"रंग में सुधार करने की सुविधा"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"आवाज़ कम-ज़्यादा करने वाले दोनों बटन दबाकर रखें. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> को चालू कर दिया गया."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"आवाज़ कम-ज़्यादा करने वाले दोनों बटन दबाकर रखें. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> को बंद कर दिया गया."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> इस्तेमाल करने के लिए आवाज़ वाले दोनों बटन तीन सेकंड तक दबाकर रखें"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"एसएस कोड चलाने के अनुरोध को वीडियो कॉल में बदला गया"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"एसएस कोड चलाने के अनुरोध को यूएसएसडी कोड चलाने के अनुरोध में बदला गया"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"एसएस कोड चलाने के नए अनुरोध में बदला गया"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"फ़िशिंग से जुड़ी चेतावनी"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"वर्क प्रोफ़ाइल"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"अलर्ट किया गया"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"विस्तार करें"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"बड़ा करें"</string>
     <string name="close_button_text" msgid="10603510034455258">"बंद करें"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"जवाब दें"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"अस्वीकार करें"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"कॉल काटें"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"आने वाला (इनकमिंग) कॉल"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"पहले से जारी कॉल"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"इनकमिंग कॉल को स्क्रीन किया जा रहा है"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> चयनित</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> चयनित</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"जारी रखने के लिए, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; को आपके डिवाइस का कैमरा ऐक्सेस करने की ज़रूरत है."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"चालू करें"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"सेंसर से जुड़ी निजता के बारे में सूचना"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index e1ae1e2..91073d4 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -582,6 +582,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Ovaj uređaj nema senzor otiska prsta."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Senzor je privremeno onemogućen."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Nastavite pomoću otiska prsta"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona otiska prsta"</string>
@@ -608,7 +609,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Lice nije prepoznato. Pokušajte ponovo."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Previše slično, promijenite pozu."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Nagnite glavu malo manje."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Nagnite glavu malo manje."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Nagnite glavu malo manje."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Uklonite sve što vam zakriva lice."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Očistite vrh zaslona, uključujući crnu traku"</string>
@@ -687,6 +689,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Omogućuje aplikaciji čitanje i pisanje konfiguracije opcije Ne ometaj."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"pokrenuti upotrebu dopuštenja za pregled"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Dopušta nositelju pokretanje upotrebe dopuštenja za aplikaciju. Ne bi smjelo biti potrebno za uobičajene aplikacije."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"pristup podacima senzora pri višoj brzini uzorkovanja"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Aplikaciji omogućuje uzorkovanje podataka senzora pri brzini većoj od 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Postavi pravila zaporke"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Upravlja duljinom i znakovima koji su dopušteni u zaporkama i PIN-ovima zaključavanja zaslona."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Nadziri pokušaje otključavanja zaslona"</string>
@@ -1686,6 +1690,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Upotrijebi prečac"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inverzija boja"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Korekcija boje"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Držali ste tipke za glasnoću. Uključila se usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Držali ste tipke za glasnoću. Isključila se usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pritisnite i zadržite tipke za glasnoću na tri sekunde da biste koristili uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1898,6 +1904,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS zahtjev promijenjen je u videopoziv"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS zahtjev promijenjen je u USSD zahtjev"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Promijenjeno u novi SS zahtjev"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Upozorenje o krađi identiteta"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Radni profil"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Upozoreni"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Proširivanje"</string>
@@ -1911,6 +1918,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maksimiziraj"</string>
     <string name="close_button_text" msgid="10603510034455258">"Zatvori"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Odgovori"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Odbij"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Prekini"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Dolazni poziv"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Poziv u tijeku"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Filtriranje dolaznog poziva"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> odabrana</item>
       <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> odabrane</item>
@@ -2242,4 +2255,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Da bi nastavila s radom, aplikacija &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; treba pristupiti fotoaparatu vašeg uređaja."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Uključi"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Privatnost senzora"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 3c04bec..32f33df 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Ez az eszköz nem rendelkezik ujjlenyomat-érzékelővel."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Az érzékelő átmenetileg le van tiltva."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"<xliff:g id="FINGERID">%d</xliff:g>. ujj"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"A folytatáshoz használja ujjlenyomatát"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ujjlenyomat ikon"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Már nem lehet felismerni az arcát. Próbálja újra."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Túlságosan hasonló, változtasson a pózon."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Kicsit kevésbé fordítsa el a fejét."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Kicsit kevésbé fordítsa el a fejét."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Kicsit kevésbé fordítsa el a fejét."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Távolítson el mindent, ami takarja az arcát."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Tisztítsa meg a képernyő tetejét, a fekete sávot is beleértve."</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Az alkalmazás olvashatja és szerkesztheti a „Ne zavarjanak” funkció beállításait."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"engedélyhasználat megtekintésének elindítása"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Lehetővé teszi a felhasználó számára, hogy elindítsa az alkalmazás engedélyhasználatát. A normál alkalmazásoknak erre soha nincs szükségük."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"hozzáférés a szenzoradatokhoz nagy mintavételezési gyakorisággal"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Lehetővé teszi az alkalmazás számára, hogy 200 Hz-nél magasabb gyakorisággal vegyen mintát a szenzoradatokból"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Jelszavakkal kapcsolatos szabályok beállítása"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"A képernyőzár jelszavaiban és PIN kódjaiban engedélyezett karakterek és hosszúság vezérlése."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Képernyőzár-feloldási kísérletek figyelése"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Billentyűparancs használata"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Színek invertálása"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Színkorrekció"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Nyomva tartotta a hangerőgombokat. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> bekapcsolva."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Nyomva tartotta a hangerőgombokat. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> kikapcsolva."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"A(z) <xliff:g id="SERVICE_NAME">%1$s</xliff:g> használatához tartsa lenyomva három másodpercig a két hangerőgombot"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Az SS-kérés módosítva videohívásra"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Az SS-kérés módosítva USSD-kérésre"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Új SS-kérésre módosítva"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Adathalászati figyelmeztetés"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Munkaprofil"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Értesítve"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Kibontás"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Teljes méret"</string>
     <string name="close_button_text" msgid="10603510034455258">"Bezárás"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Fogadás"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Elutasítás"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Befejezés"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Bejövő hívás"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Hívás folyamatban"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Bejövő hívás szűrése"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> kiválasztva</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> kiválasztva</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"A folytatáshoz a(z) &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; alkalmazásnak hozzáférésre van szüksége az eszköze kamerájához."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Bekapcsolás"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Érzékelőkkel kapcsolatos adatvédelem"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index bdd2387..cd1bbb1 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Այս սարքը չունի մատնահետքերի սկաներ։"</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Տվիչը ժամանակավորապես անջատված է:"</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Մատնահետք <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Շարունակելու համար անհրաժեշտ է ձեր մատնահետքը"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Մատնահետքի պատկերակ"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Չհաջողվեց ճանաչել դեմքը։ Նորից փորձեք:"</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Շատ նման է նախորդին։ Փոխեք ձեր դիրքը։"</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Գլուխն ուղիղ պահեք։"</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Գլուխն ուղիղ պահեք։"</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Գլուխն ուղիղ պահեք։"</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Հեռացրեք այն ամենը, ինչը թաքցնում է ձեր երեսը:"</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Մաքրեք էկրանի վերևի մասը, ներառյալ սև գոտին"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Թույլ է տալիս հավելվածին փոփոխել «Չանհանգստացնել» գործառույթի կազմաձևումը:"</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"թույլտվությունների մասին տվյալների հասանելիություն"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Հավելվածին հասանելի կդառնան թույլտվությունների մասին տվյալները։ Այս թույլտվությունն անհրաժեշտ չէ սովորական հավելվածներին։"</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"օգտագործել սենսորների տվյալները բարձր հաճախականության վրա"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Թույլ է տալիս հավելվածին փորձել սենսորների տվյալները 200 Հց-ից բարձր հաճախականության վրա"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Սահմանել գաղտնաբառի կանոնները"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Կառավարել էկրանի ապակողպման գաղտնաբառերի և PIN կոդերի թույլատրելի երկարությունն ու գրանշանները:"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Վերահսկել էկրանի ապակողպման փորձերը"</string>
@@ -1438,7 +1442,7 @@
     <string name="wallpaper_binding_label" msgid="1197440498000786738">"Պաստառ"</string>
     <string name="chooser_wallpaper" msgid="3082405680079923708">"Փոխել պաստառը"</string>
     <string name="notification_listener_binding_label" msgid="2702165274471499713">"Ծանուցման ունկնդիր"</string>
-    <string name="vr_listener_binding_label" msgid="8013112996671206429">"VR ունկնդրիչ"</string>
+    <string name="vr_listener_binding_label" msgid="8013112996671206429">"VR ունկնիր"</string>
     <string name="condition_provider_service_binding_label" msgid="8490641013951857673">"Պայմանների մատակարար"</string>
     <string name="notification_ranker_binding_label" msgid="432708245635563763">"Ծանուցումների դասակարգման ծառայություն"</string>
     <string name="vpn_title" msgid="5906991595291514182">"VPN-ը ակտիվացված է"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Օգտագործել դյուրանցումը"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Գունաշրջում"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Գունաշտկում"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ձայնի կարգավորման կոճակները սեղմվեցին։ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ծառայությունը միացավ։"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ձայնի կարգավորման կոճակները սեղմվեցին։ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ծառայությունն անջատվեց։"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"«<xliff:g id="SERVICE_NAME">%1$s</xliff:g>» ծառայությունն օգտագործելու համար սեղմեք և 3 վայրկյան պահեք ձայնի ուժգնության երկու կոճակները"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS հարցումը փոխվել է տեսազանգի"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS հարցումը փոխվել է USSD հարցման"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Փոխվել է նոր SS հարցման"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Ֆիշինգի մասին զգուշացում"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Աշխատանքային պրոֆիլ"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Ուղարկվել է զգուշացում"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Ընդարձակել"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Մեծացնել"</string>
     <string name="close_button_text" msgid="10603510034455258">"Փակել"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>՝ <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Պատասխանել"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Մերժել"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Ավարտել"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Մուտքային զանգ"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Ընթացիկ զանգ"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Մուտքային զանգի զտում"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one">Ընտրված է՝ <xliff:g id="COUNT_1">%1$d</xliff:g></item>
       <item quantity="other">Ընտրված է՝ <xliff:g id="COUNT_1">%1$d</xliff:g></item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Շարունակելու համար &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; հավելվածին անհրաժեշտ է ձեր սարքի տեսախցիկի օգտագործման թույլտվություն։"</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Միացնել"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Տվիչների գաղտնիություն"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index c84bc13..f7fe384 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Perangkat ini tidak memiliki sensor sidik jari."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor dinonaktifkan untuk sementara."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Jari <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Gunakan sidik jari untuk melanjutkan"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon sidik jari"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Tidak lagi dapat mengenali wajah. Coba lagi."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Terlalu mirip, ubah pose Anda."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Putar sedikit kepala Anda."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Putar sedikit kepala Anda."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Putar sedikit kepala Anda."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Singkirkan apa saja yang menutupi wajah Anda."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Bersihkan bagian atas layar, termasuk kotak hitam"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Mengizinkan aplikasi membaca dan menulis konfigurasi status Jangan Ganggu."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"mulai melihat penggunaan izin"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Memungkinkan pemegang memulai penggunaan izin untuk aplikasi. Tidak diperlukan untuk aplikasi normal."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"mengakses data sensor pada frekuensi pengambilan sampel yang tinggi"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Mengizinkan aplikasi mengambil sampel data sensor pada frekuensi yang lebih besar dari 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Setel aturan sandi"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Mengontrol panjang dan karakter yang diizinkan dalam sandi dan PIN kunci layar."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Pantau upaya pembukaan kunci layar"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Gunakan Pintasan"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversi Warna"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Koreksi Warna"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tombol volume ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> diaktifkan."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tombol volume ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> dinonaktifkan."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Tekan dan tahan kedua tombol volume selama tiga detik untuk menggunakan <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Permintaan SS diubah ke panggilan video"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Permintaan SS diubah ke permintaan USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Diubah ke permintaan SS baru"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Peringatan phishing"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Profil kerja"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Diingatkan"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Luaskan"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maksimalkan"</string>
     <string name="close_button_text" msgid="10603510034455258">"Tutup"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Jawab"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Tolak"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Tutup"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Panggilan masuk"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Panggilan sedang berlangsung"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Menyaring panggilan masuk"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> dipilih</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> dipilih</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Untuk melanjutkan, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; memerlukan akses ke kamera perangkat."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Aktifkan"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Privasi Sensor"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 84611a2..5824c3a6 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Þetta tæki er ekki með fingrafaralesara."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Slökkt tímabundið á skynjara."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Fingur <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Notaðu fingrafarið þitt til að halda áfram"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingrafaratákn"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Andlit þekkist ekki lengur. Reyndu aftur."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Of svipað. Stilltu þér öðruvísi upp."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Snúðu höfðinu aðeins minna."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Hallaðu höfðinu aðeins minna."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Snúðu höfðinu aðeins minna."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Fjarlægðu það sem kann að hylja andlitið."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Hreinsaðu efsta hluta skjásins þíns, þ.m.t. svörtu stikuna"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Leyfir forriti að lesa og skrifa í grunnstillingu „Ónáðið ekki“."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"heimildanotkun upphafsyfirlits"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Leyfir handhafa að byrja heimildanotkun fyrir forrit. Ætti aldrei að þurfa fyrir venjuleg forrit."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"aðgangur að skynjaragögnum með hárri upptökutíðni"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Leyfir forritinu að nota upptökutíðni yfir 200 Hz fyrir skynjaragögn"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Setja reglur um aðgangsorð"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Stjórna lengd og fjölda stafa í aðgangsorðum og PIN-númerum skjáláss."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Fylgjast með tilraunum til að taka skjáinn úr lás"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Nota flýtileið"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Umsnúningur lita"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Litaleiðrétting"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Hljóðstyrkstökkum haldið inni. Kveikt á <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Hljóðstyrkstökkum haldið inni. Slökkt á <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Haltu báðum hljóðstyrkstökkunum inni í þrjár sekúndur til að nota <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-beiðni breytt í myndsímtal"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-beiðni breytt í USSD-beiðni"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Breytt í nýja SS-beiðni"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Viðvörun um vefveiðar"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Vinnusnið"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Tilkynnt"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Stækka"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Stækka"</string>
     <string name="close_button_text" msgid="10603510034455258">"Loka"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Svara"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Hafna"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Leggja á"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Símtal berst"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Símtal í gangi"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Síar símtal sem berst"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> valið</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> valin</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Til að halda áfram þarf &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; aðgang að myndavél tækisins."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Kveikja"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Persónuvernd skynjara"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 2fcc273..d435a25 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -148,8 +148,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Solo Wi-Fi"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <!-- no translation found for crossSimFormat_spn_cross_sim_calling (5620807020002879057) -->
-    <skip />
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"Chiamate di backup <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: inoltro non effettuato"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g><xliff:g id="DIALING_NUMBER">{1}</xliff:g> dopo <xliff:g id="TIME_DELAY">{2}</xliff:g> secondi"</string>
@@ -580,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Questo dispositivo non dispone di sensore di impronte."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensore temporaneamente disattivato."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Dito <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Utilizza la tua impronta per continuare"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icona dell\'impronta"</string>
@@ -606,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Non è più possibile riconoscere il volto. Riprova."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Troppo simile; cambia posa."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Gira un po\' meno la testa."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Gira un po\' meno la testa."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Gira un po\' meno la testa."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Rimuovi tutto ciò che ti nasconde il viso."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Pulisci la parte superiore dello schermo, inclusa la barra nera"</string>
@@ -685,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Consente all\'app di leggere e modificare la configurazione della funzione Non disturbare."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"avvio dell\'uso dell\'autorizzazione di visualizzazione"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Consente al titolare di avviare l\'uso delle autorizzazioni per un\'app. Non dovrebbe essere mai necessaria per le normali applicazioni."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"Accesso ai dati dei sensori a una frequenza di campionamento elevata"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Consente all\'app di campionare i dati dei sensori a una frequenza maggiore di 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Impostare regole per le password"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Controlla la lunghezza e i caratteri ammessi nelle password e nei PIN del blocco schermo."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitorare tentativi di sblocco dello schermo"</string>
@@ -1665,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usa scorciatoia"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversione dei colori"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Correzione del colore"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tieni premuti i tasti del volume. Servizio <xliff:g id="SERVICE_NAME">%1$s</xliff:g> attivato."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tieni premuti i tasti del volume. Servizio <xliff:g id="SERVICE_NAME">%1$s</xliff:g> disattivato."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Tieni premuti entrambi i tasti del volume per tre secondi per utilizzare <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1868,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Richiesta SS modificata in videochiamata"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Richiesta SS modificata in richiesta USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Modificata in nuova richiesta SS"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Allerta phishing"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Profilo di lavoro"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Avviso inviato"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Espandi"</string>
@@ -1881,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Ingrandisci"</string>
     <string name="close_button_text" msgid="10603510034455258">"Chiudi"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Rispondi"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Rifiuta"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Riaggancia"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Chiamata in arrivo"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Chiamata in corso"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Applicazione filtro a chiamata in arrivo"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> file selezionati</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> file selezionato</item>
@@ -2209,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Per continuare, l\'app &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; deve accedere alla videocamera del dispositivo."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Attiva"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Privacy relativa ai sensori"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index f104d44..ee771df 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -585,6 +585,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"במכשיר זה אין חיישן טביעות אצבע."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"החיישן מושבת באופן זמני."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"אצבע <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"יש להשתמש בטביעת האצבע כדי להמשיך"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"סמל טביעת אצבע"</string>
@@ -611,7 +612,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"כבר לא ניתן לזהות פנים. יש לנסות שוב."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"דומה מדי, יש לשנות תנוחה."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"עליך ליישר קצת את הראש."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"עליך ליישר קצת את הראש."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"עליך ליישר קצת את הראש."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"יש להסיר כל דבר שמסתיר את הפנים."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"עליך לנקות את החלק העליון של המסך, כולל הסרגל השחור"</string>
@@ -690,6 +692,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"מאפשר לאפליקציה לקרוא ולכתוב את התצורה של \'נא לא להפריע\'."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"התחלת צפייה בהרשאות השימוש"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"מאפשרת לבעלים להפעיל את השימוש בהרשאות עבור אפליקציה מסוימת. הרשאה זו אף פעם לא נדרשת עבור אפליקציות רגילות."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"גישה לנתוני חיישנים בתדירות דגימה גבוהה"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"האפליקציה תוכל לדגום נתוני חיישנים בתדירות של מעל 200 הרץ"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"הגדר כללי סיסמה"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"קביעת האורך הנדרש והתווים המותרים בסיסמאות ובקודי הגישה של מסך הנעילה."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"מעקב אחר ניסיונות לביטול של נעילת המסך"</string>
@@ -1708,6 +1712,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"השתמש בקיצור הדרך"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"היפוך צבעים"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"תיקון צבעים"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"לחצני עוצמת הקול נלחצו בלחיצה ארוכה. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> הופעל."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"לחצני עוצמת הקול נלחצו בלחיצה ארוכה. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> הושבת."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"יש ללחוץ לחיצה ארוכה על שני לחצני עוצמת הקול למשך שלוש שניות כדי להשתמש בשירות <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1929,6 +1935,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"‏בקשת SS שונתה לשיחת וידאו"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"‏בקשת SS שונתה לבקשת USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"‏היה שינוי לבקשת SS חדשה"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"התראה על פישינג"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"פרופיל עבודה"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"נשלחה התראה"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"הרחב"</string>
@@ -1942,6 +1949,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"הגדל"</string>
     <string name="close_button_text" msgid="10603510034455258">"סגירה"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"תשובה"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"דחייה"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"ניתוק"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"שיחה נכנסת"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"שיחה פעילה"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"סינון שיחה נכנסת"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="two">בחרת <xliff:g id="COUNT_1">%1$d</xliff:g></item>
       <item quantity="many">בחרת <xliff:g id="COUNT_1">%1$d</xliff:g></item>
@@ -2276,4 +2289,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"‏כדי להמשיך, האפליקציה &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; צריכה גישה למצלמה של המכשיר שלך."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"הפעלה"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"פרטיות חיישנים"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 69822ac..b03f94c 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -203,7 +203,7 @@
     <string name="sensor_notification_service" msgid="7474531979178682676">"センサー通知サービス"</string>
     <string name="twilight_service" msgid="8964898045693187224">"トワイライト サービス"</string>
     <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Time Zone Detector(未接続)"</string>
-    <string name="gnss_time_update_service" msgid="9039489496037616095">"GNSS Time Update Service"</string>
+    <string name="gnss_time_update_service" msgid="9039489496037616095">"GNSS 時間アップデートサービス"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"デバイスのデータが消去されます"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"管理アプリを使用できません。デバイスのデータはこれから消去されます。\n\nご不明な点がある場合は、組織の管理者にお問い合わせください。"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"「<xliff:g id="OWNER_APP">%s</xliff:g>」により印刷は無効にされています。"</string>
@@ -538,10 +538,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"このアプリに画面ロックの複雑さレベル(高、中、低、なし)を認識することを許可します。複雑さレベルは、画面ロックの文字数の範囲やタイプを示すものです。アプリから一定レベルまで画面ロックを更新するよう推奨されることもありますが、ユーザーは無視したり別の操作を行ったりできます。画面ロックは平文で保存されないため、アプリが正確なパスワードを知ることはありません。"</string>
     <string name="permlab_useBiometric" msgid="6314741124749633786">"生体認証ハードウェアの使用"</string>
     <string name="permdesc_useBiometric" msgid="7502858732677143410">"生体認証ハードウェアを認証に使用することをアプリに許可します"</string>
-    <string name="permlab_manageFingerprint" msgid="7432667156322821178">"指紋ハードウェアの管理"</string>
+    <string name="permlab_manageFingerprint" msgid="7432667156322821178">"指紋認証ハードウェアの管理"</string>
     <string name="permdesc_manageFingerprint" msgid="2025616816437339865">"使用する指紋テンプレートの追加や削除を行う方法の呼び出しをアプリに許可します。"</string>
-    <string name="permlab_useFingerprint" msgid="1001421069766751922">"指紋ハードウェアの使用"</string>
-    <string name="permdesc_useFingerprint" msgid="412463055059323742">"指紋ハードウェアを認証に使用することをアプリに許可します"</string>
+    <string name="permlab_useFingerprint" msgid="1001421069766751922">"指紋認証ハードウェアの使用"</string>
+    <string name="permdesc_useFingerprint" msgid="412463055059323742">"指紋認証ハードウェアを認証に使用することをアプリに許可します"</string>
     <string name="permlab_audioWrite" msgid="8501705294265669405">"音楽コレクションの変更"</string>
     <string name="permdesc_audioWrite" msgid="8057399517013412431">"音楽コレクションの変更をアプリに許可します。"</string>
     <string name="permlab_videoWrite" msgid="5940738769586451318">"動画コレクションの変更"</string>
@@ -567,7 +567,7 @@
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"指紋認証を完了しました"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"顔を認証しました"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"顔を認証しました。[確認] を押してください"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"指紋ハードウェアは使用できません。"</string>
+    <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"指紋認証ハードウェアは使用できません。"</string>
     <string name="fingerprint_error_no_space" msgid="6126456006769817485">"指紋を保存できません。既存の指紋を削除してください。"</string>
     <string name="fingerprint_error_timeout" msgid="2946635815726054226">"指紋の読み取りがタイムアウトになりました。もう一度お試しください。"</string>
     <string name="fingerprint_error_canceled" msgid="540026881380070750">"指紋の操作をキャンセルしました。"</string>
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"このデバイスには指紋認証センサーがありません。"</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"センサーが一時的に無効になっています。"</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"指紋 <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"続行するには指紋認証を使用してください"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"指紋アイコン"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"顔を認識できなくなりました。もう一度お試しください。"</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"似すぎています。ポーズを変えてください。"</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"顔の向きを少し戻してください。"</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"顔の向きを少し戻してください。"</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"顔の向きを少し戻してください。"</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"顔を隠しているものをすべて外してください"</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"黒いバーを含め、画面の上部をきれいにしてください"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"サイレント モード設定の読み取りと書き込みをアプリに許可します。"</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"表示権限の使用の開始"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"アプリの権限使用の開始を所有者に許可します。通常のアプリでは不要です。"</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"高サンプリング レートでセンサーデータにアクセスする"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"200 Hz を超えるレートでセンサーデータをサンプリングすることをアプリに許可します"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"パスワードルールの設定"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"画面ロックのパスワードとPINの長さと使用できる文字を制御します。"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"画面ロック解除試行の監視"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ショートカットを使用"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"色反転"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"色補正"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"音量ボタンを長押ししました。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> が ON になりました。"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"音量ボタンを長押ししました。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> が OFF になりました。"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> を使用するには、音量大と音量小の両方のボタンを 3 秒間長押ししてください"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS リクエストはビデオ通話に変更されました"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS リクエストは USSD リクエストに変更されました"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"新しい SS リクエストに変更されました"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"フィッシングに関する警告"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"仕事用プロファイル"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"アラートとして送信済み"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"展開"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"最大化"</string>
     <string name="close_button_text" msgid="10603510034455258">"閉じる"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"応答"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"拒否"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"通話終了"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"着信"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"通話中"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"着信をスクリーニング中"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>件選択済み</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g>件選択済み</item>
@@ -2060,9 +2073,9 @@
     <string name="accessibility_system_action_power_dialog_label" msgid="8095341821683910781">"電源ダイアログ"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"ロック画面"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"スクリーンショット"</string>
-    <string name="accessibility_system_action_on_screen_a11y_shortcut_label" msgid="8488701469459210309">"画面上のユーザー補助のショートカット"</string>
-    <string name="accessibility_system_action_on_screen_a11y_shortcut_chooser_label" msgid="1057878690209817886">"画面上のユーザー補助のショートカットの選択メニュー"</string>
-    <string name="accessibility_system_action_hardware_a11y_shortcut_label" msgid="5764644187715255107">"ユーザー補助のショートカット"</string>
+    <string name="accessibility_system_action_on_screen_a11y_shortcut_label" msgid="8488701469459210309">"画面上のユーザー補助機能のショートカット"</string>
+    <string name="accessibility_system_action_on_screen_a11y_shortcut_chooser_label" msgid="1057878690209817886">"画面上のユーザー補助機能のショートカットの選択メニュー"</string>
+    <string name="accessibility_system_action_hardware_a11y_shortcut_label" msgid="5764644187715255107">"ユーザー補助機能のショートカット"</string>
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> のキャプション バーです。"</string>
     <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> は RESTRICTED バケットに移動しました。"</string>
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"続行するには、&lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; にデバイスのカメラへのアクセスを許可する必要があります。"</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"ON にする"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"センサー プライバシー"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 6a7d563..c25bd57 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ამ მოწყობილობას არ აქვს თითის ანაბეჭდის სენსორი."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"სენსორი დროებით გათიშულია."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"თითი <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"გასაგრძელებლად გამოიყენეთ თქვენი თითის ანაბეჭდი"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"თითის ანაბეჭდის ხატულა"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"სახის ამოცნობა ვეღარ ხერხდება. ცადეთ ხელახლა."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"მეტისმეტად მსგავსია. გთხოვთ, შეცვალოთ პოზა."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"თავი ცოტა ნაკლებად მიაბრუნეთ."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"თავი ცოტა ნაკლებად მიაბრუნეთ."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"თავი ცოტა ნაკლებად მიაბრუნეთ."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"მოაშორეთ ყველაფერი, რაც სახეს გიფარავთ."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"გაწმინდეთ ეკრანის ზედა ნაწილი, შავი ზოლის ჩათვლით."</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"საშუალებას აძლევს აპს, წაიკითხოს და დაწეროს კონფიგურაცია „არ შემაწუხოთ“."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"ნახვის ნებართვის გამოყენების დაწყება"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"მფლობელს საშუალებას აძლევს, დაიწყოს აპის ნებართვის გამოყენება. ჩვეულებრივი აპებისთვის არასოდეს უნდა იყოს საჭირო."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"სენსორის მონაცემებზე წვდომა სემპლინგის მაღალი სიხშირით"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"საშუალებას აძლევს აპს, მიიღოს სენსორის მონაცემების ნიმუშები 200 ჰც-ზე მეტი სიხშირით"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"პაროლის წესების დაყენება"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"აკონტროლეთ ეკრანის ბლოკირების პაროლებისა და PIN-ების სიმბოლოების სიგრძე."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"ეკრანის განბლოკვის მცდელობების მონიტორინგი"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"მალსახმობის გამოყენება"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"ფერთა ინვერსია"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"ფერთა კორექცია"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ხანგრძლივად დააჭირეთ ხმის ღილაკებს. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ჩართულია."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ხანგრძლივად დააჭირეთ ხმის ღილაკებს. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> გამორთულია."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> რომ გამოიყენოთ, დააჭირეთ ხმის ორივე ღილაკზე 3 წამის განმავლობაში"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS მოთხოვნა შეიცვალა ვიდეოზარის მოთხოვნით"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS მოთხოვნა შეიცვალა USSD მოთხოვნით"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"შეიცვალა ახალი SS მოთხოვნით"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"გაფრთხილება ფიშინგის შესახებ"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"სამსახურის პროფილი"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"გაფრთხილებით"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"გაშლა"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"მაქსიმალური ზომა"</string>
     <string name="close_button_text" msgid="10603510034455258">"დახურვა"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"პასუხი"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"უარყოფა"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"გათიშვა"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"შემომავალი ზარი"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"მიმდინარე ზარი"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"შემომავალი ზარების გაცხრილვა"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> შერჩეული</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> შერჩეული</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"გასაგრძელებლად &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt;-ს თქვენი მოწყობილობის კამერაზე წვდომა სჭირდება."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"ჩართვა"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"სენსორის კონფიდენციალურობა"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index aec2312..68edfea 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -148,8 +148,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Тек Wi-Fi"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <!-- no translation found for crossSimFormat_spn_cross_sim_calling (5620807020002879057) -->
-    <skip />
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"<xliff:g id="SPN">%s</xliff:g> Қосалқы қоңырау шалу"</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Басқа нөмірге бағытталмады"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>  <xliff:g id="TIME_DELAY">{2}</xliff:g> секундтан кейін"</string>
@@ -580,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Бұл құрылғыда саусақ ізін оқу сканері жоқ."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Датчик уақытша өшірулі."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"<xliff:g id="FINGERID">%d</xliff:g> саусағы"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Жалғастыру үшін саусақ ізін пайдаланыңыз."</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Саусақ ізі белгішесі"</string>
@@ -606,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Енді бет анықтау мүмкін емес. Әрекетті қайталаңыз."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Алдыңғысына тым ұқсас, басқаша қалыпта түсіңіз."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Басыңызды түзурек ұстаңыз."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Басыңызды түзурек ұстаңыз."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Басыңызды кішкене бұрыңыз."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Бетіңізді жауып тұрған нәрсені алып тастаңыз."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Экранның жоғарғы жағын, сонымен қатар қара жолақты өшіріңіз."</string>
@@ -685,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Қолданбаға «Мазаламау» конфигурациясын оқу және жазу мүмкіндігін береді."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"рұқсаттарды пайдалану туралы деректерді көру"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Пайдаланушы қолданбаға берілетін рұқсаттарды басқара алады. Ондай рұқсаттар әдеттегі қолданбаларға керек емес."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"жоғары дискретизация жиілігіндегі датчик деректерін пайдалану"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Қолданбаға жиілігі 200 Гц-тен жоғары датчик деректерінің үлгісін таңдауға рұқсат береді."</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Құпия сөз ережелерін тағайындау"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Экран бекітпесінің құпия сөздерінің және PIN кодтарының ұзындығын және оларда рұқсат етілген таңбаларды басқару."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Экран құлпын ашу әркеттерін бақылау"</string>
@@ -1665,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Төте жолды пайдалану"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Түстер инверсиясы"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Түсті түзету"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Пайдаланушы дыбыс деңгейі пернелерін басып ұстап тұрды. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> қосулы."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Дыбыс деңгейі пернелерін басып тұрған соң, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> өшірілді."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> қызметін пайдалану үшін дыбыс деңгейін реттейтін екі түймені де 3 секунд басып тұрыңыз"</string>
@@ -1868,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS сұрауы бейне қоңырауға өзгертілді"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS сұрауы USSD сұрауына өзгертілді"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Жаңа SS сұрауына өзгертілді"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Фишинг ескертуі"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Жұмыс профилі"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Ескертілді"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Жаю"</string>
@@ -1881,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Жазу"</string>
     <string name="close_button_text" msgid="10603510034455258">"Жабу"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Жауап"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Қабылдамау"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Тұтқаны қою"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Кіріс қоңырау"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Қоңырау"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Келген қоңырауды сүзу"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> таңдалды</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> таңдалды</item>
@@ -2209,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Жалғастыру үшін &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; қолданбасы құрылғыңыздың камерасына рұқсат алу керек."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Қосу"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Датчикке қатысты құпиялылық"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index d1400b9..b3516d5 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ឧបករណ៍នេះ​មិនមាន​ឧបករណ៍ចាប់​ស្នាមម្រាមដៃទេ។"</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"បានបិទ​ឧបករណ៍​ចាប់សញ្ញាជា​បណ្តោះអាសន្ន។"</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"ម្រាមដៃ <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"ប្រើ​ស្នាមម្រាមដៃ​របស់អ្នក ដើម្បីបន្ត"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"រូបស្នាមម្រាមដៃ"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"មិន​អាច​សម្គាល់មុខ​បាន​ទៀតទេ។ សូមព្យាយាមម្ដងទៀត។"</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"ស្រដៀងគ្នា​ពេក សូមផ្លាស់ប្ដូរ​កាយវិការ​របស់អ្នក។"</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"ងាកក្បាល​របស់អ្នកតិចជាងមុន​បន្តិច។"</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"ងាកក្បាល​របស់អ្នកតិចជាងមុន​បន្តិច។"</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"ងាកក្បាល​របស់អ្នក​បន្តិចទៀត។"</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"យកអ្វី​ដែលបាំង​មុខ​របស់អ្នកចេញ។"</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"សម្អាតផ្នែកខាង​លើនៃ​អេក្រង់​របស់​អ្នក រួមទាំង​របារខ្មៅ"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"អនុញ្ញាតឲ្យកម្មវិធីអាន និងសរសេរការកំណត់រចនាសម្ព័ន្ធមុខងារ កុំរំខាន។"</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"ចាប់ផ្ដើម​មើល​ការប្រើប្រាស់​ការអនុញ្ញាត"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"អនុញ្ញាត​ឱ្យម្ចាស់​ចាប់ផ្ដើម​ការប្រើប្រាស់​ការអនុញ្ញាត​សម្រាប់កម្មវិធី។ មិនគួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"ចូលប្រើទិន្នន័យ​ឧបករណ៍ចាប់សញ្ញា​នៅអត្រាសំណាកខ្ពស់"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"អនុញ្ញាតឱ្យកម្មវិធី​ធ្វើសំណាកទិន្នន័យ​ឧបករណ៍ចាប់សញ្ញា​នៅអត្រាលើសពី 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"កំណត់​ក្បួន​ពាក្យ​សម្ងាត់"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"គ្រប់គ្រងប្រវែង និងតួអក្សរដែលអនុញ្ញាតឲ្យប្រើក្នុងពាក្យសម្ងាត់ និងលេខសម្ងាត់ចាក់សោអេក្រង់។"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"តាមដាន​ការ​ព្យាយាម​ដោះ​សោ​អេក្រង់"</string>
@@ -1108,7 +1112,7 @@
     <string name="cut" msgid="2561199725874745819">"កាត់"</string>
     <string name="copy" msgid="5472512047143665218">"ចម្លង"</string>
     <string name="failed_to_copy_to_clipboard" msgid="725919885138539875">"មិនអាច​ចម្លងទៅ​អង្គចងចាំទេ"</string>
-    <string name="paste" msgid="461843306215520225">"បិទ​ភ្ជាប់"</string>
+    <string name="paste" msgid="461843306215520225">"ដាក់ចូល"</string>
     <string name="paste_as_plain_text" msgid="7664800665823182587">"បិទភ្ជាប់ជាអត្ថបទធម្មតា"</string>
     <string name="replace" msgid="7842675434546657444">"ជំនួស..."</string>
     <string name="delete" msgid="1514113991712129054">"លុប"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ប្រើប្រាស់​ផ្លូវកាត់"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"បញ្ច្រាស​ពណ៌"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"ការ​កែ​ពណ៌"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"បានសង្កត់​គ្រាប់ចុច​កម្រិតសំឡេង​ជាប់។ បាន​បើក <xliff:g id="SERVICE_NAME">%1$s</xliff:g>។"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"បានសង្កត់​គ្រាប់ចុច​កម្រិតសំឡេង​ជាប់។ បាន​បិទ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>។"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"ចុចគ្រាប់ចុច​កម្រិត​សំឡេងទាំងពីរ​ឱ្យជាប់រយៈពេលបីវិនាទី ដើម្បីប្រើ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"សំណើ SS ត្រូវបាន​ប្ដូរ​ទៅ​ការហៅ​ជា​វីដេអូ"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"សំណើ SS ត្រូវបាន​ប្ដូរ​ទៅ​សំណើ USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"បាន​ប្ដូរ​ទៅ​សំណើ SS ថ្មី"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"ការជូនដំណឹង​អំពីការ​ដាក់នុយ"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"ប្រវត្តិរូបការងារ"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"បាន​ជូនដំណឹង"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"ពង្រីក"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"ពង្រីក"</string>
     <string name="close_button_text" msgid="10603510034455258">"បិទ"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>៖ <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"ឆ្លើយ"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"បដិសេធ"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"ដាក់​ចុះ"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"ការ​ហៅ​ចូល"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"ការ​ហៅដែលកំពុងដំណើរការ"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"កំពុងពិនិត្យការ​ហៅ​ចូល"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other">បានជ្រើស <xliff:g id="COUNT_1">%1$d</xliff:g></item>
       <item quantity="one">បានជ្រើស <xliff:g id="COUNT_0">%1$d</xliff:g></item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"ដើម្បីបន្ត &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; ត្រូវការសិទ្ធិ​ចូលប្រើ​កាមេរ៉ា​របស់ឧបករណ៍អ្នក។"</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"បើក"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"ឯកជនភាព​ឧបករណ៍​ចាប់សញ្ញា"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 32e3c4d..22bdd77 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ಈ ಸಾಧನವು ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್‌‌ ಅನ್ನು ಹೊಂದಿಲ್ಲ."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"ಸೆನ್ಸಾರ್ ಅನ್ನು ತಾತ್ಕಾಲಿಕವಾಗಿ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"ಫಿಂಗರ್ <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"ಮುಂದುವರಿಸಲು ನಿಮ್ಮ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಬಳಸಿ"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಐಕಾನ್"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"ಮುಖ ಗುರುತಿಸಲು ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"ತುಂಬಾ ಸಮಾನ, ನಿಮ್ಮ ಪೋಸ್ ಬದಲಾಯಿಸಿ."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"ನಿಮ್ಮ ತಲೆಯನ್ನು ಹೆಚ್ಚು ತಿರುಗಿಸಬೇಡಿ."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"ನಿಮ್ಮ ತಲೆಯನ್ನು ಹೆಚ್ಚು ತಿರುಗಿಸಬೇಡಿ."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"ನಿಮ್ಮ ತಲೆಯನ್ನು ಸ್ವಲ್ಪ ಕಡಿಮೆ ತಿರುಗಿಸಿ."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"ನಿಮ್ಮ ಮುಖವನ್ನು ಮರೆಮಾಡುವ ಯಾವುದನ್ನಾದರೂ ತೆಗೆದುಹಾಕಿ."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"ಬ್ಲ್ಯಾಕ್ ಬಾರ್ ಸೇರಿದಂತೆ ನಿಮ್ಮ ಸ್ಕ್ರೀನ್‌ನ ಮೇಲ್ಭಾಗವನ್ನು ತೆರವುಗೊಳಿಸಿ"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಕಾನ್ಫಿಗರೇಶನ್ ಅನ್ನು ಓದಲು ಮತ್ತು ಬರೆಯಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"ವೀಕ್ಷಣಾ ಅನುಮತಿಯ ಬಳಕೆಯನ್ನು ಪ್ರಾರಂಭಿಸಿ"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"ಆ್ಯಪ್‌ಗಾಗಿ ಅನುಮತಿ ಬಳಕೆಯನ್ನು ಪ್ರಾರಂಭಿಸಲು ಹೊಂದಿರುವವರಿಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಸಾಮಾನ್ಯ ಆ್ಯಪ್‌ಗಳಿಗೆ ಎಂದಿಗೂ ಅಗತ್ಯವಿರುವುದಿಲ್ಲ."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"ಹೆಚ್ಚಿನ ನಮೂನೆ ದರದಲ್ಲಿ ಸೆನ್ಸಾರ್ ಡೇಟಾ ಪ್ರವೇಶಿಸಿ"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"200 Hz ಗಿಂತಲೂ ಹೆಚ್ಚಿನ ವೇಗದಲ್ಲಿ ಸೆನ್ಸಾರ್ ಡೇಟಾದ ಮಾದರಿ ಪರೀಕ್ಷಿಸಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸಿ"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"ಪಾಸ್‌ವರ್ಡ್ ನಿಮಯಗಳನ್ನು ಹೊಂದಿಸಿ"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"ಪರದೆ ಲಾಕ್‌ನಲ್ಲಿನ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು ಮತ್ತು ಪಿನ್‌ಗಳ ಅನುಮತಿಸಲಾದ ಅಕ್ಷರಗಳ ಪ್ರಮಾಣವನ್ನು ನಿಯಂತ್ರಿಸಿ."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"ಪರದೆಯ ಅನ್‌ಲಾಕ್ ಪ್ರಯತ್ನಗಳನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಿ"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ಶಾರ್ಟ್‌ಕಟ್ ಬಳಸಿ"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"ಬಣ್ಣ ವಿಲೋಮ"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"ಬಣ್ಣ ತಿದ್ದುಪಡಿ"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಹಿಡಿದುಕೊಳ್ಳಿ. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ಅನ್ನು ಆನ್ ಮಾಡಲಾಗಿದೆ."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳಲಾಗಿದೆ. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, ಆಫ್ ಮಾಡಲಾಗಿದೆ."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ಅನ್ನು ಬಳಸಲು ಎರಡೂ ಧ್ವನಿ ಕೀಗಳನ್ನು ಮೂರು ಸೆಕೆಂಡ್‌ಗಳ ಕಾಲ ಒತ್ತಿ ಹಿಡಿದುಕೊಳ್ಳಿ"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS ವಿನಂತಿಯನ್ನು ವೀಡಿಯೊ ಕರೆಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS ವಿನಂತಿಯನ್ನು USSD ವಿನಂತಿಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"ಹೊಸ SS ವಿನಂತಿಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"ಫಿಶಿಂಗ್ ಕುರಿತು ಎಚ್ಚರಿಕೆ‌"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"ಎಚ್ಚರಿಕೆ ನೀಡಲಾಗಿದೆ"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"ವಿಸ್ತೃತಗೊಳಿಸಿ"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"ಹಿಗ್ಗಿಸು"</string>
     <string name="close_button_text" msgid="10603510034455258">"ಮುಚ್ಚು"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"ಉತ್ತರಿಸಿ"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"ನಿರಾಕರಿಸಿ"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"ಹ್ಯಾಂಗ್ ಅಪ್"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"ಒಳಬರುವ ಕರೆ"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"ಚಾಲ್ತಿಯಲ್ಲಿರುವ ಕರೆ"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"ಒಳಬರುವ ಕರೆಯನ್ನು ಸ್ಕ್ರೀನ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"ಮುಂದುವರಿಯಲು, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; ಗೆ ನಿಮ್ಮ ಸಾಧನದ ಕ್ಯಾಮರಾದ ಪ್ರವೇಶದ ಅಗತ್ಯವಿದೆ."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"ಆನ್ ಮಾಡಿ"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"ಸೆನ್ಸರ್ ಗೌಪ್ಯತೆ"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 3407431..52f0a7c 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"기기에 지문 센서가 없습니다."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"센서가 일시적으로 사용 중지되었습니다."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"손가락 <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"계속하려면 지문을 사용하세요."</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"지문 아이콘"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"더 이상 얼굴을 인식할 수 없습니다. 다시 시도하세요."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"너무 비슷합니다. 다른 포즈를 취해 보세요."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"고개를 조금 덜 돌려 보세요."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"고개를 조금 덜 돌려 보세요."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"고개를 조금 덜 돌려 보세요."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"얼굴이 가려지지 않도록 해 주세요."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"검은색 바를 포함한 화면 상단을 청소하세요."</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"앱에서 방해 금지 모드 설정을 읽고 작성하도록 허용합니다."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"권한 사용 보기 시작"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"앱의 권한 사용을 시작하려면 보유자를 허용하세요. 일반 앱에는 필요하지 않습니다."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"더 높은 샘플링 레이트로 센서 데이터 액세스"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"앱에서 200Hz보다 빠른 속도로 센서 데이터를 샘플링하도록 허용합니다."</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"비밀번호 규칙 설정"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"화면 잠금 비밀번호와 PIN에 허용되는 길이와 문자 수를 제어합니다."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"화면 잠금 해제 시도 모니터링"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"단축키 사용"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"색상 반전"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"색상 보정"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"볼륨 키를 길게 눌렀습니다. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>이(가) 사용 설정되었습니다."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"볼륨 키를 길게 눌렀습니다. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>이(가) 사용 중지되었습니다."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> 서비스를 사용하려면 두 볼륨 키를 3초 동안 길게 누르세요"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS 요청이 화상 통화로 변경됨"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS 요청이 USSD 요청으로 변경됨"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"새 SS 요청으로 변경됨"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"피싱 알림"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"직장 프로필"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"알림 전송됨"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"펼치기"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"최대화"</string>
     <string name="close_button_text" msgid="10603510034455258">"닫기"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"답변"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"거절"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"전화 끊기"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"수신 전화"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"진행 중인 통화"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"수신 전화 검사 중"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>개 선택됨</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g>개 선택됨</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"계속하려면 &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt;에서 기기 카메라에 액세스해야 합니다."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"사용"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"센서 개인정보 보호"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 9a84d0a..4d8888e 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -298,7 +298,7 @@
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Батареянын кубаты жана трафиктин көлөмү жөнүндө билүү үчүн таптап коюңуз"</string>
     <string name="foreground_service_multiple_separator" msgid="5002287361849863168">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string>
     <string name="safeMode" msgid="8974401416068943888">"Коопсуз режим"</string>
-    <string name="android_system_label" msgid="5974767339591067210">"Android тутуму"</string>
+    <string name="android_system_label" msgid="5974767339591067210">"Android системасы"</string>
     <string name="user_owner_label" msgid="8628726904184471211">"Жеке профилге которулуу"</string>
     <string name="managed_profile_label" msgid="7316778766973512382">"Жумуш профилине которулуу"</string>
     <string name="permgrouplab_contacts" msgid="4254143639307316920">"Байланыштар"</string>
@@ -314,7 +314,7 @@
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Микрофон"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"аудио жаздыруу"</string>
     <string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"Кыймыл-аракет"</string>
-    <string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"кыймыл-аракетиңизге мүмкүнчүлүк алат"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"кыймыл-аракеттериңизге көз салып турганга мүмкүнчүлүк алат"</string>
     <string name="permgrouplab_camera" msgid="9090413408963547706">"Камера"</string>
     <string name="permgroupdesc_camera" msgid="7585150538459320326">"сүрөт жана видео тартууга"</string>
     <string name="permgrouplab_calllog" msgid="7926834372073550288">"Чалуулар тизмеси"</string>
@@ -332,7 +332,7 @@
     <string name="capability_title_canControlMagnification" msgid="7701572187333415795">"Көрүнүштү чоңойтуп кичирейтет"</string>
     <string name="capability_desc_canControlMagnification" msgid="2206586716709254805">"Экрандагы сүрөттү тууралап жайгаштырып, өлчөмүн өзгөртөт."</string>
     <string name="capability_title_canPerformGestures" msgid="9106545062106728987">"Жаңсоолорду аткаруу"</string>
-    <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Таптап, серпип, чымчып жана башка жаңсоолорду аткара алат."</string>
+    <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Таптап, сүрүп, чымчып жана башка жаңсоолорду аткара алат."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Манжа изинин жаңсоолору"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Түзмөктөгү манжа изинин сенсорунда жасалган жаңсоолорду жаздырып алат."</string>
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Скриншот тартып алуу"</string>
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Бул түзмөктө манжа изинин сенсору жок."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Сенсор убактылуу өчүрүлгөн."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"<xliff:g id="FINGERID">%d</xliff:g>-манжа"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Улантуу үчүн манжаңыздын изин колдонуңуз"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Манжа изинин сүрөтчөсү"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Жүз таанылган жок. Кайталап көрүңүз."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Мурункуга окшош болуп калды, башкача туруңуз."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Башыңызды бир аз гана эңкейтиңиз."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Башыңызды бир аз гана эңкейтиңиз."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Башыңызды бир аз гана эңкейтиңиз."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Жүзүңүздү жашырып турган нерселерди алып салыңыз."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Экраныңыздын жогору жагын, анын ичинде тилкени да тазалаңыз"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Колдонмого \"Тынчымды алба\" режиминин конфигурациясын окуу жана жазуу мүмкүнчүлүгүн берет."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"уруксаттын колдонулушун көрүп баштоо"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Колдонмонун пайдаланылышына уруксат берүүгө мүмкүнчүлүк берет. Кадимки колдонмолорго эч качан талап кылынбашы керек."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"үлгүнү жаздыруу ылдамдыгы жогору болгон сенсор дайындарынын үлгүсүнө мүмкүнчүлүк алуу"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Колдонмолорго сенсор дайындарынын үлгүсү 200 Герцтен жогору болгон үлгүлөрдү алууга уруксат берет"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Сырсөз эрежелерин коюу"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Экран кулпусунун сырсөздөрү менен PIN\'дерине уруксат берилген узундук менен белгилерди көзөмөлдөө."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Экран кулпусун ачуу аракеттерин көзөмөлдөө"</string>
@@ -886,7 +890,7 @@
     <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="2203704707679895487">"Сиз телефонду бөгөттөн чыгарууга <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес аракет кылдыңыз. Телефон баштапкы абалына келтирилет."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6807200118164539589">"<xliff:g id="NUMBER">%d</xliff:g> секунддан кийин кайталаңыз."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="8362442730606839031">"Сүрөт үлгүсүн унутуп калдыңызбы?"</string>
-    <string name="lockscreen_glogin_forgot_pattern" msgid="9218940117797602518">"Каттоо эсеби менен кулпусун ачуу"</string>
+    <string name="lockscreen_glogin_forgot_pattern" msgid="9218940117797602518">"Аккаунт менен кулпусун ачуу"</string>
     <string name="lockscreen_glogin_too_many_attempts" msgid="3775904917743034195">"Өтө көп үлгү киргизүү аракети болду"</string>
     <string name="lockscreen_glogin_instructions" msgid="4695162942525531700">"Бөгөттөн чыгарыш үчүн, Google эсебиңиз менен кириңиз."</string>
     <string name="lockscreen_glogin_username_hint" msgid="6916101478673157045">"Колдонуучунун аты (электрондук почта)"</string>
@@ -1203,7 +1207,7 @@
     <string name="unsupported_compile_sdk_check_update" msgid="1103639989147664456">"Жаңыртууну издөө"</string>
     <string name="smv_application" msgid="3775183542777792638">"<xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосу (<xliff:g id="PROCESS">%2$s</xliff:g> процесси) өз алдынча иштеткен StrictMode саясатын бузду."</string>
     <string name="smv_process" msgid="1398801497130695446">"<xliff:g id="PROCESS">%1$s</xliff:g> процесси өзүнүн мажбурланган StrictMode саясатын бузуп койду."</string>
-    <string name="android_upgrading_title" product="default" msgid="7279077384220829683">"Телефон жаңыртылууда…"</string>
+    <string name="android_upgrading_title" product="default" msgid="7279077384220829683">"Телефон жаңырууда…"</string>
     <string name="android_upgrading_title" product="tablet" msgid="4268417249079938805">"Планшет жаңыртылууда…"</string>
     <string name="android_upgrading_title" product="device" msgid="6774767702998149762">"Түзмөк жаңыртылууда…"</string>
     <string name="android_start_title" product="default" msgid="4036708252778757652">"Телефон күйгүзүлүүдө…"</string>
@@ -1213,7 +1217,7 @@
     <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Сактагыч ыңгайлаштырылууда."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Тутумду жаңыртуу аяктоодо…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> жаңыртылууда..."</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_1">%2$d</xliff:g> ичинен <xliff:g id="NUMBER_0">%1$d</xliff:g> колдонмо ыңгайлаштырылууда."</string>
+    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_1">%2$d</xliff:g> ичинен <xliff:g id="NUMBER_0">%1$d</xliff:g> колдонмо оптималдаштырылууда."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> даярдалууда."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Колдонмолорду иштетип баштоо"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Жүктөлүүдө"</string>
@@ -1664,12 +1668,14 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Кыска жолду колдонуу"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Түстү инверсиялоо"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Түсүн тууралоо"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Үндү катуулатуу/акырындатуу баскычтары басылып, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> күйгүзүлдү."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Үндү катуулатуу/акырындатуу баскычтары басылып, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> өчүрүлдү."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> кызматын колдонуу үчүн үнүн чоңойтуп/кичирейтүү баскычтарын үч секунд коё бербей басып туруңуз"</string>
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Атайын мүмкүнчүлүктөр баскычын таптаганыңызда иштей турган функцияны тандаңыз:"</string>
-    <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Атайын мүмкүнчүлүктөр жаңсоосу үчүн функцияны тандаңыз (эки манжаңыз менен экрандын ылдый жагынан өйдө карай сүрүңүз):"</string>
-    <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Атайын мүмкүнчүлүктөр жаңсоосу аркылуу иштетиле турган функцияны тандаңыз (үч манжаңыз менен экрандын ылдый жагынан өйдө карай сүрүңүз):"</string>
+    <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Атайын мүмкүнчүлүктөр жаңсоосу үчүн функцияны тандаңыз (эки манжаңыз менен экранды ылдыйдан өйдө сүрүңүз):"</string>
+    <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Атайын мүмкүнчүлүктөр жаңсоосу аркылуу иштетиле турган функцияны тандаңыз (үч манжаңыз менен экранды ылдыйдан өйдө сүрүңүз):"</string>
     <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"Функцияларды которуштуруу үчүн, Атайын мүмкүнчүлүктөр баскычын басып, кармап туруңуз."</string>
     <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"Функцияларды которуштуруу үчүн, эки манжаңыз менен өйдө сүрүп, кармап туруңуз."</string>
     <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"Башка функцияга которулуу үчүн үч манжаңыз менен экранды өйдө сүрүп, кармап туруңуз."</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS сурамы видео чалууга өзгөртүлдү"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS сурамы USSD сурамына өзгөртүлдү"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Жаңы SS сурамына өзгөртүлдү"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Фишинг жөнүндө эскертүү"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Жумуш профили"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Эскертилди"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Жайып көрсөтүү"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Чоңойтуу"</string>
     <string name="close_button_text" msgid="10603510034455258">"Жабуу"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Жооп берүү"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Четке кагуу"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Чалууну бүтүрүү"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Кирүүчү чалуу"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Учурдагы чалуу"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Кирүүчү чалууну иргөө"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> тандалды</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> тандалды</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Улантуу үчүн &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; колдонмосуна түзмөгүңүздүн камерасын пайдаланууга уруксат беришиңиз керек."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Күйгүзүү"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Сенсордун купуялыгы"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml
index 9e87a47..42c2c69 100644
--- a/core/res/res/values-land/dimens.xml
+++ b/core/res/res/values-land/dimens.xml
@@ -78,4 +78,5 @@
 
     <dimen name="chooser_preview_width">480dp</dimen>
 
+    <dimen name="toast_y_offset">24dp</dimen>
 </resources>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 9977f9f..87c2ceb 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -148,8 +148,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi​-Fi ເທົ່າ​ນັ້ນ"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <!-- no translation found for crossSimFormat_spn_cross_sim_calling (5620807020002879057) -->
-    <skip />
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"<xliff:g id="SPN">%s</xliff:g> ການໂທສຳຮອງ"</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ບໍ່ຖືກສົ່ງຕໍ່"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> ຫຼັງຈາກ <xliff:g id="TIME_DELAY">{2}</xliff:g> ວິນາທີ"</string>
@@ -580,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ອຸປະກອນນີ້ບໍ່ມີເຊັນເຊີລາຍນິ້ວມື."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"ປິດການເຮັດວຽກຂອງເຊັນເຊີໄວ້ຊົ່ວຄາວແລ້ວ."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"ນີ້ວ​ມື <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"ໃຊ້​ລາຍ​ນີ້ວ​ມື​ຂອງ​ທ່ານ​ເພື່ອ​ສືບ​ຕໍ່"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ໄອຄອນລາຍນິ້ວມື"</string>
@@ -606,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"ບໍ່ສາມາດຈຳແນກໃບໜ້າໄດ້ອີກຕໍ່ໄປ. ກະລຸນາລອງໃໝ່."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"ຄ້າຍກັນເກີນໄປ, ກະລຸນາປ່ຽນທ່າຂອງທ່ານ."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"ອຽງຫົວຂອງທ່ານໜ້ອຍໜຶ່ງ."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"ອຽງຫົວຂອງທ່ານໜ້ອຍໜຶ່ງ."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"ອຽງຫົວຂອງທ່ານໜ້ອຍໜຶ່ງ."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"ນຳສິ່ງທີ່ກີດຂວາງໃບໜ້າທ່ານອອກ."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"ທຳຄວາມສະອາດສ່ວນເທິງສຸດຂອງໜ້າຈໍທ່ານ, ຮວມທັງແຖບດຳນຳ"</string>
@@ -685,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"ອະນຸຍາດ​​ໃຫ້​ແອັບ​ອ່ານ​ ​ແລະ​ຂຽນການກນຳ​ດຄ່າ ບໍ່​ລົບ​ກວນ."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"ເລີ່ມການໃຊ້ສິດອະນຸຍາດການເບິ່ງ"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"ອະນຸຍາດໃຫ້ຜູ້ຖືເລີ່ມການໃຊ້ສິດອະນຸຍາດສຳລັບແອັບໃດໜຶ່ງໄດ້. ແອັບປົກກະຕິບໍ່ຄວນຕ້ອງໃຊ້."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"ເຂົ້າເຖິງຂໍ້ມູນເຊັນເຊີໃນອັດຕາຕົວຢ່າງສູງ"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"ອະນຸຍາດໃຫ້ແອັບສຸ່ມຕົວຢ່າງຂໍ້ມູນເຊັນເຊີໃນອັດຕາທີ່ຫຼາຍກວ່າ 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"ຕັ້ງຄ່າກົດຂອງລະຫັດຜ່ານ"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"ຄວບຄຸມຄວາມຍາວ ແລະຕົວອັກສອນທີ່ອະ​ນຸ​ຍາດ​ໃຫ້​ຢູ່​ໃນລະ​ຫັດລັອກໜ້າຈໍ ແລະ PIN."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"ຕິດຕາມການພະຍາຍາມປົດລັອກໜ້າຈໍ"</string>
@@ -1665,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ໃຊ້ປຸ່ມລັດ"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"ການປີ້ນສີ"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"ການແກ້ໄຂຄ່າສີ"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ກົດປຸ່ມລະດັບສຽງຄ້າງໄວ້. ເປີດໃຊ້ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ແລ້ວ."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ກົດປຸ່ມລະດັບສຽງຄ້າງໄວ້. ປິດ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ໄວ້ແລ້ວ."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"ກົດປຸ່ມສຽງທັງສອງພ້ອມກັນຄ້າງໄວ້ສາມວິນາທີເພື່ອໃຊ້ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1868,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"ປ່ຽນການຮ້ອງຂໍ SS ເປັນການໂທວິດີໂອແລ້ວ"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"ປ່ຽນຄຳຂໍ SS ເປັນຄຳຂໍ USSD ແລ້ວ"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"ປ່ຽນຄຳຂໍ SS ໃໝ່ແລ້ວ"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"ການແຈ້ງເຕືອນການຫຼອກເອົາຂໍ້ມູນ"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"​ໂປຣ​ໄຟລ໌​ບ່ອນ​ເຮັດ​ວຽກ"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"ເຕືອນແລ້ວ"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"ຂະຫຍາຍ"</string>
@@ -1881,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"ຂະຫຍາຍອອກ"</string>
     <string name="close_button_text" msgid="10603510034455258">"ປິດ"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"ຮັບສາຍ"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"ປະຕິເສດ"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"ວາງສາຍ"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"ສາຍໂທເຂົ້າ"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"ສາຍໂທອອກ"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"ກຳລັງກວດສອບສາຍໂທເຂົ້າ"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ຖືກເລືອກ​ແລ້ວ</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ຖືກເລືອກ​ແລ້ວ</item>
@@ -2209,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"ເພື່ອດຳເນີນການຕໍ່, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; ຕ້ອງການສິດເຂົ້າເຖິງກ້ອງຖ່າຍຮູບຂອງອຸປະກອນທ່ານ."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"ເປີດໃຊ້"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"ຄວາມເປັນສ່ວນຕົວເຊັນເຊີ"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 5f72e07..2c3742b 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -585,6 +585,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Šiame įrenginyje nėra kontrolinio kodo jutiklio."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Jutiklis laikinai išjungtas."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"<xliff:g id="FINGERID">%d</xliff:g> pirštas"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Naudokite kontrolinį kodą, kad galėtumėte tęsti"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Piršto antspaudo piktograma"</string>
@@ -611,7 +612,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Nebegalima atpažinti veido. Bandykite dar kartą."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Per daug panašu, pakeiskite veido išraišką."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Nesukite tiek galvos."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Nesukite tiek galvos."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Nesukite tiek galvos."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Patraukite viską, kas užstoja jūsų veidą."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Išvalykite ekrano viršų, įskaitant juodą juostą"</string>
@@ -690,6 +692,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Leidžiama programai skaityti ir rašyti „Do Not Disturb“ konfigūraciją."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"pradėti peržiūrėti leidimo naudojimą"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Leidžia savininkui pradėti naudoti programos leidimą. Įprastoms programoms to neturėtų prireikti."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"pasiekti jutiklių duomenis dideliu skaitmeninimo dažniu"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Programai leidžiama skaitmeninti jutiklių duomenis didesniu nei 200 Hz dažniu"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Nustatyti slaptažodžio taisykles"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Valdykite, kokio ilgio ekrano užrakto slaptažodžius ir PIN kodus galima naudoti."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Stebėti bandymus atrakinti ekraną"</string>
@@ -1708,6 +1712,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Naudoti spartųjį klavišą"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Spalvų inversija"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Spalvų taisymas"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Laikomi garsumo klavišai. „<xliff:g id="SERVICE_NAME">%1$s</xliff:g>“ įjungta."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Laikomi garsumo klavišai. „<xliff:g id="SERVICE_NAME">%1$s</xliff:g>“ išjungta."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Jei norite naudoti „<xliff:g id="SERVICE_NAME">%1$s</xliff:g>“, paspauskite abu garsumo klavišus ir palaikykite tris sekundes"</string>
@@ -1929,6 +1935,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS užklausa pakeista į vaizdo skambutį"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS užklausa pakeista į USSD užklausą"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Pakeista į naują SS užklausą"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Įspėjimas apie sukčiavimą"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Darbo profilis"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Įspėjimas išsiųstas"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Išskleisti"</string>
@@ -1942,6 +1949,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Padidinti"</string>
     <string name="close_button_text" msgid="10603510034455258">"Uždaryti"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Atsakyti"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Atmesti"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Baigti pok."</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Gaunamasis skambutis"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Vykstantis skambutis"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Gaunamojo skambučio tikrinimas"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one">Pasir. <xliff:g id="COUNT_1">%1$d</xliff:g> elem.</item>
       <item quantity="few">Pasir. <xliff:g id="COUNT_1">%1$d</xliff:g> elem.</item>
@@ -2276,4 +2289,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Kad būtų galima tęsti, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; reikalinga prieiga prie įrenginio fotoaparato."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Įjungti"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Jutiklių privatumas"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 37e417f..8d6ce86 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -582,6 +582,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Šajā ierīcē nav pirksta nospieduma sensora."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensors ir īslaicīgi atspējots."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"<xliff:g id="FINGERID">%d</xliff:g>. pirksts"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Lai turpinātu, izmantojiet pirksta nospiedumu"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Pirksta nospieduma ikona"</string>
@@ -608,7 +609,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Seju vairs nevar atpazīt. Mēģiniet vēlreiz."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Pārāk līdzīgi. Lūdzu, mainiet pozu."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Pagrieziet galvu nedaudz mazāk."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Pagrieziet galvu nedaudz mazāk."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Pagrieziet galvu nedaudz mazāk."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Noņemiet visu, kas aizsedz jūsu seju."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Notīriet ekrāna augšdaļu, tostarp melno joslu."</string>
@@ -687,6 +689,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Ļauj lietotnei lasīt un rakstīt režīma “Netraucēt” konfigurāciju."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"Datu skatīšana par izmantojamajām atļaujām"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Ļauj atļaujas īpašniekam sākt lietotnes atļauju izmantošanu. Parastām lietotnēm tas nekad nav nepieciešams."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"piekļuve sensoru datiem, izmantojot augstu iztveršanas frekvenci"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Ļauj lietotnei iztvert sensoru datus, izmantojot frekvenci, kas ir augstāka par 200 Hz."</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Paroles kārtulu iestatīšana"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Kontrolēt ekrāna bloķēšanas paroļu un PIN garumu un tajos atļautās rakstzīmes."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Ekrāna atbloķēšanas mēģinājumu pārraudzīšana"</string>
@@ -1686,6 +1690,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Izmantot saīsni"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Krāsu inversija"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Krāsu korekcija"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Turējāt nospiestas skaļuma pogas. Pakalpojums <xliff:g id="SERVICE_NAME">%1$s</xliff:g> tika ieslēgts."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Turējāt nospiestas skaļuma pogas. Pakalpojums <xliff:g id="SERVICE_NAME">%1$s</xliff:g> tika izslēgts."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Lai izmantotu pakalpojumu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, nospiediet abus skaļuma taustiņus un turiet tos trīs sekundes."</string>
@@ -1898,6 +1904,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS pieprasījums mainīts uz videozvanu"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS pieprasījums mainīts uz USSD pieprasījumu"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Mainīts uz jaunu SS pieprasījumu"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Brīdinājums par pikšķerēšanu"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Darba profils"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Brīdināts"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Izvērst"</string>
@@ -1911,6 +1918,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maksimizēt"</string>
     <string name="close_button_text" msgid="10603510034455258">"Aizvērt"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Atbildēt"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Noraidīt"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Pārtraukt"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Ienākošais zvans"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Pašreizējais zvans"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Ienākošā zvana filtrēšana"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="zero"><xliff:g id="COUNT_1">%1$d</xliff:g> atlasīti</item>
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> atlasīts</item>
@@ -2242,4 +2255,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Lai turpinātu, lietotnei &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; nepieciešama piekļuve jūsu ierīces kamerai."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Ieslēgt"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Sensoru konfidencialitāte"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mcc310-mnc950-si/strings.xml b/core/res/res/values-mcc310-mnc950-si/strings.xml
new file mode 100644
index 0000000..26fe4ac
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc950-si/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="615419724607901560">"SIM MM#2 ප්‍රතිපාදනය නොකරයි"</string>
+    <string name="mmcc_illegal_ms" msgid="7801541624846497489">"SIM MM#3 ඉඩ නොදේ"</string>
+    <string name="mmcc_illegal_me" msgid="7066936962628406316">"දුරකථනය MM#6 ඉඩ නොදේ"</string>
+</resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 5666cc2..af3ce00 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Уредов нема сензор за отпечатоци."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Сензорот е привремено оневозможен."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Прст <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Користете го отпечатокот за да продолжите"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Икона за отпечатоци"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Ликот не се препознава. Обидете се повторно."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Премногу слично, сменете ја позата."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Не вртете ја главата толку многу."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Не вртете ја главата толку многу."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Не вртете ја главата толку многу."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Отстранете ги работите што ви го покриваат лицето."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Исчистете го врвот на екранот, вклучувајќи ја црната лента"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Дозволува апликацијата да чита и пишува конфигурација Не вознемирувај."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"започнете со користење на дозволата за приказ"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Дозволува сопственикот да почне со користење на дозволата за апликација. Не треба да се користи за стандардни апликации."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"пристапува до податоците со висока фреквенција на семпл"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Дозволува апликацијата да пристапува до податоците од сензорите со фреквенција на семпл поголема од 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Постави правила за лозинката"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Контролирај ги должината и знаците што се дозволени за лозинки и PIN-броеви за отклучување екран."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Следи ги обидите за отклучување на екранот"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Користи кратенка"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Инверзија на бои"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Корекција на бои"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ги задржавте копчињата за јачина на звук. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е вклучена."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ги задржавте копчињата за јачина на звук. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е исклучена."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Притиснете ги и задржете ги двете копчиња за јачина на звукот во траење од три секунди за да користите <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Барањето SS е изменето во видео повик"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Барањето SS е изменето во барање USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Променето на ново барање SS"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Предупредување за фишинг"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Работен профил"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Предупредено"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Прошири"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Зголеми"</string>
     <string name="close_button_text" msgid="10603510034455258">"Затвори"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Одговори"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Одбиј"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Спушти"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Дојдовен повик"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Тековен повик"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Проверка на дојдовен повик"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> е избрана</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> се избрани</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"За да продолжи, на &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; ѝ е потребен пристап до камерата на уредот."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Вклучи"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Приватност на сензорот"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index e0d4b01..aaab7b5 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -148,8 +148,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"വൈഫൈ മാത്രം"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <!-- no translation found for crossSimFormat_spn_cross_sim_calling (5620807020002879057) -->
-    <skip />
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"<xliff:g id="SPN">%s</xliff:g> ബാക്കപ്പ് കോളിംഗ്"</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: കൈമാറിയില്ല"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> നിമിഷത്തിനുശേഷം <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -580,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ഈ ഉപകരണത്തിൽ ഫിംഗർപ്രിന്റ് സെൻസറില്ല."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"സെൻസർ താൽക്കാലികമായി പ്രവർത്തനരഹിതമാക്കി."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"കൈവിരൽ <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"തുടരുന്നതിന് നിങ്ങളുടെ ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കുക"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ഫിംഗർപ്രിന്റ് ഐക്കൺ"</string>
@@ -606,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"ഇനി മുഖം തിരിച്ചറിയാനാവില്ല. വീണ്ടും ശ്രമിക്കൂ."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"വളരെയധികം സമാനത, നിങ്ങളുടെ പോസ് മാറ്റുക."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"നിങ്ങളുടെ തല ഇത്ര തിരിക്കേണ്ട."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"നിങ്ങളുടെ തല ഇത്ര തിരിക്കേണ്ട."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"നിങ്ങളുടെ തല ഇത്ര തിരിക്കേണ്ട."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"നിങ്ങളുടെ മുഖം മറയ്‌ക്കുന്നത് എല്ലാം നീക്കം ചെയ്യൂ."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"കറുപ്പ് ബാർ ഉൾപ്പെടെ നിങ്ങളുടെ സ്ക്രീനിന്റെ മുകൾഭാഗം വൃത്തിയാക്കുക"</string>
@@ -685,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"\'ശല്യപ്പെടുത്തരുത്\' കോൺഫിഗറേഷൻ വായിക്കുന്നതിനും എഴുതുന്നതിനും ആപ്പിനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"അനുമതി ഉപയോഗം കാണാൻ ആരംഭിക്കുക"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"ഒരു ആപ്പിനുള്ള അനുമതി ഉപയോഗം ആരംഭിക്കാൻ ഹോൾഡറിനെ അനുവദിക്കുന്നു. സാധാരണ ആപ്പുകൾക്ക് ഒരിക്കലും ആവശ്യമില്ല."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"ഉയർന്ന സാം‍പ്ലിംഗ് റേറ്റിൽ സെൻസർ ഡാറ്റ ആക്സസ് ചെയ്യുക"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"200 Hz-നേക്കാൾ ഉയർന്ന റേറ്റിൽ സെൻസർ ഡാറ്റ സാമ്പിൾ ചെയ്യാൻ ആപ്പിനെ അനുവദിക്കുന്നു"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"പാസ്‌വേഡ് നിയമങ്ങൾ സജ്ജീകരിക്കുക"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"സ്‌ക്രീൻ ലോക്ക് പാസ്‌വേഡുകളിലും PIN-കളിലും അനുവദിച്ചിരിക്കുന്ന ദൈർഘ്യവും പ്രതീകങ്ങളും നിയന്ത്രിക്കുക."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"സ്‌ക്രീൻ അൺലോക്ക് ശ്രമങ്ങൾ നിരീക്ഷിക്കുക"</string>
@@ -1665,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"കുറുക്കുവഴി ഉപയോഗിക്കുക"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"വർണ്ണ വിപര്യയം"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"നിറം ക്രമീകരിക്കൽ"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"വോളിയം കീകൾ പിടിച്ചു. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഓണാക്കി."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"വോളിയം കീകൾ അമർത്തിപ്പിടിച്ചു. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഓഫാക്കി."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഉപയോഗിക്കാൻ, രണ്ട് വോളിയം കീകളും മൂന്ന് സെക്കൻഡ് അമർത്തിപ്പിടിക്കുക"</string>
@@ -1868,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS അഭ്യർത്ഥന, വീഡിയോ കോളിലേക്ക് മാറ്റി"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS അഭ്യർത്ഥന, USSD അഭ്യർത്ഥനയിലേക്ക് മാറ്റി"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"പുതിയ SS അഭ്യർത്ഥനയിലേക്ക് മാറ്റി"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"ഫിഷിംഗ് മുന്നറിയിപ്പ്"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"ഔദ്യോഗിക പ്രൊഫൈൽ"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"മുന്നറിയിപ്പ് നൽകി"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"വികസിപ്പിക്കുക"</string>
@@ -1881,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"വലുതാക്കുക"</string>
     <string name="close_button_text" msgid="10603510034455258">"അവസാനിപ്പിക്കുക"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"മറുപടി നൽകുക"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"നിരസിക്കുക"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"കോൾ നിർത്തുക"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"ഇൻകമിംഗ് കോൾ"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"സജീവമായ കോൾ"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"ഇൻകമിംഗ് കോൾ സ്‌ക്രീൻ ചെയ്യൽ"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> എണ്ണം തിരഞ്ഞെടുത്തു</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> എണ്ണം തിരഞ്ഞെടുത്തു</item>
@@ -2209,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"തുടരാൻ, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; ആപ്പിന് നിങ്ങളുടെ ഉപകരണത്തിന്റെ ക്യാമറയിലേക്ക് ആക്‌സസ് നൽകേണ്ടതുണ്ട്."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"ഓണാക്കുക"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"സെൻസർ സ്വകാര്യത"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 891ac47..c699285 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -325,7 +325,7 @@
     <string name="permgroupdesc_sensors" msgid="2610631290633747752">"таны биеийн байдлын талаарх мэдрэгч бүхий өгөгдөлд нэвтрэх"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Цонхны агуулгыг авах"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Таны харилцан үйлчлэх цонхны контентоос шалгах."</string>
-    <string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Хүрч танихыг асаах"</string>
+    <string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Хүрэлтээр сонсохыг асаах"</string>
     <string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"Товшсон зүйлсийг чангаар хэлэх ба дэлгэцийг дохио ашиглан таних боломжтой."</string>
     <string name="capability_title_canRequestFilterKeyEvents" msgid="2772371671541753254">"Бичсэн текстээ ажиглах"</string>
     <string name="capability_desc_canRequestFilterKeyEvents" msgid="2381315802405773092">"Кредит картын дугаар болон нууц үг зэрэг хувийн датаг агуулж байна."</string>
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Энэ төхөөрөмжид хурууны хээ мэдрэгч алга."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Мэдрэгчийг түр хугацаанд идэвхгүй болгосон."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Хурууны хээ <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Үргэлжлүүлэхийн тулд хурууны хээгээ ашиглаарай"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Хурууны хээний дүрс"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Царайг таних боломжгүй боллоо. Дахин оролдоно уу."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Хэт адилхан байгаа тул байрлалаа өөрчилнө үү."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Толгойгоо арай багаар эргүүлнэ үү."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Толгойгоо арай багаар эргүүлнэ үү."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Толгойгоо арай багаар эргүүлнэ үү."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Таны нүүрийг далдалж буй аливаа зүйлийг хасна уу."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Хар хэсэг зэрэг дэлгэцийнхээ дээд хэсгийг цэвэрлэнэ үү"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Апп-д Бүү саад бол тохируулгыг уншиж, бичихийг зөвшөөрөх"</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"зөвшөөрлийн ашиглалтыг харж эхлэх"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Эзэмшигчид аппын зөвшөөрлөө ашиглаж эхлэхийг зөвшөөрдөг. Энгийн аппуудад шаардлагагүй."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"түүврийн өндөр хувиар мэдрэгчийн өгөгдөлд хандах"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Аппад 200 Гц-ээс их хувиар мэдрэгчийн өгөгдлийг түүвэрлэх боломжийг олгодог"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Нууц үгний дүрмийг тохируулах"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Дэлгэц түгжих нууц үг болон ПИН кодны урт болон нийт тэмдэгтийн уртыг хянах."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Дэлгэцийн түгжээг тайлах оролдлогыг хянах"</string>
@@ -1002,9 +1006,9 @@
     <string name="searchview_description_clear" msgid="1989371719192982900">"Асуулгыг цэвэрлэх"</string>
     <string name="searchview_description_submit" msgid="6771060386117334686">"Асуулгыг илгээх"</string>
     <string name="searchview_description_voice" msgid="42360159504884679">"Дуут хайлт"</string>
-    <string name="enable_explore_by_touch_warning_title" msgid="5095399706284943314">"Хүрч хайх функцийг идэвхтэй болгох уу?"</string>
-    <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="1037295476738940824">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> нь Хүрч танихыг идэвхжүүлэхийг шаардаж байна. Хүрч таних идэвхжсэн үед та хуруун доороо юу байгааг сонсох, тайлбарыг харах боломжтой ба таблеттайгаа дохиогоор харилцах боломжтой."</string>
-    <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> нь Хүрч танихыг идэвхжүүлэхийг шаардаж байна. Хүрч таних идэвхжсэн тохиолдолд та хуруун доороо юу байгааг сонсох, тайлбарыг харах боломжтой ба утастайгаа дохиогоор харилцах боломжтой."</string>
+    <string name="enable_explore_by_touch_warning_title" msgid="5095399706284943314">"Хүрэлтээр сонсохыг идэвхжүүлэх үү?"</string>
+    <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="1037295476738940824">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> нь Хүрэлтээр сонсохыг идэвхжүүлэхийг шаардаж байна. Хүрэлтээр сонсох идэвхжсэн үед та хуруун доороо юу байгааг сонсох, тайлбарыг харах боломжтой ба таблеттайгаа дохиогоор харилцах боломжтой."</string>
+    <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> нь Хүрэлтээр сонсохыг идэвхжүүлэхийг шаардаж байна. Хүрэлтээр сонсох идэвхжсэн тохиолдолд та хуруун доороо юу байгааг сонсох, тайлбарыг харах боломжтой ба утастайгаа дохиогоор харилцах боломжтой."</string>
     <string name="oneMonthDurationPast" msgid="4538030857114635777">"1 сарын өмнө"</string>
     <string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"1 сарын өмнө"</string>
     <plurals name="last_num_days" formatted="false" msgid="687443109145393632">
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Товчлол ашиглах"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Өнгө хувиргалт"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Өнгөний засвар"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Дууны түвшний түлхүүрийг удаан дарсан. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>-г асаалаа."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Дууны түвшний түлхүүрийг удаан дарсан. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>-г унтраалаа."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>-г ашиглахын тулд дууны түвшнийг ихэсгэх, багасгах түлхүүрийг 3 секундийн турш зэрэг дарна уу"</string>
@@ -1867,11 +1873,12 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS хүсэлтийг видео дуудлага болгон өөрчилсөн"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS хүсэлтийг USSD хүсэлт болгон өөрчилсөн"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Шинэ SS хүсэлт болгон өөрчилсөн"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Фишинг сэрэмжлүүлэг"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Ажлын профайл"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Мэдэгдсэн"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Дэлгэх"</string>
     <string name="expand_button_content_description_expanded" msgid="7484217944948667489">"Буулгах"</string>
-    <string name="expand_action_accessibility" msgid="1947657036871746627">"унтраах/асаах өргөтгөл"</string>
+    <string name="expand_action_accessibility" msgid="1947657036871746627">"асаах/унтраах өргөтгөл"</string>
     <string name="usb_midi_peripheral_name" msgid="490523464968655741">"Андройд USB Peripheral Port"</string>
     <string name="usb_midi_peripheral_manufacturer_name" msgid="7557148557088787741">"Android"</string>
     <string name="usb_midi_peripheral_product_name" msgid="2836276258480904434">"USB Peripheral Port"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Томруулах"</string>
     <string name="close_button_text" msgid="10603510034455258">"Хаах"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Хариулах"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Татгалзах"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Таслах"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Ирсэн дуудлага"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Дуудлага хийгдэж байна"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Ирсэн дуудлагыг харуулж байна"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> сонгосон</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> сонгосон</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Үргэлжлүүлэхийн тулд &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; таны төхөөрөмжийн камерт хандах шаардлагатай."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Асаах"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Мэдрэгчийн нууцлал"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index d57c4c1..a31951a 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -148,8 +148,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"केवळ वाय-फाय"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <!-- no translation found for crossSimFormat_spn_cross_sim_calling (5620807020002879057) -->
-    <skip />
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"<xliff:g id="SPN">%s</xliff:g> बॅकअप कॉलिंग"</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: फॉरवर्ड केला नाही"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> सेकंदांनंतर <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -580,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"या डिव्हाइसमध्ये फिंगरप्रिंट सेन्सर नाही."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"सेन्सर तात्पुरता बंद केला आहे."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"<xliff:g id="FINGERID">%d</xliff:g> बोट"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"पुढे सुरू ठेवण्‍यासाठी तुमची फिंगरप्रिंट वापरा"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"फिंगरप्रिंट आयकन"</string>
@@ -606,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"चेहरा ओळखू शकत नाही. पुन्हा प्रयत्न करा."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"एकाच प्रकारची पोझ देत आहात कृपया तुमची पोझ बदला."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"तुमचे डोके थोडे कमी फिरवा."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"तुमचे डोके थोडे कमी फिरवा."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"तुमचे डोके थोडे कमी फिरवा."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"तुमचा चहेरा लपवणारे काहीही काढून टाका."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"ब्लॅक बार सह तुमच्या स्क्रीनची वरची बाजू साफ करा"</string>
@@ -685,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"व्यत्यय आणू नका कॉंफिगरेशन वाचण्यासाठी आणि लिहिण्यासाठी ॲपला अनुमती देते."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"व्ह्यू परवानगी वापर सुरू करा"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"धारकास अ‍ॅपसाठी परवानगी वापरणे सुरू करण्याची अनुमती देते. सामान्य अ‍ॅप्ससाठी कधीही आवश्यकता नसते."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"उच्च नमुना दराने सेन्सर डेटा अ‍ॅक्सेस करते"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"ॲपला २०० Hz पेक्षा जास्त दराने सेन्सर डेटाचा नमुना तयार करण्याची अनुमती देते"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"पासवर्ड नियम सेट करा"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"स्क्रीन लॉक पासवर्ड आणि पिन मध्ये अनुमती दिलेले लांबी आणि वर्ण नियंत्रित करा."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"स्क्रीन अनलॉक प्रयत्नांचे परीक्षण करा"</string>
@@ -1665,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"शॉर्टकट वापरा"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"रंगांची उलटापालट"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"रंग सुधारणा"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"धरून ठेवलेल्या व्हॉल्यूम की. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> सुरू केला आहे."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"धरून ठेवलेल्या व्हॉल्यूम की. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> बंद केले आहे."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> वापरण्यासाठी दोन्ही व्हॉल्युम की तीन सेकंद दाबा आणि धरून ठेवा"</string>
@@ -1868,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS विनंती व्हिडिओ कॉलवर बदलली"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS विनंती USSD विनंतीवर बदलली"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"नवीन SS विनंतीवर बदलली"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"फिशिंगशी संबंधित सूचना"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"कार्य प्रोफाईल"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"सूचना दिल्या"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"विस्तृत करा"</string>
@@ -1881,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"मोठे करा"</string>
     <string name="close_button_text" msgid="10603510034455258">"बंद करा"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"उत्तर द्या"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"नकार द्या"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"कॉल बंद करा"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"इनकमिंग कॉल"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"सुरू असलेला कॉल"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"इनकमिंग कॉल स्क्रीन करत आहे"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> निवडले</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> निवडला</item>
@@ -2209,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"पुढे सुरू ठेवण्यासाठी, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; ला तुमच्या डिव्हाइसचा कॅमेरा अ‍ॅक्सेस करण्याची आवश्यकता आहे."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"सुरू करा"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"सेन्सरशी संबंधित गोपनीयतेबाबत सूचना"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index ec0aa5d..5e5b29f 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -325,7 +325,7 @@
     <string name="permgroupdesc_sensors" msgid="2610631290633747752">"akses data penderia tentang tanda vital anda"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Dapatkan kembali kandungan tetingkap"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Periksa kandungan tetingkap yang berinteraksi dengan anda."</string>
-    <string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Hidupkan Jelajah melalui Sentuhan"</string>
+    <string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Hidupkan Teroka melalui Sentuhan"</string>
     <string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"Item yang diketik akan dituturkan dengan lantang dan skrin boleh dijelajah menggunakan gerak isyarat."</string>
     <string name="capability_title_canRequestFilterKeyEvents" msgid="2772371671541753254">"Perhatikan teks yang anda taip"</string>
     <string name="capability_desc_canRequestFilterKeyEvents" msgid="2381315802405773092">"Termasuk data peribadi seperti nombor kad kredit dan kata laluan."</string>
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Peranti ini tiada penderia cap jari."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Penderia dilumpuhkan sementara."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Jari <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Gunakan cap jari anda untuk teruskan"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon cap jari"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Tidak lagi dapat mengecam wajah. Cuba lagi."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Terlalu serupa, sila ubah lagak gaya anda."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Pusingkan kepala anda kurang sedikit."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Pusingkan kepala anda kurang sedikit."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Pusingkan kepala anda kurang sedikit."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Alih keluar apa saja yang melindungi wajah anda."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Bersihkan bahagian atas skrin anda, termasuk bar hitam"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Membenarkan apl membaca dan menulis konfigurasi Jangan Ganggu."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"mulakan lihat penggunaan kebenaran"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Membenarkan pemegang memulakan penggunaan kebenaran untuk apl. Tidak sekali-kali diperlukan untuk apl biasa."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"akses data penderia pada data pensampelan yang tinggi"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Membenarkan apl mengambil sampel data penderia pada kadar yang lebih besar daripada 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Tetapkan peraturan kata laluan"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Mengawal panjang dan aksara yang dibenarkan dalam kata laluan  dan PIN kunci skrin."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Pantau percubaan buka kunci skrin"</string>
@@ -1002,9 +1006,9 @@
     <string name="searchview_description_clear" msgid="1989371719192982900">"Pertanyaan jelas"</string>
     <string name="searchview_description_submit" msgid="6771060386117334686">"Serah pertanyaan"</string>
     <string name="searchview_description_voice" msgid="42360159504884679">"Carian suara"</string>
-    <string name="enable_explore_by_touch_warning_title" msgid="5095399706284943314">"Dayakan Jelajah melalui Sentuhan?"</string>
-    <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="1037295476738940824">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ingin mendayakan Jelajah melalui Sentuhan. Apabila Jelajah melalui Sentuhan didayakan, anda boleh mendengar atau melihat penerangan tentang apa di bawah jari anda atau melakukan gerak isyarat untuk berinteraksi dengan tablet."</string>
-    <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ingin mendayakan Jelajah melalui Sentuhan. Apabila Jelajah melalui Sentuhan didayakan, anda boleh mendengar atau melihat penerangan tentang apa di bawah jari anda atau melakukan gerak isyarat untuk berinteraksi dengan telefon."</string>
+    <string name="enable_explore_by_touch_warning_title" msgid="5095399706284943314">"Dayakan Teroka melalui Sentuhan?"</string>
+    <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="1037295476738940824">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ingin mendayakan Teroka melalui Sentuhan. Apabila Teroka melalui Sentuhan didayakan, anda boleh mendengar atau melihat penerangan tentang apa-apa di bawah jari anda atau melakukan gerak isyarat untuk berinteraksi dengan tablet."</string>
+    <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ingin mendayakan Teroka melalui Sentuhan. Apabila Teroka melalui Sentuhan didayakan, anda boleh mendengar atau melihat penerangan tentang apa-apa di bawah jari anda atau melakukan gerak isyarat untuk berinteraksi dengan telefon."</string>
     <string name="oneMonthDurationPast" msgid="4538030857114635777">"1 bulan yang lalu"</string>
     <string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Sebelum 1 bulan yang lalu"</string>
     <plurals name="last_num_days" formatted="false" msgid="687443109145393632">
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Gunakan Pintasan"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Penyongsangan Warna"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Pembetulan Warna"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Kekunci kelantangan ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> dihidupkan."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Kekunci kelantangan ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> dimatikan."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Tekan dan tahan kedua-dua kekunci kelantangan selama tiga saat untuk menggunakan <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Permintaan SS ditukar kepada panggilan video"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Permintaan SS ditukar kepada permintaan USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Bertukar kepada permintaan SS baharu"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Amaran pancingan data"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Profil kerja"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Dimaklumkan"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Kembangkan"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maksimumkan"</string>
     <string name="close_button_text" msgid="10603510034455258">"Tutup"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Jawapan"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Tolak"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Tamatkan Panggilan"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Panggilan masuk"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Panggilan sedang berlangsung"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Menyaring panggilan masuk"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> dipilih</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> dipilih</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Untuk meneruskan proses, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; memerlukan akses kepada kamera peranti anda."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Hidupkan"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Privasi Penderia"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 7b4a430fc..137c138 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ဤစက်တွင် လက်ဗွေအာရုံခံကိရိယာ မရှိပါ။"</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"အာရုံခံကိရိယာကို ယာယီပိတ်ထားသည်။"</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"လက်ချောင်း <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"ရှေ့ဆက်ရန် သင့်လက်ဗွေကို သုံးပါ"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"လက်ဗွေ သင်္ကေတ"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"မျက်နှာ မမှတ်သားနိုင်တော့ပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"ဆင်တူနေသည်၊ အမူအရာ ပြောင်းပါ။"</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"ခေါင်းကို သိပ်မလှည့်ပါနှင့်။"</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"ခေါင်းကို သိပ်မလှည့်ပါနှင့်။"</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"ခေါင်းကို သိပ်မလှည့်ပါနှင့်။"</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"သင့်မျက်နှာကို ကွယ်နေသည့်အရာအားလုံး ဖယ်ပါ။"</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"အနက်ရောင်ဘားအပါအဝင် ဖန်သားပြင်ထိပ်ကို သန့်ရှင်းရေး လုပ်ပါ"</string>
@@ -648,8 +650,8 @@
     <string name="permdesc_bind_incall_service" msgid="4124917526967765162">"အက်ပ်အား အသုံးပြုသူက ခေါ်ဆိုမှုအဝင် မျက်နှာပြင် ဘယ်အချိန်မှာ ဘယ်လို မြင်ရမှာကို ထိန်းချုပ်ခွင့်ပေးရန်"</string>
     <string name="permlab_bind_connection_service" msgid="5409268245525024736">"တယ်လီဖုန်း ဝန်ဆောင်မှုများနှင့် အပြန်အလှန် တုံ့ပြန်မှု"</string>
     <string name="permdesc_bind_connection_service" msgid="6261796725253264518">"အက်ပ်အား ခေါ်ဆိုမှုများ လုပ်ခြင်း/လက်ခံခြင်း ပြုလုပ်နိုင်ရန် တယ်လီဖုန်း ဝန်ဆောင်မှုများနှင့် အပြန်အလှန် တုံ့ပြန်မှုကို ခွင့်ပြုသည်။"</string>
-    <string name="permlab_control_incall_experience" msgid="6436863486094352987">"အသုံးပြုသူ အတွက် ခေါ်ဆိုမှုအဝင် လုပ်ကိုင်ပုံကို စီစဉ်ပေးခြင်း"</string>
-    <string name="permdesc_control_incall_experience" msgid="5896723643771737534">"အက်ပ်အား အသုံးပြုသူ အတွက် ခေါ်ဆိုမှုအဝင် လုပ်ကိုင်ပုံကို စီစဉ်ခွင့် ပြုသည်။"</string>
+    <string name="permlab_control_incall_experience" msgid="6436863486094352987">"အဝင်ခေါ်ဆိုမှုအတွက် အသုံးပြုသူ၏ နှစ်သက်မှုကို ခွင့်ပြုခြင်း"</string>
+    <string name="permdesc_control_incall_experience" msgid="5896723643771737534">"အဝင်ခေါ်ဆိုမှုအတွက် အသုံးပြုသူ၏ နှစ်သက်မှုကို ပံ့ပိုးပေးရန် အက်ပ်အား ခွင့်ပြုသည်။"</string>
     <string name="permlab_readNetworkUsageHistory" msgid="8470402862501573795">"ရာဇဝင်အလိုက် ကွန်ယက်သုံစွဲမှုအား ဖတ်ခြင်း"</string>
     <string name="permdesc_readNetworkUsageHistory" msgid="1112962304941637102">"အက်ပ်အား အထူး ကွန်ရက်များ နှင့် အက်ပ်များ အတွက် ကွန်ရက် အသုံးပြုမှု မှတ်တမ်းကို ဖတ်ကြားခွင့် ပြုသည်။"</string>
     <string name="permlab_manageNetworkPolicy" msgid="6872549423152175378">"ကွန်ယက်မူဝါဒအား စီမံခြင်း"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"မနှောင့်ယှက်ရန် ချိန်ညှိမှုကို အပ်ဖ်များ ဖတ်ခြင်း ပြင်ခြင်းပြုလုပ်နိုင်ရန် ခွင့်ပြုမည်။"</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"အစမြင်ကွင်း ခွင့်ပြုချက် အသုံးပြုမှု"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"အက်ပ်တစ်ခုအတွက် ခွင့်ပြုချက်စတင်အသုံးပြုမှုကို ကိုင်ဆောင်သူအား ခွင့်ပြုသည်။ ပုံမှန်အက်ပ်များအတွက် ဘယ်သောအခါမျှ မလိုအပ်ပါ။"</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"နမူနာနှုန်းမြင့်သော အာရုံခံစနစ်ဒေတာကို သုံးပါ"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"၂၀၀ Hz နှုန်းထက်ပိုများသော အာရုံခံစနစ်ဒေတာကို နမူနာယူရန် အက်ပ်အား ခွင့်ပြုပါ"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"စကားဝှက်စည်းမျဥ်းကိုသတ်မှတ်ရန်"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"မျက်နှာပြင်သော့ခတ်သည့် စကားဝှက်များနှင့် PINများရှိ ခွင့်ပြုထားသည့် စာလုံးအရေအတွက်နှင့် အက္ခရာများအား ထိန်းချုပ်ရန်။"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"မျက်နှာပြင်လော့ခ်ဖွင့်ရန် ကြိုးပမ်းမှုများကို စောင့်ကြည့်ပါ"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ဖြတ်လမ်းလင့်ခ်ကို သုံးရန်"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"အရောင် ပြောင်းပြန်လှန်ခြင်း"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"အရောင်ပြင်ဆင်ခြင်း"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"အသံခလုတ်များကို ဖိထားသည်။ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ဖွင့်လိုက်သည်။"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"အသံခလုတ်များကို ဖိထားသည်။ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ပိတ်လိုက်သည်။"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ကို သုံးရန် အသံအတိုးအလျှော့ ခလုတ်နှစ်ခုလုံးကို သုံးစက္ကန့်ကြာ ဖိထားပါ"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS တောင်းဆိုမှုကို ဗီဒီယိုခေါ်ဆိုမှုသို့ ပြောင်းထားသည်"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS တောင်းဆိုမှုကို USSD တောင်းဆိုမှုအဖြစ် ပြောင်းထားသည်"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"SS တောင်းဆိုမှုအသစ်သို့ ပြောင်းထားသည်"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"အယောင်ဆောင်ဖြားယောင်းခြင်း သတိပေးချက်"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"အလုပ်ကိုယ်ရေးအချက်အလက်"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"သတိပေးထားသည်"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"ချဲ့ရန်"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"အများဆုံး လုပ်ပေးရန်"</string>
     <string name="close_button_text" msgid="10603510034455258">"ပိတ်ရန်"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>− <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"ဖုန်းကိုင်ရန်"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"ငြင်းပယ်ရန်"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"ဖုန်းချရန်"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"အဝင်ခေါ်ဆိုမှု"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"လက်ရှိခေါ်ဆိုမှု"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"အဝင်ခေါ်ဆိုမှုကို စစ်ဆေးနေသည်"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ရွေးချယ်ပြီးပါပြီ</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ရွေးချယ်ပြီးပါပြီ</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"ဆက်လက်လုပ်ဆောင်ရန် &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; က သင့်စက်၏ ကင်မရာကို အသုံးပြုခွင့်ရရန် လိုအပ်သည်။"</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"ဖွင့်ရန်"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"အာရုံခံကိရိယာ လုံခြုံရေး"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 4968184..de71c39 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Denne enheten har ikke fingeravtrykkssensor."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensoren er midlertidig slått av."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Bruk fingeravtrykket ditt for å fortsette"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon for fingeravtrykk"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Kan ikke gjenkjenne ansiktet lenger. Prøv igjen."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"For likt – endre posituren din."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Vri hodet ditt litt mindre."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Vri hodet ditt litt mindre."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Vri hodet ditt litt mindre."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Fjern alt som skjuler ansiktet ditt."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Rengjør den øverste delen av skjermen, inkludert den svarte linjen"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Lar appen lese og skrive konfigurasjon av Ikke forstyrr."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"start visning av bruk av tillatelser"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Lar innehaveren starte bruk av tillatelser for en app. Dette skal aldri være nødvendig for vanlige apper."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"tilgang til sensordata ved høy samplingfrekvens"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Lar appen samle inn sensordata ved en hastighet som er høyere enn 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Angi passordregler"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Kontrollerer tillatt lengde og tillatte tegn i passord og PIN-koder for opplåsing av skjermen."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Overvåk forsøk på å låse opp skjermen"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Bruk snarveien"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Fargeinvertering"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Fargekorrigering"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Volumtastene holdes inne. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er slått på."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Volumtastene holdes inne. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er slått av."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Trykk og hold inne begge volumtastene i tre sekunder for å bruke <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-forespørsel endret til videoanrop"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-forespørsel endret til USSD-forespørsel"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Endret til ny SS-forespørsel"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Varsel om nettfisking"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Arbeidsprofil"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Varslet"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Vis"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maksimer"</string>
     <string name="close_button_text" msgid="10603510034455258">"Lukk"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g><xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Svar"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Avvis"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Legg på"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Innkommende anrop"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Pågående samtale"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Filtrerer et innkommende anrop"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> er valgt</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> er valgt</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"For å fortsette må &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; ha tilgang til enhetskameraet."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Slå på"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Sensorpersonvern"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 541ace8..83c03a4 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -148,8 +148,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi मात्र"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <!-- no translation found for crossSimFormat_spn_cross_sim_calling (5620807020002879057) -->
-    <skip />
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"<xliff:g id="SPN">%s</xliff:g> ब्याकअप कलिङ"</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: अगाडि पठाइएको छैन"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> पछि <xliff:g id="TIME_DELAY">{2}</xliff:g> सेकेन्ड"</string>
@@ -580,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"यो यन्त्रमा कुनै पनि फिंगरप्रिन्ट सेन्सर छैन।"</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"केही समयका लागि सेन्सर असक्षम पारियो।"</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"औंला <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"जारी राख्न आफ्नो फिंगरप्रिन्ट प्रयोग गर्नुहोस्"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"फिंगरप्रिन्ट आइकन"</string>
@@ -606,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"अब उप्रान्त अनुहार पहिचान गर्न सकिएन। फेरि प्रयास गर्नुहोस्।"</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"अनुहार उस्तै भयो, कृपया आफ्नो पोज बदल्नुहोस्।"</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"आफ्नो टाउको अलि थोरै घुमाउनुहोस्।"</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"आफ्नो टाउको अलि थोरै घुमाउनुहोस्।"</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"आफ्नो टाउको अलि थोरै घुमाउनुहोस्।"</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"तपाईंको अनुहार लुकाउने सबै कुरा लुकाउनुहोस्।"</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"कालो रङको पट्टीलगायत आफ्नो स्क्रिनको माथिल्लो भाग सफा गर्नुहोस्"</string>
@@ -685,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"बाधा नपुर्याउँनुहोस् कन्फिगरेसन पढ्न र लेख्‍नको लागि एपलाई अनुमति दिनुहोस्।"</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"हेर्ने अनुमतिको प्रयोग सुरु गर्नुहोस्"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"वाहकलाई कुनै एपसम्बन्धी अनुमतिको प्रयोग सुरु गर्न दिन्छ। साधारण एपहरूलाई कहिल्यै आवश्यक नपर्नु पर्ने हो।"</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"नमुना लिने उच्च दरमा सेन्सरसम्बन्धी डेटा प्रयोग गर्ने"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"यो अनुमति दिइएमा एपले २०० हर्जभन्दा बढी दरमा सेन्सरसम्बन्धी डेटाको नमुना लिन सक्छ"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"पासवर्ड नियमहरू मिलाउनुहोस्"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"स्क्रिन लक पासवर्ड र PIN हरूमा अनुमति दिइएको लम्बाइ र वर्णहरूको नियन्त्रण गर्नुहोस्।"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"मनिटरको स्क्रिन अनलक गर्ने प्रयासहरू"</string>
@@ -1665,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"सर्टकट प्रयोग गर्नुहोस्"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"रङ्ग उल्टाउने सुविधा"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"रङ्ग सच्याउने सुविधा"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> अन भयो।"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> अफ भयो।"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> प्रयोग गर्न दुवै भोल्युम कुञ्जीहरूलाई तीन सेकेन्डसम्म थिचिराख्नुहोस्"</string>
@@ -1868,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS अनुरोधलाई भिडियो कलमा परिवर्तन गरियो"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS अनुरोधलाई USSD अनुरोधमा परिवर्तन गरियो"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"नयाँ SS अनुरोधमा परिवर्तन गरियो"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"फिसिङसम्बन्धी अलर्ट"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"कार्य प्रोफाइल"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"सतर्कता गरियो"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"विस्तृत गर्नुहोस्"</string>
@@ -1881,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"ठुलो बनाउनुहोस्"</string>
     <string name="close_button_text" msgid="10603510034455258">"बन्द गर्नुहोस्"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"कलको जवाफ दिनु…"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"अस्वीकार गर्नुहोस्"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"फोन राख्नुहोस्"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"आगमन कल"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"भइरहेको कल"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"आगमन कल जाँचिँदै छ"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> चयन गरियो</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> चयन गरियो</item>
@@ -2209,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"जारी राख्न &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; लाई तपाईंको यन्त्रको क्यामेरा प्रयोग गर्ने अनुमति दिनु पर्ने हुन्छ।"</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"अन गर्नुहोस्"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"सेन्सरसम्बन्धी गोपनीयता"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-night/colors.xml b/core/res/res/values-night/colors.xml
index 29f2b6f..4410e94 100644
--- a/core/res/res/values-night/colors.xml
+++ b/core/res/res/values-night/colors.xml
@@ -26,6 +26,10 @@
 
     <color name="notification_default_color_dark">#ddffffff</color>
 
+    <color name="notification_primary_text_color_current">@color/notification_primary_text_color_dark</color>
+    <color name="notification_secondary_text_color_current">@color/notification_secondary_text_color_dark</color>
+    <color name="notification_default_color_current">@color/notification_default_color_dark</color>
+
     <color name="chooser_row_divider">@color/list_divider_color_dark</color>
     <color name="chooser_gradient_background">@color/loading_gradient_background_color_dark</color>
     <color name="chooser_gradient_highlight">@color/loading_gradient_highlight_color_dark</color>
diff --git a/core/res/res/values-night/values.xml b/core/res/res/values-night/values.xml
index 952cdd0..3fd82b8 100644
--- a/core/res/res/values-night/values.xml
+++ b/core/res/res/values-night/values.xml
@@ -28,9 +28,4 @@
     </style>
 
     <style name="Theme.DeviceDefault.QuickSettings.Dialog" parent="Theme.DeviceDefault.Dialog" />
-
-    <style name="TextAppearance.Material.Notification">
-        <item name="textColor">?attr/textColorPrimary</item>
-        <item name="textSize">@dimen/notification_text_size</item>
-    </style>
 </resources>
\ No newline at end of file
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 7f23cbb..e2be98d 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -515,9 +515,9 @@
     <string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"Hiermee kan de app pakketten ontvangen die via multicastadressen naar alle apparaten in een wifi-netwerk worden verzonden, niet alleen naar je Android TV-apparaat. Het stroomgebruik ligt hierbij hoger dan in de niet-multicastmodus."</string>
     <string name="permdesc_changeWifiMulticastState" product="default" msgid="8296627590220222740">"Hiermee kan de app pakketten ontvangen die via multicastadressen naar alle apparaten in een wifi-netwerk worden verzonden, niet alleen naar je telefoon. Het stroomgebruik ligt hierbij hoger dan in de niet-multicastmodus."</string>
     <string name="permlab_bluetoothAdmin" msgid="6490373569441946064">"Bluetooth-instellingen openen"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="5370837055438574863">"Hiermee kan de app de lokale bluetooth-tablet configureren en externe apparaten zoeken en koppelen."</string>
-    <string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"Hiermee kan de app Bluetooth op je Android TV-apparaat configureren en externe apparaten zoeken en koppelen."</string>
-    <string name="permdesc_bluetoothAdmin" product="default" msgid="7381341743021234863">"Hiermee kan de app de lokale bluetooth-telefoon configureren en externe apparaten zoeken en koppelen."</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="5370837055438574863">"Hiermee kan de app de lokale bluetooth-tablet instellen en externe apparaten zoeken en koppelen."</string>
+    <string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"Hiermee kan de app Bluetooth op je Android TV-apparaat isntellen en externe apparaten zoeken en koppelen."</string>
+    <string name="permdesc_bluetoothAdmin" product="default" msgid="7381341743021234863">"Hiermee kan de app de lokale bluetooth-telefoon instellen en externe apparaten zoeken en koppelen."</string>
     <string name="permlab_accessWimaxState" msgid="7029563339012437434">"WiMAX-verbinding maken en verbreken"</string>
     <string name="permdesc_accessWimaxState" msgid="5372734776802067708">"Hiermee kan de app bepalen of WiMAX is ingeschakeld en informatie bekijken over alle WiMAX-netwerken waarmee verbinding is gemaakt."</string>
     <string name="permlab_changeWimaxState" msgid="6223305780806267462">"WiMAX-status wijzigen"</string>
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Dit apparaat heeft geen vingerafdruksensor."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor tijdelijk uitgeschakeld."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Vinger <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Gebruik je vingerafdruk om door te gaan."</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Vingerafdruk-icoon"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Herkent gezicht niet meer. Probeer het nog eens."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Lijkt te veel op elkaar. Verander je pose."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Draai je hoofd iets minder."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Draai je hoofd iets minder."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Draai je hoofd iets minder."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Zorg dat je gezicht volledig zichtbaar is."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Reinig de bovenkant van je scherm, inclusief de zwarte balk"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Hiermee kan de app configuratie voor Niet storen lezen en schrijven."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"rechtengebruik starten"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Hiermee kan de houder het rechtengebruik voor een app starten. Nooit vereist voor normale apps."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"toegang krijgen tot sensorgegevens met een hoge samplingsnelheid"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Hiermee kan de app sensorgegevens samplen met een snelheid die hoger is dan 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Wachtwoordregels instellen"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"De lengte en het aantal tekens beheren die zijn toegestaan in wachtwoorden en pincodes voor schermvergrendeling."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Pogingen voor schermontgrendeling bijhouden"</string>
@@ -1346,7 +1350,7 @@
     <string name="select_input_method" msgid="3971267998568587025">"Invoermethode selecteren"</string>
     <string name="show_ime" msgid="6406112007347443383">"Dit op het scherm weergeven terwijl het fysieke toetsenbord actief is"</string>
     <string name="hardware" msgid="1800597768237606953">"Virtueel toetsenbord tonen"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Fysiek toetsenbord configureren"</string>
+    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Fysiek toetsenbord instellen"</string>
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Tik om een taal en indeling te selecteren"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1369,7 +1373,7 @@
     <string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Je moet het apparaat misschien opnieuw formatteren. Tik om het uit te werpen."</string>
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> niet ondersteund"</string>
     <string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> werkt niet"</string>
-    <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Dit apparaat biedt geen ondersteuning voor deze <xliff:g id="NAME">%s</xliff:g>. Tik om te configureren in een ondersteunde indeling."</string>
+    <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Dit apparaat biedt geen ondersteuning voor deze <xliff:g id="NAME">%s</xliff:g>. Tik om in te stellen in een ondersteunde indeling."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"Dit apparaat biedt geen ondersteuning voor deze <xliff:g id="NAME">%s</xliff:g>. Selecteer om in te stellen in een ondersteunde indeling."</string>
     <string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Je moet het apparaat misschien opnieuw formatteren"</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> is onverwacht verwijderd"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Sneltoets gebruiken"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Kleurinversie"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Kleurcorrectie"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Volumetoetsen ingedrukt gehouden. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> is ingeschakeld."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Volumetoetsen ingedrukt gehouden. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> uitgeschakeld."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Houd beide volumetoetsen drie seconden ingedrukt om <xliff:g id="SERVICE_NAME">%1$s</xliff:g> te gebruiken"</string>
@@ -1856,7 +1862,7 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Weekend"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Afspraken"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Slapen"</string>
-    <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> dempt sommige geluiden"</string>
+    <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> zet sommige geluiden uit"</string>
     <string name="system_error_wipe_data" msgid="5910572292172208493">"Er is een intern probleem met je apparaat. Het apparaat kan instabiel zijn totdat u het apparaat terugzet naar de fabrieksinstellingen."</string>
     <string name="system_error_manufacturer" msgid="703545241070116315">"Er is een intern probleem met je apparaat. Neem contact op met de fabrikant voor meer informatie."</string>
     <string name="stk_cc_ussd_to_dial" msgid="3139884150741157610">"USSD-verzoek gewijzigd in normaal gesprek"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-verzoek gewijzigd in videogesprek"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-verzoek gewijzigd in USSD-verzoek"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Gewijzigd in nieuw SS-verzoek"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Phishingmelding"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Werkprofiel"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Gemeld"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Uitvouwen"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maximaliseren"</string>
     <string name="close_button_text" msgid="10603510034455258">"Sluiten"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Beantwoorden"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Weigeren"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Ophangen"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Inkomend gesprek"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Actief gesprek"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Een inkomend gesprek screenen"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> geselecteerd</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> geselecteerd</item>
@@ -1924,7 +1937,7 @@
     <string name="demo_starting_message" msgid="6577581216125805905">"Demo starten…"</string>
     <string name="demo_restarting_message" msgid="1160053183701746766">"Apparaat resetten…"</string>
     <string name="suspended_widget_accessibility" msgid="6331451091851326101">"<xliff:g id="LABEL">%1$s</xliff:g> uitgeschakeld"</string>
-    <string name="conference_call" msgid="5731633152336490471">"Conferencecall"</string>
+    <string name="conference_call" msgid="5731633152336490471">"Telefonische vergadering"</string>
     <string name="tooltip_popup_title" msgid="7863719020269945722">"Knopinfo"</string>
     <string name="app_category_game" msgid="4534216074910244790">"Games"</string>
     <string name="app_category_audio" msgid="8296029904794676222">"Muziek en audio"</string>
@@ -2000,7 +2013,7 @@
     <string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> wil segmenten van <xliff:g id="APP_2">%2$s</xliff:g> weergeven"</string>
     <string name="screenshot_edit" msgid="7408934887203689207">"Bewerken"</string>
     <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Trillen bij gesprekken en meldingen"</string>
-    <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Gesprekken en meldingen zijn gedempt"</string>
+    <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Telefoon- en meldingsgeluid wordt uitgezet"</string>
     <string name="notification_channel_system_changes" msgid="2462010596920209678">"Systeemwijzigingen"</string>
     <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Niet storen"</string>
     <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Nieuw: \'Niet storen\' verbergt meldingen"</string>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"&lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; heeft toegang tot de camera van je apparaat nodig om door te gaan."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Aanzetten"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Sensorprivacy"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index f02d157..bc76142 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -148,8 +148,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"କେବଳ ୱାଇ-ଫାଇ"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <!-- no translation found for crossSimFormat_spn_cross_sim_calling (5620807020002879057) -->
-    <skip />
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"<xliff:g id="SPN">%s</xliff:g> ବ୍ୟାକଅପ୍ କଲିଂ"</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ଫରୱାର୍ଡ କରାଯାଇନାହିଁ"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> ସେକେଣ୍ଡ ପରେ"</string>
@@ -580,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ଏହି ଡିଭାଇସ୍‌ରେ ଟିପଚିହ୍ନ ସେନ୍‍ସର୍ ନାହିଁ।"</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"ସେନ୍ସରକୁ ଅସ୍ଥାୟୀ ଭାବେ ଅକ୍ଷମ କରାଯାଇଛି।"</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"ଆଙ୍ଗୁଠି <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"ଜାରି ରଖିବାକୁ ଆପଣଙ୍କ ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ଟିପଚିହ୍ନ ଆଇକନ୍"</string>
@@ -606,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"ଆଉ ମୁହଁ ଚିହ୍ନଟ କରିହେଲା ନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"ଅତ୍ୟନ୍ତ ସମପରି, ଦୟାକରି ଆପଣଙ୍କର ପୋଜ୍ ବଦଳାନ୍ତୁ।"</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"ଆପଣଙ୍କର ମୁଣ୍ଡକୁ ଟିକିଏ ବୁଲାନ୍ତୁ।"</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"ଆପଣଙ୍କର ମୁଣ୍ଡକୁ ଟିକିଏ ବୁଲାନ୍ତୁ।"</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"ଆପଣଙ୍କର ମୁଣ୍ଡକୁ ଟିକିଏ ବୁଲାନ୍ତୁ।"</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"ଆପଣଙ୍କର ମୁହଁ ଲୁଚାଉଥିବା ଜିନିଷକୁ କାଢ଼ି ଦିଅନ୍ତୁ।"</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"କଳା ବାର୍ ସମେତ ଆପଣଙ୍କ ସ୍କ୍ରିନ୍‌ର ଶୀର୍ଷକୁ ସଫା କରନ୍ତୁ"</string>
@@ -685,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"\"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" କନଫିଗରେଶନ୍‍ ପଢ଼ିବା ତଥା ଲେଖିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"ଅନୁମତି ବ୍ୟବହାର ଦେଖିବା ଆରମ୍ଭ କରନ୍ତୁ"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"ଏକ ଆପ୍ ପାଇଁ ଅନୁମତିର ବ୍ୟବହାର ଆରମ୍ଭ କରିବାକୁ ଧାରକକୁ ଅନୁମତି ଦେଇଥାଏ। ସାଧାରଣ ଆପ୍‌ଗୁଡ଼ିକ ପାଇଁ ଏହା ଆବଶ୍ୟକ ନୁହେଁ।"</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"ଏକ ଉଚ୍ଚ ନମୁନାକରଣ ରେଟରେ ସେନ୍ସର୍ ଡାଟାକୁ ଆକ୍ସେସ୍ କରନ୍ତୁ"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"200 Hz ଠାରୁ ଅଧିକ ଏକ ରେଟରେ ସେନ୍ସର୍ ଡାଟାର ନମୁନା ନେବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦିଏ"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"ପାସ୍‌ୱର୍ଡ ନିୟମାବଳୀ ସେଟ୍ କରନ୍ତୁ"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"ଲକ୍‍ ସ୍କ୍ରୀନ୍‍ ପାସ୍‌ୱର୍ଡ ଓ PINରେ ଅନୁମୋଦିତ ଦୀର୍ଘତା ଓ ବର୍ଣ୍ଣ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ।"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"ସ୍କ୍ରୀନ୍-ଅନଲକ୍ କରିବା ଉଦ୍ୟମ ନୀରିକ୍ଷଣ କରନ୍ତୁ"</string>
@@ -1665,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ଶର୍ଟକଟ୍‍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"ରଙ୍ଗ ବଦଳାଇବାର ସୁବିଧା"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"ରଙ୍ଗ ସଂଶୋଧନ"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ଭଲ୍ୟୁମ୍ କୀ\'ଗୁଡ଼ିକୁ ଧରି ରଖାଯାଇଛି। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ଚାଲୁ ହୋଇଛି।"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ଭଲ୍ୟୁମ୍ କୀ\'ଗୁଡ଼ିକୁ ଧରି ରଖାଯାଇଛି। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ବନ୍ଦ ହୋଇଛି।"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ବ୍ୟବହାର କରିବାକୁ ତିନି ସେକେଣ୍ଡ ପାଇଁ ଉଭୟ ଭଲ୍ୟୁମ୍‍ କୀ ଦବାଇ ଧରି ରଖନ୍ତୁ"</string>
@@ -1868,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SSଙ୍କ ଅନୁରୋଧକୁ ଭିଡିଓ କଲ୍‌ରେ ପରିବର୍ତ୍ତନ କରାଗଲା"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS ଅନୁରୋଧ, USSD ଅନୁରୋଧକୁ ପରିବର୍ତ୍ତନ ହେଲା"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"ନୂତନ SS ଅନୁରୋଧରେ ପରିବର୍ତ୍ତନ ହେଲା"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"ଫିସିଂ ଆଲର୍ଟ"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"ୱର୍କ ପ୍ରୋଫାଇଲ୍‌"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"ଆଲର୍ଟ କରାଯାଇଛି"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"ବଢ଼ାନ୍ତୁ"</string>
@@ -1881,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"ବଡ଼ କରନ୍ତୁ"</string>
     <string name="close_button_text" msgid="10603510034455258">"ବନ୍ଦ କରନ୍ତୁ"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"ଉତ୍ତର ଦିଅନ୍ତୁ"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"ଅଗ୍ରାହ୍ୟ କର"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"ସମାପ୍ତ କରନ୍ତୁ"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"ଇନକମିଂ କଲ୍"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"ଚାଲିଥିବା କଲ୍"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"ଏକ ଇନକମିଂ କଲକୁ ସ୍କ୍ରିନ୍ କରୁଛି"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ଚୟନିତ</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ଚୟନିତ</item>
@@ -2209,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"ଜାରି ରଖିବାକୁ, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; ଆପଣଙ୍କ ଡିଭାଇସର କ୍ୟାମେରାକୁ ଆକ୍ସେସ୍ ଆବଶ୍ୟକ କରେ।"</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"ଚାଲୁ କରନ୍ତୁ"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"ସେନ୍ସର୍ ଗୋପନୀୟତା"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index a717af6..c9f57ef 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -148,8 +148,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"ਸਿਰਫ਼ ਵਾਈ-ਫਾਈ"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <!-- no translation found for crossSimFormat_spn_cross_sim_calling (5620807020002879057) -->
-    <skip />
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"<xliff:g id="SPN">%s</xliff:g> ਬੈਕਅੱਪ ਕਾਲਿੰਗ"</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ਅੱਗੇ ਨਹੀਂ ਭੇਜਿਆ ਗਿਆ"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> ਸਕਿੰਟਾਂ ਬਾਅਦ"</string>
@@ -580,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ਇਸ ਡੀਵਾਈਸ ਵਿੱਚ ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਨਹੀਂ ਹੈ।"</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"ਸੈਂਸਰ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਬੰਦ ਕੀਤਾ ਗਿਆ।"</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"ਉਂਗਲ <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"ਜਾਰੀ ਰੱਖਣ ਲਈ ਆਪਣਾ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤੋ"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਪ੍ਰਤੀਕ"</string>
@@ -606,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"ਹੁਣ ਚਿਹਰਾ ਪਛਾਣਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"ਬਹੁਤ ਮਿਲਦਾ-ਜੁਲਦਾ ਹੈ, ਕਿਰਪਾ ਕਰਕੇ ਆਪਣਾ ਅੰਦਾਜ਼ ਬਦਲੋ।"</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"ਆਪਣਾ ਸਿਰ ਥੋੜਾ ਜਿਹਾ ਝੁਕਾਓ।"</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"ਆਪਣਾ ਸਿਰ ਥੋੜਾ ਜਿਹਾ ਝੁਕਾਓ।"</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"ਆਪਣਾ ਸਿਰ ਥੋੜਾ ਜਿਹਾ ਝੁਕਾਓ।"</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"ਤੁਹਾਡਾ ਚਿਹਰਾ ਲੁਕਾਉਣ ਵਾਲੀ ਕੋਈ ਵੀ ਚੀਜ਼ ਹਟਾਓ।"</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"ਕਾਲੀ ਪੱਟੀ ਸਮੇਤ, ਆਪਣੀ ਸਕ੍ਰੀਨ ਦੇ ਸਿਖਰ ਨੂੰ ਸਾਫ਼ ਕਰੋ"</string>
@@ -685,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"ਐਪ ਨੂੰ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ ਕੌਂਫਿਗਰੇਸ਼ਨ ਨੂੰ ਪੜ੍ਹਨ ਅਤੇ ਲਿਖਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"ਇਜਾਜ਼ਤ ਵਰਤੋਂ ਦੇਖਣਾ ਸ਼ੁਰੂ ਕਰੋ"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"ਧਾਰਕ ਨੂੰ ਕਿਸੇ ਹੋਰ ਐਪ ਲਈ ਇਜਾਜ਼ਤ ਵਰਤੋਂ ਨੂੰ ਸ਼ੁਰੂ ਕਰਨ ਦਿੰਦਾ ਹੈ। ਸਧਾਰਨ ਐਪਾਂ ਲਈ ਕਦੇ ਵੀ ਲੋੜੀਂਦਾ ਨਹੀਂ ਹੋਵੇਗਾ।"</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"ਉੱਚ ਸੈਂਪਲਿੰਗ ਰੇਟ \'ਤੇ ਸੈਂਸਰ ਡਾਟਾ ਤੱਕ ਪਹੁੰਚ ਕਰੋ"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"ਐਪ ਨੂੰ 200 Hz ਤੋਂ ਵੱਧ ਦੀ ਦਰ \'ਤੇ ਸੈਂਸਰ ਡਾਟੇ ਦਾ ਨਮੂਨਾ ਲੈਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"ਪਾਸਵਰਡ ਨਿਯਮ ਸੈੱਟ ਕਰੋ"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"ਸਕ੍ਰੀਨ ਲਾਕ ਪਾਸਵਰਡਾਂ ਅਤੇ ਪਿੰਨ ਵਿੱਚ ਆਗਿਆ ਦਿੱਤੀ ਲੰਮਾਈ ਅਤੇ ਅੱਖਰਾਂ ਤੇ ਨਿਯੰਤਰਣ ਪਾਓ।"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"ਸਕ੍ਰੀਨ ਅਣਲਾਕ ਕਰਨ ਦੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ \'ਤੇ ਨਿਗਰਾਨੀ ਰੱਖੋ"</string>
@@ -1665,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ਸ਼ਾਰਟਕੱਟ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"ਰੰਗ ਪਲਟਨਾ"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"ਰੰਗ ਸੁਧਾਈ"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ਅਵਾਜ਼ੀ ਕੁੰਜੀਆਂ ਦਬਾ ਕੇ ਰੱਖੀਆਂ ਗਈਆਂ। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ।"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ਅਵਾਜ਼ੀ ਕੁੰਜੀਆਂ ਦਬਾ ਕੇ ਰੱਖੀਆਂ ਗਈਆਂ। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਨੂੰ ਬੰਦ ਕੀਤਾ ਗਿਆ।"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ ਦੋਵੇਂ ਅਵਾਜ਼ ਕੁੰਜੀਆਂ ਨੂੰ 3 ਸਕਿੰਟਾਂ ਲਈ ਦਬਾਈ ਰੱਖੋ"</string>
@@ -1868,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS ਬੇਨਤੀ ਨੂੰ ਵੀਡੀਓ ਕਾਲ ਵਿੱਚ ਬਦਲਿਆ ਗਿਆ"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS ਬੇਨਤੀ ਨੂੰ USSD ਬੇਨਤੀ ਵਿੱਚ ਬਦਲਿਆ ਗਿਆ"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"ਨਵੀਂ SS ਬੇਨਤੀ ਵਿੱਚ ਬਦਲਿਆ ਗਿਆ"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"ਫ਼ਿਸ਼ਿੰਗ ਸੰਬੰਧੀ ਸੁਚੇਤਨਾ"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"ਸੁਚੇਤਨਾਵਾਂ"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"ਵਿਸਤਾਰ ਕਰੋ"</string>
@@ -1881,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"ਵੱਡਾ ਕਰੋ"</string>
     <string name="close_button_text" msgid="10603510034455258">"ਬੰਦ ਕਰੋ"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"ਜਵਾਬ ਦਿਓ"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"ਅਸਵੀਕਾਰ ਕਰੋ"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"ਸਮਾਪਤ ਕਰੋ"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"ਇਨਕਮਿੰਗ ਕਾਲ"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"ਜਾਰੀ ਕਾਲ"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"ਇਨਕਮਿੰਗ ਕਾਲ ਦੀ ਸਕ੍ਰੀਨਿੰਗ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ਚੁਣਿਆ ਗਿਆ</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ਚੁਣਿਆ ਗਿਆ</item>
@@ -2209,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"ਜਾਰੀ ਰੱਖਣ ਲਈ, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; ਨੂੰ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੇ ਕੈਮਰਾ ਤੱਕ ਪਹੁੰਚ ਦੀ ਲੋੜ ਹੈ।"</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"ਚਾਲੂ ਕਰੋ"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"ਸੈਂਸਰ ਪਰਦੇਦਾਰੀ"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index f73b382..6c12366 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -585,6 +585,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"To urządzenie nie jest wyposażone w czytnik linii papilarnych."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Czujnik jest tymczasowo wyłączony."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Odcisk palca <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Użyj odcisku palca, by kontynuować"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona odcisku palca"</string>
@@ -611,7 +612,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Nie można już rozpoznać twarzy. Spróbuj ponownie."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Za mała różnica. Zmień pozycję."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Trochę mniej obróć głowę."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Trochę mniej obróć głowę."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Trochę mniej obróć głowę."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Usuń wszystko, co zasłania Ci twarz."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Wyczyść górną krawędź ekranu, w tym czarny pasek"</string>
@@ -690,6 +692,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Pozwala aplikacji na odczyt i zmianę konfiguracji trybu Nie przeszkadzać."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"rozpocząć wyświetlanie użycia uprawnień"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Umożliwia rozpoczęcie korzystania z uprawnienia dotyczącego danej aplikacji jego posiadaczowi. Zwykłe aplikacje nie powinny potrzebować tego uprawnienia."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"dostęp do danych czujnika z wysoką częstotliwością"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Zezwala aplikacji na pobieranie próbek danych z czujnika z częstotliwością wyższą niż 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Określ reguły hasła"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Kontrolowanie długości haseł blokady ekranu i kodów PIN oraz dozwolonych w nich znaków."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitorowanie prób odblokowania ekranu"</string>
@@ -1708,6 +1712,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Użyj skrótu"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Odwrócenie kolorów"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Korekcja kolorów"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Przytrzymano klawisze głośności. Usługa <xliff:g id="SERVICE_NAME">%1$s</xliff:g> została włączona."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Przytrzymano klawisze głośności. Usługa <xliff:g id="SERVICE_NAME">%1$s</xliff:g> została wyłączona."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Naciśnij i przytrzymaj oba przyciski głośności przez trzy sekundy, by użyć usługi <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1929,6 +1935,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Żądanie SS zmienione na rozmowę wideo"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Żądanie SS zmienione na żądanie USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Zmieniono na nowe żądanie SS"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Alert o phishingu"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Profil służbowy"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Alert"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Rozwiń"</string>
@@ -1942,6 +1949,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maksymalizuj"</string>
     <string name="close_button_text" msgid="10603510034455258">"Zamknij"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Odbierz"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Odrzuć"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Rozłącz"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Połączenie przychodzące"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Trwa połączenie"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Filtruję połączenie przychodzące"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="few">Wybrano <xliff:g id="COUNT_1">%1$d</xliff:g></item>
       <item quantity="many">Wybrano <xliff:g id="COUNT_1">%1$d</xliff:g></item>
@@ -2276,4 +2289,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Aby kontynuować, musisz przyznać aplikacji „<xliff:g id="APP">%s</xliff:g>” dostęp do aparatu urządzenia."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Włącz"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Poufność danych z czujników"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 693af83..d5cec26 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Este dispositivo não tem um sensor de impressão digital."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor desativado temporariamente."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Use sua impressão digital para continuar"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ícone de impressão digital"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"O rosto não é mais reconhecido. Tente novamente."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Muito parecido, mude de posição."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Incline a cabeça um pouco menos."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Incline a cabeça um pouco menos."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Incline a cabeça um pouco menos."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Remova tudo que esteja ocultando seu rosto."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Limpe a parte superior da tela, inclusive a barra preta"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Permitir que o app leia e grave a configuração \"Não perturbe\"."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"iniciar uso da permissão para visualização"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Permite que o sistema inicie o uso de permissão para um app. Não deve ser necessário para apps comuns."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"acessar os dados do sensor em uma taxa de amostragem elevada"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Permite que o app receba amostras de dados do sensor em uma taxa maior que 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Definir regras para senha"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Controla o tamanho e os caracteres permitidos nos PINs e nas senhas do bloqueio de tela."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitorar tentativas de desbloqueio de tela"</string>
@@ -864,7 +868,7 @@
     <string name="lockscreen_transport_pause_description" msgid="6705284702135372494">"Pausar"</string>
     <string name="lockscreen_transport_play_description" msgid="106868788691652733">"Reproduzir"</string>
     <string name="lockscreen_transport_stop_description" msgid="1449552232598355348">"Parar"</string>
-    <string name="lockscreen_transport_rew_description" msgid="7680106856221622779">"Retroceder"</string>
+    <string name="lockscreen_transport_rew_description" msgid="7680106856221622779">"Voltar"</string>
     <string name="lockscreen_transport_ffw_description" msgid="4763794746640196772">"Avançar"</string>
     <string name="emergency_calls_only" msgid="3057351206678279851">"Só chamadas de emergência"</string>
     <string name="lockscreen_network_locked_message" msgid="2814046965899249635">"Rede bloqueada"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usar atalho"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversão de cores"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Correção de cor"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume pressionadas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ativado."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume pressionadas. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Toque nos dois botões de volume e os mantenha pressionados por três segundo para usar o <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Solicitação SS alterada para videochamada"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Solicitação SS alterada para solicitação USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Alterada para uma nova solicitação SS"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Alerta de phishing"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Perfil de trabalho"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Alertado"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Expandir"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maximizar"</string>
     <string name="close_button_text" msgid="10603510034455258">"Fechar"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Atender"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Recusar"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Desligar"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Chamada recebida"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Chamada em andamento"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Filtrando uma chamada recebida"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionado</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Para continuar, o app &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; precisa acessar a câmera do dispositivo."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Ativar"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Privacidade do sensor"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index e00034a..6867950 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Este dispositivo não tem sensor de impressões digitais."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor temporariamente desativado."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Utilize a sua impressão digital para continuar."</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ícone de impressão digital"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Impossível reconhecer o rosto. Tente novamente."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Muito parecida, mude de pose."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Rode a cabeça um pouco menos."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Rode a cabeça um pouco menos."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Rode a cabeça um pouco menos."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Remova tudo o que esteja a ocultar o seu rosto."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Limpe a parte superior do ecrã, incluindo a barra preta."</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Permite à app ler e alterar a configuração de Não incomodar"</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"iniciar utilização da autorização de visualização"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Permite que o titular inicie a utilização de autorizações para uma app. Nunca deverá ser necessário para aplicações normais."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"aceder aos dados de sensores a uma taxa de amostragem elevada"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Permite que a app obtenha uma amostra dos dados de sensores a uma taxa superior a 200 Hz."</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Definir regras de palavra-passe"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Controlar o comprimento e os carateres permitidos nos PINs e nas palavras-passe do bloqueio de ecrã."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitorizar tentativas de desbloqueio do ecrã"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilizar atalho"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversão de cores"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Correção da cor"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas do volume premidas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ativado."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume premidas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Prima sem soltar as teclas de volume durante três segundos para utilizar o serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"O pedido SS foi alterado para uma videochamada."</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"O pedido SS foi alterado para um novo pedido USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Foi alterado para um novo pedido SS."</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Alerta de phishing."</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Perfil de trabalho"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Alertado"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Expandir"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maximizar"</string>
     <string name="close_button_text" msgid="10603510034455258">"Fechar"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Atender"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Recusar"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Desligar"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Chamada recebida"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Chamada em curso"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"A filtrar uma chamada recebida…"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selecionado</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Para continuar, a app &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; precisa de acesso à câmara do dispositivo."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Ativar"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Privacidade dos sensores"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 693af83..d5cec26 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Este dispositivo não tem um sensor de impressão digital."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor desativado temporariamente."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Use sua impressão digital para continuar"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ícone de impressão digital"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"O rosto não é mais reconhecido. Tente novamente."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Muito parecido, mude de posição."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Incline a cabeça um pouco menos."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Incline a cabeça um pouco menos."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Incline a cabeça um pouco menos."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Remova tudo que esteja ocultando seu rosto."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Limpe a parte superior da tela, inclusive a barra preta"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Permitir que o app leia e grave a configuração \"Não perturbe\"."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"iniciar uso da permissão para visualização"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Permite que o sistema inicie o uso de permissão para um app. Não deve ser necessário para apps comuns."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"acessar os dados do sensor em uma taxa de amostragem elevada"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Permite que o app receba amostras de dados do sensor em uma taxa maior que 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Definir regras para senha"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Controla o tamanho e os caracteres permitidos nos PINs e nas senhas do bloqueio de tela."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitorar tentativas de desbloqueio de tela"</string>
@@ -864,7 +868,7 @@
     <string name="lockscreen_transport_pause_description" msgid="6705284702135372494">"Pausar"</string>
     <string name="lockscreen_transport_play_description" msgid="106868788691652733">"Reproduzir"</string>
     <string name="lockscreen_transport_stop_description" msgid="1449552232598355348">"Parar"</string>
-    <string name="lockscreen_transport_rew_description" msgid="7680106856221622779">"Retroceder"</string>
+    <string name="lockscreen_transport_rew_description" msgid="7680106856221622779">"Voltar"</string>
     <string name="lockscreen_transport_ffw_description" msgid="4763794746640196772">"Avançar"</string>
     <string name="emergency_calls_only" msgid="3057351206678279851">"Só chamadas de emergência"</string>
     <string name="lockscreen_network_locked_message" msgid="2814046965899249635">"Rede bloqueada"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usar atalho"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversão de cores"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Correção de cor"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume pressionadas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ativado."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume pressionadas. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Toque nos dois botões de volume e os mantenha pressionados por três segundo para usar o <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Solicitação SS alterada para videochamada"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Solicitação SS alterada para solicitação USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Alterada para uma nova solicitação SS"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Alerta de phishing"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Perfil de trabalho"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Alertado"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Expandir"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maximizar"</string>
     <string name="close_button_text" msgid="10603510034455258">"Fechar"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Atender"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Recusar"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Desligar"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Chamada recebida"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Chamada em andamento"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Filtrando uma chamada recebida"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionado</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Para continuar, o app &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; precisa acessar a câmera do dispositivo."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Ativar"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Privacidade do sensor"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 5fd6f1a..690884a 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -582,6 +582,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Dispozitivul nu are senzor de amprentă."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Senzorul este dezactivat temporar."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Degetul <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Folosiți amprenta pentru a continua"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Pictograma amprentă"</string>
@@ -608,7 +609,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Nu se mai poate recunoaște fața. Încercați din nou."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Prea asemănător, schimbați poziția."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Întoarceți capul mai puțin."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Întoarceți capul mai puțin."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Întoarceți capul mai puțin."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Eliminați orice vă ascunde chipul."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Curățați partea de sus a ecranului, inclusiv bara neagră"</string>
@@ -687,6 +689,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Permite aplicației să citească și să scrie configurația Nu deranja."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"porniți folosirea permisiunii de vizualizare"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Permite proprietarului să pornească folosirea permisiunii pentru o aplicație. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"să acceseze date de la senzori la o rată de eșantionare mare"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Permite aplicației să colecteze date de la senzori la o rată de eșantionare de peste 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Să seteze reguli pentru parolă"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Stabiliți lungimea și tipul de caractere permise pentru parolele și codurile PIN de blocare a ecranului."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Să monitorizeze încercările de deblocare a ecranului"</string>
@@ -1686,6 +1690,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilizați comanda rapidă"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversarea culorilor"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Corecția culorii"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"S-au apăsat lung tastele de volum. S-a activat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"S-au apăsat lung tastele de volum. S-a dezactivat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Apăsați ambele butoane de volum timp de trei secunde pentru a folosi <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1898,6 +1904,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Solicitarea SS a fost schimbată cu un apel video"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Solicitarea SS a fost schimbată cu o solicitare USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Schimbat cu o solicitare SS nouă"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Alertă privind phishingul"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Profil de serviciu"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Notificat"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Extindeți"</string>
@@ -1911,6 +1918,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maximizați"</string>
     <string name="close_button_text" msgid="10603510034455258">"Închideți"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Răspundeți"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Respingeți"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Încheiați"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Apel primit"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Apel în desfășurare"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Se filtrează un apel primit"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> selectate</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selectate</item>
@@ -2242,4 +2255,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Pentru a continua, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; necesită acces la camera dispozitivului."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Activați"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Confidențialitatea privind senzorii"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index d1cd374..84752d5 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -585,6 +585,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"На этом устройстве нет сканера отпечатков пальцев."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Сканер отпечатков пальцев временно отключен."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Отпечаток <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Чтобы продолжить, используйте цифровой отпечаток"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Значок отпечатка пальца"</string>
@@ -611,7 +612,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Не удалось распознать лицо. Повторите попытку."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Слишком похожее выражение лица. Измените позу."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Держите голову ровнее."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Держите голову ровнее."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Держите голову ровнее."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Ваше лицо плохо видно."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Протрите верхнюю часть экрана (в том числе черную панель)."</string>
@@ -690,6 +692,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Открывает приложению доступ к настройкам режима \"Не беспокоить\" и позволяет изменять их."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"Просмотр данных об используемых разрешениях"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Приложение получит доступ к данным об используемых разрешениях. Это разрешение не требуется обычным приложениям."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"Доступ к данным датчиков при высокой частоте дискретизации"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Приложение сможет считывать данные датчиков на частоте более 200 Гц."</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Настройка правил для паролей"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Контролировать длину и символы при вводе пароля и PIN-кода."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Отслеживание попыток разблокировать экран"</string>
@@ -1708,6 +1712,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Использовать быстрое включение"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Инверсия цветов"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Коррекция цвета"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Использован жест с кнопками регулировки громкости. Функция \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\" включена."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Использован жест с кнопками регулировки громкости. Функция \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\" отключена."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Чтобы использовать сервис \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\", нажмите и удерживайте обе клавиши громкости в течение трех секунд."</string>
@@ -1929,6 +1935,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-запрос преобразован в видеовызов"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-запрос преобразован в USSD-запрос"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Преобразовано в SS-запрос"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Предупреждение о фишинге"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Рабочий профиль"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Отправлено оповещение"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Развернуть"</string>
@@ -1942,6 +1949,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Развернуть"</string>
     <string name="close_button_text" msgid="10603510034455258">"Закрыть"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Ответить"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Отклонить"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Завершить"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Входящий вызов"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Текущий вызов"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Фильтрация входящего вызова"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one">Выбрано: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
       <item quantity="few">Выбрано: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
@@ -2276,4 +2289,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Чтобы продолжить, предоставьте приложению &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; доступ к камере устройства."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Включить"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Конфиденциальность датчиков"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index d102183..66547de 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"මෙම උපාංගයේ ඇඟිලි සලකුණු සංවේදකයක් නොමැත."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"සංවේදකය තාවකාලිකව අබල කර ඇත."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"ඇඟිලි <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"ඉදිරියට යාමට ඔබගේ ඇඟිලි සලකුණ භාවිත කරන්න"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ඇඟිලි සලකුණු නිරූපකය"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"තවදුරටත් මුහුණ හඳුනාගත නොහැක. නැවත උත්සාහ කරන්න."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"ඉතා සමානයි, ඔබේ හැඩ ගැසීම වෙනස් කරන්න."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"ඔබේ හිස ටිකක් අඩුවෙන් කරකවන්න."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"ඔබේ හිස ටිකක් අඩුවෙන් කරකවන්න."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"ඔබේ හිස ටිකක් අඩුවෙන් කරකවන්න."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"ඔබේ මුහුණ සඟවන කිසිවක් ඉවත් කරන්න."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"කලු තීරුව ඇතුළුව, ඔබේ තිරයෙහි මුදුන පිරිසිදු කරන්න"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"බාධා නොකරන්න වින්‍යාස කිරීම කියවීමට සහ ලිවීමට යෙදුමට ඉඩ දෙයි."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"අවසර භාවිතය බැලීමට ආරම්භ කරන්න"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"තබා සිටින්නාට යෙදුමක් සඳහා අවසර භාවිතය ආරම්භ කිරීමට ඉඩ දෙයි. සාමාන්‍ය යෙදුම් සඳහා කිසි විටෙක අවශ්‍ය නොවිය යුතු ය."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"ඉහළ නියැදි කිරීමේ වේගයකින් සංවේදක දත්ත වෙත පිවිසෙන්න"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"200 Hz ට වඩා වැඩි වේගයකින් සංවේදක දත්ත නියැදි කිරීමට යෙදුමට ඉඩ දෙයි"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"මුරපද නීති සකස් කිරීම"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"තිර අගුලු මුරපද සහ PIN තුළ ඉඩ දෙන දිග සහ අනුලකුණු පාලනය කිරීම."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"තිරය අගුළු ඇරීමේ උත්සාහයන් නිරීක්ෂණය කරන්න"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"කෙටිමඟ භාවිතා කරන්න"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"වර්ණ අපවර්තනය"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"වර්ණ නිවැරදි කිරීම"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"හඬ පරිමා යතුරු අල්ලා ගන්න <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ක්‍රියාත්මකයි."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"හඬ පරිමා යතුරු අල්ලා ගන්න <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ක්‍රියාවිරහිතයි."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> භාවිත කිරීමට හඬ පරිමා යතුරු දෙකම තත්පර තුනකට ඔබාගෙන සිටින්න"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS ඉල්ලීම වීඩියෝ ඇමතුමට වෙනස් කරන ලදී"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS ඉල්ලීම USSD ඉල්ලීමට වෙනස් කරන ලදී"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"නව SS ඉල්ලීමට වෙනස් කරන ලදී"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"තතුබෑම් ඇඟවීම"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"කාර්යාල පැතිකඩ"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"අනතුරු අඟවන ලදී"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"දිග හරින්න"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"විහිදන්න"</string>
     <string name="close_button_text" msgid="10603510034455258">"වසන්න"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"පිළිතුරු දෙ."</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"ප්‍රතික්ෂේප ක"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"විසන්ධි කරන්න"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"එන ඇමතුම"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"කරගෙන යන ඇමතුම"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"එන ඇමතුමක් පරීක්ෂා කරන්න"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ක් තෝරන ලදි</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ක් තෝරන ලදි</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"දිගටම කර ගෙන යාමට, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; හට ඔබගේ උපාංගයෙහි කැමරාවට ප්‍රවේශය අවශ්‍යයි."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"ක්‍රියාත්මක කරන්න"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"සංවේදක පෞද්ගලිකත්වය"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index ffa4b26..487b818 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -585,6 +585,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Toto zariadenie nemá senzor odtlačkov prstov."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Senzor je dočasne vypnutý."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Prst: <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Pokračujte nasnímaním odtlačku prsta"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona odtlačku prsta"</string>
@@ -611,7 +612,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Tvár už nie je možné rozpoznať. Skúste to znova."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Príliš rovnaké, zmeňte postoj."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Otočte hlavu o niečo menej."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Otočte hlavu o niečo menej."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Otočte hlavu o niečo menej."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Odstráňte všetko, čo vám zakrýva tvár."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Vyčistite hornú časť obrazovky vrátane čierneho panela"</string>
@@ -690,6 +692,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Umožňuje aplikácii čítať a zapisovať konfiguráciu režimu bez vyrušení."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"spustenie používania povolenia na zobrazenie"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Umožňuje držiteľovi spustiť používanie povolenia aplikáciou. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"prístup k dátam senzorom s vysokou vzorkovacou frekvenciou"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Umožňuje aplikácii vzorkovať dáta senzorov s frekvenciou vyššou ako 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Nastaviť pravidlá pre heslo"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Nastavte dĺžku hesiel na odomknutie obrazovky aj kódov PIN a v nich používané znaky."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Sledovanie pokusov o odomknutie obrazovky"</string>
@@ -1708,6 +1712,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Použiť skratku"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inverzia farieb"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Úprava farieb"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Pridržali ste tlačidlá hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je zapnutá."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Pridržali ste tlačidlá hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je vypnutá."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Ak chcete používať službu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, pridržte tri sekundy oba klávesy hlasitosti"</string>
@@ -1929,6 +1935,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Žiadosť SS bola zmenená na videohovor"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Žiadosť SS bola zmenená na žiadosť USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Zmenené na novú žiadosť SS"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Upozornenie na phishing"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Pracovný profil"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Upozornené"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Rozbaliť"</string>
@@ -1942,6 +1949,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maximalizovať"</string>
     <string name="close_button_text" msgid="10603510034455258">"Zavrieť"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Prijať"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Odmietnuť"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Zložiť"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Prichádzajúci hovor"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Prebiehajúci hovor"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Preveruje sa prichádzajúci hovor"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="few">Vybrané: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
       <item quantity="many">Vybrané: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
@@ -2276,4 +2289,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Ak chcete pokračovať, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; požaduje prístup k fotoaparátu zariadenia."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Zapnúť"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Ochrana súkromia senzorov"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index d09ef04..87a66b3 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -150,8 +150,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Samo Wi-Fi"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <!-- no translation found for crossSimFormat_spn_cross_sim_calling (5620807020002879057) -->
-    <skip />
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"Pomožno klicanje prek operaterja <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ni posredovano"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> po toliko sekundah: <xliff:g id="TIME_DELAY">{2}</xliff:g>"</string>
@@ -586,6 +585,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Ta naprava nima tipala prstnih odtisov."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Tipalo je začasno onemogočeno."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Uporabite prstni odtis, če želite nadaljevati."</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona prstnih odtisov"</string>
@@ -612,7 +612,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Obraza ni več mogoče prepoznati. Poskusite znova."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Preveč podobno, spremenite položaj."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Glejte malce bolj naravnost."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Malce manj nagnite glavo."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Glejte malce bolj naravnost."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Umaknite vse, kar vam morda zakriva obraz."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Očistite vrhnji del zaslona, vključno s črno vrstico"</string>
@@ -691,6 +692,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Aplikaciji omogoča branje in pisanje konfiguracije načina »ne moti«."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"začetek uporabe dovoljenja za ogledovanje"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Imetniku omogoča začetek uporabe dovoljenj za aplikacijo. Nikoli ni potrebno za navadne aplikacije."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"dostop do podatkov tipal z večjo hitrostjo vzorčenja"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Aplikaciji dovoljuje, da vzorči podatke tipal s hitrostjo, večjo od 200 Hz."</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Nastavitev pravil za geslo"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Nadzor nad dolžino in znaki, ki so dovoljeni v geslih in kodah PIN za odklepanje zaslona."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Nadzor nad poskusi odklepanja zaslona"</string>
@@ -1709,6 +1712,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Uporabi bližnjico"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inverzija barv"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Popravljanje barv"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tipki za glasnost sta pridržani. Storitev <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je vklopljena."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tipki za glasnost sta pridržani. Storitev <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je izklopljena."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Za uporabo storitve <xliff:g id="SERVICE_NAME">%1$s</xliff:g> pritisnite obe tipki za glasnost in ju pridržite tri sekunde"</string>
@@ -1930,6 +1935,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Zahteva SS je spremenjena v videoklic"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Zahteva SS je spremenjena v zahtevo USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Spremenjeno v novo zahtevo SS"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Opozorilo o lažnem predstavljanju"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Delovni profil"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Opozorilo prikazano"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Razširi"</string>
@@ -1943,6 +1949,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maksimiziraj"</string>
     <string name="close_button_text" msgid="10603510034455258">"Zapri"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Sprejmi"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Zavrni"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Prekini klic"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Dohodni klic"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Aktivni klic"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Preverjanje dohodnega klica"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> izbran</item>
       <item quantity="two"><xliff:g id="COUNT_1">%1$d</xliff:g> izbrana</item>
@@ -2277,4 +2289,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Za nadaljevanje potrebuje aplikacija &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; dostop do fotoaparata v napravi."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Vklopi"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Zasebnost pri uporabi tipal"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 592e54d..4c37424 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Kjo pajisje nuk ka sensor të gjurmës së gishtit."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensori është çaktivizuar përkohësisht."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Gishti <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Përdor gjurmën e gishtit për të vazhduar"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona e gjurmës së gishtit"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Fytyra nuk mund të njihet më. Provo përsëri."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Tepër e ngjashme, ndrysho pozën"</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Ktheje kokën pak më pak."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Ktheje kokën pak më pak."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Ktheje kokën pak më pak."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Hiq gjithçka që fsheh fytyrën tënde."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Pastro kreun e ekranit, duke përfshirë shiritin e zi"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Lejon aplikacionin të lexojë dhe shkruajë konfigurimin e \"Mos shqetëso\"."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"nis përdorimin e lejes për shikimin"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Lejon që mbajtësi të nisë përdorimin e lejeve për një aplikacion. Nuk duhet të nevojitet asnjëherë për aplikacionet normale."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"qasu te të dhënat e sensorit me një shpejtësi më të lartë shembulli"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Lejon aplikacionin të mbledhë shembujt e të dhënave të sensorit me shpejtësi më të lartë se 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Cakto rregullat e fjalëkalimit"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Kontrollo gjatësinë dhe karakteret e lejuara në fjalëkalimet dhe kodet PIN të kyçjes së ekranit."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitoro tentativat e shkyçjes së ekranit"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Përdor shkurtoren"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Kthimi i ngjyrës"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Korrigjimi i ngjyrës"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tastet e volumit të mbajtura shtypur. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> i aktivizuar."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tastet e volumit të mbajtura shtypur. U çaktivizua \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\"."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Shtyp dhe mbaj shtypur të dy butonat e volumit për tre sekonda për të përdorur <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Kërkesa SS u ndryshua në telefonatë me video"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Kërkesa SS u ndryshua në kërkesë USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"U ndryshua në kërkesë të re SS"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Sinjalizim për mashtrim"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Profili i punës"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Sinjalizuar"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Zgjero"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maksimizo"</string>
     <string name="close_button_text" msgid="10603510034455258">"Mbyll"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Përgjigju"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Refuzo"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Mbyll"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Telefonatë hyrëse"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Telefonatë në vazhdim"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Po filtron një telefonatë hyrëse"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> të zgjedhura</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> i zgjedhur</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Për të vazhduar, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; ka nevojë të qaset në kamerën e pajisjes sate."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Aktivizo"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Privatësia e sensorit"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 65037a0..d061d6f 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -582,6 +582,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Овај уређај нема сензор за отисак прста."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Сензор је привремено онемогућен."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Прст <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Наставите помоћу отиска прста"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Икона отиска прста"</string>
@@ -608,7 +609,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Више не може да се препозна лице. Пробајте поново."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Превише је слично, промените позу."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Мало мање померите главу."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Мало мање померите главу."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Мало мање померите главу."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Уклоните све што вам заклања лице."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Очистите горњи део екрана, укључујући црну траку"</string>
@@ -687,6 +689,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Дозвољава апликацији да чита и уписује конфигурацију подешавања Не узнемиравај."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"почетак коришћења дозволе за преглед"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Дозвољава власнику да започне коришћење дозволе за апликацију. Никада не би требало да буде потребна за уобичајене апликације."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"приступ подацима сензора при великој брзини узорковања"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Дозвољава апликацији да узима узорак података сензора при брзини већој од 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Подешавање правила за лозинку"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Контролише дужину и знакове дозвољене у лозинкама и PIN-овима за закључавање екрана."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Надгледајте покушаје откључавања екрана"</string>
@@ -1686,6 +1690,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Користи пречицу"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Инверзија боја"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Корекција боја"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Држали сте тастере за јачину звука. Услуга <xliff:g id="SERVICE_NAME">%1$s</xliff:g> је укључена."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Држали сте тастере за јачину звука. Услуга <xliff:g id="SERVICE_NAME">%1$s</xliff:g> је искључена."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Притисните и задржите оба тастера за јачину звука три секунде да бисте користили <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1898,6 +1904,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS захтев је промењен у видео позив"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS захтев је промењен у USSD захтев"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Промењено је у нови SS захтев"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Упозорење о „пецању“"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Пословни профил"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Обавештено"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Прошири"</string>
@@ -1911,6 +1918,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Увећај"</string>
     <string name="close_button_text" msgid="10603510034455258">"Затвори"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Одговори"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Одбиј"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Прекини везу"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Долазни позив"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Позив је у току"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Проверава се долазни позив"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one">Изабрана је <xliff:g id="COUNT_1">%1$d</xliff:g> ставка</item>
       <item quantity="few">Изабране су <xliff:g id="COUNT_1">%1$d</xliff:g> ставке</item>
@@ -2242,4 +2255,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"&lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; захтева приступ камери уређаја ради настављања."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Укључи"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Приватност сензора"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index ef7a102..8288d41 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Enheten har ingen fingeravtryckssensor."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensorn har tillfälligt inaktiverats."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Fortsätt med hjälp av ditt fingeravtryck"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon för fingeravtryck"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Ansiktet kan inte längre kännas igen. Försök igen."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"För likt. Ändra ansiktsposition."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Vrid mindre på huvudet."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Vrid mindre på huvudet."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Vrid mindre på huvudet."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Ta bort allt som täcker ansiktet."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Rengör skärmens överkant, inklusive det svarta fältet"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Ger appen läs- och skrivbehörighet till konfigurationen för Stör ej."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"börja visa behörighetsanvändningen"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Gör att innehavaren kan öppna behörighetsanvändning för en app. Ska inte behövas för vanliga appar."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"åtkomst till sensordata med en hög samplingsfrekvens"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Tillåter att appen får åtkomst till sensordata med en högre samplingsfrekvens än 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Ange lösenordsregler"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Styr tillåten längd och tillåtna tecken i lösenord och pinkoder för skärmlåset."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Övervaka försök att låsa upp skärmen"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Använd kortkommandot"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inverterade färger"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Färgkorrigering"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Volymknapparna har tryckts ned. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> har aktiverats."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Volymknapparna har tryckts ned. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> har inaktiverats."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Tryck och håll båda volymknapparna i tre sekunder för att använda <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-begäran har ändrats till videosamtal"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-begäran har ändrats till en USSD-begäran"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Har ändrats till ny SS-begäran"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Varning om nätfiske"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Jobbprofil"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Aviserad"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Utöka"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maximera"</string>
     <string name="close_button_text" msgid="10603510034455258">"Stäng"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Svara"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Avvisa"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Lägg på"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Inkommande samtal"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Pågående samtal"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Ett inkommande samtal förhandsgranskas"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> har valts</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> har valts</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"&lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; behöver behörighet till enhetens kamera för att fortsätta."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Aktivera"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Sensorintegritet"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index cc82f4e..6ac7d2a 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Kifaa hiki hakina kitambua alama ya kidole."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Kitambuzi kimezimwa kwa muda."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Kidole cha <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Tumia alama ya kidole chako ili uendelee"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Aikoni ya alama ya kidole"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Haiwezi tena kutambua uso. Jaribu tena."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Inafanana sana, tafadhali badilisha mkao wako."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Geuza kichwa chako kidogo."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Geuza kichwa chako kidogo."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Geuza kichwa chako kidogo."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Ondoa kitu chochote kinachoficha uso wako."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Safisha sehemu ya juu ya skrini yako, ikiwa ni pamoja na upau mweusi"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Inaruhusu programu kusoma na kuandika usanidi wa kipengee cha Usinisumbue."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"anzisha kipengele cha kuona matumizi ya ruhusa"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Huruhusu kishikiliaji kuanzisha matumizi ya ruhusa ya programu. Haipaswi kuhitajika kwa ajili ya programu za kawaida."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"fikia data ya vitambuzi kwa kasi ya juu ya sampuli"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Huruhusu programu kujaribu sampuli ya data ya vitambuzi kwa kasi inayozidi Hz 200"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Kuweka kanuni za nenosiri"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Dhibiti urefu na maandishi yanayokubalika katika nenosiri la kufunga skrini na PIN."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Kuhesabu mara ambazo skrini inajaribu kufunguliwa"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Tumia Njia ya Mkato"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Ugeuzaji rangi"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Usahihishaji wa rangi"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Vitufe vya sauti vilivyoshikiliwa. Umewasha <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Vitufe vya sauti vimeshikiliwa. Umezima <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Bonyeza na ushikilie vitufe vyote viwili vya sauti kwa sekunde tatu ili utumie <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Imebadilisha ombi la SS kuwa simu ya video"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Imebadilisha ombi la SS kuwa ombi la USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Imebadilisha kuwa ombi jipya la SS"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Arifa ya wizi wa data binafsi"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Wasifu wa kazini"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Imearifu"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Panua"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Panua"</string>
     <string name="close_button_text" msgid="10603510034455258">"Funga"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Jibu"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Kataa"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Kata simu"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Simu uliyopigiwa"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Simu inayoendelea"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Inachuja simu unayopigiwa"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> vimechaguliwa</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> kimechaguliwa</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Ili uendelee, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; inahitaji ruhusa ya kufikia kamera ya kifaa chako."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Washa"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Faragha ya Kitambuzi"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index ca90171..1ac1734 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"இந்தச் சாதனத்தில் கைரேகை சென்சார் இல்லை."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"சென்சார் தற்காலிகமாக முடக்கப்பட்டுள்ளது."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"கைரேகை <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"தொடர்வதற்கு கைரேகையைப் பயன்படுத்துங்கள்"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"கைரேகை ஐகான்"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"முகத்தைக் கண்டறிய இயலவில்லை. மீண்டும் முயலவும்."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"மீண்டும் அதே போஸ் தருகிறீர்கள், வேறு முயலுங்கள்."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"தலையை லேசாகத் திருப்பவும்."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"தலையை லேசாகத் திருப்பவும்."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"உங்கள் தலையைச் சற்றுத் திருப்பவும்."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"உங்கள் முகத்தை மறைக்கும் அனைத்தையும் நீக்குக."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"திரையையும் அதிலுள்ள கருப்புப் பட்டியையும் சுத்தம் செய்யவும்"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"தொந்தரவு செய்ய வேண்டாம் உள்ளமைவைப் படிக்கவும் எழுதவும், ஆப்ஸை அனுமதிக்கிறது."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"அனுமதி உபயோகத்தை அணுகுதல்"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"ஆப்ஸிற்கான அனுமதி உபயோகத்தை ஹோல்டருக்கு வழங்கும். இயல்பான ஆப்ஸிற்கு இது எப்போதுமே தேவைப்படாது."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"அதிகளவிலான சாம்பிளிங் ரேட்டில் சென்சார் தரவை அணுகுதல்"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"200 ஹெர்ட்ஸ்க்கும் அதிகமான வீதத்தில் சென்சார் தரவை மாதிரியாக்க ஆப்ஸை அனுமதிக்கும்"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"கடவுச்சொல் விதிகளை அமைக்கவும்"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"திரைப் பூட்டின் கடவுச்சொற்கள் மற்றும் பின்களில் அனுமதிக்கப்படும் நீளத்தையும் எழுத்துக்குறிகளையும் கட்டுப்படுத்தும்."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"திரையைத் திறப்பதற்கான முயற்சிகளைக் கண்காணி"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ஷார்ட்கட்டைப் பயன்படுத்து"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"கலர் இன்வெர்ஷன்"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"வண்ணத் திருத்தம்"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ஒலியளவுக்கான விசைகளைப் பிடித்திருந்தீர்கள். <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ஆன் செய்யப்பட்டது."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ஒலியளவுக்கான விசைகளைப் பிடித்திருந்தீர்கள். <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ஆஃப் செய்யப்பட்டது."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>ஐப் பயன்படுத்த 3 விநாடிகளுக்கு இரண்டு ஒலியளவு பட்டன்களையும் அழுத்திப் பிடிக்கவும்"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS கோரிக்கை, வீடியோ அழைப்பிற்கு மாற்றப்பட்டது"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS கோரிக்கை, USSD கோரிக்கைக்கு மாற்றப்பட்டது"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"புதிய SS கோரிக்கைக்கு மாற்றப்பட்டது"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"ஃபிஷிங் எச்சரிக்கை"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"பணிக் கணக்கு"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"விழிப்பூட்டல் ஐகான்"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"விரிவாக்கும்"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"பெரிதாக்கு"</string>
     <string name="close_button_text" msgid="10603510034455258">"மூடு"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"பதிலளி"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"நிராகரி"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"துண்டி"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"உள்வரும் அழைப்பு"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"செயலில் இருக்கும் அழைப்பு"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"உள்வரும் அழைப்பை மதிப்பாய்வு செய்கிறது"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> தேர்ந்தெடுக்கப்பட்டன</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> தேர்ந்தெடுக்கப்பட்டது</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"தொடர, உங்கள் சாதனத்தின் கேமராவை அணுகுவதற்கு &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; ஆப்ஸுக்கு அனுமதி வேண்டும்."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"ஆன் செய்"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"சென்சார் தனியுரிமை"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index b0726e8..9f822e3 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -148,8 +148,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi మాత్రమే"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <!-- no translation found for crossSimFormat_spn_cross_sim_calling (5620807020002879057) -->
-    <skip />
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"<xliff:g id="SPN">%s</xliff:g> బ్యాకప్ కాలింగ్"</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ఫార్వార్డ్ చేయబడలేదు"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> సెకన్ల తర్వాత <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -580,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ఈ పరికరంలో వేలిముద్ర సెన్సార్ ఎంపిక లేదు."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"సెన్సార్ తాత్కాలికంగా డిజేబుల్ చేయబడింది."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"వేలు <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"కొనసాగించడానికి మీ వేలిముద్రను ఉపయోగించండి"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"వేలిముద్ర చిహ్నం"</string>
@@ -606,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"ఇక ముఖం గుర్తించలేదు. మళ్లీ ప్రయత్నించండి."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"ఒకే మాదిరిగా ఉంది, దయచేసి భంగిమను మార్చండి."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"మీ తలను ఇంకాస్త తక్కువ తిప్పండి."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"మీ తలను ఇంకాస్త తక్కువ తిప్పండి."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"మీ తలను ఎడమ/కుడి వైపుగా ఇంకాస్త తిప్పండి."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"మీ ముఖానికి అడ్డుగా ఉన్నవాటిని తీసివేస్తుంది."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"నల్లని పట్టీతో సహా మీ స్క్రీన్ పైభాగం అంతటినీ శుభ్రంగా తుడవండి"</string>
@@ -685,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"అంతరాయం కలిగించవద్దు ఎంపిక కాన్ఫిగరేషన్ చదవడానికి మరియు వ్రాయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"వీక్షణ అనుమతి వినియోగాన్ని ప్రారంభించండి"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"యాప్‌నకు అనుమతి వినియోగాన్ని ప్రారంభించడానికి హోల్డర్‌‌ను అనుమతిస్తుంది. సాధారణ యాప్‌లకు ఎప్పటికీ ఇటువంటి అనుమతి అవసరం ఉండదు."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"అధిక శాంపిల్ రేటు వద్ద సెన్సార్ డేటాను యాక్సెస్ చేయండి"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"200 Hz కంటే ఎక్కువ రేట్ వద్ద శాంపిల్ సెన్సార్ డేటాకు యాప్‌ను అనుమతిస్తుంది"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"పాస్‌వర్డ్ నియమాలను సెట్ చేయండి"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"స్క్రీన్ లాక్ పాస్‌వర్డ్‌లు మరియు PINల్లో అనుమతించబడిన పొడవు మరియు అక్షరాలను నియంత్రిస్తుంది."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"స్క్రీన్ అన్‌లాక్ ప్రయత్నాలను పర్యవేక్షించండి"</string>
@@ -1665,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"సత్వరమార్గాన్ని ఉపయోగించు"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"కలర్ మార్పిడి"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"కలర్ సరిచేయడం"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"వాల్యూమ్ కీలు నొక్కి ఉంచబడ్డాయి. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ఆన్ చేయబడింది"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"వాల్యూమ్ కీలు నొక్కి ఉంచబడ్డాయి. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ఆఫ్ చేయబడింది"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>ని ఉపయోగించడానికి వాల్యూమ్ కీలు రెండింటినీ 3 సెకన్లు నొక్కి ఉంచండి"</string>
@@ -1868,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS అభ్యర్థన వీడియో కాల్‌కి మార్చబడింది"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS అభ్యర్థన USSD అభ్యర్థనకు మార్చబడింది"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"కొత్త SS అభ్యర్థనకు మార్చబడింది"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"ఫిషింగ్ అలర్ట్"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"కార్యాలయ ప్రొఫైల్‌"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"హెచ్చరించబడింది"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"విస్తరింపజేయి"</string>
@@ -1881,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"గరిష్టీకరించు"</string>
     <string name="close_button_text" msgid="10603510034455258">"మూసివేయి"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"సమాధానం ఇవ్వు"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"తిరస్కరించండి"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"కాల్ ముగించు"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"ఇన్‌కమింగ్ కాల్"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"కాల్ కొనసాగుతోంది"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"ఇన్‌కమింగ్ కాల్‌ను స్క్రీన్ చేయండి"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ఎంచుకోబడ్డాయి</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ఎంచుకోబడింది</item>
@@ -2209,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"కొనసాగించడానికి, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&amp;gtకు మీ పరికరం యొక్క కెమెరా యాక్సెస్ అవసరం."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"ఆన్ చేయి"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"సెన్సార్ గోప్యత"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 5079f23..21865cd 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"อุปกรณ์นี้ไม่มีเซ็นเซอร์ลายนิ้วมือ"</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"ปิดใช้เซ็นเซอร์ชั่วคราวแล้ว"</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"นิ้ว <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"ใช้ลายนิ้วมือของคุณเพื่อดำเนินการต่อ"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ไอคอนลายนิ้วมือ"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"จำใบหน้าไม่ได้แล้ว ลองอีกครั้ง"</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"ใกล้เคียงเกินไป โปรดเปลี่ยนท่าโพส"</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"จัดตำแหน่งศีรษะให้ตรง"</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"จัดตำแหน่งศีรษะให้ตรง"</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"จัดตำแหน่งศีรษะให้ตรง"</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"เอาสิ่งที่ปิดบังใบหน้าออก"</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"ทำความสะอาดด้านบนของหน้าจอ รวมถึงแถบสีดำ"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"อนุญาตให้แอปอ่านและเขียนการกำหนดค่าโหมดห้ามรบกวน"</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"เริ่มการใช้สิทธิ์การดู"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"อนุญาตให้เจ้าของเริ่มการใช้สิทธิ์ของแอป ไม่จำเป็นสำหรับแอปทั่วไป"</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"เข้าถึงข้อมูลเซ็นเซอร์ที่อัตราการสุ่มตัวอย่างสูง"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"อนุญาตให้แอปสุ่มตัวอย่างข้อมูลเซ็นเซอร์ที่อัตราสูงกว่า 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"ตั้งค่ากฎรหัสผ่าน"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"ควบคุมความยาวและอักขระที่สามารถใช้ในรหัสผ่านของการล็อกหน้าจอและ PIN"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"ตรวจสอบความพยายามในการปลดล็อกหน้าจอ"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ใช้ทางลัด"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"การกลับสี"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"การแก้สี"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"กดปุ่มปรับระดับเสียงค้างไว้แล้ว เปิด <xliff:g id="SERVICE_NAME">%1$s</xliff:g> แล้ว"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"กดปุ่มปรับระดับเสียงค้างไว้แล้ว ปิด <xliff:g id="SERVICE_NAME">%1$s</xliff:g> แล้ว"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"กดปุ่มปรับระดับเสียงทั้ง 2 ปุ่มค้างไว้ 3 วินาทีเพื่อใช้ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"คำขอ SS เปลี่ยนเป็นวิดีโอคอลแล้ว"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"คำขอ SS เปลี่ยนเป็นคำขอ USSD แล้ว"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"เปลี่ยนเป็นคำขอ SS ใหม่แล้ว"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"การแจ้งเตือนฟิชชิง"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"โปรไฟล์งาน"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"แจ้งเตือนแล้ว"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"ขยาย"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"ขยายใหญ่สุด"</string>
     <string name="close_button_text" msgid="10603510034455258">"ปิด"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"รับสาย"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"ปฏิเสธ"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"วางสาย"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"สายเรียกเข้า"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"สายที่สนทนาอยู่"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"กำลังสกรีนสายเรียกเข้า"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other">เลือกไว้ <xliff:g id="COUNT_1">%1$d</xliff:g> รายการ</item>
       <item quantity="one">เลือกไว้ <xliff:g id="COUNT_0">%1$d</xliff:g> รายการ</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"&lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; ต้องได้รับสิทธิ์เข้าถึงกล้องของอุปกรณ์เพื่อดำเนินการต่อ"</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"เปิด"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"ความเป็นส่วนตัวสำหรับเซ็นเซอร์"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 81bfe52..37d06f8 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Walang sensor ng fingerprint ang device na ito."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Pansamantalang na-disable ang sensor."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Daliri <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Gamitin ang iyong fingerprint para magpatuloy"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icon ng fingerprint"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Hindi na makilala ang mukha. Subukang muli."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Masyadong magkatulad, pakibago ang pose mo."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Huwag masyadong lumingon."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Huwag masyadong tumingala o yumuko."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Huwag masyadong lumingon."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Alisin ang anumang humaharang sa iyong mukha."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Linisin ang itaas ng iyong screen, kasama ang itim na bar"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Nagbibigay-daan sa app na basahin at isulat ang configuration ng Huwag Istorbohin."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"simulan ang paggamit sa pahintulot sa pagtingin"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Binibigyang-daan ang may hawak na simulan ang paggamit ng pahintulot para sa isang app. Hindi dapat kailanganin kailanman para sa mga normal na app."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"mag-access ng data ng sensor sa mataas na rate ng pag-sample"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Pinapahintulutan ang app na mag-sample ng data ng sensor sa rate na higit sa 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Magtakda ng mga panuntunan sa password"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Kontrolin ang haba at ang mga character na pinapayagan sa mga password at PIN sa screen lock."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Subaybayan ang mga pagsubok sa pag-unlock ng screen"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Gamitin ang Shortcut"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Pag-invert ng Kulay"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Pagwawasto ng Kulay"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Pinindot nang matagal ang volume keys. Na-on ang <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Pinindot nang matagal ang volume keys. Na-off ang <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pindutin nang matagal ang parehong volume key sa loob ng tatlong segundo para magamit ang <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Ginawang video call ang SS na kahilingan"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Ginawang USSD na kahilingan ang SS na kahilingan"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Ginawang bagong SS na kahilingan"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Alerto sa phishing"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Profile sa trabaho"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Naalertuhan"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Palawakin"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"I-maximize"</string>
     <string name="close_button_text" msgid="10603510034455258">"Isara"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Sagutin"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Tanggihan"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Ibaba"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Papasok na tawag"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Kasalukuyang tawag"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Nagsi-screen ng papasok na tawag"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ang napili</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ang napili</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Para magpatuloy, kailangan ng &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; ng access sa camera ng iyong device."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"I-on"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Privacy ng Sensor"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 7095bb8..2132aac 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Bu cihazda parmak izi sensörü yok."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensör geçici olarak devre dışı bırakıldı."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"<xliff:g id="FINGERID">%d</xliff:g>. parmak"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Devam etmek için parmak izinizi kullanın"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Parmak izi simgesi"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Yüz artık tanınamıyor. Tekrar deneyin."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Duruşunuz çok benzer, lütfen pozunuzu değiştirin."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Başınızı biraz daha az çevirin."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Başınızı biraz daha az çevirin."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Başınızı biraz daha az çevirin."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Yüzünüzün görünmesini engelleyen şeyleri kaldırın."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Siyah çubuk da dahil olmak üzere ekranınızın üst kısmını temizleyin"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Uygulamaya, Rahatsız Etmeyin yapılandırmasını okuma ve yazma izni verir."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"izin kullanımı görüntülemeye başlama"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"İzin sahibinin bir uygulama için izin kullanımı başlatmasına olanak tanır. Normal uygulamalar için hiçbir zaman kullanılmamalıdır."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"sensör verilerine daha yüksek örnekleme hızında eriş"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Uygulamanın, sensör verilerini 200 Hz\'den daha yüksek bir hızda örneklemesine olanak tanır"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Şifre kuralları ayarla"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Ekran kilidini açma şifrelerinde ve PIN\'lerde izin verilen uzunluğu ve karakterleri denetleyin."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Ekran kilidini açma denemelerini izle"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Kısayolu Kullan"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Rengi Ters Çevirme"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Renk Düzeltme"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ses tuşlarını basılı tuttunuz. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> açıldı."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ses tuşlarını basılı tuttunuz. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> kapatıldı."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> hizmetini kullanmak için her iki ses tuşunu basılı tutun"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS isteği görüntülü görüşme olarak değişti"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS isteği USSD isteği olarak değişti"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Yeni SS isteği olarak değişti"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Kimlik avı uyarısı"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"İş profili"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Sesli uyarıldı"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Genişlet"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Ekranı Kapla"</string>
     <string name="close_button_text" msgid="10603510034455258">"Kapat"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Yanıtla"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Reddet"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Kapat"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Gelen çağrı"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Devam eden çağrı"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Gelen arama süzülüyor"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> öğe seçildi</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> öğe seçildi</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Devam etmek için &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; uygulamasının cihazınızın kamerasına erişmesi gerekiyor."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Aç"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Sensör Gizliliği"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 9864b4b..3b9db40 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -585,6 +585,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"На цьому пристрої немає сканера відбитків пальців."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Датчик тимчасово вимкнено."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Відбиток пальця <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Щоб продовжити, скористайтеся своїм відбитком пальця"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Значок відбитка пальця"</string>
@@ -611,7 +612,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Розпізнати обличчя вже не вдається. Повторіть спробу."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Надто схоже на попередню спробу, змініть позу."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Трохи перемістіть обличчя."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Трохи перемістіть обличчя."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Трохи поверніть обличчя."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Приберіть об’єкти, які затуляють ваше обличчя."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Очистьте верхню частину екрана, зокрема чорну панель"</string>
@@ -690,6 +692,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Додаток зможе переглядати та змінювати конфігурацію режиму \"Не турбувати\"."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"перегляньте дані про використання дозволів"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Власник зможе використовувати дозволи для цього додатка. Цей дозвіл не потрібен для звичайних додатків."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"доступ до даних датчиків із високою частотою дикретизації"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Додаток зможе дискретизувати дані даних датчиків із частотою понад 200 Гц"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Устан. правила пароля"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Укажіть максимальну довжину та кількість символів для паролів розблокування екрана та PIN-кодів."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Відстежувати спроби розблокування екрана"</string>
@@ -1708,6 +1712,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Використовувати ярлик"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Інверсія кольорів"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Корекція кольорів"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Утримано клавіші гучності. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> увімкнено."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Утримано клавіші гучності. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> вимкнено."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Щоб скористатися службою <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, утримуйте обидві клавіші гучності впродовж трьох секунд"</string>
@@ -1929,6 +1935,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Запит SS змінено на відеовиклик"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Запит SS змінено на запит USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Змінено на новий запит SS"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Попередження про фішинг"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Робочий профіль"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Зі звуком"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Розгорнути"</string>
@@ -1942,6 +1949,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Розгорнути"</string>
     <string name="close_button_text" msgid="10603510034455258">"Закрити"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Відповісти"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Відхилити"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Завершити"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Вхідний виклик"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Активний виклик"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Фільтрування вхідного виклику"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one">Вибрано <xliff:g id="COUNT_1">%1$d</xliff:g></item>
       <item quantity="few">Вибрано <xliff:g id="COUNT_1">%1$d</xliff:g></item>
@@ -2276,4 +2289,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Щоб продовжити, надайте додатку &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; доступ до камери пристрою."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Увімкнути"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Конфіденційність датчиків"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 64fb2fc..c10f3e9 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -148,8 +148,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"‏صرف Wi-Fi"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <!-- no translation found for crossSimFormat_spn_cross_sim_calling (5620807020002879057) -->
-    <skip />
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"<xliff:g id="SPN">%s</xliff:g> بیک اپ کالنگ"</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : فارورڈ نہیں کی گئی"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> بعد از <xliff:g id="TIME_DELAY">{2}</xliff:g> سیکنڈ"</string>
@@ -580,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"اس آلہ میں فنگر پرنٹ سینسر نہیں ہے۔"</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"سینسر عارضی طور غیر فعال ہے۔"</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"انگلی <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"جاری رکھنے کیلئے اپنا فنگر پرنٹ استعمال کریں"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"فنگر پرنٹ آئیکن"</string>
@@ -606,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"اب چہرے کی شناخت نہیں کر سکتے۔ پھر آزمائيں۔"</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"کافی ملتا جلتا ہے، براہ کرم اپنا پوز بدلیں۔"</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"اپنا سر تھوڑا کم کریں۔"</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"اپنا سر تھوڑا کم کریں۔"</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"اپنا سر تھوڑا کم کریں۔"</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"آپ کے چہرہ کو چھپانے والی ہر چیز کو ہٹائیں۔"</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"سیاہ بار سمیت، اپنی اسکرین کے اوپری حصے کو صاف کریں"</string>
@@ -685,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"ایپ کو ڈسٹرب نہ کریں کنفیگریشن لکھنے اور پڑھنے کے قابل کرتا ہے۔"</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"اجازت کی استعمال کا ملاحظہ شروع کریں"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"حامل کو ایپ کی اجازت کے استعمال کو شروع کرنے کی اجازت دیتا ہے۔ عام ایپس کے لیے کبھی بھی درکار نہیں ہونا چاہیے۔"</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"نمونہ کاری کی اعلی شرح پر سینسر کے ڈیٹا تک رسائی حاصل کریں"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"‏ایپ کو Hz‏200 سے زیادہ شرح پر سینسر ڈیٹا کا نمونہ لینے کی اجازت دیتی ہے"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"پاس ورڈ کے اصول سیٹ کریں"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"‏اسکرین لاک پاس ورڈز اور PINs میں اجازت یافتہ لمبائی اور حروف کو کنٹرول کریں۔"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"اسکرین غیر مقفل کرنے کی کوششیں مانیٹر کریں"</string>
@@ -1665,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"شارٹ کٹ استعمال کریں"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"رنگوں کی تقلیب"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"رنگ کی تصحیح"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"والیوم کی کلیدوں کو دبائے رکھا گیا۔ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> آن ہے۔"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"والیوم کی کلیدوں کو دبائے رکھا گیا۔ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> آف ہے۔"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> کا استعمال کرنے کے لیے 3 سیکنڈ تک والیوم کی دونوں کلیدوں کو چھوئیں اور دبائے رکھیں"</string>
@@ -1868,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"‏SS درخواست کو ویڈیو کال میں تبدیل کر دیا گیا"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"‏SS درخواست کو USSD درخواست میں تبدیل کر دیا گیا"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"‏نئی SS درخواست میں تبدیل کر دیا گیا"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"فریب دہی کا الرٹ"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"دفتری پروفائل"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"الرٹ کیا گیا"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"پھیلائیں"</string>
@@ -1881,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"بڑا کریں"</string>
     <string name="close_button_text" msgid="10603510034455258">"بند کریں"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"جواب"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"مسترد کریں"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"منقطع کر دیں"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"اِن کمنگ کال"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"جاری کال"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"اِن کمنگ کال کی اسکریننگ"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> منتخب کردہ</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> منتخب کردہ</item>
@@ -2209,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"‏جاری رکھنے کیلئے ‎&lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt;‎ کو آپ کے آلے کے کیمرے تک رسائی درکار ہے۔"</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"آن کریں"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"سینسر کی رازداری"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 6612cc9..f77de7d 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Bu qurilmada barmoq izi skaneri mavjud emas."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor vaqtincha faol emas."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Barmoq izi <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Davom etish uchun barmoq izingizdan foydalaning"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Barmoq izi belgisi"</string>
@@ -605,7 +606,7 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Yuz tanilmadi. Qaytadan urining."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Yuz ifodasi oldingiday. Holatingizni oʻzgartiring."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Boshingizni asta buring."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Boshingizni asta buring."</string>
+    <string name="face_acquired_tilt_too_extreme" msgid="8618210742620248049">"Boshingizni asta qiyalang."</string>
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Boshingizni asta buring."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Yuzingizni berkitayotgan narsalarni olib tashlang."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Ekranning yuqori qismini, shuningdek, qora panelni ham tozalang"</string>
@@ -684,6 +685,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"“Bezovta qilinmasin” rejimi sozlamalarini ko‘rish va o‘zgartirish."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"foydalaniladigan ruxsatlar axborotini ochish"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Ilova foydalanadigan ruxsatlar axborotini ishga tushirishga ruxsat beradi. Oddiy ilovalar uchun talab qilinmaydi."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"yuqori diskretlash chastotali sensor axborotiga ruxsat"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Ilova sensor axborotini 200 Hz dan yuqori tezlikda hisoblashi mumkin"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Parol qoidalarini o‘rnatish"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Ekran qulfi paroli va PIN kodlari uchun qo‘yiladigan talablarni (belgilar soni va uzunligi) nazorat qiladi."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Ekranni qulfdan chiqarishga urinishlarni nazorat qilish"</string>
@@ -1664,6 +1667,7 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Tezkor ishga tushirishdan foydalanish"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Ranglarni akslantirish"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Rangni tuzatish"</string>
+    <string name="reduce_bright_colors_feature_name" msgid="8978255324027479398">"Yorqinlikni pasaytirish"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tovush tugmalari bosib turildi. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> yoqildi."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tovush tugmalari bosib turildi. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> faolsizlantirildi."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> xizmatidan foydalanish uchun ikkala ovoz balandligi tugmalarini uzoq bosib turing"</string>
@@ -1867,6 +1871,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS talabi video chaqiruvga almashtirildi"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS talabi USSD talabiga almashtirildi"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Yangi SS talabiga almashtirildi"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Fishing signali"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Ish profili"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Ogohlantirildi"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Yoyish"</string>
@@ -1880,6 +1885,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Maksimallashtirish"</string>
     <string name="close_button_text" msgid="10603510034455258">"Yopish"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Javob berish"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Rad etish"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Tugatish"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Kiruvchi chaqiruv"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Joriy chaqiruv"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Kiruvchi chaqiruvni filtrlash"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other">Belgilandi: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
       <item quantity="one">Belgilandi: <xliff:g id="COUNT_0">%1$d</xliff:g></item>
@@ -2208,4 +2219,6 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Davom etish uchun &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; qurilmangiz kamerasiga kirishi kerak."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Yoqish"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Sensorlar maxfiyligi"</string>
+    <string name="splash_screen_view_icon_description" msgid="180638751260598187">"Ilova belgisi"</string>
+    <string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Ilova brendining rasmi"</string>
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 8f8e0bc..baf0b86d 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Thiết bị này không có cảm biến vân tay."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Đã tạm thời tắt cảm biến."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Ngón tay <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Sử dụng dấu vân tay của bạn để tiếp tục"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Biểu tượng vân tay"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Không nhận ra khuôn mặt. Hãy thử lại."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Khuôn mặt quá giống nhau, vui lòng đổi tư thế."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Hãy bớt di chuyển đầu."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Hãy bớt di chuyển đầu."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Hãy bớt di chuyển đầu."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Hãy loại bỏ mọi thứ che khuất khuôn mặt bạn."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Vệ sinh phần đầu màn hình, bao gồm cả thanh màu đen"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Cho phép ứng dụng đọc và ghi cấu hình Không làm phiền."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"cấp quyền xem"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Cho phép chủ sở hữu cấp quyền cho một ứng dụng. Các ứng dụng thông thường sẽ không bao giờ cần quyền này."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"truy cập vào dữ liệu cảm biến ở tốc độ lấy mẫu cao"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Cho phép ứng dụng lấy mẫu dữ liệu cảm biến ở tốc độ lớn hơn 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Đặt quy tắc mật khẩu"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Kiểm soát độ dài và ký tự được phép trong mật khẩu khóa màn hình và mã PIN."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Giám sát những lần thử mở khóa màn hình"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Sử dụng phím tắt"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Đảo màu"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Chỉnh màu"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Bạn đã giữ các phím âm lượng. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> đã bật."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Bạn đã giữ các phím âm lượng. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> đã tắt."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Nhấn và giữ đồng thời cả hai phím âm lượng trong 3 giây để sử dụng <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Yêu cầu SS đã thay đổi thành cuộc gọi video"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Yêu cầu SS đã thay đổi thành yêu cầu USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Đã thay đổi thành yêu cầu SS mới"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Cảnh báo về hành vi lừa đảo"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Hồ sơ công việc"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Đã phát âm báo"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Mở rộng"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Tối đa hóa"</string>
     <string name="close_button_text" msgid="10603510034455258">"Đóng"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Trả lời"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Từ chối"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Kết thúc"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Cuộc gọi đến"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Cuộc gọi đang thực hiện"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Đang sàng lọc cuộc gọi đến"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other">Đã chọn <xliff:g id="COUNT_1">%1$d</xliff:g></item>
       <item quantity="one">Đã chọn <xliff:g id="COUNT_0">%1$d</xliff:g></item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Để tiếp tục, &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; cần quyền truy cập vào máy ảnh trên thiết bị của bạn."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Bật"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Quyền riêng tư khi sử dụng cảm biến"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index af5f846..9345fc82 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"此设备没有指纹传感器。"</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"传感器已暂时停用。"</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"手指 <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"使用指纹完成验证才能继续"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"指纹图标"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"已无法识别人脸,请重试。"</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"与先前的姿势太相近,请换一个姿势。"</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"请将您的头稍微上下倾斜。"</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"请将您的头稍微上下倾斜。"</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"请将您的头稍微左右旋转。"</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"请移除所有遮挡您面部的物体。"</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"请将屏幕顶部(包括黑色条栏)清理干净"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"允许此应用读取和写入“勿扰”模式配置。"</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"授权使用“查看权限”"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"允许该应用开始查看应用的权限使用情况(普通应用绝不需要此权限)。"</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"以高采样率访问传感器数据"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"允许应用以高于 200 Hz 的频率对传感器数据进行采样"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"设置密码规则"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"控制锁屏密码和 PIN 码所允许的长度和字符。"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"监控屏幕解锁尝试次数"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"使用快捷方式"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"颜色反转"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"色彩校正"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"已按住音量键。<xliff:g id="SERVICE_NAME">%1$s</xliff:g>已开启。"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"已按住音量键。<xliff:g id="SERVICE_NAME">%1$s</xliff:g>已关闭。"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"同时按住两个音量键 3 秒钟即可使用 <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS 请求已更改为视频通话"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS 请求已更改为 USSD 请求"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"已更改为新的 SS 请求"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"网上诱骗警报"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"工作资料"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"已提醒"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"展开"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"最大化"</string>
     <string name="close_button_text" msgid="10603510034455258">"关闭"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>:<xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"接听"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"拒接"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"挂断"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"来电"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"正在通话"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"正在过滤来电"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other">已选择 <xliff:g id="COUNT_1">%1$d</xliff:g> 项</item>
       <item quantity="one">已选择 <xliff:g id="COUNT_0">%1$d</xliff:g> 项</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"如要继续操作,请向&lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt;授予设备的相机使用权。"</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"开启"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"传感器隐私权"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 65586f7..1187f00 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -148,7 +148,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"只限 Wi-Fi"</string>
     <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
     <skip />
-    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"「<xliff:g id="SPN">%s</xliff:g>」備用通話網路"</string>
+    <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"「<xliff:g id="SPN">%s</xliff:g>」備用通話"</string>
     <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:尚未轉接"</string>
     <string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> 於 <xliff:g id="TIME_DELAY">{2}</xliff:g> 秒後轉接"</string>
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"此裝置沒有指紋感應器。"</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"感應器已暫時停用。"</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"手指 <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"請使用您的指紋繼續"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"指紋圖示"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"無法再識別臉孔。請再試一次。"</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"臉孔位置太相近,請改變您的姿勢。"</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"減少頭部左右轉動幅度。"</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"減少頭部上下轉動幅度。"</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"減少頭部左右轉動幅度。"</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"移除遮住您臉孔的任何東西。"</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"請清理螢幕頂部,包括黑色列"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"允許應用程式讀取和寫入「請勿騷擾」設定。"</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"開始查看權限使用情況"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"允許應用程式開始查看應用程式的權限使用情況 (一般應用程式並不需要)。"</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"以高取樣率存取感應器資料"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"允許應用程式以大於 200 Hz 的頻率對感應器資料進行取樣"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"設定密碼規則"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"控制螢幕鎖定密碼和 PIN 所允許的長度和字元。"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"監控螢幕解鎖嘗試次數"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"使用快速鍵"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"色彩反轉"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"色彩校正"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"已按住音量鍵。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> 已開啟。"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"已按住音量鍵。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> 已關閉。"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"㩒住兩個音量鍵 3 秒就可以用 <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS 要求已變更為視像通話"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS 要求已變更為 USSD 要求"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"已變更為新的 SS 要求"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"仿冒詐騙警示"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"工作設定檔"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"已提醒"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"展開"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"最大化"</string>
     <string name="close_button_text" msgid="10603510034455258">"關閉"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>:<xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"接聽"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"拒接"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"掛斷"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"來電"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"通話中"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"正在過濾來電"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other">已選取 <xliff:g id="COUNT_1">%1$d</xliff:g> 個項目</item>
       <item quantity="one">已選取 <xliff:g id="COUNT_0">%1$d</xliff:g> 個項目</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"如要繼續,&lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; 需要裝置的相機存取權。"</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"開啟"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"感應器私隱"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 6facceb..9492572 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"這個裝置沒有指紋感應器。"</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"感應器已暫時停用。"</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"手指 <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"使用指紋完成驗證才能繼續操作"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"指紋圖示"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"已無法辨識臉孔,請再試一次。"</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"與先前的姿勢太相似,請換一個姿勢。"</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"請將你的頭部稍微向左或向右轉動。"</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"請將你的頭部稍微向上或向下傾斜。"</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"請將你的頭部稍微向左或向右旋轉。"</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"請移除任何會遮住臉孔的物體。"</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"請清理螢幕頂端,包括黑色橫列"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"允許應用程式讀取及寫入「零打擾」設定。"</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"啟動檢視權限用途"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"允許應用程式開始使用其他應用程式 (一般應用程式並不需要)。"</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"以高取樣率存取感應器資料"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"允許應用程式以高於 200 Hz 的頻率對感應器資料進行取樣"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"設定密碼規則"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"管理螢幕鎖定密碼和 PIN 碼支援的字元和長度上限。"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"監控螢幕解鎖嘗試次數"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"使用捷徑"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"色彩反轉"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"色彩校正"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"已按住音量鍵。「<xliff:g id="SERVICE_NAME">%1$s</xliff:g>」已開啟。"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"已按住音量鍵。「<xliff:g id="SERVICE_NAME">%1$s</xliff:g>」已關閉。"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"同時按住調低及調高音量鍵三秒即可使用「<xliff:g id="SERVICE_NAME">%1$s</xliff:g>」"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS 要求已變更為視訊通話"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS 要求已變更為 USSD 要求"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"已變更為新的 SS 要求"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"網路詐騙警示"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"工作資料夾"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"已提醒"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"展開"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"最大化"</string>
     <string name="close_button_text" msgid="10603510034455258">"關閉"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>:<xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"接聽"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"拒接"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"掛斷"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"來電"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"通話中"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"正在過濾來電"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="other">已選取 <xliff:g id="COUNT_1">%1$d</xliff:g> 個項目</item>
       <item quantity="one">已選取 <xliff:g id="COUNT_0">%1$d</xliff:g> 個項目</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"如要繼續操作,請將裝置的相機存取權授予「<xliff:g id="APP">%s</xliff:g>」&lt;b&gt;&lt;/b&gt;。"</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"開啟"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"感應器隱私權"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 3b22e94..e5a026bd 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -579,6 +579,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Le divayisi ayinayo inzwa yezigxivizo zeminwe."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Inzwa ikhutshazwe okwesikhashana."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Umunwe ongu-<xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Sebenzisa izigxivizo zakho zeminwe ukuze uqhubeke"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Isithonjana sezigxivizo zeminwe"</string>
@@ -605,7 +606,8 @@
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Ayisakwazi ukubona ubuso. Zama futhi."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Kufana kakhulu, sicela ushintshe ukuma kwakho."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Jikisa ikhanda lakho kancane."</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Jikisa ikhanda lakho kancane."</string>
+    <!-- no translation found for face_acquired_tilt_too_extreme (8618210742620248049) -->
+    <skip />
     <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"Jikisa ikhanda lakho kancane."</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Susa noma yini efihle ubuso bakho."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Hlanza okuphezulu kwesikrini sakho, kufaka phakathi ibha emnyama"</string>
@@ -684,6 +686,8 @@
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Ivumela izinhlelo zokusebenza ukufunda nokubhala ukulungiswa kokuthi Ungaphazamisi."</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"qala ukusetshenziswa kokubuka imvume"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Ivumela umphathi ukuthi aqale ukusetshenziswa kwemvume kohlelo lokusebenza. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string>
+    <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"finyelela idatha yenzwa ngenani eliphezulu lokwenza isampuli"</string>
+    <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Ivumela uhlelo lokusebenza lusampule idatha yenzwa ngenani elikhulu kuno-200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Misa imithetho yephasiwedi"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Lawula ubude nezinhlamvu ezivunyelwe kumaphasiwedi wokukhiya isikrini nama-PIN."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Qapha imizamo yokuvula isikrini sakho"</string>
@@ -1664,6 +1668,8 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Sebenzisa isinqamuleli"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Ukuguqulwa kombala"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Ukulungiswa kombala"</string>
+    <!-- no translation found for reduce_bright_colors_feature_name (8978255324027479398) -->
+    <skip />
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ubambe okhiye bevolumu. I-<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ivuliwe."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ubambe okhiye bevolumu. I-<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ivaliwe."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Cindezela uphinde ubambe bobabili okhiye bevolumu ngamasekhondi amathathu ukuze usebenzise i-<xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1867,6 +1873,7 @@
     <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Isicelo se-SS sishintshele kukholi yevidiyo"</string>
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Isicelo se-SS sishintshele kusicelo se-USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Ishintshele kusicelo esisha se-SS"</string>
+    <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Isexwayiso sobugebengu bokweba imininingwane ebucayi"</string>
     <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Iphrofayela yomsebenzi"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"Kuxwayisiwe"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Nweba"</string>
@@ -1880,6 +1887,12 @@
     <string name="maximize_button_text" msgid="4258922519914732645">"Khulisa"</string>
     <string name="close_button_text" msgid="10603510034455258">"Vala"</string>
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+    <string name="call_notification_answer_action" msgid="5999246836247132937">"Phendula"</string>
+    <string name="call_notification_decline_action" msgid="3700345945214000726">"Yenqaba"</string>
+    <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Vala Ucingo"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Ikholi engenayo"</string>
+    <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Ikholi eqhubekayo"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Ukuveza ikholi engenayo"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> okukhethiwe</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> okukhethiwe</item>
@@ -2208,4 +2221,8 @@
     <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Ukuze uqhubeke, &lt;b&gt;i-<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; idinga ukufinyelela ikhamera yakho."</string>
     <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Vula"</string>
     <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Ubumfihlo Benzwa"</string>
+    <!-- no translation found for splash_screen_view_icon_description (180638751260598187) -->
+    <skip />
+    <!-- no translation found for splash_screen_view_branding_description (7911129347402728216) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 69bb20c..100983b 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4117,6 +4117,94 @@
              user's time zone. Please refer to {@link java.util.TimeZone} for more
              information about time zone ids. -->
         <attr name="timeZone" format="string"/>
+        <!-- Tint to apply to the dial graphic. -->
+        <attr name="dialTint" format="color" />
+        <!-- Blending mode used to apply the dial graphic tint. -->
+        <attr name="dialTintMode">
+            <!-- The tint is drawn on top of the drawable.
+                 [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] -->
+            <enum name="src_over" value="3" />
+            <!-- The tint is masked by the alpha channel of the drawable. The drawable’s
+                 color channels are thrown out. [Sa * Da, Sc * Da] -->
+            <enum name="src_in" value="5" />
+            <!-- The tint is drawn above the drawable, but with the drawable’s alpha
+                 channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] -->
+            <enum name="src_atop" value="9" />
+            <!-- Multiplies the color and alpha channels of the drawable with those of
+                 the tint. [Sa * Da, Sc * Dc] -->
+            <enum name="multiply" value="14" />
+            <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -->
+            <enum name="screen" value="15" />
+            <!-- Combines the tint and drawable color and alpha channels, clamping the
+                 result to valid color values. Saturate(S + D) -->
+            <enum name="add" value="16" />
+        </attr>
+        <!-- Tint to apply to the hour hand graphic. -->
+        <attr name="hand_hourTint" format="color" />
+        <!-- Blending mode used to apply the hour hand graphic tint. -->
+        <attr name="hand_hourTintMode">
+            <!-- The tint is drawn on top of the drawable.
+                 [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] -->
+            <enum name="src_over" value="3" />
+            <!-- The tint is masked by the alpha channel of the drawable. The drawable’s
+                 color channels are thrown out. [Sa * Da, Sc * Da] -->
+            <enum name="src_in" value="5" />
+            <!-- The tint is drawn above the drawable, but with the drawable’s alpha
+                 channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] -->
+            <enum name="src_atop" value="9" />
+            <!-- Multiplies the color and alpha channels of the drawable with those of
+                 the tint. [Sa * Da, Sc * Dc] -->
+            <enum name="multiply" value="14" />
+            <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -->
+            <enum name="screen" value="15" />
+            <!-- Combines the tint and drawable color and alpha channels, clamping the
+                 result to valid color values. Saturate(S + D) -->
+            <enum name="add" value="16" />
+        </attr>
+        <!-- Tint to apply to the minute hand graphic. -->
+        <attr name="hand_minuteTint" format="color" />
+        <!-- Blending mode used to apply the minute hand graphic tint. -->
+        <attr name="hand_minuteTintMode">
+            <!-- The tint is drawn on top of the drawable.
+                 [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] -->
+            <enum name="src_over" value="3" />
+            <!-- The tint is masked by the alpha channel of the drawable. The drawable’s
+                 color channels are thrown out. [Sa * Da, Sc * Da] -->
+            <enum name="src_in" value="5" />
+            <!-- The tint is drawn above the drawable, but with the drawable’s alpha
+                 channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] -->
+            <enum name="src_atop" value="9" />
+            <!-- Multiplies the color and alpha channels of the drawable with those of
+                 the tint. [Sa * Da, Sc * Dc] -->
+            <enum name="multiply" value="14" />
+            <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -->
+            <enum name="screen" value="15" />
+            <!-- Combines the tint and drawable color and alpha channels, clamping the
+                 result to valid color values. Saturate(S + D) -->
+            <enum name="add" value="16" />
+        </attr>
+        <!-- Tint to apply to the second hand graphic. -->
+        <attr name="hand_secondTint" format="color" />
+        <!-- Blending mode used to apply the second hand graphic tint. -->
+        <attr name="hand_secondTintMode">
+            <!-- The tint is drawn on top of the drawable.
+                 [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] -->
+            <enum name="src_over" value="3" />
+            <!-- The tint is masked by the alpha channel of the drawable. The drawable’s
+                 color channels are thrown out. [Sa * Da, Sc * Da] -->
+            <enum name="src_in" value="5" />
+            <!-- The tint is drawn above the drawable, but with the drawable’s alpha
+                 channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] -->
+            <enum name="src_atop" value="9" />
+            <!-- Multiplies the color and alpha channels of the drawable with those of
+                 the tint. [Sa * Da, Sc * Dc] -->
+            <enum name="multiply" value="14" />
+            <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -->
+            <enum name="screen" value="15" />
+            <!-- Combines the tint and drawable color and alpha channels, clamping the
+                 result to valid color values. Saturate(S + D) -->
+            <enum name="add" value="16" />
+        </attr>
     </declare-styleable>
     <declare-styleable name="Button">
     </declare-styleable>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 0ae6a76..45e11ba 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1893,6 +1893,11 @@
             <!-- User data will remain unchanged during rollback. -->
             <enum name="retain" value="2" />
         </attr>
+
+        <!-- Applications can set this attribute to an xml resource within their app where they
+         specified the rules determining which files and directories can be copied from the device
+         as part of backup or transfer operations. -->
+        <attr name="dataExtractionRules" format="reference"/>
     </declare-styleable>
 
     <!-- An attribution is a logical part of an app and is identified by a tag.
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 59c260c..d79c01f 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -143,6 +143,10 @@
     <color name="notification_default_color_dark">@color/primary_text_default_material_light</color>
     <color name="notification_default_color_light">#a3202124</color>
 
+    <color name="notification_primary_text_color_current">@color/notification_primary_text_color_light</color>
+    <color name="notification_secondary_text_color_current">@color/notification_secondary_text_color_light</color>
+    <color name="notification_default_color_current">@color/notification_default_color_light</color>
+
     <color name="notification_default_color">#757575</color> <!-- Gray 600 -->
 
     <color name="notification_action_button_text_color">@color/notification_default_color</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index faa2157..12cb398 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1173,6 +1173,9 @@
     <!-- Default value for LED off time when the battery is low on charge in miliseconds -->
     <integer name="config_notificationsBatteryLedOff">2875</integer>
 
+    <!-- If true, only colorized CallStyle notifications will apply custom colors -->
+    <bool name="config_callNotificationActionColorsRequireColorized">true</bool>
+
     <!-- Number of notifications to keep in the notification service historical archive -->
     <integer name="config_notificationServiceArchiveSize">100</integer>
 
@@ -1950,6 +1953,8 @@
     <string name="config_systemShell" translatable="false">com.android.shell</string>
     <!-- The name of the package that will hold the system contacts role. -->
     <string name="config_systemContacts" translatable="false">com.android.contacts</string>
+    <!-- The name of the package that will hold the speech recognizer role by default. -->
+    <string name="config_systemSpeechRecognizer" translatable="false"></string>
 
     <!-- The name of the package that will be allowed to change its components' label/icon. -->
     <string name="config_overrideComponentUiPackage" translatable="false"></string>
@@ -3205,6 +3210,10 @@
          panning to scaling the magnification viewport. -->
     <item name="config_screen_magnification_scaling_threshold" format="float" type="dimen">0.3</item>
 
+    <!-- Whether to support magnification area. If not enabled, it would hide the entry in
+         magnification settings and adjust the default magnification capability.  -->
+    <bool name="config_magnification_area">true</bool>
+
     <!-- If true, the display will be shifted around in ambient mode. -->
     <bool name="config_enableBurnInProtection">false</bool>
 
@@ -4588,11 +4597,12 @@
         <item>com.android.systemui</item>
     </string-array>
 
-    <!-- Package name of custom media key dispatcher class used by MediaSessionService. -->
+    <!-- Component name of custom media key dispatcher class used by MediaSessionService. -->
     <string name="config_customMediaKeyDispatcher"></string>
 
-    <!-- Package name of custom session policy provider class used by MediaSessionService. -->
-    <string name="config_customSessionPolicyProvider"></string>
+    <!-- Component name of custom media session policy provider class used by
+         MediaSessionService. -->
+    <string name="config_customMediaSessionPolicyProvider"></string>
 
     <!-- The max scale for the wallpaper when it's zoomed in -->
     <item name="config_wallpaperMaxScale" format="float" type="dimen">1.10</item>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 7066419..c2b6b99 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -30,7 +30,13 @@
          will be displayed in the app launcher and elsewhere. -->
     <dimen name="app_icon_size">48dip</dimen>
 
-    <dimen name="toast_y_offset">24dp</dimen>
+    <!--  Offset from the bottom of the device a toast shows -->
+    <dimen name="toast_y_offset">48dp</dimen>
+    <!-- Max width of a toast -->
+    <dimen name="toast_width">300dp</dimen>
+    <!-- Text size of the message within a toast -->
+    <dimen name="toast_text_size">14sp</dimen>
+
     <!-- Height of the status bar -->
     <dimen name="status_bar_height">@dimen/status_bar_height_portrait</dimen>
     <!-- Height of the status bar in portrait. The height should be
@@ -265,11 +271,8 @@
     <!-- The top margin before the notification progress bar. -->
     <dimen name="notification_progress_margin_top">8dp</dimen>
 
-    <!-- height of the notification header when the notification is alone (minimized / groups) -->
-    <dimen name="notification_header_solo_height">48dp</dimen>
-
-    <!-- height of the notification header when in a "big" layout -->
-    <dimen name="notification_header_big_height">56dp</dimen>
+    <!-- height of the notification header -->
+    <dimen name="notification_header_height">56dp</dimen>
 
     <!-- The height of the background for a notification header on a group -->
     <dimen name="notification_header_background_height">49.5dp</dimen>
@@ -316,26 +319,22 @@
     <!-- The top padding for the notification expand button. -->
     <dimen name="notification_expand_button_padding_top">1dp</dimen>
 
-    <!-- minimum vertical margin for the headerless notification content, when cap = 60dp -->
-    <dimen name="notification_headerless_margin_minimum">8dp</dimen>
+    <!-- Vertical margin for the headerless notification content, when content has 1 line -->
+    <!-- 16 * 2 (margins) + 24 (1 line) = 56 (notification) -->
+    <dimen name="notification_headerless_margin_oneline">16dp</dimen>
 
-    <!-- extra vertical margin for the headerless notification content, when cap = 60dp -->
-    <dimen name="notification_headerless_margin_extra">10dp</dimen>
-
-    <!-- minimum vertical margin for the headerless notification content, when cap = 48dp -->
-    <dimen name="notification_headerless_margin_constrained_minimum">14dp</dimen>
-
-    <!-- extra vertical margin for the headerless notification content, when cap = 48dp -->
-    <dimen name="notification_headerless_margin_constrained_extra">4dp</dimen>
+    <!-- Vertical margin for the headerless notification content, when content has 2 lines -->
+    <!-- 20 * 2 (margins) + 24 * 2 (2 lines) = 88 (notification) -->
+    <dimen name="notification_headerless_margin_twoline">20dp</dimen>
 
     <!-- The height of each of the 1 or 2 lines in the headerless notification template -->
-    <dimen name="notification_headerless_line_height">20sp</dimen>
+    <dimen name="notification_headerless_line_height">24dp</dimen>
 
     <!-- vertical margin for the headerless notification content -->
     <dimen name="notification_headerless_min_height">56dp</dimen>
 
     <!-- Height of a small notification in the status bar -->
-    <dimen name="notification_min_height">76dp</dimen>
+    <dimen name="notification_min_height">88dp</dimen>
 
     <!-- The width of the big icons in notifications. -->
     <dimen name="notification_large_icon_width">64dp</dimen>
@@ -359,7 +358,7 @@
     <dimen name="media_notification_expanded_image_margin_bottom">20dp</dimen>
 
     <!-- The absolute height for the header in a media notification. -->
-    <dimen name="media_notification_header_height">@dimen/notification_header_big_height</dimen>
+    <dimen name="media_notification_header_height">@dimen/notification_header_height</dimen>
 
     <!-- The margin of the content to an image-->
     <dimen name="notification_content_image_margin_end">8dp</dimen>
@@ -496,14 +495,20 @@
     <!-- The padding on top of inbox style elements -->
     <dimen name="notification_inbox_item_top_padding">5dp</dimen>
 
+    <!-- Size of the verification icon for call notifications -->
+    <dimen name="notification_verification_icon_size">@dimen/notification_badge_size</dimen>
+
     <!-- Size of the feedback indicator for notifications -->
     <dimen name="notification_feedback_size">20dp</dimen>
 
+    <!-- Size of the phishing alert for notifications -->
+    <dimen name="notification_phishing_alert_size">@dimen/notification_badge_size</dimen>
+
     <!-- Size of the profile badge for notifications -->
     <dimen name="notification_badge_size">12dp</dimen>
 
     <!-- Size of the alerted icon for notifications -->
-    <dimen name="notification_alerted_size">12dp</dimen>
+    <dimen name="notification_alerted_size">@dimen/notification_badge_size</dimen>
 
     <!-- Keyguard dimensions -->
     <!-- TEMP -->
@@ -729,10 +734,11 @@
     <!-- The maximum width of a image in a media notification. The images will be reduced to that width in case they are bigger.-->
     <dimen name="notification_media_image_max_width">280dp</dimen>
     <!-- The size of the right icon -->
-    <dimen name="notification_right_icon_size">52dp</dimen>
+    <dimen name="notification_right_icon_size">48dp</dimen>
     <!-- The top and bottom margin of the right icon in the normal notification states -->
-    <dimen name="notification_right_icon_headerless_margin">12dp</dimen>
+    <dimen name="notification_right_icon_headerless_margin">20dp</dimen>
     <!-- The top margin of the right icon in the "big" notification states -->
+    <!--  TODO(b/181048615): Move the large icon below the expander in big states  -->
     <dimen name="notification_right_icon_big_margin_top">16dp</dimen>
     <!-- The size of the left icon -->
     <dimen name="notification_left_icon_size">@dimen/notification_icon_circle_size</dimen>
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index ab4e0f3..0f0ac56 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -145,6 +145,7 @@
 
   <item type="id" name="remote_input_tag" />
   <item type="id" name="pending_intent_tag" />
+  <item type="id" name="remote_checked_change_listener_tag" />
 
   <item type="id" name="cross_task_transition" />
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 22dce9b..2004d0a 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3076,6 +3076,15 @@
     <public name="maxResizeHeight" />
     <public name="targetCellWidth" />
     <public name="targetCellHeight" />
+    <public name="dialTint"/>
+    <public name="dialTintMode"/>
+    <public name="hand_hourTint"/>
+    <public name="hand_hourTintMode"/>
+    <public name="hand_minuteTint"/>
+    <public name="hand_minuteTintMode"/>
+    <public name="hand_secondTint"/>
+    <public name="hand_secondTintMode"/>
+    <public name="dataExtractionRules"/>
   </public-group>
 
   <public-group type="drawable" first-id="0x010800b5">
@@ -3153,6 +3162,12 @@
     <public name="config_systemShell" />
     <!-- @hide @SystemApi -->
     <public name="config_systemContacts" />
+    <!-- @hide @SystemApi -->
+    <public name="config_customMediaKeyDispatcher" />
+    <!-- @hide @SystemApi -->
+    <public name="config_customMediaSessionPolicyProvider" />
+    <!-- @hide @SystemApi -->
+    <public name="config_systemSpeechRecognizer" />
   </public-group>
 
   <public-group type="id" first-id="0x01020055">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 9ebe23a..71ba44b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1644,7 +1644,7 @@
     <!-- Message shown during acqusition when the user's face is turned too far left or right [CHAR LIMIT=50] -->
     <string name="face_acquired_pan_too_extreme">Turn your head a little less.</string>
     <!-- Message shown during acqusition when the user's face is tilted too high or too low [CHAR LIMIT=50] -->
-    <string name="face_acquired_tilt_too_extreme">Turn your head a little less.</string>
+    <string name="face_acquired_tilt_too_extreme">Tilt your head a little less.</string>
     <!-- Message shown during acquisiton when the user's face is tilted too far left or right [CHAR LIMIT=50] -->
     <string name="face_acquired_roll_too_extreme">Turn your head a little less.</string>
     <!-- Message shown during acquisition when the user's face is obscured [CHAR LIMIT=50] -->
@@ -4538,7 +4538,7 @@
     <string name="color_correction_feature_name">Color Correction</string>
 
     <!-- Title of Reduce Brightness feature, shown in the warning dialog about the accessibility shortcut. [CHAR LIMIT=none] -->
-    <string name="reduce_bright_colors_feature_name">Reduce Brightness</string>
+    <string name="reduce_bright_colors_feature_name">Reduce brightness</string>
 
     <!-- Text in toast to alert the user that the accessibility shortcut turned on an accessibility service. [CHAR LIMIT=none] -->
     <string name="accessibility_shortcut_enabling_service">Held volume keys. <xliff:g id="service_name" example="TalkBack">%1$s</xliff:g> turned on.</string>
@@ -5002,12 +5002,18 @@
     <string name="stk_cc_ss_to_ussd">SS request changed to USSD request</string>
     <string name="stk_cc_ss_to_ss">Changed to new SS request</string>
 
+    <!-- Content description of the phishing alert icon in the notification. [CHAR_LIMIT=NONE] -->
+    <string name="notification_phishing_alert_content_description">Phishing alert</string>
+
     <!-- Content description of the work profile icon in the notification. -->
     <string name="notification_work_profile_content_description">Work profile</string>
 
     <!-- Content description of the alerting icon in the notification. [CHAR_LIMIT=NONE] -->
     <string name="notification_alerted_content_description">Alerted</string>
 
+    <!-- Default content description of the verification icon in the call notification. [CHAR_LIMIT=NONE] -->
+    <string name="notification_verified_content_description">Verified</string>
+
     <!-- Content description of the expand button icon in the notification when collaped.-->
     <string name="expand_button_content_description_collapsed">Expand</string>
 
@@ -5846,4 +5852,8 @@
     <!--- Label for notification channel for all sensor privacy related notifications. [CHAR LIMIT=NONE] -->
     <string name="sensor_privacy_notification_channel_label">Sensor Privacy</string>
 
+    <!-- Content description for the icon on the splash screen. [CHAR LIMIT=50] -->
+    <string name="splash_screen_view_icon_description">Application icon</string>
+    <!-- Content description for the branding image on the splash screen. [CHAR LIMIT=50] -->
+    <string name="splash_screen_view_branding_description">Application branding image</string>
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 24afe07..c7ded0c 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -964,8 +964,9 @@
     </style>
 
     <style name="TextAppearance.Toast">
-        <item name="fontFamily">sans-serif</item>
+        <item name="fontFamily">@*android:string/config_headlineFontFamily</item>
         <item name="textSize">14sp</item>
+        <item name="textColor">?android:attr/textColorPrimary</item>
     </style>
 
     <style name="TextAppearance.Tooltip">
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 158289a..3c4a5d4 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -466,18 +466,20 @@
     </style>
 
     <style name="TextAppearance.Material.Notification">
-        <item name="textColor">@color/notification_secondary_text_color_light</item>
+        <item name="textColor">@color/notification_secondary_text_color_current</item>
         <item name="textSize">@dimen/notification_text_size</item>
     </style>
 
     <style name="TextAppearance.Material.Notification.Reply" />
 
     <style name="TextAppearance.Material.Notification.Title">
+        <item name="textColor">@color/notification_primary_text_color_current</item>
         <item name="fontFamily">sans-serif-medium</item>
         <item name="textSize">@dimen/notification_title_text_size</item>
     </style>
 
     <style name="TextAppearance.Material.Notification.BigTitle">
+        <item name="textColor">@color/notification_primary_text_color_current</item>
         <item name="fontFamily">sans-serif-medium</item>
         <item name="textSize">@dimen/notification_big_title_text_size</item>
     </style>
@@ -492,9 +494,8 @@
 
     <style name="TextAppearance.Material.Notification.Time" parent="TextAppearance.Material.Notification.Info" />
 
-    <style name="TextAppearance.Material.Notification.Emphasis">
-        <item name="textColor">#66000000</item>
-    </style>
+    <!-- unused; keep identical to parent -->
+    <style name="TextAppearance.Material.Notification.Emphasis"/>
 
     <style name="TextAppearance.Material.Notification.Conversation.AppName" parent="TextAppearance.Material.Notification.Title">
         <item name="android:textSize">16sp</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index f66d33b..dbb584d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -233,6 +233,7 @@
   <java-symbol type="id" name="pin_confirm_text" />
   <java-symbol type="id" name="pin_error_message" />
   <java-symbol type="id" name="timePickerLayout" />
+  <java-symbol type="id" name="phishing_alert" />
   <java-symbol type="id" name="profile_badge" />
   <java-symbol type="id" name="alerted_icon" />
   <java-symbol type="id" name="transitionPosition" />
@@ -2285,6 +2286,7 @@
   <java-symbol type="string" name="config_wifi_tether_enable" />
   <java-symbol type="bool" name="config_intrusiveNotificationLed" />
   <java-symbol type="bool" name="config_notificationBadging" />
+  <java-symbol type="bool" name="config_callNotificationActionColorsRequireColorized" />
   <java-symbol type="dimen" name="preference_fragment_padding_bottom" />
   <java-symbol type="dimen" name="preference_fragment_padding_side" />
   <java-symbol type="drawable" name="expander_ic_maximized" />
@@ -2814,6 +2816,7 @@
   <java-symbol type="id" name="smart_reply_container" />
   <java-symbol type="id" name="remote_input_tag" />
   <java-symbol type="id" name="pending_intent_tag" />
+  <java-symbol type="id" name="remote_checked_change_listener_tag" />
   <java-symbol type="id" name="notification_action_index_tag" />
 
   <java-symbol type="attr" name="seekBarDialogPreferenceStyle" />
@@ -2892,8 +2895,6 @@
   <java-symbol type="id" name="alternate_expand_target" />
   <java-symbol type="id" name="notification_header" />
   <java-symbol type="id" name="notification_top_line" />
-  <java-symbol type="id" name="notification_headerless_margin_extra_top" />
-  <java-symbol type="id" name="notification_headerless_margin_extra_bottom" />
   <java-symbol type="id" name="time_divider" />
   <java-symbol type="id" name="header_text_divider" />
   <java-symbol type="id" name="header_text_secondary_divider" />
@@ -2915,8 +2916,8 @@
   <java-symbol type="dimen" name="notification_header_icon_size" />
   <java-symbol type="dimen" name="notification_header_app_name_margin_start" />
   <java-symbol type="dimen" name="notification_header_separating_margin" />
-  <java-symbol type="dimen" name="notification_headerless_margin_constrained_minimum" />
-  <java-symbol type="dimen" name="notification_headerless_margin_constrained_extra" />
+  <java-symbol type="dimen" name="notification_headerless_margin_oneline" />
+  <java-symbol type="dimen" name="notification_headerless_margin_twoline" />
   <java-symbol type="string" name="default_notification_channel_label" />
   <java-symbol type="string" name="importance_from_user" />
   <java-symbol type="string" name="importance_from_person" />
@@ -3109,8 +3110,10 @@
   <java-symbol type="dimen" name="call_notification_collapsible_indent"/>
   <java-symbol type="drawable" name="ic_call_answer" />
   <java-symbol type="drawable" name="ic_call_decline" />
+  <java-symbol type="id" name="verification_divider" />
   <java-symbol type="id" name="verification_icon" />
   <java-symbol type="id" name="verification_text" />
+  <java-symbol type="string" name="notification_verified_content_description" />
 
   <!-- Notification handler / dashboard package -->
   <java-symbol type="string" name="config_notificationHandlerPackage" />
@@ -4113,8 +4116,6 @@
 
   <java-symbol type="string" name="notification_history_title_placeholder" />
 
-  <java-symbol type="string" name="config_customMediaKeyDispatcher" />
-  <java-symbol type="string" name="config_customSessionPolicyProvider" />
   <!-- The max scale for the wallpaper when it's zoomed in -->
   <java-symbol type="dimen" name="config_wallpaperMaxScale"/>
 
@@ -4174,6 +4175,8 @@
   <java-symbol type="string" name="turn_on_magnification_settings_action" />
   <java-symbol type="string" name="dismiss_action" />
 
+  <java-symbol type="bool" name="config_magnification_area" />
+
   <java-symbol type="bool" name="config_trackerAppNeedsPermissions"/>
 
   <!-- Package with global data query permissions for AppSearch -->
@@ -4201,4 +4204,6 @@
   <java-symbol type="bool" name="config_telephony5gNonStandalone" />
 
   <java-symbol type="bool" name="config_voice_data_sms_auto_fallback" />
+
+  <java-symbol type="bool" name="config_enableOneHandedKeyguard" />
 </resources>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index e7e049da..16d720b 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -238,6 +238,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -271,6 +273,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -306,6 +310,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -340,6 +346,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -417,6 +425,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -449,6 +459,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -482,6 +494,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -531,6 +545,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -565,6 +581,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -597,6 +615,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -631,6 +651,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -664,6 +686,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -697,6 +721,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -730,6 +756,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
+        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -763,6 +791,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
+        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -800,6 +830,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -834,6 +866,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -865,6 +899,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -1069,6 +1105,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
+        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1101,6 +1139,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
+        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1134,6 +1174,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
+        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1169,6 +1211,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
+        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1203,6 +1247,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
+        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1281,6 +1327,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
+        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1316,6 +1364,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
+        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1352,6 +1402,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
+        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1426,6 +1478,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
+        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1463,6 +1517,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
+        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1498,6 +1554,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
+        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1532,6 +1590,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
+        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1565,6 +1625,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
+        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1598,6 +1660,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
+        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1629,6 +1693,8 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
+        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1750,6 +1816,8 @@
         <item name="colorSecondary">@color/secondary_device_default_settings</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -1782,6 +1850,8 @@
         <item name="colorSecondary">@color/secondary_device_default_settings</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
+        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1824,6 +1894,8 @@
         <item name="colorSecondary">@color/secondary_device_default_settings</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
+        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1859,6 +1931,8 @@
         <item name="colorSecondary">@color/secondary_device_default_settings</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
+        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
         <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
         <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
         <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
diff --git a/core/sysprop/Android.bp b/core/sysprop/Android.bp
index 237ede2..f89099e 100644
--- a/core/sysprop/Android.bp
+++ b/core/sysprop/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 sysprop_library {
     name: "com.android.sysprop.localization",
     srcs: ["LocalizationProperties.sysprop"],
diff --git a/core/tests/BroadcastRadioTests/Android.bp b/core/tests/BroadcastRadioTests/Android.bp
index b8efd19..113f45d 100644
--- a/core/tests/BroadcastRadioTests/Android.bp
+++ b/core/tests/BroadcastRadioTests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "BroadcastRadioTests",
     privileged: true,
diff --git a/core/tests/ConnectivityManagerTest/Android.bp b/core/tests/ConnectivityManagerTest/Android.bp
index a33d219..beaf176 100644
--- a/core/tests/ConnectivityManagerTest/Android.bp
+++ b/core/tests/ConnectivityManagerTest/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ConnectivityManagerTest",
     libs: [
diff --git a/core/tests/GameManagerTests/Android.bp b/core/tests/GameManagerTests/Android.bp
index e178776..2789e9f 100644
--- a/core/tests/GameManagerTests/Android.bp
+++ b/core/tests/GameManagerTests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworksCoreGameManagerTests",
     // Include all test java files
diff --git a/core/tests/PackageInstallerSessions/Android.bp b/core/tests/PackageInstallerSessions/Android.bp
index 055249d..c112cbb 100644
--- a/core/tests/PackageInstallerSessions/Android.bp
+++ b/core/tests/PackageInstallerSessions/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworksCorePackageInstallerSessionsTests",
 
diff --git a/core/tests/PlatformCompatFramework/Android.bp b/core/tests/PlatformCompatFramework/Android.bp
index 3380265..95e23ad 100644
--- a/core/tests/PlatformCompatFramework/Android.bp
+++ b/core/tests/PlatformCompatFramework/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "PlatformCompatFrameworkTests",
     // Include all test java files.
diff --git a/core/tests/bandwidthtests/Android.bp b/core/tests/bandwidthtests/Android.bp
index 5d881b8..f1ecd45 100644
--- a/core/tests/bandwidthtests/Android.bp
+++ b/core/tests/bandwidthtests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "BandwidthTests",
     // Include all test java files.
diff --git a/core/tests/batterystatstests/BatteryStatsLoadTests/Android.bp b/core/tests/batterystatstests/BatteryStatsLoadTests/Android.bp
index ade97b8..1c0ea83 100644
--- a/core/tests/batterystatstests/BatteryStatsLoadTests/Android.bp
+++ b/core/tests/batterystatstests/BatteryStatsLoadTests/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "BatteryStatsLoadTests",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/batterystatstests/BatteryStatsViewer/Android.bp b/core/tests/batterystatstests/BatteryStatsViewer/Android.bp
index 1e0498b..c2e7d81 100644
--- a/core/tests/batterystatstests/BatteryStatsViewer/Android.bp
+++ b/core/tests/batterystatstests/BatteryStatsViewer/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "BatteryStatsViewer",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/benchmarks/Android.bp b/core/tests/benchmarks/Android.bp
index 8dd7928..4cd5467 100644
--- a/core/tests/benchmarks/Android.bp
+++ b/core/tests/benchmarks/Android.bp
@@ -16,6 +16,15 @@
 // build framework base core benchmarks
 // ============================================================
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library {
     name: "frameworks-base-core-benchmarks",
     installable: true,
diff --git a/core/tests/benchmarks/src/android/os/ParcelableBenchmark.java b/core/tests/benchmarks/src/android/os/ParcelableBenchmark.java
new file mode 100644
index 0000000..1cf4302
--- /dev/null
+++ b/core/tests/benchmarks/src/android/os/ParcelableBenchmark.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.annotation.SuppressLint;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.util.MergedConfiguration;
+import android.view.InsetsSource;
+import android.view.InsetsState;
+
+import com.google.caliper.AfterExperiment;
+import com.google.caliper.BeforeExperiment;
+
+/**
+ * Benchmark of read/write large Parcelable class. This also shows the performance of different
+ * implementations for nested Parcelable class:
+ * <ul>
+ *   <li>Well-written read/writeFromParcel (direct access)</li>
+ *   <li>read/writeTypedObject (object creation + addition int to indicate nullity)</li>
+ *   <li>read/writeParcelable (object creation + addition type String)</li>
+ * </ul>
+ */
+public class ParcelableBenchmark {
+    private Parcel mParcel;
+
+    @BeforeExperiment
+    protected void setUp() {
+        mParcel = Parcel.obtain();
+    }
+
+    @AfterExperiment
+    protected void tearDown() {
+        mParcel.recycle();
+        mParcel = null;
+    }
+
+    public void timeReadWriteMergedConfiguration(int reps) {
+        final MergedConfiguration mergedConfiguration = new MergedConfiguration();
+        for (int i = 0; i < reps; i++) {
+            mergedConfiguration.writeToParcel(mParcel, 0);
+            mParcel.setDataPosition(0);
+            mergedConfiguration.readFromParcel(mParcel);
+        }
+    }
+
+    public void timeReadWriteInsetsState(int reps) {
+        final InsetsState insetsState = new InsetsState();
+        for (int i = 0; i < InsetsState.SIZE; i++) {
+            insetsState.addSource(new InsetsSource(i));
+        }
+        for (int i = 0; i < reps; i++) {
+            insetsState.writeToParcel(mParcel, 0);
+            mParcel.setDataPosition(0);
+            insetsState.readFromParcel(mParcel);
+        }
+    }
+
+    public void timeReadWritePointArray(int reps) {
+        final PointArray pointArray = new PointArray();
+        for (int i = 0; i < reps; i++) {
+            pointArray.writeToParcel(mParcel, 0);
+            mParcel.setDataPosition(0);
+            pointArray.readFromParcel(mParcel);
+        }
+    }
+
+    public void timeReadWritePointArrayFast(int reps) {
+        final PointArrayFast pointArray = new PointArrayFast();
+        for (int i = 0; i < reps; i++) {
+            pointArray.writeToParcel(mParcel, 0);
+            mParcel.setDataPosition(0);
+            pointArray.readFromParcel(mParcel);
+        }
+    }
+
+    @SuppressLint("ParcelCreator")
+    private static class PointArray implements Parcelable {
+        Rect mBounds = new Rect();
+        Point[] mPoints = new Point[10];
+        {
+            for (int i = 0; i < mPoints.length; i++) {
+                mPoints[i] = new Point();
+            }
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeParcelable(mBounds, flags);
+            dest.writeParcelableArray(mPoints, flags);
+        }
+
+        void readFromParcel(Parcel in) {
+            mBounds = in.readParcelable(Rect.class.getClassLoader());
+            mPoints = in.readParcelableArray(Point.class.getClassLoader(), Point.class);
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+    }
+
+    @SuppressLint("ParcelCreator")
+    private static class PointArrayFast extends PointArray {
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            mBounds.writeToParcel(dest, flags);
+            dest.writeTypedArray(mPoints, flags);
+        }
+
+        @Override
+        void readFromParcel(Parcel in) {
+            mBounds.readFromParcel(in);
+            in.readTypedArray(mPoints, Point.CREATOR);
+        }
+    }
+}
diff --git a/core/tests/bluetoothtests/Android.bp b/core/tests/bluetoothtests/Android.bp
index 4b6f9db..a2e4dff 100644
--- a/core/tests/bluetoothtests/Android.bp
+++ b/core/tests/bluetoothtests/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "BluetoothTests",
     // Include all test java files.
diff --git a/core/tests/bugreports/Android.bp b/core/tests/bugreports/Android.bp
index e42b4b4..f87797a 100644
--- a/core/tests/bugreports/Android.bp
+++ b/core/tests/bugreports/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "BugreportManagerTestCases",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index e2b975f..fbabf4a 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworksCoreTests",
 
diff --git a/core/tests/coretests/BinderDeathRecipientHelperApp/Android.bp b/core/tests/coretests/BinderDeathRecipientHelperApp/Android.bp
index 25e4fc3..b47c470 100644
--- a/core/tests/coretests/BinderDeathRecipientHelperApp/Android.bp
+++ b/core/tests/coretests/BinderDeathRecipientHelperApp/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "BinderDeathRecipientHelperApp1",
 
diff --git a/core/tests/coretests/BinderProxyCountingTestApp/Android.bp b/core/tests/coretests/BinderProxyCountingTestApp/Android.bp
index 6279a48..b1df8db 100644
--- a/core/tests/coretests/BinderProxyCountingTestApp/Android.bp
+++ b/core/tests/coretests/BinderProxyCountingTestApp/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "BinderProxyCountingTestApp",
 
diff --git a/core/tests/coretests/BinderProxyCountingTestService/Android.bp b/core/tests/coretests/BinderProxyCountingTestService/Android.bp
index 22718cb..52c23a1 100644
--- a/core/tests/coretests/BinderProxyCountingTestService/Android.bp
+++ b/core/tests/coretests/BinderProxyCountingTestService/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "BinderProxyCountingTestService",
 
diff --git a/core/tests/coretests/BstatsTestApp/Android.bp b/core/tests/coretests/BstatsTestApp/Android.bp
index a89d728..c82da9e 100644
--- a/core/tests/coretests/BstatsTestApp/Android.bp
+++ b/core/tests/coretests/BstatsTestApp/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "BstatsTestApp",
 
diff --git a/core/tests/coretests/DisabledTestApp/Android.bp b/core/tests/coretests/DisabledTestApp/Android.bp
index 419816e..3ab3218 100644
--- a/core/tests/coretests/DisabledTestApp/Android.bp
+++ b/core/tests/coretests/DisabledTestApp/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "DisabledTestApp",
 
diff --git a/core/tests/coretests/EnabledTestApp/Android.bp b/core/tests/coretests/EnabledTestApp/Android.bp
index bc4f4bd..750b578 100644
--- a/core/tests/coretests/EnabledTestApp/Android.bp
+++ b/core/tests/coretests/EnabledTestApp/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "EnabledTestApp",
 
diff --git a/core/tests/coretests/aidl/Android.bp b/core/tests/coretests/aidl/Android.bp
index 6e442db..2d848cc 100644
--- a/core/tests/coretests/aidl/Android.bp
+++ b/core/tests/coretests/aidl/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_test {
     name: "coretests-aidl",
     sdk_version: "current",
diff --git a/core/tests/coretests/apks/Android.bp b/core/tests/coretests/apks/Android.bp
index 20c87b2..eda875ac 100644
--- a/core/tests/coretests/apks/Android.bp
+++ b/core/tests/coretests/apks/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_defaults {
     name: "FrameworksCoreTests_apks_defaults",
     sdk_version: "current",
diff --git a/core/tests/coretests/apks/install/Android.bp b/core/tests/coretests/apks/install/Android.bp
index e783fe2..652b491 100644
--- a/core/tests/coretests/apks/install/Android.bp
+++ b/core/tests/coretests/apks/install/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FrameworksCoreTests_install",
     defaults: ["FrameworksCoreTests_apks_defaults"],
diff --git a/core/tests/coretests/apks/install_bad_dex/Android.bp b/core/tests/coretests/apks/install_bad_dex/Android.bp
index d156793..7b96c9b4 100644
--- a/core/tests/coretests/apks/install_bad_dex/Android.bp
+++ b/core/tests/coretests/apks/install_bad_dex/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FrameworksCoreTests_install_bad_dex_",
     defaults: ["FrameworksCoreTests_apks_defaults"],
diff --git a/core/tests/coretests/apks/install_complete_package_info/Android.bp b/core/tests/coretests/apks/install_complete_package_info/Android.bp
index 123558bd..3fee0c6 100644
--- a/core/tests/coretests/apks/install_complete_package_info/Android.bp
+++ b/core/tests/coretests/apks/install_complete_package_info/Android.bp
@@ -1,7 +1,15 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FrameworksCoreTests_install_complete_package_info",
     defaults: ["FrameworksCoreTests_apks_defaults"],
 
     srcs: ["**/*.java"],
 }
-
diff --git a/core/tests/coretests/apks/install_decl_perm/Android.bp b/core/tests/coretests/apks/install_decl_perm/Android.bp
index 868e8b5..bf1f0de 100644
--- a/core/tests/coretests/apks/install_decl_perm/Android.bp
+++ b/core/tests/coretests/apks/install_decl_perm/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FrameworksCoreTests_install_decl_perm",
     defaults: ["FrameworksCoreTests_apks_defaults"],
diff --git a/core/tests/coretests/apks/install_jni_lib/Android.bp b/core/tests/coretests/apks/install_jni_lib/Android.bp
index df19fa0..d315e7b 100644
--- a/core/tests/coretests/apks/install_jni_lib/Android.bp
+++ b/core/tests/coretests/apks/install_jni_lib/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_test_library {
     name: "libframeworks_coretests_jni",
     defaults: ["FrameworksCoreTests_apks_defaults"],
diff --git a/core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.bp b/core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.bp
index 602b704..20cc96e 100644
--- a/core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.bp
+++ b/core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FrameworksCoreTests_install_jni_lib_open_from_apk",
     defaults: ["FrameworksCoreTests_apks_defaults"],
diff --git a/core/tests/coretests/apks/install_loc_auto/Android.bp b/core/tests/coretests/apks/install_loc_auto/Android.bp
index 6393915..37daf76 100644
--- a/core/tests/coretests/apks/install_loc_auto/Android.bp
+++ b/core/tests/coretests/apks/install_loc_auto/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FrameworksCoreTests_install_loc_auto",
     defaults: ["FrameworksCoreTests_apks_defaults"],
diff --git a/core/tests/coretests/apks/install_loc_internal/Android.bp b/core/tests/coretests/apks/install_loc_internal/Android.bp
index 770aaa5..3e23313 100644
--- a/core/tests/coretests/apks/install_loc_internal/Android.bp
+++ b/core/tests/coretests/apks/install_loc_internal/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FrameworksCoreTests_install_loc_internal",
     defaults: ["FrameworksCoreTests_apks_defaults"],
diff --git a/core/tests/coretests/apks/install_loc_sdcard/Android.bp b/core/tests/coretests/apks/install_loc_sdcard/Android.bp
index 1779401..708e655 100644
--- a/core/tests/coretests/apks/install_loc_sdcard/Android.bp
+++ b/core/tests/coretests/apks/install_loc_sdcard/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FrameworksCoreTests_install_loc_sdcard",
     defaults: ["FrameworksCoreTests_apks_defaults"],
diff --git a/core/tests/coretests/apks/install_loc_unspecified/Android.bp b/core/tests/coretests/apks/install_loc_unspecified/Android.bp
index 21c0f82..76869e9 100644
--- a/core/tests/coretests/apks/install_loc_unspecified/Android.bp
+++ b/core/tests/coretests/apks/install_loc_unspecified/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FrameworksCoreTests_install_loc_unspecified",
     defaults: ["FrameworksCoreTests_apks_defaults"],
diff --git a/core/tests/coretests/apks/install_use_perm_good/Android.bp b/core/tests/coretests/apks/install_use_perm_good/Android.bp
index bb41ebb..89700dd 100644
--- a/core/tests/coretests/apks/install_use_perm_good/Android.bp
+++ b/core/tests/coretests/apks/install_use_perm_good/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FrameworksCoreTests_install_use_perm_good",
     defaults: ["FrameworksCoreTests_apks_defaults"],
diff --git a/core/tests/coretests/apks/install_uses_feature/Android.bp b/core/tests/coretests/apks/install_uses_feature/Android.bp
index 0ec747b..913a96a 100644
--- a/core/tests/coretests/apks/install_uses_feature/Android.bp
+++ b/core/tests/coretests/apks/install_uses_feature/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FrameworksCoreTests_install_uses_feature",
     defaults: ["FrameworksCoreTests_apks_defaults"],
diff --git a/core/tests/coretests/apks/install_verifier_bad/Android.bp b/core/tests/coretests/apks/install_verifier_bad/Android.bp
index 1265739..ed13d74 100644
--- a/core/tests/coretests/apks/install_verifier_bad/Android.bp
+++ b/core/tests/coretests/apks/install_verifier_bad/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FrameworksCoreTests_install_verifier_bad",
     defaults: ["FrameworksCoreTests_apks_defaults"],
diff --git a/core/tests/coretests/apks/install_verifier_good/Android.bp b/core/tests/coretests/apks/install_verifier_good/Android.bp
index 4911ffb..fe9a24f 100644
--- a/core/tests/coretests/apks/install_verifier_good/Android.bp
+++ b/core/tests/coretests/apks/install_verifier_good/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FrameworksCoreTests_install_verifier_good",
     defaults: ["FrameworksCoreTests_apks_defaults"],
diff --git a/core/tests/coretests/apks/keyset/Android.bp b/core/tests/coretests/apks/keyset/Android.bp
index e252b08..93c3b1f 100644
--- a/core/tests/coretests/apks/keyset/Android.bp
+++ b/core/tests/coretests/apks/keyset/Android.bp
@@ -1,4 +1,13 @@
 //apks signed by keyset_A
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FrameworksCoreTests_keyset_sa_unone",
     defaults: ["FrameworksCoreTests_apks_defaults"],
diff --git a/core/tests/coretests/apks/locales/Android.bp b/core/tests/coretests/apks/locales/Android.bp
index 4a730ef..4fe6c7f 100644
--- a/core/tests/coretests/apks/locales/Android.bp
+++ b/core/tests/coretests/apks/locales/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FrameworksCoreTests_locales",
     defaults: ["FrameworksCoreTests_apks_defaults"],
diff --git a/core/tests/coretests/apks/overlay_config/Android.bp b/core/tests/coretests/apks/overlay_config/Android.bp
index 9573557..9c971fd 100644
--- a/core/tests/coretests/apks/overlay_config/Android.bp
+++ b/core/tests/coretests/apks/overlay_config/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FrameworksCoreTests_overlay_config",
     defaults: ["FrameworksCoreTests_apks_defaults"],
diff --git a/core/tests/coretests/apks/version/Android.bp b/core/tests/coretests/apks/version/Android.bp
index 371ccfc..8b750f7 100644
--- a/core/tests/coretests/apks/version/Android.bp
+++ b/core/tests/coretests/apks/version/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FrameworksCoreTests_version_1",
     defaults: ["FrameworksCoreTests_apks_defaults"],
diff --git a/core/tests/coretests/apks/version_nosys/Android.bp b/core/tests/coretests/apks/version_nosys/Android.bp
index 5756678..de40f49 100644
--- a/core/tests/coretests/apks/version_nosys/Android.bp
+++ b/core/tests/coretests/apks/version_nosys/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FrameworksCoreTests_version_1_nosys",
     defaults: ["FrameworksCoreTests_apks_defaults"],
diff --git a/core/tests/coretests/certs/Android.bp b/core/tests/coretests/certs/Android.bp
index bd5c829..8411183 100644
--- a/core/tests/coretests/certs/Android.bp
+++ b/core/tests/coretests/certs/Android.bp
@@ -1,3 +1,14 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app_certificate {
     name: "FrameworksCoreTests_keyset_A_cert",
     certificate: "keyset_A",
diff --git a/core/tests/coretests/jni/Android.bp b/core/tests/coretests/jni/Android.bp
index bb090e2..edac8ef 100644
--- a/core/tests/coretests/jni/Android.bp
+++ b/core/tests/coretests/jni/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_test_library {
     name: "libpowermanagertest_jni",
     srcs: [
diff --git a/core/tests/coretests/src/android/app/backup/BackupAgentTest.java b/core/tests/coretests/src/android/app/backup/BackupAgentTest.java
index ea903f2..37cf470 100644
--- a/core/tests/coretests/src/android/app/backup/BackupAgentTest.java
+++ b/core/tests/coretests/src/android/app/backup/BackupAgentTest.java
@@ -57,14 +57,6 @@
     }
 
     @Test
-    public void testGetIncludeExcludeRules_isMigration_returnsEmptyRules()  throws Exception {
-        mBackupAgent = getAgentForOperationType(OperationType.MIGRATION);
-
-        IncludeExcludeRules rules = mBackupAgent.getIncludeExcludeRules(mBackupScheme);
-        assertThat(rules).isEqualTo(IncludeExcludeRules.emptyRules());
-    }
-
-    @Test
     public void testGetIncludeExcludeRules_isNotMigration_returnsRules() throws Exception {
         PathWithRequiredFlags path = new PathWithRequiredFlags("path", /* requiredFlags */ 0);
         Map<String, Set<PathWithRequiredFlags>> includePaths = Collections.singletonMap("test",
diff --git a/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java b/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java
index 1573c19..7cb6804 100644
--- a/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java
+++ b/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java
@@ -37,6 +37,7 @@
 import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.os.Parcel;
+import android.os.UserHandle;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -124,13 +125,13 @@
     }
 
     @Test
-    public void testUid() {
+    public void testUserHandle() {
         PeopleSpaceTile tile = new PeopleSpaceTile
                 .Builder(new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps)
-                .setUid(42)
+                .setUserHandle(new UserHandle(0))
                 .build();
 
-        assertThat(tile.getUid()).isEqualTo(42);
+        assertThat(tile.getUserHandle()).isEqualTo(new UserHandle(0));
     }
 
     @Test
@@ -227,7 +228,7 @@
                 .setUserName("name")
                 .setUserIcon(mIcon)
                 .setContactUri(Uri.parse("contact"))
-                .setUid(42)
+                .setUserHandle(new UserHandle(1))
                 .setPackageName("package.name")
                 .setLastInteractionTimestamp(7L)
                 .setIsImportantConversation(true)
@@ -246,7 +247,7 @@
         assertThat(readTile.getUserName()).isEqualTo(tile.getUserName());
         assertThat(readTile.getUserIcon().toString()).isEqualTo(tile.getUserIcon().toString());
         assertThat(readTile.getContactUri()).isEqualTo(tile.getContactUri());
-        assertThat(readTile.getUid()).isEqualTo(tile.getUid());
+        assertThat(readTile.getUserHandle()).isEqualTo(tile.getUserHandle());
         assertThat(readTile.getPackageName()).isEqualTo(tile.getPackageName());
         assertThat(readTile.getLastInteractionTimestamp()).isEqualTo(
                 tile.getLastInteractionTimestamp());
diff --git a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
index 50b52eb..6c8b941 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
@@ -148,13 +148,15 @@
         PersistableBundle persistableBundle = new PersistableBundle();
         persistableBundle.putInt("k", 4);
         IBinder assistToken = new Binder();
+        IBinder shareableActivityToken = new Binder();
 
         Supplier<LaunchActivityItem> itemSupplier = () -> new LaunchActivityItemBuilder()
                 .setIntent(intent).setIdent(ident).setInfo(activityInfo).setCurConfig(config())
                 .setOverrideConfig(overrideConfig).setCompatInfo(compat).setReferrer(referrer)
                 .setProcState(procState).setState(bundle).setPersistentState(persistableBundle)
                 .setPendingResults(resultInfoList()).setPendingNewIntents(referrerIntentList())
-                .setIsForward(true).setAssistToken(assistToken).build();
+                .setIsForward(true).setAssistToken(assistToken)
+                .setShareableActivityToken(shareableActivityToken).build();
 
         LaunchActivityItem emptyItem = new LaunchActivityItemBuilder().build();
         LaunchActivityItem item = itemSupplier.get();
diff --git a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java
index 02e75dd..1a06789e 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java
@@ -109,6 +109,7 @@
         private boolean mIsForward;
         private ProfilerInfo mProfilerInfo;
         private IBinder mAssistToken;
+        private IBinder mShareableActivityToken;
         private FixedRotationAdjustments mFixedRotationAdjustments;
 
         LaunchActivityItemBuilder setIntent(Intent intent) {
@@ -196,6 +197,11 @@
             return this;
         }
 
+        LaunchActivityItemBuilder setShareableActivityToken(IBinder shareableActivityToken) {
+            mShareableActivityToken = shareableActivityToken;
+            return this;
+        }
+
         LaunchActivityItemBuilder setFixedRotationAdjustments(FixedRotationAdjustments fra) {
             mFixedRotationAdjustments = fra;
             return this;
@@ -206,7 +212,8 @@
                     mCurConfig, mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor,
                     mProcState, mState, mPersistentState, mPendingResults, mPendingNewIntents,
                     mActivityOptions, mIsForward, mProfilerInfo, mAssistToken,
-                    null /* activityClientController */, mFixedRotationAdjustments);
+                    null /* activityClientController */, mFixedRotationAdjustments,
+                    mShareableActivityToken);
         }
     }
 }
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index f6d985b..6f3d7ae 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -207,6 +207,7 @@
                 .setPendingResults(resultInfoList()).setActivityOptions(ActivityOptions.makeBasic())
                 .setPendingNewIntents(referrerIntentList()).setIsForward(true)
                 .setAssistToken(new Binder()).setFixedRotationAdjustments(fixedRotationAdjustments)
+                .setShareableActivityToken(new Binder())
                 .build();
 
         writeAndPrepareForReading(item);
diff --git a/core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java b/core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java
index 266ff3d..1c6b3cc 100644
--- a/core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java
+++ b/core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java
@@ -33,17 +33,20 @@
 
     @Test
     public void testEquals() {
-        ExternalTimeSuggestion one = new ExternalTimeSuggestion(ARBITRARY_TIME);
+        ExternalTimeSuggestion one = new ExternalTimeSuggestion(
+                ARBITRARY_TIME.getReferenceTimeMillis(),
+                ARBITRARY_TIME.getValue());
         assertEquals(one, one);
 
-        ExternalTimeSuggestion two = new ExternalTimeSuggestion(ARBITRARY_TIME);
+        ExternalTimeSuggestion two = new ExternalTimeSuggestion(
+                ARBITRARY_TIME.getReferenceTimeMillis(),
+                ARBITRARY_TIME.getValue());
         assertEquals(one, two);
         assertEquals(two, one);
 
-        TimestampedValue<Long> differentTime = new TimestampedValue<>(
+        ExternalTimeSuggestion three = new ExternalTimeSuggestion(
                 ARBITRARY_TIME.getReferenceTimeMillis() + 1,
                 ARBITRARY_TIME.getValue());
-        ExternalTimeSuggestion three = new ExternalTimeSuggestion(differentTime);
         assertNotEquals(one, three);
         assertNotEquals(three, one);
 
@@ -55,7 +58,9 @@
 
     @Test
     public void testParcelable() {
-        ExternalTimeSuggestion suggestion = new ExternalTimeSuggestion(ARBITRARY_TIME);
+        ExternalTimeSuggestion suggestion = new ExternalTimeSuggestion(
+                ARBITRARY_TIME.getReferenceTimeMillis(),
+                ARBITRARY_TIME.getValue());
         assertRoundTripParcelable(suggestion);
 
         // DebugInfo should also be stored (but is not checked by equals())
diff --git a/core/tests/coretests/src/android/content/pm/AppSearchShortcutInfoTest.java b/core/tests/coretests/src/android/content/pm/AppSearchShortcutInfoTest.java
index da92e69..ffe93bc 100644
--- a/core/tests/coretests/src/android/content/pm/AppSearchShortcutInfoTest.java
+++ b/core/tests/coretests/src/android/content/pm/AppSearchShortcutInfoTest.java
@@ -47,15 +47,16 @@
         final Intent shortcutIntent = new Intent(Intent.ACTION_VIEW);
         final ShortcutInfo shortcut = new AppSearchShortcutInfo.Builder(id)
                 .setActivity(activity)
-                .setText(id)
+                .setLongLabel(id)
                 .setIconResName(shortcutIconResName)
                 .setIntent(shortcutIntent)
                 .setPerson(person)
                 .setCategories(categorySet)
                 .setFlags(ShortcutInfo.FLAG_LONG_LIVED)
                 .build()
-                .toShortcutInfo();
+                .toShortcutInfo(0);
 
+        assertThat(shortcut.getUserId()).isEqualTo(0);
         assertThat(shortcut.getId()).isEqualTo(id);
         assertThat(shortcut.getShortLabel()).isEqualTo(id);
         assertThat(shortcut.getIconResName()).isEqualTo(shortcutIconResName);
diff --git a/core/tests/coretests/src/android/hardware/input/InputDeviceLightsManagerTest.java b/core/tests/coretests/src/android/hardware/input/InputDeviceLightsManagerTest.java
new file mode 100644
index 0000000..412b367
--- /dev/null
+++ b/core/tests/coretests/src/android/hardware/input/InputDeviceLightsManagerTest.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input;
+
+import static android.hardware.lights.LightsRequest.Builder;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertNotNull;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.hardware.lights.Light;
+import android.hardware.lights.LightState;
+import android.hardware.lights.LightsManager;
+import android.os.IBinder;
+import android.platform.test.annotations.Presubmit;
+import android.util.ArrayMap;
+import android.view.InputDevice;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.MockitoRule;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Tests for {@link InputDeviceLightsManager}.
+ *
+ * Build/Install/Run:
+ * atest FrameworksCoreTests:InputDeviceLightsManagerTest
+ */
+@Presubmit
+@RunWith(MockitoJUnitRunner.class)
+public class InputDeviceLightsManagerTest {
+    private static final String TAG = "InputDeviceLightsManagerTest";
+
+    private static final int DEVICE_ID = 1000;
+    private static final int PLAYER_ID = 3;
+
+    @Rule public final MockitoRule mockito = MockitoJUnit.rule();
+
+    private InputManager mInputManager;
+
+    @Mock private IInputManager mIInputManagerMock;
+
+    @Before
+    public void setUp() throws Exception {
+        when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{DEVICE_ID});
+
+        when(mIInputManagerMock.getInputDevice(eq(DEVICE_ID))).thenReturn(
+                createInputDevice(DEVICE_ID));
+
+        mInputManager = InputManager.resetInstance(mIInputManagerMock);
+
+        ArrayMap<Integer, LightState> lightStatesById = new ArrayMap<>();
+        doAnswer(invocation -> {
+            final int[] lightIds = (int[]) invocation.getArguments()[1];
+            final LightState[] lightStates =
+                    (LightState[]) invocation.getArguments()[2];
+            for (int i = 0; i < lightIds.length; i++) {
+                lightStatesById.put(lightIds[i], lightStates[i]);
+            }
+            return null;
+        }).when(mIInputManagerMock).setLightStates(eq(DEVICE_ID),
+                any(int[].class), any(LightState[].class), any(IBinder.class));
+
+        doAnswer(invocation -> {
+            int lightId = (int) invocation.getArguments()[1];
+            if (lightStatesById.containsKey(lightId)) {
+                return lightStatesById.get(lightId);
+            }
+            return new LightState(0);
+        }).when(mIInputManagerMock).getLightState(eq(DEVICE_ID), anyInt());
+    }
+
+    @After
+    public void tearDown() {
+        InputManager.clearInstance();
+    }
+
+    private InputDevice createInputDevice(int id) {
+        return new InputDevice(id, 0 /* generation */, 0 /* controllerNumber */, "name",
+                0 /* vendorId */, 0 /* productId */, "descriptor", true /* isExternal */,
+                0 /* sources */, 0 /* keyboardType */, null /* keyCharacterMap */,
+                false /* hasVibrator */, false /* hasMicrophone */, false /* hasButtonUnderpad */,
+                false /* hasSensor */, false /* hasBattery */);
+    }
+
+    private void mockLights(Light[] lights) throws Exception {
+        // Mock the Lights returned form InputManagerService
+        when(mIInputManagerMock.getLights(eq(DEVICE_ID))).thenReturn(
+                new ArrayList(Arrays.asList(lights)));
+    }
+
+    @Test
+    public void testGetInputDeviceLights() throws Exception {
+        InputDevice device = mInputManager.getInputDevice(DEVICE_ID);
+        assertNotNull(device);
+
+        Light[] mockedLights = {
+            new Light(1 /* id */, 0 /* ordinal */, Light.LIGHT_TYPE_INPUT_SINGLE),
+            new Light(2 /* id */, 0 /* ordinal */, Light.LIGHT_TYPE_INPUT_RGB),
+            new Light(3 /* id */, 0 /* ordinal */, Light.LIGHT_TYPE_INPUT_PLAYER_ID)
+        };
+        mockLights(mockedLights);
+
+        LightsManager lightsManager = device.getLightsManager();
+        List<Light> lights = lightsManager.getLights();
+        verify(mIInputManagerMock).getLights(eq(DEVICE_ID));
+        assertEquals(lights, Arrays.asList(mockedLights));
+    }
+
+    @Test
+    public void testControlMultipleLights() throws Exception {
+        InputDevice device = mInputManager.getInputDevice(DEVICE_ID);
+        assertNotNull(device);
+
+        Light[] mockedLights = {
+            new Light(1 /* id */, 0 /* ordinal */, Light.LIGHT_TYPE_INPUT_RGB),
+            new Light(2 /* id */, 0 /* ordinal */, Light.LIGHT_TYPE_INPUT_RGB),
+            new Light(3 /* id */, 0 /* ordinal */, Light.LIGHT_TYPE_INPUT_RGB),
+            new Light(4 /* id */, 0 /* ordinal */, Light.LIGHT_TYPE_INPUT_RGB)
+        };
+        mockLights(mockedLights);
+
+        LightsManager lightsManager = device.getLightsManager();
+        List<Light> lightList = lightsManager.getLights();
+        LightState[] states = new LightState[]{new LightState(0xf1), new LightState(0xf2),
+                new LightState(0xf3)};
+        // Open a session to request turn 3/4 lights on:
+        LightsManager.LightsSession session = lightsManager.openSession();
+        session.requestLights(new Builder()
+                .addLight(lightsManager.getLights().get(0), states[0])
+                .addLight(lightsManager.getLights().get(1), states[1])
+                .addLight(lightsManager.getLights().get(2), states[2])
+                .build());
+        IBinder token = session.getToken();
+
+        verify(mIInputManagerMock).openLightSession(eq(DEVICE_ID),
+                any(String.class), eq(token));
+        verify(mIInputManagerMock).setLightStates(eq(DEVICE_ID), eq(new int[]{1, 2, 3}),
+                eq(states), eq(token));
+
+        // Then all 3 should turn on.
+        assertThat(lightsManager.getLightState(lightsManager.getLights().get(0)).getColor())
+                .isEqualTo(0xf1);
+        assertThat(lightsManager.getLightState(lightsManager.getLights().get(1)).getColor())
+                .isEqualTo(0xf2);
+        assertThat(lightsManager.getLightState(lightsManager.getLights().get(2)).getColor())
+                .isEqualTo(0xf3);
+
+        // And the 4th should remain off.
+        assertThat(lightsManager.getLightState(lightsManager.getLights().get(3)).getColor())
+                .isEqualTo(0x00);
+
+        // close session
+        session.close();
+        verify(mIInputManagerMock).closeLightSession(eq(DEVICE_ID), eq(token));
+    }
+
+    @Test
+    public void testControlPlayerIdLight() throws Exception {
+        InputDevice device = mInputManager.getInputDevice(DEVICE_ID);
+        assertNotNull(device);
+
+        Light[] mockedLights = {
+            new Light(1 /* id */, 0 /* ordinal */,  Light.LIGHT_TYPE_INPUT_PLAYER_ID),
+            new Light(2 /* id */, 0 /* ordinal */,  Light.LIGHT_TYPE_INPUT_SINGLE),
+            new Light(3 /* id */, 0 /* ordinal */,  Light.LIGHT_TYPE_INPUT_RGB),
+        };
+        mockLights(mockedLights);
+
+        LightsManager lightsManager = device.getLightsManager();
+        List<Light> lightList = lightsManager.getLights();
+        LightState[] states = new LightState[]{new LightState(0xf1, PLAYER_ID)};
+        // Open a session to request set Player ID light:
+        LightsManager.LightsSession session = lightsManager.openSession();
+        session.requestLights(new Builder()
+                .addLight(lightsManager.getLights().get(0), states[0])
+                .build());
+        IBinder token = session.getToken();
+
+        verify(mIInputManagerMock).openLightSession(eq(DEVICE_ID),
+                any(String.class), eq(token));
+        verify(mIInputManagerMock).setLightStates(eq(DEVICE_ID), eq(new int[]{1}),
+                eq(states), eq(token));
+
+        // Verify the light state
+        assertThat(lightsManager.getLightState(lightsManager.getLights().get(0)).getColor())
+                .isEqualTo(0xf1);
+        assertThat(lightsManager.getLightState(lightsManager.getLights().get(0)).getPlayerId())
+                .isEqualTo(PLAYER_ID);
+
+        // close session
+        session.close();
+        verify(mIInputManagerMock).closeLightSession(eq(DEVICE_ID), eq(token));
+    }
+}
diff --git a/core/tests/coretests/src/android/os/VibrationEffectTest.java b/core/tests/coretests/src/android/os/VibrationEffectTest.java
index 1d56e17..d555cd9 100644
--- a/core/tests/coretests/src/android/os/VibrationEffectTest.java
+++ b/core/tests/coretests/src/android/os/VibrationEffectTest.java
@@ -220,6 +220,10 @@
         restored = scaledDown.scale(1.25f);
         // Does not restore to the exact original value because scale up is a bit offset.
         assertEquals(101, restored.getAmplitude(), AMPLITUDE_SCALE_TOLERANCE);
+
+        // Does not go below min amplitude while scaling down.
+        VibrationEffect.OneShot minAmplitude = new VibrationEffect.OneShot(TEST_TIMING, 1);
+        assertEquals(1, minAmplitude.scale(0.5f).getAmplitude());
     }
 
     @Test
@@ -245,6 +249,15 @@
     }
 
     @Test
+    public void testResolveOneshotFailsWhenAmplitudeNonPositive() {
+        try {
+            TEST_ONE_SHOT.resolve(0);
+            fail("Amplitude is set to zero, should throw IllegalArgumentException");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    @Test
     public void testScaleWaveform() {
         VibrationEffect.Waveform initial = (VibrationEffect.Waveform) TEST_WAVEFORM;
 
@@ -255,6 +268,10 @@
         assertEquals(216, scaled.getAmplitudes()[0], AMPLITUDE_SCALE_TOLERANCE);
         assertEquals(0, scaled.getAmplitudes()[1]);
         assertEquals(-1, scaled.getAmplitudes()[2]);
+
+        VibrationEffect.Waveform minAmplitude = new VibrationEffect.Waveform(
+                new long[]{100}, new int[] {1}, -1);
+        assertArrayEquals(new int[]{1}, minAmplitude.scale(0.5f).getAmplitudes());
     }
 
     @Test
diff --git a/core/tests/coretests/src/android/util/RotationUtilsTest.java b/core/tests/coretests/src/android/util/RotationUtilsTest.java
new file mode 100644
index 0000000..5dbe03e
--- /dev/null
+++ b/core/tests/coretests/src/android/util/RotationUtilsTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import static android.util.RotationUtils.rotateBounds;
+import static android.view.Surface.ROTATION_180;
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
+
+import static org.junit.Assert.assertEquals;
+
+import android.graphics.Rect;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link RotationUtils}.
+ *
+ * Build/Install/Run:
+ *  atest FrameworksCoreTests:RotationUtilsTest
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class RotationUtilsTest {
+
+    @Test
+    public void testRotateBounds() {
+        Rect testParent = new Rect(0, 0, 1000, 600);
+        Rect testInner = new Rect(40, 20, 120, 80);
+
+        Rect testResult = new Rect(testInner);
+        rotateBounds(testResult, testParent, ROTATION_90);
+        assertEquals(new Rect(20, 880, 80, 960), testResult);
+
+        testResult.set(testInner);
+        rotateBounds(testResult, testParent, ROTATION_180);
+        assertEquals(new Rect(880, 520, 960, 580), testResult);
+
+        testResult.set(testInner);
+        rotateBounds(testResult, testParent, ROTATION_270);
+        assertEquals(new Rect(520, 40, 580, 120), testResult);
+    }
+}
diff --git a/core/tests/coretests/src/android/view/BlurAggregatorTest.java b/core/tests/coretests/src/android/view/BlurAggregatorTest.java
new file mode 100644
index 0000000..b01f275
--- /dev/null
+++ b/core/tests/coretests/src/android/view/BlurAggregatorTest.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import static androidx.test.InstrumentationRegistry.getInstrumentation;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertNotNull;
+import static junit.framework.TestCase.assertNull;
+import static junit.framework.TestCase.assertTrue;
+
+import android.content.Context;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.internal.graphics.drawable.BackgroundBlurDrawable;
+import com.android.internal.graphics.drawable.BackgroundBlurDrawable.Aggregator;
+import com.android.internal.graphics.drawable.BackgroundBlurDrawable.BlurRegion;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class BlurAggregatorTest {
+    private static final int TEST_BLUR_RADIUS = 30;
+    private static final int TEST_FRAME_NUMBER = 1;
+
+    private Context mContext;
+
+    private Aggregator mAggregator;
+    private BackgroundBlurDrawable mDrawable;
+
+    private ViewRootImpl mViewRoot;
+
+    @Before
+    public void setUp() {
+        mContext = getInstrumentation().getTargetContext();
+        getInstrumentation().runOnMainSync(() -> {
+            mViewRoot = new ViewRootImpl(mContext, mContext.getDisplayNoVerify());
+        });
+        mAggregator = new Aggregator(mViewRoot);
+        mDrawable = createTestBackgroundBlurDrawable();
+    }
+
+    private BackgroundBlurDrawable createTestBackgroundBlurDrawable() {
+        final BackgroundBlurDrawable drawable = mAggregator.createBackgroundBlurDrawable(mContext);
+        drawable.setBlurRadius(TEST_BLUR_RADIUS);
+        final boolean hasUpdates = mAggregator.hasUpdates();
+        final BlurRegion[] blurRegions = mAggregator.getBlurRegionsCopyForRT();
+        mAggregator.getBlurRegionsToDispatchToSf(TEST_FRAME_NUMBER, blurRegions, hasUpdates);
+        return drawable;
+    }
+
+    @Test
+    public void testBlurRadiusUpdatePropagatesToRenderThreadIfNeeded() {
+        mDrawable.setBlurRadius(TEST_BLUR_RADIUS);
+        assertFalse(mAggregator.hasUpdates());
+
+        mDrawable.setBlurRadius(0);
+        assertTrue(mAggregator.hasUpdates());
+        BlurRegion[] blurRegions = mAggregator.getBlurRegionsCopyForRT();
+        assertEquals(0, blurRegions.length);
+        assertFalse(mAggregator.hasUpdates());
+
+        mDrawable.setBlurRadius(TEST_BLUR_RADIUS);
+        assertTrue(mAggregator.hasUpdates());
+        blurRegions = mAggregator.getBlurRegionsCopyForRT();
+        assertEquals(1, blurRegions.length);
+        assertEquals(TEST_BLUR_RADIUS, blurRegions[0].blurRadius);
+        assertFalse(mAggregator.hasUpdates());
+
+    }
+
+    @Test
+    public void testAlphaUpdatePropagatesToRenderThreadIfNeeded() {
+        mDrawable.setAlpha(20);
+        assertTrue(mAggregator.hasUpdates());
+        BlurRegion[] blurRegions = mAggregator.getBlurRegionsCopyForRT();
+        assertEquals(1, blurRegions.length);
+        assertEquals(20 / 255f, blurRegions[0].alpha);
+        assertFalse(mAggregator.hasUpdates());
+
+        mDrawable.setAlpha(20);
+        assertFalse(mAggregator.hasUpdates());
+
+        mDrawable.setAlpha(0);
+        assertTrue(mAggregator.hasUpdates());
+        blurRegions = mAggregator.getBlurRegionsCopyForRT();
+        assertEquals(0, blurRegions.length);
+        assertFalse(mAggregator.hasUpdates());
+    }
+
+    @Test
+    public void testCornerRadiusUpdatePropagatesToRenderThreadIfNeeded() {
+        mDrawable.setCornerRadius(1f, 2f, 3f, 4f);
+        assertTrue(mAggregator.hasUpdates());
+        final BlurRegion[] blurRegions = mAggregator.getBlurRegionsCopyForRT();
+        assertEquals(1, blurRegions.length);
+        assertEquals(1f, blurRegions[0].cornerRadiusTL);
+        assertEquals(2f, blurRegions[0].cornerRadiusTR);
+        assertEquals(3f, blurRegions[0].cornerRadiusBL);
+        assertEquals(4f, blurRegions[0].cornerRadiusBR);
+        assertFalse(mAggregator.hasUpdates());
+    }
+
+    @Test
+    public void testVisibleUpdatePropagatesToRenderThreadIfNeeded() {
+        mDrawable.setVisible(false, /* restart= */false);
+        assertTrue(mAggregator.hasUpdates());
+        BlurRegion[] blurRegions = mAggregator.getBlurRegionsCopyForRT();
+        assertEquals(0, blurRegions.length);
+        assertFalse(mAggregator.hasUpdates());
+
+        mDrawable.setVisible(true, /* restart= */ false);
+        assertTrue(mAggregator.hasUpdates());
+        blurRegions = mAggregator.getBlurRegionsCopyForRT();
+        assertEquals(1, blurRegions.length);
+        assertEquals(TEST_BLUR_RADIUS, blurRegions[0].blurRadius);
+        assertFalse(mAggregator.hasUpdates());
+    }
+
+    @Test
+    public void testBlurRegionCopyForRtIsSameIfNoUiUpdates() {
+        mDrawable.setBlurRadius(30);
+        BlurRegion[] blurRegions1 = mAggregator.getBlurRegionsCopyForRT();
+        assertEquals(1, blurRegions1.length);
+        assertEquals(30, blurRegions1[0].blurRadius);
+
+        BlurRegion[] blurRegions2 = mAggregator.getBlurRegionsCopyForRT();
+        assertEquals(blurRegions1, blurRegions2);
+    }
+
+    @Test
+    public void testPositionUpdateAppearsInBlurRegion() {
+        BlurRegion[] blurRegions = mAggregator.getBlurRegionsCopyForRT();
+        assertEquals(1, blurRegions.length);
+
+        mDrawable.mPositionUpdateListener.positionChanged(TEST_FRAME_NUMBER, 1, 2, 3, 4);
+        mAggregator.getBlurRegionsToDispatchToSf(TEST_FRAME_NUMBER, blurRegions,
+                mAggregator.hasUpdates());
+        assertEquals(1, blurRegions[0].rect.left);
+        assertEquals(2, blurRegions[0].rect.top);
+        assertEquals(3, blurRegions[0].rect.right);
+        assertEquals(4, blurRegions[0].rect.bottom);
+    }
+
+    @Test
+    public void testNoBlurRegionsDispatchedWhenNoUpdates() {
+        final boolean hasUpdates = mAggregator.hasUpdates();
+        assertFalse(hasUpdates);
+        final BlurRegion[] blurRegions = mAggregator.getBlurRegionsCopyForRT();
+        assertEquals(1, blurRegions.length);
+
+        float[][] blurRegionsForSf = mAggregator.getBlurRegionsToDispatchToSf(
+                TEST_FRAME_NUMBER, blurRegions, hasUpdates);
+        assertNull(blurRegionsForSf);
+    }
+
+    @Test
+    public void testBlurRegionDispatchedIfOnlyDrawableUpdated() {
+        mDrawable.setBlurRadius(50);
+        final boolean hasUpdates = mAggregator.hasUpdates();
+        assertTrue(hasUpdates);
+        final BlurRegion[] blurRegions = mAggregator.getBlurRegionsCopyForRT();
+        assertEquals(1, blurRegions.length);
+
+        float[][] blurRegionsForSf = mAggregator.getBlurRegionsToDispatchToSf(
+                TEST_FRAME_NUMBER, blurRegions, hasUpdates);
+        assertNotNull(blurRegionsForSf);
+        assertEquals(1, blurRegionsForSf.length);
+        assertEquals(50f, blurRegionsForSf[0][0]);
+    }
+
+    @Test
+    public void testBlurRegionDispatchedIfOnlyPositionUpdated() {
+        final boolean hasUpdates = mAggregator.hasUpdates();
+        assertFalse(hasUpdates);
+        final BlurRegion[] blurRegions = mAggregator.getBlurRegionsCopyForRT();
+        assertEquals(1, blurRegions.length);
+
+        mDrawable.mPositionUpdateListener.positionChanged(TEST_FRAME_NUMBER, 1, 2, 3, 4);
+        float[][] blurRegionsForSf = mAggregator.getBlurRegionsToDispatchToSf(
+                TEST_FRAME_NUMBER, blurRegions, hasUpdates);
+        assertNotNull(blurRegionsForSf);
+        assertEquals(1, blurRegionsForSf.length);
+        assertEquals((float) TEST_BLUR_RADIUS, blurRegionsForSf[0][0]);
+        assertEquals(1f, blurRegionsForSf[0][2]);
+        assertEquals(2f, blurRegionsForSf[0][3]);
+        assertEquals(3f, blurRegionsForSf[0][4]);
+        assertEquals(4f, blurRegionsForSf[0][5]);
+    }
+
+    @Test
+    public void testPositionUpdateIsAppliedInNextFrameIfMissed() {
+        final boolean hasUpdates = mAggregator.hasUpdates();
+        assertFalse(hasUpdates);
+        final BlurRegion[] blurRegions = mAggregator.getBlurRegionsCopyForRT();
+        assertEquals(1, blurRegions.length);
+
+        mDrawable.mPositionUpdateListener.positionChanged(TEST_FRAME_NUMBER, 1, 2, 3, 4);
+        float[][] blurRegionsForSf = mAggregator.getBlurRegionsToDispatchToSf(
+                TEST_FRAME_NUMBER + 1, blurRegions, hasUpdates);
+        assertNotNull(blurRegionsForSf);
+        assertEquals(1, blurRegionsForSf.length);
+        assertEquals((float) TEST_BLUR_RADIUS, blurRegionsForSf[0][0]);
+        assertEquals(1f, blurRegionsForSf[0][2]);
+        assertEquals(2f, blurRegionsForSf[0][3]);
+        assertEquals(3f, blurRegionsForSf[0][4]);
+        assertEquals(4f, blurRegionsForSf[0][5]);
+    }
+
+    @Test
+    public void testMultipleDrawablesDispatchedToSfIfOneIsUpdated() {
+        final BackgroundBlurDrawable drawable2 = createTestBackgroundBlurDrawable();
+        drawable2.setBlurRadius(50);
+        final boolean hasUpdates = mAggregator.hasUpdates();
+        assertTrue(hasUpdates);
+        final BlurRegion[] blurRegions = mAggregator.getBlurRegionsCopyForRT();
+        assertEquals(2, blurRegions.length);
+
+        // Check that an update in one of the drawables triggers a dispatch of all blur regions
+        float[][] blurRegionsForSf = mAggregator.getBlurRegionsToDispatchToSf(
+                TEST_FRAME_NUMBER, blurRegions, hasUpdates);
+        assertNotNull(blurRegionsForSf);
+        assertEquals(2, blurRegionsForSf.length);
+
+        // Check that the Aggregator deleted all position updates for frame TEST_FRAME_NUMBER
+        blurRegionsForSf = mAggregator.getBlurRegionsToDispatchToSf(
+                TEST_FRAME_NUMBER, blurRegions, /* hasUiUpdates= */ false);
+        assertNull(blurRegionsForSf);
+
+        // Check that a position update triggers a dispatch of all blur regions
+        drawable2.mPositionUpdateListener.positionChanged(TEST_FRAME_NUMBER, 1, 2, 3, 4);
+        blurRegionsForSf = mAggregator.getBlurRegionsToDispatchToSf(
+                TEST_FRAME_NUMBER + 1, blurRegions, hasUpdates);
+        assertNotNull(blurRegionsForSf);
+        assertEquals(2, blurRegionsForSf.length);
+    }
+
+    @Test
+    public void testUiThreadUpdatesDoNotChangeStateOnRenderThread() {
+        // Updates for frame N
+        mDrawable.setBlurRadius(50);
+        mDrawable.setCornerRadius(1, 2, 3, 4);
+        mDrawable.setAlpha(20);
+
+        final BlurRegion[] blurRegions = mAggregator.getBlurRegionsCopyForRT();
+        assertEquals(1, blurRegions.length);
+        assertEquals(50, blurRegions[0].blurRadius);
+        assertEquals(20 / 255f, blurRegions[0].alpha);
+        assertEquals(1f, blurRegions[0].cornerRadiusTL);
+        assertEquals(2f, blurRegions[0].cornerRadiusTR);
+        assertEquals(3f, blurRegions[0].cornerRadiusBL);
+        assertEquals(4f, blurRegions[0].cornerRadiusBR);
+
+        // Updates for frame N+1
+        mDrawable.setBlurRadius(60);
+        mDrawable.setCornerRadius(10, 20, 30, 40);
+        mDrawable.setAlpha(40);
+
+        // Assert state for frame N is untouched
+        assertEquals(50, blurRegions[0].blurRadius);
+        assertEquals(20 / 255f, blurRegions[0].alpha);
+        assertEquals(1f, blurRegions[0].cornerRadiusTL);
+        assertEquals(2f, blurRegions[0].cornerRadiusTR);
+        assertEquals(3f, blurRegions[0].cornerRadiusBL);
+        assertEquals(4f, blurRegions[0].cornerRadiusBR);
+    }
+
+    @Test
+    public void testPositionUpdatesForFutureFramesAreNotAppliedForCurrentFrame() {
+        final BlurRegion[] blurRegions = mAggregator.getBlurRegionsCopyForRT();
+
+        mDrawable.mPositionUpdateListener.positionChanged(TEST_FRAME_NUMBER, 1, 2, 3, 4);
+        mDrawable.mPositionUpdateListener.positionChanged(TEST_FRAME_NUMBER + 1, 5, 6, 7, 8);
+
+        final float[][] blurRegionsForSf = mAggregator.getBlurRegionsToDispatchToSf(
+                TEST_FRAME_NUMBER, blurRegions, /* hasUiUpdates= */ false);
+        assertNotNull(blurRegionsForSf);
+        assertEquals(1, blurRegionsForSf.length);
+        // Assert state for first frame is not affected by update for second frame
+        assertEquals((float) TEST_BLUR_RADIUS, blurRegionsForSf[0][0]);
+        assertEquals(1f, blurRegionsForSf[0][2]);
+        assertEquals(2f, blurRegionsForSf[0][3]);
+        assertEquals(3f, blurRegionsForSf[0][4]);
+        assertEquals(4f, blurRegionsForSf[0][5]);
+
+        final float[][] blurRegionsForSfForNextFrame = mAggregator.getBlurRegionsToDispatchToSf(
+                TEST_FRAME_NUMBER + 1, blurRegions, /* hasUiUpdates= */ false);
+        assertNotNull(blurRegionsForSfForNextFrame);
+        assertEquals(1, blurRegionsForSfForNextFrame.length);
+        // Assert second frame updates are applied normally
+        assertEquals((float) TEST_BLUR_RADIUS, blurRegionsForSfForNextFrame[0][0]);
+        assertEquals(5f, blurRegionsForSfForNextFrame[0][2]);
+        assertEquals(6f, blurRegionsForSfForNextFrame[0][3]);
+        assertEquals(7f, blurRegionsForSfForNextFrame[0][4]);
+        assertEquals(8f, blurRegionsForSfForNextFrame[0][5]);
+    }
+
+}
diff --git a/core/tests/coretests/src/android/view/InsetsSourceTest.java b/core/tests/coretests/src/android/view/InsetsSourceTest.java
index c61f33e..2106b4b 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceTest.java
@@ -169,6 +169,13 @@
     }
 
     @Test
+    public void testCalculateInsetsForIme_noIntersection_horizontal() {
+        mImeSource.setFrame(new Rect(0, 0, 100, 500));
+        Insets insets = mImeSource.calculateInsets(new Rect(100, 0, 500, 500), false);
+        assertEquals(Insets.NONE, insets);
+    }
+
+    @Test
     public void testCalculateInsets_zeroWidthIntersection_horizontal_start() {
         mSource.setFrame(new Rect(0, 0, 100, 500));
         Insets insets = mSource.calculateInsets(new Rect(0, 0, 500, 0), false);
diff --git a/core/tests/coretests/src/android/view/MotionEventTest.java b/core/tests/coretests/src/android/view/MotionEventTest.java
index 786ae89..b3450de 100644
--- a/core/tests/coretests/src/android/view/MotionEventTest.java
+++ b/core/tests/coretests/src/android/view/MotionEventTest.java
@@ -169,4 +169,24 @@
             assertEquals(0x3 << 30, ID_SOURCE_MASK & event.getId());
         }
     }
+
+    @Test
+    public void testEventRotation() {
+        final MotionEvent event = MotionEvent.obtain(0 /* downTime */, 0 /* eventTime */,
+                    ACTION_DOWN, 30 /* x */, 50 /* y */, 0 /* metaState */);
+        MotionEvent rot90 = MotionEvent.obtain(event);
+        rot90.transform(MotionEvent.createRotateMatrix(/* 90 deg */1, 1000, 600));
+        assertEquals(50, (int) rot90.getX());
+        assertEquals(570, (int) rot90.getY());
+
+        MotionEvent rot180 = MotionEvent.obtain(event);
+        rot180.transform(MotionEvent.createRotateMatrix(/* 180 deg */2, 1000, 600));
+        assertEquals(970, (int) rot180.getX());
+        assertEquals(550, (int) rot180.getY());
+
+        MotionEvent rot270 = MotionEvent.obtain(event);
+        rot270.transform(MotionEvent.createRotateMatrix(/* 270 deg */3, 1000, 600));
+        assertEquals(950, (int) rot270.getX());
+        assertEquals(30, (int) rot270.getY());
+    }
 }
diff --git a/core/tests/coretests/src/android/view/OWNERS b/core/tests/coretests/src/android/view/OWNERS
index 5031ff9..80165f0 100644
--- a/core/tests/coretests/src/android/view/OWNERS
+++ b/core/tests/coretests/src/android/view/OWNERS
@@ -1,7 +1,7 @@
 # Input
-per-file *MotionEventTest.* = michaelwr@google.com, svv@google.com
-per-file *KeyEventTest.* = michaelwr@google.com, svv@google.com
-per-file VelocityTest.java = michaelwr@google.com, svv@google.com
+per-file *MotionEventTest.* = file:/services/core/java/com/android/server/input/OWNERS
+per-file *KeyEventTest.* = file:/services/core/java/com/android/server/input/OWNERS
+per-file VelocityTest.java = file:/services/core/java/com/android/server/input/OWNERS
 
 # WindowManager
 per-file *Display* = file:/services/core/java/com/android/server/wm/OWNERS
diff --git a/core/tests/coretests/src/android/view/ScrollCaptureConnectionTest.java b/core/tests/coretests/src/android/view/ScrollCaptureConnectionTest.java
index b9cf1e4..516fb76 100644
--- a/core/tests/coretests/src/android/view/ScrollCaptureConnectionTest.java
+++ b/core/tests/coretests/src/android/view/ScrollCaptureConnectionTest.java
@@ -16,16 +16,12 @@
 
 package android.view;
 
-import static androidx.test.InstrumentationRegistry.getInstrumentation;
 import static androidx.test.InstrumentationRegistry.getTargetContext;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -35,6 +31,7 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Handler;
+import android.os.ICancellationSignal;
 
 import androidx.test.runner.AndroidJUnit4;
 
@@ -42,9 +39,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
-import org.mockito.stubbing.Answer;
 
 /**
  * Tests of {@link ScrollCaptureConnection}.
@@ -56,261 +51,138 @@
     private final Point mPositionInWindow = new Point(1, 2);
     private final Rect mLocalVisibleRect = new Rect(2, 3, 4, 5);
     private final Rect mScrollBounds = new Rect(3, 4, 5, 6);
+    private final TestScrollCaptureCallback mCallback = new TestScrollCaptureCallback();
+
+    private ScrollCaptureTarget mTarget;
+    private ScrollCaptureConnection mConnection;
 
     private Handler mHandler;
-    private ScrollCaptureTarget mTarget1;
 
     @Mock
     private Surface mSurface;
     @Mock
-    private IScrollCaptureCallbacks mConnectionCallbacks;
+    private IScrollCaptureCallbacks mRemote;
     @Mock
-    private View mMockView1;
-    @Mock
-    private ScrollCaptureCallback mCallback1;
+    private View mView;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mHandler = new Handler(getTargetContext().getMainLooper());
+        when(mSurface.isValid()).thenReturn(true);
+        when(mView.getScrollCaptureHint()).thenReturn(View.SCROLL_CAPTURE_HINT_INCLUDE);
 
-        when(mMockView1.getHandler()).thenReturn(mHandler);
-        when(mMockView1.getScrollCaptureHint()).thenReturn(View.SCROLL_CAPTURE_HINT_INCLUDE);
-
-        mTarget1 = new ScrollCaptureTarget(
-                mMockView1, mLocalVisibleRect, mPositionInWindow, mCallback1);
-        mTarget1.setScrollBounds(mScrollBounds);
-    }
-
-    /** Test the DelayedAction timeout helper class works as expected. */
-    @Test
-    public void testDelayedAction() {
-        Runnable action = Mockito.mock(Runnable.class);
-        ScrollCaptureConnection.DelayedAction delayed =
-                new ScrollCaptureConnection.DelayedAction(mHandler, 100, action);
-        try {
-            Thread.sleep(200);
-        } catch (InterruptedException ex) {
-            /* ignore */
-        }
-        getInstrumentation().waitForIdleSync();
-        assertFalse(delayed.cancel());
-        assertFalse(delayed.timeoutNow());
-        verify(action, times(1)).run();
-    }
-
-    /** Test the DelayedAction cancel() */
-    @Test
-    public void testDelayedAction_cancel() {
-        Runnable action = Mockito.mock(Runnable.class);
-        ScrollCaptureConnection.DelayedAction delayed =
-                new ScrollCaptureConnection.DelayedAction(mHandler, 100, action);
-        try {
-            Thread.sleep(50);
-        } catch (InterruptedException ex) {
-            /* ignore */
-        }
-        assertTrue(delayed.cancel());
-        assertFalse(delayed.timeoutNow());
-        try {
-            Thread.sleep(200);
-        } catch (InterruptedException ex) {
-            /* ignore */
-        }
-        getInstrumentation().waitForIdleSync();
-        verify(action, never()).run();
-    }
-
-    /** Test the DelayedAction timeoutNow() - for testing only */
-    @Test
-    public void testDelayedAction_timeoutNow() {
-        Runnable action = Mockito.mock(Runnable.class);
-        ScrollCaptureConnection.DelayedAction delayed =
-                new ScrollCaptureConnection.DelayedAction(mHandler, 100, action);
-        try {
-            Thread.sleep(50);
-        } catch (InterruptedException ex) {
-            /* ignore */
-        }
-        assertTrue(delayed.timeoutNow());
-        assertFalse(delayed.cancel());
-        getInstrumentation().waitForIdleSync();
-        verify(action, times(1)).run();
+        mTarget = new ScrollCaptureTarget(mView, mLocalVisibleRect, mPositionInWindow, mCallback);
+        mTarget.setScrollBounds(mScrollBounds);
+        mConnection = new ScrollCaptureConnection(Runnable::run, mTarget, mRemote);
     }
 
     /** Test creating a client with valid info */
     @Test
     public void testConstruction() {
-        new ScrollCaptureConnection(mTarget1, mConnectionCallbacks);
+        ScrollCaptureTarget target = new ScrollCaptureTarget(
+                mView, mLocalVisibleRect, mPositionInWindow, mCallback);
+        target.setScrollBounds(new Rect(1, 2, 3, 4));
+        new ScrollCaptureConnection(Runnable::run, target, mRemote);
     }
 
     /** Test creating a client fails if arguments are not valid. */
     @Test
     public void testConstruction_requiresScrollBounds() {
         try {
-            mTarget1.setScrollBounds(null);
-            new ScrollCaptureConnection(mTarget1, mConnectionCallbacks);
+            mTarget.setScrollBounds(null);
+            new ScrollCaptureConnection(Runnable::run, mTarget, mRemote);
             fail("An exception was expected.");
         } catch (RuntimeException ex) {
             // Ignore, expected.
         }
     }
 
-    @SuppressWarnings("SameParameterValue")
-    private static Answer<Void> runRunnable(int arg) {
-        return invocation -> {
-            Runnable r = invocation.getArgument(arg);
-            r.run();
-            return null;
-        };
-    }
-
-    @SuppressWarnings("SameParameterValue")
-    private static Answer<Void> reportBufferSent(int sessionArg, long frameNum, Rect capturedArea) {
-        return invocation -> {
-            ScrollCaptureSession session = invocation.getArgument(sessionArg);
-            session.notifyBufferSent(frameNum, capturedArea);
-            return null;
-        };
-    }
-
     /** @see ScrollCaptureConnection#startCapture(Surface) */
     @Test
     public void testStartCapture() throws Exception {
-        final ScrollCaptureConnection connection = new ScrollCaptureConnection(mTarget1,
-                mConnectionCallbacks);
+        mConnection.startCapture(mSurface);
 
-        // Have the session start accepted immediately
-        doAnswer(runRunnable(1)).when(mCallback1)
-                .onScrollCaptureStart(any(ScrollCaptureSession.class), any(Runnable.class));
-        connection.startCapture(mSurface);
-        getInstrumentation().waitForIdleSync();
+        mCallback.completeStartRequest();
+        assertTrue(mConnection.isStarted());
 
-        verify(mCallback1, times(1))
-                .onScrollCaptureStart(any(ScrollCaptureSession.class), any(Runnable.class));
-        verify(mConnectionCallbacks, times(1)).onCaptureStarted();
-        verifyNoMoreInteractions(mConnectionCallbacks);
+        verify(mRemote, times(1)).onCaptureStarted();
+        verifyNoMoreInteractions(mRemote);
     }
 
     @Test
-    public void testStartCaptureTimeout() throws Exception {
-        final ScrollCaptureConnection connection = new ScrollCaptureConnection(mTarget1,
-                mConnectionCallbacks);
-        connection.startCapture(mSurface);
+    public void testStartCapture_cancellation() throws Exception {
+        ICancellationSignal signal = mConnection.startCapture(mSurface);
+        signal.cancel();
 
-        // Force timeout to fire
-        connection.getTimeoutAction().timeoutNow();
+        mCallback.completeStartRequest();
+        assertFalse(mConnection.isStarted());
 
-        getInstrumentation().waitForIdleSync();
-        verify(mCallback1, times(1)).onScrollCaptureEnd(any(Runnable.class));
-    }
-
-    private void startCapture(ScrollCaptureConnection connection) throws Exception {
-        doAnswer(runRunnable(1)).when(mCallback1)
-                .onScrollCaptureStart(any(ScrollCaptureSession.class), any(Runnable.class));
-        connection.startCapture(mSurface);
-        getInstrumentation().waitForIdleSync();
-        reset(mCallback1, mConnectionCallbacks);
+        verifyNoMoreInteractions(mRemote);
     }
 
     /** @see ScrollCaptureConnection#requestImage(Rect) */
     @Test
     public void testRequestImage() throws Exception {
-        final ScrollCaptureConnection connection = new ScrollCaptureConnection(mTarget1,
-                mConnectionCallbacks);
-        startCapture(connection);
+        mConnection.startCapture(mSurface);
+        mCallback.completeStartRequest();
+        reset(mRemote);
 
-        // Stub the callback to complete the request immediately
-        doAnswer(reportBufferSent(/* sessionArg */ 0, /* frameNum */ 1L, new Rect(1, 2, 3, 4)))
-                .when(mCallback1)
-                .onScrollCaptureImageRequest(any(ScrollCaptureSession.class), any(Rect.class));
+        mConnection.requestImage(new Rect(1, 2, 3, 4));
+        mCallback.completeImageRequest(new Rect(1, 2, 3, 4));
 
-        // Make the inbound binder call
-        connection.requestImage(new Rect(1, 2, 3, 4));
-
-        // Wait for handler thread dispatch
-        getInstrumentation().waitForIdleSync();
-        verify(mCallback1, times(1)).onScrollCaptureImageRequest(
-                any(ScrollCaptureSession.class), eq(new Rect(1, 2, 3, 4)));
-
-        // Wait for binder thread dispatch
-        getInstrumentation().waitForIdleSync();
-        verify(mConnectionCallbacks, times(1))
-                .onCaptureBufferSent(eq(1L), eq(new Rect(1, 2, 3, 4)));
-
-        verifyNoMoreInteractions(mCallback1, mConnectionCallbacks);
+        verify(mRemote, times(1))
+                .onImageRequestCompleted(eq(0), eq(new Rect(1, 2, 3, 4)));
+        verifyNoMoreInteractions(mRemote);
     }
 
     @Test
-    public void testRequestImageTimeout() throws Exception {
-        final ScrollCaptureConnection connection = new ScrollCaptureConnection(mTarget1,
-                mConnectionCallbacks);
-        startCapture(connection);
+    public void testRequestImage_cancellation() throws Exception {
+        mConnection.startCapture(mSurface);
+        mCallback.completeStartRequest();
+        reset(mRemote);
 
-        // Make the inbound binder call
-        connection.requestImage(new Rect(1, 2, 3, 4));
+        ICancellationSignal signal = mConnection.requestImage(new Rect(1, 2, 3, 4));
+        signal.cancel();
+        mCallback.completeImageRequest(new Rect(1, 2, 3, 4));
 
-        // Wait for handler thread dispatch
-        getInstrumentation().waitForIdleSync();
-        verify(mCallback1, times(1)).onScrollCaptureImageRequest(
-                any(ScrollCaptureSession.class), eq(new Rect(1, 2, 3, 4)));
-
-        // Force timeout to fire
-        connection.getTimeoutAction().timeoutNow();
-        getInstrumentation().waitForIdleSync();
-
-        // (callback not stubbed, does nothing)
-        // Timeout triggers request to end capture
-        verify(mCallback1, times(1)).onScrollCaptureEnd(any(Runnable.class));
-        verifyNoMoreInteractions(mCallback1, mConnectionCallbacks);
+        verifyNoMoreInteractions(mRemote);
     }
 
     /** @see ScrollCaptureConnection#endCapture() */
     @Test
     public void testEndCapture() throws Exception {
-        final ScrollCaptureConnection connection = new ScrollCaptureConnection(mTarget1,
-                mConnectionCallbacks);
-        startCapture(connection);
+        mConnection.startCapture(mSurface);
+        mCallback.completeStartRequest();
+        reset(mRemote);
 
-        // Stub the callback to complete the request immediately
-        doAnswer(runRunnable(0))
-                .when(mCallback1)
-                .onScrollCaptureEnd(any(Runnable.class));
+        mConnection.endCapture();
+        mCallback.completeEndRequest();
 
-        // Make the inbound binder call
-        connection.endCapture();
+        // And the reply is sent
+        verify(mRemote, times(1)).onCaptureEnded();
+        verifyNoMoreInteractions(mRemote);
+    }
 
-        // Wait for handler thread dispatch
-        getInstrumentation().waitForIdleSync();
-        verify(mCallback1, times(1)).onScrollCaptureEnd(any(Runnable.class));
+    /** @see ScrollCaptureConnection#endCapture() */
+    @Test
+    public void testEndCapture_cancellation() throws Exception {
+        mConnection.startCapture(mSurface);
+        mCallback.completeStartRequest();
+        reset(mRemote);
 
-        // Wait for binder thread dispatch
-        getInstrumentation().waitForIdleSync();
-        verify(mConnectionCallbacks, times(1)).onConnectionClosed();
+        ICancellationSignal signal = mConnection.endCapture();
+        signal.cancel();
+        mCallback.completeEndRequest();
 
-        verifyNoMoreInteractions(mCallback1, mConnectionCallbacks);
+        verifyNoMoreInteractions(mRemote);
     }
 
     @Test
-    public void testEndCaptureTimeout() throws Exception {
-        final ScrollCaptureConnection connection = new ScrollCaptureConnection(mTarget1,
-                mConnectionCallbacks);
-        startCapture(connection);
-
-        // Make the inbound binder call
-        connection.endCapture();
-
-        // Wait for handler thread dispatch
-        getInstrumentation().waitForIdleSync();
-        verify(mCallback1, times(1)).onScrollCaptureEnd(any(Runnable.class));
-
-        // Force timeout to fire
-        connection.getTimeoutAction().timeoutNow();
-
-        // Wait for binder thread dispatch
-        getInstrumentation().waitForIdleSync();
-        verify(mConnectionCallbacks, times(1)).onConnectionClosed();
-
-        verifyNoMoreInteractions(mCallback1, mConnectionCallbacks);
+    public void testClose() throws Exception {
+        mConnection.close();
+        assertFalse(mConnection.isConnected());
+        verifyNoMoreInteractions(mRemote);
     }
+
 }
diff --git a/core/tests/coretests/src/android/view/ScrollCaptureSearchResultsTest.java b/core/tests/coretests/src/android/view/ScrollCaptureSearchResultsTest.java
new file mode 100644
index 0000000..cc229e1
--- /dev/null
+++ b/core/tests/coretests/src/android/view/ScrollCaptureSearchResultsTest.java
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import static androidx.test.InstrumentationRegistry.getTargetContext;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.CancellationSignal;
+import android.os.SystemClock;
+
+import androidx.annotation.NonNull;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+/**
+ * Tests of {@link ScrollCaptureTargetSelector}.
+ */
+@RunWith(AndroidJUnit4.class)
+public class ScrollCaptureSearchResultsTest {
+
+
+    private static final Rect EMPTY_RECT = new Rect();
+    private static final String TAG = "Test";
+
+    private final Executor mDirectExec = Runnable::run;
+    private Executor mBgExec;
+
+    @Before
+    public void setUp() {
+        mBgExec = Executors.newSingleThreadExecutor();
+    }
+
+    @Test
+    public void testNoTargets() {
+        ScrollCaptureSearchResults results = new ScrollCaptureSearchResults(mDirectExec);
+        assertTrue(results.isComplete());
+
+        assertNull("Expected null due to empty queue", results.getTopResult());
+    }
+
+    @Test
+    public void testNoValidTargets() {
+        ScrollCaptureSearchResults results = new ScrollCaptureSearchResults(mDirectExec);
+
+        FakeScrollCaptureCallback callback1 = new FakeScrollCaptureCallback(mDirectExec);
+        callback1.setScrollBounds(EMPTY_RECT);
+        ScrollCaptureTarget target1 = createTarget(callback1, new Rect(20, 30, 40, 50),
+                new Point(0, 0), View.SCROLL_CAPTURE_HINT_AUTO);
+
+        // Supplies scrollBounds = empty rect
+        FakeScrollCaptureCallback callback2 = new FakeScrollCaptureCallback(mDirectExec);
+        callback2.setScrollBounds(EMPTY_RECT);
+        ScrollCaptureTarget target2 = createTarget(callback2, new Rect(20, 30, 40, 50),
+                new Point(0, 20), View.SCROLL_CAPTURE_HINT_INCLUDE);
+
+        results.addTarget(target1);
+        results.addTarget(target2);
+
+        assertTrue(results.isComplete());
+        assertNull("Expected null due to no valid targets", results.getTopResult());
+    }
+
+    @Test
+    public void testSingleTarget() {
+        ScrollCaptureSearchResults results = new ScrollCaptureSearchResults(mDirectExec);
+        FakeScrollCaptureCallback callback = new FakeScrollCaptureCallback(mDirectExec);
+        ScrollCaptureTarget target = createTarget(callback,
+                new Rect(20, 30, 40, 50), new Point(10, 10),
+                View.SCROLL_CAPTURE_HINT_AUTO);
+        callback.setScrollBounds(new Rect(2, 2, 18, 18));
+
+        results.addTarget(target);
+        assertTrue(results.isComplete());
+
+        ScrollCaptureTarget result = results.getTopResult();
+        assertSame("Excepted the same target as a result", target, result);
+        assertEquals("result has wrong scroll bounds",
+                new Rect(2, 2, 18, 18), result.getScrollBounds());
+    }
+
+    @Test
+    public void testSingleTarget_backgroundThread() throws InterruptedException {
+        FakeScrollCaptureCallback callback1 = new FakeScrollCaptureCallback(mBgExec);
+        ScrollCaptureTarget target1 = createTarget(callback1,
+                new Rect(20, 30, 40, 50), new Point(10, 10),
+                View.SCROLL_CAPTURE_HINT_AUTO);
+        callback1.setDelay(100);
+        callback1.setScrollBounds(new Rect(2, 2, 18, 18));
+
+        ScrollCaptureSearchResults results = new ScrollCaptureSearchResults(mDirectExec);
+        results.addTarget(target1);
+
+        CountDownLatch latch = new CountDownLatch(1);
+        results.setOnCompleteListener(latch::countDown);
+        if (!latch.await(200, TimeUnit.MILLISECONDS)) {
+            fail("onComplete listener was expected");
+        }
+
+        ScrollCaptureTarget result = results.getTopResult();
+        assertSame("Excepted the single target1 as a result", target1, result);
+        assertEquals("Result has wrong scroll bounds",
+                new Rect(2, 2, 18, 18), result.getScrollBounds());
+    }
+
+    @Test
+    public void testRanking() {
+
+        // 1 - Empty
+        FakeScrollCaptureCallback callback1 = new FakeScrollCaptureCallback(mDirectExec);
+        callback1.setScrollBounds(EMPTY_RECT);
+        ViewGroup targetView1 = new FakeView(getTargetContext(), 0, 0, 60, 60, 1);
+        ScrollCaptureTarget target1 = createTargetWithView(targetView1, callback1,
+                new Rect(0, 0, 60, 60), new Point(0, 0), View.SCROLL_CAPTURE_HINT_AUTO);
+
+        // 2 - 10x10 + HINT_INCLUDE
+        FakeScrollCaptureCallback callback2 = new FakeScrollCaptureCallback(mDirectExec);
+        callback2.setScrollBounds(new Rect(0, 0, 10, 10));
+        ViewGroup targetView2 = new FakeView(getTargetContext(), 0, 0, 60, 60, 2);
+        ScrollCaptureTarget target2 = createTargetWithView(targetView2, callback2,
+                 new Rect(0, 0, 60, 60), new Point(0, 0), View.SCROLL_CAPTURE_HINT_INCLUDE);
+
+        // 3 - 20x20 + AUTO
+        FakeScrollCaptureCallback callback3 = new FakeScrollCaptureCallback(mDirectExec);
+        callback3.setScrollBounds(new Rect(0, 0, 20, 20));
+        ViewGroup targetView3 = new FakeView(getTargetContext(), 0, 0, 60, 60, 3);
+        ScrollCaptureTarget target3 = createTargetWithView(targetView3, callback3,
+                new Rect(0, 0, 60, 60), new Point(0, 0), View.SCROLL_CAPTURE_HINT_AUTO);
+
+        // 4 - 30x30 + AUTO
+        FakeScrollCaptureCallback callback4 = new FakeScrollCaptureCallback(mDirectExec);
+        callback4.setScrollBounds(new Rect(0, 0, 10, 10));
+        ViewGroup targetView4 = new FakeView(getTargetContext(), 0, 0, 60, 60, 4);
+        ScrollCaptureTarget target4 = createTargetWithView(targetView4, callback4,
+                new Rect(0, 0, 60, 60), new Point(0, 0), View.SCROLL_CAPTURE_HINT_AUTO);
+
+        // 5 - 10x10 + child of #4
+        FakeScrollCaptureCallback callback5 = new FakeScrollCaptureCallback(mDirectExec);
+        callback5.setScrollBounds(new Rect(0, 0, 10, 10));
+        ViewGroup targetView5 = new FakeView(getTargetContext(), 0, 0, 60, 60, 5);
+        ScrollCaptureTarget target5 = createTargetWithView(targetView5, callback5,
+                new Rect(0, 0, 60, 60), new Point(0, 0), View.SCROLL_CAPTURE_HINT_AUTO);
+        targetView4.addView(targetView5);
+
+        // 6 - 20x20 + child of #4
+        FakeScrollCaptureCallback callback6 = new FakeScrollCaptureCallback(mDirectExec);
+        callback6.setScrollBounds(new Rect(0, 0, 20, 20));
+        ViewGroup targetView6 = new FakeView(getTargetContext(), 0, 0, 60, 60, 6);
+        ScrollCaptureTarget target6 = createTargetWithView(targetView6, callback6,
+                new Rect(0, 0, 60, 60), new Point(0, 0), View.SCROLL_CAPTURE_HINT_AUTO);
+        targetView4.addView(targetView6);
+
+        ScrollCaptureSearchResults results = new ScrollCaptureSearchResults(mDirectExec);
+        results.addTarget(target1);
+        results.addTarget(target2);
+        results.addTarget(target3);
+        results.addTarget(target4);
+        results.addTarget(target5);
+        results.addTarget(target6);
+        assertTrue(results.isComplete());
+
+        // Verify "top" result
+        assertEquals(target2, results.getTopResult());
+
+        // Verify priority ("best" first)
+        assertThat(results.getTargets())
+                .containsExactly(
+                        target2,
+                        target6,
+                        target5,
+                        target4,
+                        target3,
+                        target1);
+    }
+
+    /**
+     * If a timeout expires, late results are ignored.
+     */
+    @Test
+    public void testTimeout() {
+        ScrollCaptureSearchResults results = new ScrollCaptureSearchResults(mDirectExec);
+
+        // callback 1, 10x10, hint=AUTO, responds after 100ms from bg thread
+        FakeScrollCaptureCallback callback1 = new FakeScrollCaptureCallback(mBgExec);
+        callback1.setScrollBounds(new Rect(5, 5, 15, 15));
+        callback1.setDelay(100);
+        ScrollCaptureTarget target1 = createTarget(
+                callback1, new Rect(20, 30, 40, 50), new Point(10, 10),
+                View.SCROLL_CAPTURE_HINT_AUTO);
+        results.addTarget(target1);
+
+        // callback 2, 20x20, hint=AUTO, responds after 5s from bg thread
+        FakeScrollCaptureCallback callback2 = new FakeScrollCaptureCallback(mBgExec);
+        callback2.setScrollBounds(new Rect(0, 0, 20, 20));
+        callback2.setDelay(1000);
+        ScrollCaptureTarget target2 = createTarget(
+                callback2, new Rect(20, 30, 40, 50), new Point(10, 10),
+                View.SCROLL_CAPTURE_HINT_AUTO);
+        results.addTarget(target2);
+
+        // callback 3, 20x20, hint=INCLUDE, responds after 10s from bg thread
+        FakeScrollCaptureCallback callback3 = new FakeScrollCaptureCallback(mBgExec);
+        callback3.setScrollBounds(new Rect(0, 0, 20, 20));
+        callback3.setDelay(1500);
+        ScrollCaptureTarget target3 = createTarget(
+                callback3, new Rect(20, 30, 40, 50), new Point(10, 10),
+                View.SCROLL_CAPTURE_HINT_INCLUDE);
+        results.addTarget(target3);
+
+        // callback 1 will be received
+        // callback 2 & 3 will be ignored due to timeout
+        SystemClock.sleep(500);
+        results.finish();
+
+        ScrollCaptureTarget result = results.getTopResult();
+        assertSame("Expected target1 as the result, due to timeouts of others", target1, result);
+        assertEquals("callback1 should have been called",
+                1, callback1.getOnScrollCaptureSearchCount());
+        assertEquals("callback2 should have been called",
+                1, callback2.getOnScrollCaptureSearchCount());
+        assertEquals("callback3 should have been called",
+                1, callback3.getOnScrollCaptureSearchCount());
+
+        assertEquals("result has wrong scroll bounds",
+                new Rect(5, 5, 15, 15), result.getScrollBounds());
+        assertNull("target2 should not have been updated",
+                target2.getScrollBounds());
+        assertNull("target3 should not have been updated",
+                target3.getScrollBounds());
+    }
+
+    @Test
+    public void testWithCallbackMultipleReplies() {
+        // Calls response methods 3 times each
+        ScrollCaptureCallback callback1 = new CallbackStub() {
+            @Override
+            public void onScrollCaptureSearch(@NonNull CancellationSignal signal,
+                    @NonNull Consumer<Rect> onReady) {
+                onReady.accept(new Rect(1, 2, 3, 4));
+                onReady.accept(new Rect(9, 10, 11, 12));
+            }
+        };
+
+        ScrollCaptureTarget target1 = createTarget(callback1, new Rect(20, 30, 40, 50),
+                new Point(10, 10), View.SCROLL_CAPTURE_HINT_AUTO);
+
+        ScrollCaptureSearchResults results = new ScrollCaptureSearchResults(mDirectExec);
+        results.addTarget(target1);
+        assertTrue(results.isComplete());
+
+        ScrollCaptureTarget result = results.getTopResult();
+        assertSame("Expected target1", target1, result);
+        assertEquals("result has wrong scroll bounds",
+                new Rect(1, 2, 3, 4), result.getScrollBounds());
+    }
+
+    private void setupTargetView(View view, Rect localVisibleRect, int scrollCaptureHint) {
+        view.setScrollCaptureHint(scrollCaptureHint);
+        view.onVisibilityAggregated(true);
+        // Treat any offset as padding, outset localVisibleRect on all sides and use this as
+        // child bounds
+        Rect bounds = new Rect(localVisibleRect);
+        bounds.inset(-bounds.left, -bounds.top, bounds.left, bounds.top);
+        view.layout(bounds.left, bounds.top, bounds.right, bounds.bottom);
+        view.onVisibilityAggregated(true);
+    }
+
+    private ScrollCaptureTarget createTarget(ScrollCaptureCallback callback, Rect localVisibleRect,
+            Point positionInWindow, int scrollCaptureHint) {
+        View mockView = new View(getTargetContext());
+        return createTargetWithView(mockView, callback, localVisibleRect, positionInWindow,
+                scrollCaptureHint);
+    }
+
+    private ScrollCaptureTarget createTargetWithView(View view, ScrollCaptureCallback callback,
+            Rect localVisibleRect, Point positionInWindow, int scrollCaptureHint) {
+        setupTargetView(view, localVisibleRect, scrollCaptureHint);
+        return new ScrollCaptureTarget(view, localVisibleRect, positionInWindow, callback);
+    }
+
+
+    static class FakeView extends ViewGroup implements ViewParent {
+        FakeView(Context context, int l, int t, int r, int b, int id) {
+            super(context);
+            layout(l, t, r, b);
+            setId(id);
+        }
+
+        @Override
+        protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        }
+    }
+
+    static class FakeScrollCaptureCallback implements ScrollCaptureCallback {
+        private final Executor mExecutor;
+        private Rect mScrollBounds;
+        private long mDelayMillis;
+        private int mOnScrollCaptureSearchCount;
+        FakeScrollCaptureCallback(Executor executor) {
+            mExecutor = executor;
+        }
+        public int getOnScrollCaptureSearchCount() {
+            return mOnScrollCaptureSearchCount;
+        }
+
+        @Override
+        public void onScrollCaptureSearch(CancellationSignal signal, Consumer<Rect> onReady) {
+            mOnScrollCaptureSearchCount++;
+            run(() -> {
+                Rect b = getScrollBounds();
+                onReady.accept(b);
+            });
+        }
+
+        @Override
+        public void onScrollCaptureStart(ScrollCaptureSession session, CancellationSignal signal,
+                Runnable onReady) {
+            run(onReady);
+        }
+
+        @Override
+        public void onScrollCaptureImageRequest(ScrollCaptureSession session,
+                CancellationSignal signal, Rect captureArea, Consumer<Rect> onReady) {
+            run(() -> onReady.accept(captureArea));
+        }
+
+        @Override
+        public void onScrollCaptureEnd(Runnable onReady) {
+            run(onReady);
+        }
+
+        public void setScrollBounds(@Nullable Rect scrollBounds) {
+            mScrollBounds = scrollBounds;
+        }
+
+        public void setDelay(long delayMillis) {
+            mDelayMillis = delayMillis;
+        }
+
+        protected Rect getScrollBounds() {
+            return mScrollBounds;
+        }
+
+        protected void run(Runnable r) {
+            mExecutor.execute(() -> {
+                delay();
+                r.run();
+            });
+        }
+
+        protected void delay() {
+            if (mDelayMillis > 0) {
+                try {
+                    Thread.sleep(mDelayMillis);
+                } catch (InterruptedException e) {
+                    // Ignore
+                }
+            }
+        }
+    }
+    static class CallbackStub implements ScrollCaptureCallback {
+        @Override
+        public void onScrollCaptureSearch(@NonNull CancellationSignal signal,
+                @NonNull Consumer<Rect> onReady) {
+        }
+
+        @Override
+        public void onScrollCaptureStart(@NonNull ScrollCaptureSession session,
+                @NonNull CancellationSignal signal, @NonNull Runnable onReady) {
+        }
+
+        @Override
+        public void onScrollCaptureImageRequest(@NonNull ScrollCaptureSession session,
+                @NonNull CancellationSignal signal, @NonNull Rect captureArea,
+                Consumer<Rect> onReady) {
+        }
+
+        @Override
+        public void onScrollCaptureEnd(@NonNull Runnable onReady) {
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/view/ScrollCaptureTargetResolverTest.java b/core/tests/coretests/src/android/view/ScrollCaptureTargetResolverTest.java
deleted file mode 100644
index 8b21b8e..0000000
--- a/core/tests/coretests/src/android/view/ScrollCaptureTargetResolverTest.java
+++ /dev/null
@@ -1,498 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import static androidx.test.InstrumentationRegistry.getTargetContext;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-
-import android.annotation.Nullable;
-import android.content.Context;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.os.Handler;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.LinkedList;
-import java.util.function.Consumer;
-
-/**
- * Tests of {@link ScrollCaptureTargetResolver}.
- */
-@RunWith(AndroidJUnit4.class)
-public class ScrollCaptureTargetResolverTest {
-
-    private static final long TEST_TIMEOUT_MS = 2000;
-    private static final long RESOLVER_TIMEOUT_MS = 1000;
-
-    private Handler mHandler;
-    private TargetConsumer mTargetConsumer;
-
-    @Before
-    public void setUp() {
-        mTargetConsumer = new TargetConsumer();
-        mHandler = new Handler(getTargetContext().getMainLooper());
-    }
-
-    @Test(timeout = TEST_TIMEOUT_MS)
-    public void testEmptyQueue() throws InterruptedException {
-        ScrollCaptureTargetResolver resolver = new ScrollCaptureTargetResolver(new LinkedList<>());
-        resolver.start(mHandler, RESOLVER_TIMEOUT_MS, mTargetConsumer);
-
-        // Test only
-        resolver.waitForResult();
-
-        ScrollCaptureTarget result = mTargetConsumer.getLastValue();
-        assertNull("Expected null due to empty queue", result);
-    }
-
-    @Test(timeout = TEST_TIMEOUT_MS)
-    public void testNoValidTargets() throws InterruptedException {
-        LinkedList<ScrollCaptureTarget> targetQueue = new LinkedList<>();
-
-        // Supplies scrollBounds = null
-        FakeScrollCaptureCallback callback1 = new FakeScrollCaptureCallback();
-        callback1.setScrollBounds(null);
-        ScrollCaptureTarget target1 = createTarget(callback1, new Rect(20, 30, 40, 50),
-                new Point(0, 0), View.SCROLL_CAPTURE_HINT_AUTO);
-
-        // Supplies scrollBounds = empty rect
-        FakeScrollCaptureCallback callback2 = new FakeScrollCaptureCallback();
-        callback2.setScrollBounds(new Rect());
-        ScrollCaptureTarget target2 = createTarget(callback2, new Rect(20, 30, 40, 50),
-                new Point(0, 20), View.SCROLL_CAPTURE_HINT_INCLUDE);
-
-        targetQueue.add(target1);
-        targetQueue.add(target2);
-
-        ScrollCaptureTargetResolver resolver = new ScrollCaptureTargetResolver(targetQueue);
-        resolver.start(mHandler, RESOLVER_TIMEOUT_MS, mTargetConsumer);
-
-        // Test only
-        resolver.waitForResult();
-
-        ScrollCaptureTarget result = mTargetConsumer.getLastValue();
-        assertNull("Expected null due to no valid targets", result);
-    }
-
-    @Test(timeout = TEST_TIMEOUT_MS)
-    public void testSingleTarget() throws InterruptedException {
-        FakeScrollCaptureCallback callback = new FakeScrollCaptureCallback();
-        ScrollCaptureTarget target = createTarget(callback,
-                new Rect(20, 30, 40, 50), new Point(10, 10),
-                View.SCROLL_CAPTURE_HINT_AUTO);
-        callback.setScrollBounds(new Rect(2, 2, 18, 18));
-
-        LinkedList<ScrollCaptureTarget> targetQueue = new LinkedList<>();
-        targetQueue.add(target);
-        ScrollCaptureTargetResolver resolver = new ScrollCaptureTargetResolver(targetQueue);
-        resolver.start(mHandler, RESOLVER_TIMEOUT_MS, mTargetConsumer);
-
-        // Test only
-        resolver.waitForResult();
-
-        ScrollCaptureTarget result = mTargetConsumer.getLastValue();
-        assertSame("Excepted the same target as a result", target, result);
-        assertEquals("result has wrong scroll bounds",
-                new Rect(2, 2, 18, 18), result.getScrollBounds());
-    }
-
-    @Test(timeout = TEST_TIMEOUT_MS)
-    public void testSingleTarget_backgroundThread() throws InterruptedException {
-        BackgroundTestCallback callback1 = new BackgroundTestCallback();
-        ScrollCaptureTarget target1 = createTarget(callback1,
-                new Rect(20, 30, 40, 50), new Point(10, 10),
-                View.SCROLL_CAPTURE_HINT_AUTO);
-        callback1.setDelay(100);
-        callback1.setScrollBounds(new Rect(2, 2, 18, 18));
-
-        LinkedList<ScrollCaptureTarget> targetQueue = new LinkedList<>();
-        targetQueue.add(target1);
-
-        ScrollCaptureTargetResolver resolver = new ScrollCaptureTargetResolver(targetQueue);
-        resolver.start(mHandler, RESOLVER_TIMEOUT_MS, mTargetConsumer);
-
-        // Test only
-        resolver.waitForResult();
-
-        ScrollCaptureTarget result = mTargetConsumer.getLastValue();
-        assertSame("Excepted the single target1 as a result", target1, result);
-        assertEquals("Result has wrong scroll bounds",
-                new Rect(2, 2, 18, 18), result.getScrollBounds());
-    }
-
-    @Test(timeout = TEST_TIMEOUT_MS)
-    public void testPreferNonEmptyBounds() throws InterruptedException {
-        LinkedList<ScrollCaptureTarget> targetQueue = new LinkedList<>();
-
-        FakeScrollCaptureCallback callback1 = new FakeScrollCaptureCallback();
-        callback1.setScrollBounds(new Rect());
-        ScrollCaptureTarget target1 = createTarget(callback1, new Rect(20, 30, 40, 50),
-                new Point(0, 0), View.SCROLL_CAPTURE_HINT_AUTO);
-
-        FakeScrollCaptureCallback callback2 = new FakeScrollCaptureCallback();
-        callback2.setScrollBounds(new Rect(0, 0, 20, 20));
-        ScrollCaptureTarget target2 = createTarget(callback2, new Rect(20, 30, 40, 50),
-                new Point(0, 20), View.SCROLL_CAPTURE_HINT_INCLUDE);
-
-        FakeScrollCaptureCallback callback3 = new FakeScrollCaptureCallback();
-        callback3.setScrollBounds(null);
-        ScrollCaptureTarget target3 = createTarget(callback3, new Rect(20, 30, 40, 50),
-                new Point(0, 40), View.SCROLL_CAPTURE_HINT_AUTO);
-
-        targetQueue.add(target1);
-        targetQueue.add(target2); // scrollBounds not null or empty()
-        targetQueue.add(target3);
-
-        ScrollCaptureTargetResolver resolver = new ScrollCaptureTargetResolver(targetQueue);
-        resolver.start(mHandler, RESOLVER_TIMEOUT_MS, mTargetConsumer);
-        resolver.waitForResult();
-
-        ScrollCaptureTarget result = mTargetConsumer.getLastValue();
-        assertEquals("Expected " + target2 + " as a result", target2, result);
-        assertEquals("result has wrong scroll bounds",
-                new Rect(0, 0, 20, 20), result.getScrollBounds());
-    }
-
-    @Test(timeout = TEST_TIMEOUT_MS)
-    public void testPreferHintInclude() throws InterruptedException {
-        LinkedList<ScrollCaptureTarget> targetQueue = new LinkedList<>();
-
-        FakeScrollCaptureCallback callback1 = new FakeScrollCaptureCallback();
-        callback1.setScrollBounds(new Rect(0, 0, 20, 20));
-        ScrollCaptureTarget target1 = createTarget(callback1, new Rect(20, 30, 40, 50),
-                new Point(0, 0), View.SCROLL_CAPTURE_HINT_AUTO);
-
-        FakeScrollCaptureCallback callback2 = new FakeScrollCaptureCallback();
-        callback2.setScrollBounds(new Rect(1, 1, 19, 19));
-        ScrollCaptureTarget target2 = createTarget(callback2, new Rect(20, 30, 40, 50),
-                new Point(0, 20), View.SCROLL_CAPTURE_HINT_INCLUDE);
-
-        FakeScrollCaptureCallback callback3 = new FakeScrollCaptureCallback();
-        callback3.setScrollBounds(new Rect(2, 2, 18, 18));
-        ScrollCaptureTarget target3 = createTarget(callback3, new Rect(20, 30, 40, 50),
-                new Point(0, 40), View.SCROLL_CAPTURE_HINT_AUTO);
-
-        targetQueue.add(target1);
-        targetQueue.add(target2); // * INCLUDE > AUTO
-        targetQueue.add(target3);
-
-        ScrollCaptureTargetResolver resolver = new ScrollCaptureTargetResolver(targetQueue);
-        resolver.start(mHandler, RESOLVER_TIMEOUT_MS, mTargetConsumer);
-
-        resolver.waitForResult();
-
-        ScrollCaptureTarget result = mTargetConsumer.getLastValue();
-        assertEquals("input = " + targetQueue + " Expected " + target2
-                + " as the result, due to hint=INCLUDE", target2, result);
-        assertEquals("result has wrong scroll bounds",
-                new Rect(1, 1, 19, 19), result.getScrollBounds());
-    }
-
-    @Test(timeout = TEST_TIMEOUT_MS)
-    public void testDescendantPreferred() throws InterruptedException {
-        LinkedList<ScrollCaptureTarget> targetQueue = new LinkedList<>();
-
-        ViewGroup targetView1 = new FakeRootView(getTargetContext(), 0, 0, 60, 60); // 60x60
-        ViewGroup targetView2 = new FakeRootView(getTargetContext(), 20, 30, 40, 50); // 20x20
-        ViewGroup targetView3 = new FakeRootView(getTargetContext(), 5, 5, 15, 15); // 10x10
-
-        targetView1.addView(targetView2);
-        targetView2.addView(targetView3);
-
-        // Create first target with an unrelated parent
-        FakeScrollCaptureCallback callback1 = new FakeScrollCaptureCallback();
-        callback1.setScrollBounds(new Rect(0, 0, 60, 60));
-        ScrollCaptureTarget target1 = createTargetWithView(targetView1, callback1,
-                new Rect(0, 0, 60, 60),
-                new Point(0, 0), View.SCROLL_CAPTURE_HINT_AUTO);
-
-        // Create second target associated with a view within parent2
-        FakeScrollCaptureCallback callback2 = new FakeScrollCaptureCallback();
-        callback2.setScrollBounds(new Rect(0, 0, 20, 20));
-        ScrollCaptureTarget target2 = createTargetWithView(targetView2, callback2,
-                new Rect(0, 0, 20, 20),
-                new Point(20, 30), View.SCROLL_CAPTURE_HINT_AUTO);
-
-        // Create third target associated with a view within parent3
-        FakeScrollCaptureCallback callback3 = new FakeScrollCaptureCallback();
-        callback3.setScrollBounds(new Rect(0, 0, 15, 15));
-        ScrollCaptureTarget target3 = createTargetWithView(targetView3, callback3,
-                new Rect(0, 0, 15, 15),
-                new Point(25, 35), View.SCROLL_CAPTURE_HINT_AUTO);
-
-        targetQueue.add(target1); // auto, 60x60
-        targetQueue.add(target2); // auto, 20x20
-        targetQueue.add(target3); // auto, 15x15 <- innermost scrollable
-
-        ScrollCaptureTargetResolver resolver = new ScrollCaptureTargetResolver(targetQueue);
-        resolver.start(mHandler, RESOLVER_TIMEOUT_MS, mTargetConsumer);
-
-        // Test only
-        resolver.waitForResult();
-
-        ScrollCaptureTarget result = mTargetConsumer.getLastValue();
-        assertSame("Expected target3 as the result, due to relation", target3, result);
-        assertEquals("result has wrong scroll bounds",
-                new Rect(0, 0, 15, 15), result.getScrollBounds());
-    }
-
-    /**
-     * If a timeout expires, late results are ignored.
-     */
-    @Test(timeout = TEST_TIMEOUT_MS)
-    public void testTimeout() throws InterruptedException {
-        LinkedList<ScrollCaptureTarget> targetQueue = new LinkedList<>();
-
-        // callback 1, 10x10, hint=AUTO, responds immediately from bg thread
-        BackgroundTestCallback callback1 = new BackgroundTestCallback();
-        callback1.setScrollBounds(new Rect(5, 5, 15, 15));
-        ScrollCaptureTarget target1 = createTarget(
-                callback1, new Rect(20, 30, 40, 50), new Point(10, 10),
-                View.SCROLL_CAPTURE_HINT_AUTO);
-        targetQueue.add(target1);
-
-        // callback 2, 20x20, hint=AUTO, responds after 5s from bg thread
-        BackgroundTestCallback callback2 = new BackgroundTestCallback();
-        callback2.setScrollBounds(new Rect(0, 0, 20, 20));
-        callback2.setDelay(5000);
-        ScrollCaptureTarget target2 = createTarget(
-                callback2, new Rect(20, 30, 40, 50), new Point(10, 10),
-                View.SCROLL_CAPTURE_HINT_AUTO);
-        targetQueue.add(target2);
-
-        // callback 3, 20x20, hint=INCLUDE, responds after 10s from bg thread
-        BackgroundTestCallback callback3 = new BackgroundTestCallback();
-        callback3.setScrollBounds(new Rect(0, 0, 20, 20));
-        callback3.setDelay(10000);
-        ScrollCaptureTarget target3 = createTarget(
-                callback3, new Rect(20, 30, 40, 50), new Point(10, 10),
-                View.SCROLL_CAPTURE_HINT_INCLUDE);
-        targetQueue.add(target3);
-
-        // callback 1 will be received
-        // callback 2 & 3 will be ignored due to timeout
-
-        ScrollCaptureTargetResolver resolver = new ScrollCaptureTargetResolver(targetQueue);
-        resolver.start(mHandler, RESOLVER_TIMEOUT_MS, mTargetConsumer);
-
-        resolver.waitForResult();
-
-        ScrollCaptureTarget result = mTargetConsumer.getLastValue();
-        assertSame("Expected target1 as the result, due to timeouts of others", target1, result);
-        assertEquals("result has wrong scroll bounds",
-                new Rect(5, 5, 15, 15), result.getScrollBounds());
-        assertEquals("callback1 should have been called",
-                1, callback1.getOnScrollCaptureSearchCount());
-        assertEquals("callback2 should have been called",
-                1, callback2.getOnScrollCaptureSearchCount());
-        assertEquals("callback3 should have been called",
-                1, callback3.getOnScrollCaptureSearchCount());
-    }
-
-    @Test(timeout = TEST_TIMEOUT_MS)
-    public void testWithCallbackMultipleReplies() throws InterruptedException {
-        // Calls response methods 3 times each
-        RepeatingCaptureCallback callback1 = new RepeatingCaptureCallback(3);
-        callback1.setScrollBounds(new Rect(2, 2, 18, 18));
-        ScrollCaptureTarget target1 = createTarget(callback1, new Rect(20, 30, 40, 50),
-                new Point(10, 10), View.SCROLL_CAPTURE_HINT_AUTO);
-
-        FakeScrollCaptureCallback callback2 = new FakeScrollCaptureCallback();
-        callback2.setScrollBounds(new Rect(0, 0, 20, 20));
-        ScrollCaptureTarget target2 = createTarget(callback2, new Rect(20, 30, 40, 50),
-                new Point(10, 10), View.SCROLL_CAPTURE_HINT_AUTO);
-
-        LinkedList<ScrollCaptureTarget> targetQueue = new LinkedList<>();
-        targetQueue.add(target1);
-        targetQueue.add(target2);
-
-        ScrollCaptureTargetResolver resolver = new ScrollCaptureTargetResolver(targetQueue);
-        resolver.start(mHandler, RESOLVER_TIMEOUT_MS, mTargetConsumer);
-
-        resolver.waitForResult();
-
-        ScrollCaptureTarget result = mTargetConsumer.getLastValue();
-        assertSame("Expected target2 as the result, due to hint=INCLUDE", target2, result);
-        assertEquals("result has wrong scroll bounds",
-                new Rect(0, 0, 20, 20), result.getScrollBounds());
-        assertEquals("callback1 should have been called once",
-                1, callback1.getOnScrollCaptureSearchCount());
-        assertEquals("callback2 should have been called once",
-                1, callback2.getOnScrollCaptureSearchCount());
-    }
-
-    private static class TargetConsumer implements Consumer<ScrollCaptureTarget> {
-        volatile ScrollCaptureTarget mResult;
-        int mAcceptCount;
-
-        ScrollCaptureTarget getLastValue() {
-            return mResult;
-        }
-
-        int acceptCount() {
-            return mAcceptCount;
-        }
-
-        @Override
-        public void accept(@Nullable ScrollCaptureTarget t) {
-            mAcceptCount++;
-            mResult = t;
-        }
-    }
-
-    private void setupTargetView(View view, Rect localVisibleRect, int scrollCaptureHint) {
-        view.setScrollCaptureHint(scrollCaptureHint);
-        view.onVisibilityAggregated(true);
-        // Treat any offset as padding, outset localVisibleRect on all sides and use this as
-        // child bounds
-        Rect bounds = new Rect(localVisibleRect);
-        bounds.inset(-bounds.left, -bounds.top, bounds.left, bounds.top);
-        view.layout(bounds.left, bounds.top, bounds.right, bounds.bottom);
-        view.onVisibilityAggregated(true);
-    }
-
-    private ScrollCaptureTarget createTarget(ScrollCaptureCallback callback, Rect localVisibleRect,
-            Point positionInWindow, int scrollCaptureHint) {
-        View mockView = new View(getTargetContext());
-        return createTargetWithView(mockView, callback, localVisibleRect, positionInWindow,
-                scrollCaptureHint);
-    }
-
-    private ScrollCaptureTarget createTargetWithView(View view, ScrollCaptureCallback callback,
-            Rect localVisibleRect, Point positionInWindow, int scrollCaptureHint) {
-        setupTargetView(view, localVisibleRect, scrollCaptureHint);
-        return new ScrollCaptureTarget(view, localVisibleRect, positionInWindow, callback);
-    }
-
-
-    static class FakeRootView extends ViewGroup implements ViewParent {
-        FakeRootView(Context context, int l, int t, int r, int b) {
-            super(context);
-            layout(l, t, r, b);
-        }
-
-        @Override
-        protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        }
-    }
-
-    static class FakeScrollCaptureCallback implements ScrollCaptureCallback {
-        private Rect mScrollBounds;
-        private long mDelayMillis;
-        private int mOnScrollCaptureSearchCount;
-
-        public int getOnScrollCaptureSearchCount() {
-            return mOnScrollCaptureSearchCount;
-        }
-
-        @Override
-        public void onScrollCaptureSearch(Consumer<Rect> onReady) {
-            mOnScrollCaptureSearchCount++;
-            run(() -> {
-                Rect b = getScrollBounds();
-                onReady.accept(b);
-            });
-        }
-
-        @Override
-        public void onScrollCaptureStart(ScrollCaptureSession session, Runnable onReady) {
-            run(onReady);
-        }
-
-        @Override
-        public void onScrollCaptureImageRequest(ScrollCaptureSession session, Rect captureArea) {
-            run(() -> session.notifyBufferSent(0, captureArea));
-        }
-
-        @Override
-        public void onScrollCaptureEnd(Runnable onReady) {
-            run(onReady);
-        }
-
-        public void setScrollBounds(@Nullable Rect scrollBounds) {
-            mScrollBounds = scrollBounds;
-        }
-
-        public void setDelay(long delayMillis) {
-            mDelayMillis = delayMillis;
-        }
-
-        protected Rect getScrollBounds() {
-            return mScrollBounds;
-        }
-
-        protected void run(Runnable r) {
-            delay();
-            r.run();
-        }
-
-        protected void delay() {
-            if (mDelayMillis > 0) {
-                try {
-                    Thread.sleep(mDelayMillis);
-                } catch (InterruptedException e) {
-                    // Ignore
-                }
-            }
-        }
-    }
-
-    static class RepeatingCaptureCallback extends FakeScrollCaptureCallback {
-        private int mRepeatCount;
-
-        RepeatingCaptureCallback(int repeatCount) {
-            mRepeatCount = repeatCount;
-        }
-
-        protected void run(Runnable r) {
-            delay();
-            for (int i = 0; i < mRepeatCount; i++) {
-                r.run();
-            }
-        }
-    }
-
-    /** Response to async calls on an arbitrary background thread */
-    static class BackgroundTestCallback extends FakeScrollCaptureCallback {
-        static int sCount = 0;
-        private void runOnBackgroundThread(Runnable r) {
-            final Runnable target = () -> {
-                delay();
-                r.run();
-            };
-            Thread t = new Thread(target);
-            synchronized (BackgroundTestCallback.this) {
-                sCount++;
-            }
-            t.setName("Background-Thread-" + sCount);
-            t.start();
-        }
-
-        @Override
-        protected void run(Runnable r) {
-            runOnBackgroundThread(r);
-        }
-    }
-}
diff --git a/core/tests/coretests/src/android/view/SoundEffectConstantsTest.java b/core/tests/coretests/src/android/view/SoundEffectConstantsTest.java
new file mode 100644
index 0000000..45ffb122
--- /dev/null
+++ b/core/tests/coretests/src/android/view/SoundEffectConstantsTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link SoundEffectConstants}
+ *
+ * Build/Install/Run:
+ *  atest FrameworksCoreTests:SoundEffectConstantsTest
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SoundEffectConstantsTest {
+
+    @Test
+    public void testIsNavigationRepeat() {
+        assertTrue(SoundEffectConstants.isNavigationRepeat(
+                SoundEffectConstants.NAVIGATION_REPEAT_RIGHT));
+        assertTrue(SoundEffectConstants.isNavigationRepeat(
+                SoundEffectConstants.NAVIGATION_REPEAT_LEFT));
+        assertTrue(
+                SoundEffectConstants.isNavigationRepeat(SoundEffectConstants.NAVIGATION_REPEAT_UP));
+        assertTrue(SoundEffectConstants.isNavigationRepeat(
+                SoundEffectConstants.NAVIGATION_REPEAT_DOWN));
+        assertFalse(SoundEffectConstants.isNavigationRepeat(SoundEffectConstants.NAVIGATION_RIGHT));
+        assertFalse(SoundEffectConstants.isNavigationRepeat(SoundEffectConstants.NAVIGATION_LEFT));
+        assertFalse(SoundEffectConstants.isNavigationRepeat(SoundEffectConstants.NAVIGATION_UP));
+        assertFalse(SoundEffectConstants.isNavigationRepeat(SoundEffectConstants.NAVIGATION_DOWN));
+        assertFalse(SoundEffectConstants.isNavigationRepeat(-1));
+    }
+}
diff --git a/core/tests/coretests/src/android/view/SurfaceControlFpsListenerTest.java b/core/tests/coretests/src/android/view/SurfaceControlFpsListenerTest.java
new file mode 100644
index 0000000..36104cf
--- /dev/null
+++ b/core/tests/coretests/src/android/view/SurfaceControlFpsListenerTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class SurfaceControlFpsListenerTest {
+
+    @Test
+    public void registersAndUnregisters() {
+
+        SurfaceControlFpsListener listener = new SurfaceControlFpsListener() {
+            @Override
+            public void onFpsReported(float fps) {
+                // Ignore
+            }
+        };
+
+        listener.register(new SurfaceControl());
+
+        listener.unregister();
+    }
+}
diff --git a/core/tests/coretests/src/android/view/TestScrollCaptureCallback.java b/core/tests/coretests/src/android/view/TestScrollCaptureCallback.java
new file mode 100644
index 0000000..1520c6e
--- /dev/null
+++ b/core/tests/coretests/src/android/view/TestScrollCaptureCallback.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import static org.junit.Assert.*;
+
+import android.graphics.Rect;
+import android.os.CancellationSignal;
+
+import androidx.annotation.NonNull;
+
+import java.util.function.Consumer;
+
+class TestScrollCaptureCallback implements ScrollCaptureCallback {
+    private Consumer<Rect> mSearchConsumer;
+    private Runnable mStartOnReady;
+    private Consumer<Rect> mImageOnComplete;
+    private Runnable mOnEndReady;
+    private volatile int mModCount;
+
+    @Override
+    public void onScrollCaptureSearch(@NonNull CancellationSignal signal,
+            @NonNull Consumer<Rect> onReady) {
+        mSearchConsumer = onReady;
+        mModCount++;
+    }
+
+    @Override
+    public void onScrollCaptureStart(@NonNull ScrollCaptureSession session,
+            @NonNull CancellationSignal signal, @NonNull Runnable onReady) {
+        mStartOnReady = onReady;
+        mModCount++;
+    }
+
+    @Override
+    public void onScrollCaptureImageRequest(@NonNull ScrollCaptureSession session,
+            @NonNull CancellationSignal signal, @NonNull Rect captureArea,
+            @NonNull Consumer<Rect> onComplete) {
+        mImageOnComplete = onComplete;
+        mModCount++;
+    }
+
+    @Override
+    public void onScrollCaptureEnd(@NonNull Runnable onReady) {
+        mOnEndReady = onReady;
+    }
+
+    void completeSearchRequest(Rect scrollBounds) {
+        assertNotNull("Did not receive search request", mSearchConsumer);
+        mSearchConsumer.accept(scrollBounds);
+        mModCount++;
+    }
+
+    void verifyZeroInteractions() {
+        assertEquals("Expected zero interactions", 0, mModCount);
+    }
+
+    void completeStartRequest() {
+        assertNotNull("Did not receive start request", mStartOnReady);
+        mStartOnReady.run();
+    }
+
+    void completeImageRequest(Rect captured) {
+        assertNotNull("Did not receive image request", mImageOnComplete);
+        mImageOnComplete.accept(captured);
+    }
+
+    void completeEndRequest() {
+        assertNotNull("Did not receive end request", mOnEndReady);
+        mOnEndReady.run();
+    }
+}
diff --git a/core/tests/coretests/src/android/view/ViewGroupScrollCaptureTest.java b/core/tests/coretests/src/android/view/ViewGroupScrollCaptureTest.java
index 3af0533..41cd4c5 100644
--- a/core/tests/coretests/src/android/view/ViewGroupScrollCaptureTest.java
+++ b/core/tests/coretests/src/android/view/ViewGroupScrollCaptureTest.java
@@ -19,7 +19,9 @@
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.testng.AssertJUnit.assertSame;
 
@@ -27,19 +29,20 @@
 import android.content.Context;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.os.CancellationSignal;
 import android.platform.test.annotations.Presubmit;
 
+import androidx.annotation.NonNull;
 import androidx.test.filters.FlakyTest;
 import androidx.test.filters.MediumTest;
 import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
 
-import java.util.LinkedList;
-import java.util.Queue;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
 
 /**
  * Exercises Scroll Capture search in {@link ViewGroup}.
@@ -50,10 +53,7 @@
 @RunWith(MockitoJUnitRunner.class)
 public class ViewGroupScrollCaptureTest {
 
-    @Mock
-    ScrollCaptureCallback mMockCallback;
-    @Mock
-    ScrollCaptureCallback mMockCallback2;
+    private static final Executor DIRECT_EXECUTOR = Runnable::run;
 
     /** Make sure the hint flags are saved and loaded correctly. */
     @Test
@@ -103,25 +103,24 @@
     public void testDispatchScrollCaptureSearch_noCallback_hintAuto() throws Exception {
         final Context context = getInstrumentation().getContext();
         final MockViewGroup viewGroup = new MockViewGroup(context, 0, 0, 200, 200);
+        TestScrollCaptureCallback callback = new TestScrollCaptureCallback();
 
         // When system internal scroll capture is requested, this callback is returned.
-        viewGroup.setScrollCaptureCallbackInternalForTest(mMockCallback);
+        viewGroup.setScrollCaptureCallbackInternalForTest(callback);
 
         Rect localVisibleRect = new Rect(0, 0, 200, 200);
         Point windowOffset = new Point();
-        LinkedList<ScrollCaptureTarget> targetList = new LinkedList<>();
+        ScrollCaptureSearchResults results = new ScrollCaptureSearchResults(DIRECT_EXECUTOR);
 
         // Dispatch
-        viewGroup.dispatchScrollCaptureSearch(localVisibleRect, windowOffset, targetList);
-
-        // Verify the system checked for fallback support
-        viewGroup.assertDispatchScrollCaptureCount(1);
-        viewGroup.assertLastDispatchScrollCaptureArgs(localVisibleRect, windowOffset);
+        viewGroup.dispatchScrollCaptureSearch(localVisibleRect, windowOffset, results::addTarget);
+        callback.completeSearchRequest(new Rect(1, 2, 3, 4));
+        assertTrue(results.isComplete());
 
         // Verify the target is as expected.
-        assertEquals(1, targetList.size());
-        ScrollCaptureTarget target = targetList.get(0);
-        assertSame("Target has the wrong callback", mMockCallback, target.getCallback());
+        ScrollCaptureTarget target = results.getTopResult();
+        assertNotNull("Target not found", target);
+        assertSame("Target has the wrong callback", callback, target.getCallback());
         assertSame("Target has the wrong View", viewGroup, target.getContainingView());
         assertEquals("Target hint is incorrect", View.SCROLL_CAPTURE_HINT_AUTO,
                 target.getContainingView().getScrollCaptureHint());
@@ -139,18 +138,22 @@
         final MockViewGroup viewGroup =
                 new MockViewGroup(context, 0, 0, 200, 200, View.SCROLL_CAPTURE_HINT_EXCLUDE);
 
+        TestScrollCaptureCallback callback = new TestScrollCaptureCallback();
+
         // When system internal scroll capture is requested, this callback is returned.
-        viewGroup.setScrollCaptureCallbackInternalForTest(mMockCallback);
+        viewGroup.setScrollCaptureCallbackInternalForTest(callback);
 
         Rect localVisibleRect = new Rect(0, 0, 200, 200);
         Point windowOffset = new Point();
-        LinkedList<ScrollCaptureTarget> targetList = new LinkedList<>();
+        ScrollCaptureSearchResults results = new ScrollCaptureSearchResults(DIRECT_EXECUTOR);
+        assertTrue(results.isComplete());
 
         // Dispatch
-        viewGroup.dispatchScrollCaptureSearch(localVisibleRect, windowOffset, targetList);
+        viewGroup.dispatchScrollCaptureSearch(localVisibleRect, windowOffset, results::addTarget);
+        callback.verifyZeroInteractions();
 
         // Verify the results.
-        assertEquals("Target list size should be zero.", 0, targetList.size());
+        assertTrue("Results should be empty.", results.isEmpty());
     }
 
     /**
@@ -164,27 +167,34 @@
         final Context context = getInstrumentation().getContext();
         MockViewGroup viewGroup = new MockViewGroup(context, 0, 0, 200, 200);
 
+        TestScrollCaptureCallback callback = new TestScrollCaptureCallback();
+        TestScrollCaptureCallback callback2 = new TestScrollCaptureCallback();
+
         // With an already provided scroll capture callback
-        viewGroup.setScrollCaptureCallback(mMockCallback);
+        viewGroup.setScrollCaptureCallback(callback);
 
         // When system internal scroll capture is requested, this callback is returned.
-        viewGroup.setScrollCaptureCallbackInternalForTest(mMockCallback);
+        viewGroup.setScrollCaptureCallbackInternalForTest(callback2);
 
         Rect localVisibleRect = new Rect(0, 0, 200, 200);
         Point windowOffset = new Point();
-        LinkedList<ScrollCaptureTarget> targetList = new LinkedList<>();
+        ScrollCaptureSearchResults results = new ScrollCaptureSearchResults(DIRECT_EXECUTOR);
 
         // Dispatch to the ViewGroup
-        viewGroup.dispatchScrollCaptureSearch(localVisibleRect, windowOffset, targetList);
-
-        // Confirm that framework support was not requested,
-        // because this view already had a callback set.
-        viewGroup.assertCreateScrollCaptureCallbackInternalCount(0);
+        viewGroup.dispatchScrollCaptureSearch(localVisibleRect, windowOffset, results::addTarget);
+        callback.completeSearchRequest(new Rect(1, 2, 3, 4));
 
         // Verify the target is as expected.
-        assertEquals(1, targetList.size());
-        ScrollCaptureTarget target = targetList.get(0);
-        assertSame("Target has the wrong callback", mMockCallback, target.getCallback());
+        assertFalse(results.isEmpty());
+        assertTrue(results.isComplete());
+
+        // internal framework callback was not requested
+        callback2.verifyZeroInteractions();
+
+        ScrollCaptureTarget target = results.getTopResult();
+
+        assertNotNull("Target not found", target);
+        assertSame("Target has the wrong callback", callback, target.getCallback());
         assertSame("Target has the wrong View", viewGroup, target.getContainingView());
         assertEquals("Target hint is incorrect", View.SCROLL_CAPTURE_HINT_AUTO,
                 target.getContainingView().getScrollCaptureHint());
@@ -201,22 +211,22 @@
         final Context context = getInstrumentation().getContext();
         MockViewGroup viewGroup =
                 new MockViewGroup(context, 0, 0, 200, 200, View.SCROLL_CAPTURE_HINT_EXCLUDE);
+
+        TestScrollCaptureCallback callback = new TestScrollCaptureCallback();
+
         // With an already provided scroll capture callback
-        viewGroup.setScrollCaptureCallback(mMockCallback);
+        viewGroup.setScrollCaptureCallback(callback);
 
         Rect localVisibleRect = new Rect(0, 0, 200, 200);
         Point windowOffset = new Point();
-        LinkedList<ScrollCaptureTarget> targetList = new LinkedList<>();
+        ScrollCaptureSearchResults results = new ScrollCaptureSearchResults(DIRECT_EXECUTOR);
 
         // Dispatch to the ViewGroup itself
-        viewGroup.dispatchScrollCaptureSearch(localVisibleRect, windowOffset, targetList);
-
-        // Confirm that framework support was not requested, because this view is excluded.
-        // (And because this view has a callback set.)
-        viewGroup.assertCreateScrollCaptureCallbackInternalCount(0);
+        viewGroup.dispatchScrollCaptureSearch(localVisibleRect, windowOffset, results::addTarget);
+        callback.verifyZeroInteractions();
 
         // Has callback, but hint=excluded, so excluded.
-        assertTrue(targetList.isEmpty());
+        assertNull(results.getTopResult());
     }
 
     /**
@@ -252,37 +262,43 @@
         // |               |          |
         // +---------------+----------+ (200,200)
 
-        // View 1 is clipped and not visible.
+        // View 1 is fully clipped and not visible.
         final MockView view1 = new MockView(context, 0, 0, 200, 25);
         viewGroup.addView(view1);
 
-        // View 2 is partially visible.
+        // View 2 is partially visible. (75x75)
         final MockView view2 = new MockView(context, 0, 25, 150, 100);
         viewGroup.addView(view2);
 
-        // View 3 is partially visible.
+        TestScrollCaptureCallback callback1 = new TestScrollCaptureCallback();
+
+        // View 3 is partially visible (175x50)
         // Pretend View3 can scroll by having framework provide fallback support
         final MockView view3 = new MockView(context, 0, 100, 200, 200);
         // When system internal scroll capture is requested for this view, return this callback.
-        view3.setScrollCaptureCallbackInternalForTest(mMockCallback);
+        view3.setScrollCaptureCallbackInternalForTest(callback1);
         viewGroup.addView(view3);
 
         // View 4 is invisible and should be ignored.
         final MockView view4 = new MockView(context, 150, 25, 200, 100, View.INVISIBLE);
         viewGroup.addView(view4);
 
-        // View 4 is invisible and should be ignored.
+        TestScrollCaptureCallback callback2 = new TestScrollCaptureCallback();
+
+        // View 5 is partially visible and explicitly included via flag. (25x50)
         final MockView view5 = new MockView(context, 150, 100, 200, 200);
-        // When system internal scroll capture is requested for this view, return this callback.
-        view5.setScrollCaptureCallback(mMockCallback2);
+        view5.setScrollCaptureCallback(callback2);
         view5.setScrollCaptureHint(View.SCROLL_CAPTURE_HINT_INCLUDE);
         viewGroup.addView(view5);
 
         // Where targets are added
-        final LinkedList<ScrollCaptureTarget> targetList = new LinkedList<>();
+        final ScrollCaptureSearchResults results = new ScrollCaptureSearchResults(DIRECT_EXECUTOR);
 
         // Dispatch to the ViewGroup
-        viewGroup.dispatchScrollCaptureSearch(localVisibleRect, windowOffset, targetList);
+        viewGroup.dispatchScrollCaptureSearch(localVisibleRect, windowOffset, results::addTarget);
+        callback1.completeSearchRequest(new Rect(0, 0, 200, 100));
+        callback2.completeSearchRequest(new Rect(0, 0, 50, 100));
+        assertTrue(results.isComplete());
 
         // View 1 is entirely clipped by the parent and not visible, dispatch
         // skips this view entirely.
@@ -317,18 +333,14 @@
         view5.assertCreateScrollCaptureCallbackInternalCount(0);
 
         // 2 views should have been returned, view3 & view5
-        assertEquals(2, targetList.size());
+        assertFalse(results.isEmpty());
+        assertTrue(results.isComplete());
 
-        ScrollCaptureTarget target = targetList.get(0);
-        assertSame("First target has the wrong View", view3, target.getContainingView());
-        assertSame("First target has the wrong callback", mMockCallback, target.getCallback());
-        assertEquals("First target hint is incorrect", View.SCROLL_CAPTURE_HINT_AUTO,
-                target.getContainingView().getScrollCaptureHint());
-
-        target = targetList.get(1);
-        assertSame("Second target has the wrong View", view5, target.getContainingView());
-        assertSame("Second target has the wrong callback", mMockCallback2, target.getCallback());
-        assertEquals("Second target hint is incorrect", View.SCROLL_CAPTURE_HINT_INCLUDE,
+        ScrollCaptureTarget target = results.getTopResult();
+        assertNotNull("Target not found", target);
+        assertSame("Result is the wrong View", view5, target.getContainingView());
+        assertSame("Result is the wrong callback", callback2, target.getCallback());
+        assertEquals("First target hint is incorrect", View.SCROLL_CAPTURE_HINT_INCLUDE,
                 target.getContainingView().getScrollCaptureHint());
     }
 
@@ -371,7 +383,7 @@
         }
 
         void assertCreateScrollCaptureCallbackInternalCount(int count) {
-            assertEquals("Unexpected number of calls to createScrollCaptureCallackInternal",
+            assertEquals("Unexpected number of calls to createScrollCaptureCallbackInternal",
                     count, mCreateScrollCaptureCallbackInternalCount);
         }
 
@@ -385,11 +397,11 @@
 
         @Override
         public void dispatchScrollCaptureSearch(Rect localVisibleRect, Point windowOffset,
-                Queue<ScrollCaptureTarget> targets) {
+                Consumer<ScrollCaptureTarget> results) {
             mDispatchScrollCaptureSearchNumCalls++;
             mDispatchScrollCaptureSearchLastLocalVisibleRect = new Rect(localVisibleRect);
             mDispatchScrollCaptureSearchLastWindowOffset = new Point(windowOffset);
-            super.dispatchScrollCaptureSearch(localVisibleRect, windowOffset, targets);
+            super.dispatchScrollCaptureSearch(localVisibleRect, windowOffset, results);
         }
 
         @Override
@@ -401,13 +413,31 @@
         }
     }
 
+    static class CallbackStub implements ScrollCaptureCallback {
+
+        @Override
+        public void onScrollCaptureSearch(@NonNull CancellationSignal signal,
+                @NonNull Consumer<Rect> onReady) {
+        }
+
+        @Override
+        public void onScrollCaptureStart(@NonNull ScrollCaptureSession session,
+                @NonNull CancellationSignal signal, @NonNull Runnable onReady) {
+        }
+
+        @Override
+        public void onScrollCaptureImageRequest(@NonNull ScrollCaptureSession session,
+                @NonNull CancellationSignal signal, @NonNull Rect captureArea,
+                Consumer<Rect> onComplete) {
+        }
+
+        @Override
+        public void onScrollCaptureEnd(@NonNull Runnable onReady) {
+        }
+    };
+
     public static final class MockViewGroup extends ViewGroup {
         private ScrollCaptureCallback mInternalCallback;
-        private int mDispatchScrollCaptureSearchNumCalls;
-        private Rect mDispatchScrollCaptureSearchLastLocalVisibleRect;
-        private Point mDispatchScrollCaptureSearchLastWindowOffset;
-        private int mCreateScrollCaptureCallbackInternalCount;
-
 
         MockViewGroup(Context context) {
             this(context, /* left */ 0, /* top */0, /* right */ 0, /* bottom */0);
@@ -428,16 +458,10 @@
             mInternalCallback = internal;
         }
 
-        void assertDispatchScrollCaptureSearchCount(int count) {
-            assertEquals("Unexpected number of calls to dispatchScrollCaptureSearch",
-                    count, mDispatchScrollCaptureSearchNumCalls);
-        }
-
         @Override
         @Nullable
         public ScrollCaptureCallback createScrollCaptureCallbackInternal(Rect localVisibleRect,
                 Point offsetInWindow) {
-            mCreateScrollCaptureCallbackInternalCount++;
             return mInternalCallback;
         }
 
@@ -445,36 +469,5 @@
         protected void onLayout(boolean changed, int l, int t, int r, int b) {
             // We don't layout this view.
         }
-
-        void assertDispatchScrollCaptureCount(int count) {
-            assertEquals(count, mDispatchScrollCaptureSearchNumCalls);
-        }
-
-        void assertLastDispatchScrollCaptureArgs(Rect localVisibleRect, Point windowOffset) {
-            assertEquals("arg localVisibleRect to dispatchScrollCaptureCallback was incorrect.",
-                    localVisibleRect, mDispatchScrollCaptureSearchLastLocalVisibleRect);
-            assertEquals("arg windowOffset to dispatchScrollCaptureCallback was incorrect.",
-                    windowOffset, mDispatchScrollCaptureSearchLastWindowOffset);
-        }
-        void assertCreateScrollCaptureCallbackInternalCount(int count) {
-            assertEquals("Unexpected number of calls to createScrollCaptureCallackInternal",
-                    count, mCreateScrollCaptureCallbackInternalCount);
-        }
-
-        void reset() {
-            mDispatchScrollCaptureSearchNumCalls = 0;
-            mDispatchScrollCaptureSearchLastWindowOffset = null;
-            mDispatchScrollCaptureSearchLastLocalVisibleRect = null;
-            mCreateScrollCaptureCallbackInternalCount = 0;
-        }
-
-        @Override
-        public void dispatchScrollCaptureSearch(Rect localVisibleRect, Point windowOffset,
-                Queue<ScrollCaptureTarget> targets) {
-            mDispatchScrollCaptureSearchNumCalls++;
-            mDispatchScrollCaptureSearchLastLocalVisibleRect = new Rect(localVisibleRect);
-            mDispatchScrollCaptureSearchLastWindowOffset = new Point(windowOffset);
-            super.dispatchScrollCaptureSearch(localVisibleRect, windowOffset, targets);
-        }
     }
 }
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index c67174f..7746bc2 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -207,7 +207,7 @@
         final CountDownLatch latch = new CountDownLatch(1);
         mViewRootImpl.handleScrollCaptureRequest(new IScrollCaptureCallbacks.Default() {
             @Override
-            public void onUnavailable() {
+            public void onScrollCaptureResponse(ScrollCaptureResponse response) {
                 latch.countDown();
             }
         });
@@ -220,6 +220,37 @@
     }
 
     /**
+     * Ensure scroll capture request handles a ViewRootImpl with no view tree.
+     */
+    @Test
+    public void requestScrollCapture_timeout() {
+        final View view = new View(mContext);
+        view.setScrollCaptureCallback(new TestScrollCaptureCallback()); // Does nothing
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            WindowManager.LayoutParams wmlp =
+                    new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
+            // Set a fake token to bypass 'is your activity running' check
+            wmlp.token = new Binder();
+            view.setLayoutParams(wmlp);
+            mViewRootImpl.setView(view, wmlp, null);
+        });
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        mViewRootImpl.setScrollCaptureRequestTimeout(100);
+        mViewRootImpl.handleScrollCaptureRequest(new IScrollCaptureCallbacks.Default() {
+            @Override
+            public void onScrollCaptureResponse(ScrollCaptureResponse response) {
+                latch.countDown();
+            }
+        });
+        try {
+            if (!latch.await(2500, TimeUnit.MILLISECONDS)) {
+                fail("requestScrollCapture timeout did not occur");
+            }
+        } catch (InterruptedException e) { /* ignore */ }
+    }
+
+    /**
      * When window doesn't have focus, keys should be dropped.
      */
     @Test
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureContextTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureContextTest.java
index 4680a64..ddb6729 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureContextTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureContextTest.java
@@ -17,14 +17,17 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.app.assist.ActivityId;
 import android.content.ComponentName;
+import android.os.Binder;
+import android.os.IBinder;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
 /**
- * Unit test for {@link ContentCaptureEvent}.
+ * Unit test for {@link ContentCaptureContext}.
  *
  * <p>To run it:
  * {@code atest FrameworksCoreTests:android.view.contentcapture.ContentCaptureContextTest}
@@ -35,13 +38,17 @@
     @Test
     public void testConstructorAdditionalFlags() {
         final ComponentName componentName = new ComponentName("component", "name");
+        final IBinder token = new Binder();
         final ContentCaptureContext ctx = new ContentCaptureContext(/* clientContext= */ null,
-                componentName, /* taskId= */ 666, /* displayId= */ 42, /* flags= */ 1);
+                new ActivityId(/* taskId= */ 666, token), componentName, /* displayId= */
+                42, /* flags= */ 1);
         final ContentCaptureContext newCtx = new ContentCaptureContext(ctx, /* extraFlags= */ 2);
         assertThat(newCtx.getFlags()).isEqualTo(3);
-
         assertThat(newCtx.getActivityComponent()).isEqualTo(componentName);
-        assertThat(newCtx.getTaskId()).isEqualTo(666);
+        ActivityId activityId = newCtx.getActivityId();
+        assertThat(activityId).isNotNull();
+        assertThat(activityId.getTaskId()).isEqualTo(666);
+        assertThat(activityId.getToken()).isEqualTo(token);
         assertThat(newCtx.getDisplayId()).isEqualTo(42);
         assertThat(newCtx.getExtras()).isNull();
         assertThat(newCtx.getLocusId()).isNull();
diff --git a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
index 10aaf31..9cb7876 100644
--- a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
@@ -105,7 +105,8 @@
         mTracker = Mockito.spy(
                 new FrameTracker(session, handler, mRenderer, mViewRootWrapper,
                         mSurfaceControlWrapper, mChoreographer, mWrapper,
-                        /*traceThresholdMissedFrames=*/ 1, /*traceThresholdFrameTimeMillis=*/ -1));
+                        /*traceThresholdMissedFrames=*/ 1, /*traceThresholdFrameTimeMillis=*/ -1,
+                        null));
         doNothing().when(mTracker).triggerPerfetto();
     }
 
diff --git a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
index c4c475b..8f4948c 100644
--- a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
@@ -96,7 +96,7 @@
                 new ViewRootWrapper(mView.getViewRootImpl()), new SurfaceControlWrapper(),
                 mock(FrameTracker.ChoreographerWrapper.class),
                 new FrameMetricsWrapper(), /*traceThresholdMissedFrames=*/ 1,
-                /*traceThresholdFrameTimeMillis=*/ -1));
+                /*traceThresholdFrameTimeMillis=*/ -1, null));
         doReturn(tracker).when(monitor).createFrameTracker(any(), any());
 
         // Simulate a trace session and see if begin / end are invoked.
@@ -123,21 +123,12 @@
     @Test
     public void testCheckInitState() {
         InteractionJankMonitor monitor = new InteractionJankMonitor(mWorker);
+        View view = new View(mActivity);
+        assertThat(view.isAttachedToWindow()).isFalse();
 
-        // Should return false if invoking begin / end without init invocation.
-        assertThat(monitor.begin(mView, CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse();
+        // Should return false if the view passed in is not attached to window yet.
+        assertThat(monitor.begin(view, CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse();
         assertThat(monitor.end(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse();
-
-        // Everything should be fine if invoking init first.
-        boolean thrown = false;
-        try {
-            assertThat(monitor.begin(mView, CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isTrue();
-            assertThat(monitor.end(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isTrue();
-        } catch (Exception ex) {
-            thrown = true;
-        } finally {
-            assertThat(thrown).isFalse();
-        }
     }
 
     @Test
@@ -152,7 +143,7 @@
                 new ViewRootWrapper(mView.getViewRootImpl()), new SurfaceControlWrapper(),
                 mock(FrameTracker.ChoreographerWrapper.class),
                 new FrameMetricsWrapper(), /*traceThresholdMissedFrames=*/ 1,
-                /*traceThresholdFrameTimeMillis=*/ -1));
+                /*traceThresholdFrameTimeMillis=*/ -1, null));
         doReturn(tracker).when(monitor).createFrameTracker(any(), any());
 
         assertThat(monitor.begin(mView, session.getCuj())).isTrue();
diff --git a/core/tests/coretests/src/com/android/internal/os/AmbientDisplayPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/AmbientDisplayPowerCalculatorTest.java
index e2a1064..add0469 100644
--- a/core/tests/coretests/src/com/android/internal/os/AmbientDisplayPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/AmbientDisplayPowerCalculatorTest.java
@@ -19,6 +19,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.os.BatteryConsumer;
+import android.os.BatteryUsageStatsQuery;
 import android.os.SystemBatteryConsumer;
 import android.view.Display;
 
@@ -33,18 +34,29 @@
 @SmallTest
 public class AmbientDisplayPowerCalculatorTest {
     private static final double PRECISION = 0.00001;
+    private static final long MINUTE_IN_MS = 60 * 1000;
 
     @Rule
     public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
-            .setAveragePower(PowerProfile.POWER_AMBIENT_DISPLAY, 360.0);
+            .setAveragePower(PowerProfile.POWER_AMBIENT_DISPLAY, 10.0);
 
     @Test
-    public void testTimerBasedModel() {
+    public void testMeasuredEnergyBasedModel() {
         BatteryStatsImpl stats = mStatsRule.getBatteryStats();
 
-        stats.noteScreenStateLocked(Display.STATE_ON, 1000, 1000, 1000);
-        stats.noteScreenStateLocked(Display.STATE_DOZE, 2000, 2000, 2000);
-        stats.noteScreenStateLocked(Display.STATE_OFF, 3000, 3000, 3000);
+        stats.updateDisplayEnergyLocked(300_000_000, Display.STATE_ON, 0);
+
+        stats.noteScreenStateLocked(Display.STATE_DOZE, 30 * MINUTE_IN_MS, 30 * MINUTE_IN_MS,
+                30 * MINUTE_IN_MS);
+
+        stats.updateDisplayEnergyLocked(200_000_000, Display.STATE_DOZE,
+                30 * MINUTE_IN_MS);
+
+        stats.noteScreenStateLocked(Display.STATE_OFF, 120 * MINUTE_IN_MS, 120 * MINUTE_IN_MS,
+                120 * MINUTE_IN_MS);
+
+        stats.updateDisplayEnergyLocked(100_000_000, Display.STATE_OFF,
+                120 * MINUTE_IN_MS);
 
         AmbientDisplayPowerCalculator calculator =
                 new AmbientDisplayPowerCalculator(mStatsRule.getPowerProfile());
@@ -55,8 +67,32 @@
                 mStatsRule.getSystemBatteryConsumer(
                         SystemBatteryConsumer.DRAIN_TYPE_AMBIENT_DISPLAY);
         assertThat(consumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_USAGE))
-                .isEqualTo(1000);
+                .isEqualTo(90 * MINUTE_IN_MS);
         assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE))
-                .isWithin(PRECISION).of(0.1);
+                .isWithin(PRECISION).of(7.5075075);
+    }
+
+    @Test
+    public void testPowerProfileBasedModel() {
+        BatteryStatsImpl stats = mStatsRule.getBatteryStats();
+
+        stats.noteScreenStateLocked(Display.STATE_DOZE, 30 * MINUTE_IN_MS, 30 * MINUTE_IN_MS,
+                30 * MINUTE_IN_MS);
+        stats.noteScreenStateLocked(Display.STATE_OFF, 120 * MINUTE_IN_MS, 120 * MINUTE_IN_MS,
+                120 * MINUTE_IN_MS);
+
+        AmbientDisplayPowerCalculator calculator =
+                new AmbientDisplayPowerCalculator(mStatsRule.getPowerProfile());
+
+        mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(),
+                calculator);
+
+        SystemBatteryConsumer consumer =
+                mStatsRule.getSystemBatteryConsumer(
+                        SystemBatteryConsumer.DRAIN_TYPE_AMBIENT_DISPLAY);
+        assertThat(consumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_USAGE))
+                .isEqualTo(90 * MINUTE_IN_MS);
+        assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE))
+                .isWithin(PRECISION).of(15.0);
     }
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
index 9cac7e7..ff728d6 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
@@ -77,6 +77,7 @@
  * bit FrameworksCoreTests:com.android.internal.os.BatteryStatsCpuTimesTest
  */
 @SmallTest
+@SkipPresubmit("b/180015146")
 @RunWith(AndroidJUnit4.class)
 public class BatteryStatsCpuTimesTest {
     @Mock
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryIteratorTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryIteratorTest.java
new file mode 100644
index 0000000..263daf0
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryIteratorTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.BatteryManager;
+import android.os.BatteryStats;
+import android.os.Process;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BatteryStatsHistoryIteratorTest {
+    private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
+
+    @Rule
+    public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule();
+
+    @Test
+    public void testIterator() {
+        MockBatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
+        batteryStats.setRecordAllHistoryLocked(true);
+        batteryStats.forceRecordAllHistory();
+
+        mStatsRule.setTime(1000, 1000);
+        batteryStats.setNoAutoReset(true);
+
+        batteryStats.setBatteryStateLocked(BatteryManager.BATTERY_STATUS_DISCHARGING, 100,
+                /* plugType */ 0, 90, 72, 3700, 3_600_000, 4_000_000, 0, 1_000_000,
+                1_000_000, 1_000_000);
+        batteryStats.setBatteryStateLocked(BatteryManager.BATTERY_STATUS_DISCHARGING, 100,
+                /* plugType */ 0, 80, 72, 3700, 2_400_000, 4_000_000, 0, 2_000_000,
+                2_000_000, 2_000_000);
+
+        batteryStats.noteAlarmStartLocked("foo", null, APP_UID, 3_000_000, 2_000_000);
+        batteryStats.noteAlarmFinishLocked("foo", null, APP_UID, 3_001_000, 2_001_000);
+
+        final BatteryStatsHistoryIterator iterator =
+                batteryStats.createBatteryStatsHistoryIterator();
+
+        BatteryStats.HistoryItem item = new BatteryStats.HistoryItem();
+
+        assertThat(iterator.next(item)).isTrue();
+        assertHistoryItem(item,
+                BatteryStats.HistoryItem.CMD_RESET, BatteryStats.HistoryItem.EVENT_NONE,
+                null, 0, 3_600_000, 90, 1_000_000);
+
+        assertThat(iterator.next(item)).isTrue();
+        assertHistoryItem(item,
+                BatteryStats.HistoryItem.CMD_UPDATE, BatteryStats.HistoryItem.EVENT_NONE,
+                null, 0, 3_600_000, 90, 1_000_000);
+
+        assertThat(iterator.next(item)).isTrue();
+        assertHistoryItem(item,
+                BatteryStats.HistoryItem.CMD_UPDATE, BatteryStats.HistoryItem.EVENT_NONE,
+                null, 0, 2_400_000, 80, 2_000_000);
+
+        assertThat(iterator.next(item)).isTrue();
+        assertHistoryItem(item,
+                BatteryStats.HistoryItem.CMD_UPDATE, BatteryStats.HistoryItem.EVENT_NONE,
+                null, 0, 2_400_000, 80, 2_000_000);
+
+        assertThat(iterator.next(item)).isTrue();
+        assertHistoryItem(item,
+                BatteryStats.HistoryItem.CMD_UPDATE,
+                BatteryStats.HistoryItem.EVENT_ALARM | BatteryStats.HistoryItem.EVENT_FLAG_START,
+                "foo", APP_UID, 2_400_000, 80, 3_000_000);
+
+        assertThat(iterator.next(item)).isTrue();
+        assertHistoryItem(item,
+                BatteryStats.HistoryItem.CMD_UPDATE,
+                BatteryStats.HistoryItem.EVENT_ALARM | BatteryStats.HistoryItem.EVENT_FLAG_FINISH,
+                "foo", APP_UID, 2_400_000, 80, 3_001_000);
+
+        assertThat(iterator.next(item)).isFalse();
+    }
+
+    private void assertHistoryItem(BatteryStats.HistoryItem item, int command, int eventCode,
+            String tag, int uid, int batteryChargeUah, int batteryLevel,
+            long elapsedTimeMs) {
+        assertThat(item.cmd).isEqualTo(command);
+        assertThat(item.eventCode).isEqualTo(eventCode);
+        if (tag == null) {
+            assertThat(item.eventTag).isNull();
+        } else {
+            assertThat(item.eventTag.string).isEqualTo(tag);
+            assertThat(item.eventTag.uid).isEqualTo(uid);
+        }
+        assertThat(item.batteryChargeUah).isEqualTo(batteryChargeUah);
+        assertThat(item.batteryLevel).isEqualTo(batteryLevel);
+
+        assertThat(item.time).isEqualTo(elapsedTimeMs);
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
index 4b37dd2..24baa93 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
@@ -73,6 +73,7 @@
     }
 
     @Test
+    @SkipPresubmit("b/180015146")
     public void testUpdateProcStateCpuTimes() {
         mBatteryStatsImpl.setOnBatteryInternal(true);
         mBatteryStatsImpl.updateTimeBasesLocked(false, Display.STATE_ON, 0, 0);
@@ -230,6 +231,7 @@
     }
 
     @Test
+    @SkipPresubmit("b/180015146")
     public void testCopyFromAllUidsCpuTimes() {
         mBatteryStatsImpl.setOnBatteryInternal(false);
         mBatteryStatsImpl.updateTimeBasesLocked(false, Display.STATE_ON, 0, 0);
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
index 6652c64..931611e 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
@@ -295,6 +295,7 @@
     }
 
     @SmallTest
+    @SkipPresubmit("b/180015146")
     public void testAlarmStartAndFinishLocked() throws Exception {
         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
@@ -332,6 +333,7 @@
     }
 
     @SmallTest
+    @SkipPresubmit("b/180015146")
     public void testAlarmStartAndFinishLocked_workSource() throws Exception {
         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java
index 3b27f18..dd814e6 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java
@@ -56,6 +56,7 @@
     }
 
     @SmallTest
+    @SkipPresubmit("b/180015146")
     public void testEndSampleAndContinueWhenTimeOrCountDecreases() throws Exception {
         final MockClocks clocks = new MockClocks();
         final BatteryStatsImpl.TimeBase timeBase = Mockito.mock(BatteryStatsImpl.TimeBase.class);
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
index 2e6e0de..74c37ada 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
@@ -30,6 +30,7 @@
         BatteryStatsDualTimerTest.class,
         BatteryStatsDurationTimerTest.class,
         BatteryStatsHelperTest.class,
+        BatteryStatsHistoryIteratorTest.class,
         BatteryStatsHistoryTest.class,
         BatteryStatsImplTest.class,
         BatteryStatsNoteTest.class,
@@ -40,12 +41,15 @@
         BatteryStatsTimeBaseTest.class,
         BatteryStatsTimerTest.class,
         BatteryStatsUidTest.class,
+        BatteryUsageStatsProviderTest.class,
         BatteryUsageStatsTest.class,
         BatteryStatsUserLifecycleTests.class,
         BluetoothPowerCalculatorTest.class,
         BstatsCpuTimesValidationTest.class,
         CameraPowerCalculatorTest.class,
         CpuPowerCalculatorTest.class,
+        CustomMeasuredPowerCalculatorTest.class,
+        DischargedPowerCalculatorTest.class,
         FlashlightPowerCalculatorTest.class,
         GnssPowerCalculatorTest.class,
         IdlePowerCalculatorTest.class,
@@ -69,9 +73,9 @@
         UserPowerCalculatorTest.class,
         VideoPowerCalculatorTest.class,
         WakelockPowerCalculatorTest.class,
+        WifiPowerCalculatorTest.class,
 
         com.android.internal.power.MeasuredEnergyStatsTest.class
     })
 public class BatteryStatsTests {
-}
-
+}
\ No newline at end of file
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsUserLifecycleTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsUserLifecycleTests.java
index e7a1bca..e90bcb7 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsUserLifecycleTests.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsUserLifecycleTests.java
@@ -78,6 +78,7 @@
     }
 
     @Test
+    @SkipPresubmit("b/180015146")
     public void testNoCpuDataForRemovedUser() throws Exception {
         mIam.startUserInBackground(mTestUserId);
         waitUntilTrue("No uids for started user " + mTestUserId,
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java
new file mode 100644
index 0000000..0f59143
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.os.BatteryManager;
+import android.os.BatteryStats;
+import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
+import android.os.Parcel;
+import android.os.Process;
+import android.os.UidBatteryConsumer;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class BatteryUsageStatsProviderTest {
+    private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
+    private static final long MINUTE_IN_MS = 60 * 1000;
+
+    @Rule
+    public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule();
+
+    @Test
+    public void test_getBatteryUsageStats() {
+        BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
+
+        batteryStats.noteActivityResumedLocked(APP_UID,
+                10 * MINUTE_IN_MS, 10 * MINUTE_IN_MS);
+        batteryStats.noteUidProcessStateLocked(APP_UID, ActivityManager.PROCESS_STATE_TOP,
+                10 * MINUTE_IN_MS, 10 * MINUTE_IN_MS);
+        batteryStats.noteActivityPausedLocked(APP_UID,
+                30 * MINUTE_IN_MS, 30 * MINUTE_IN_MS);
+        batteryStats.noteUidProcessStateLocked(APP_UID, ActivityManager.PROCESS_STATE_SERVICE,
+                30 * MINUTE_IN_MS, 30 * MINUTE_IN_MS);
+        batteryStats.noteUidProcessStateLocked(APP_UID, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
+                40 * MINUTE_IN_MS, 40 * MINUTE_IN_MS);
+
+        Context context = InstrumentationRegistry.getContext();
+        BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(context, batteryStats);
+
+        final BatteryUsageStats batteryUsageStats =
+                provider.getBatteryUsageStats(BatteryUsageStatsQuery.DEFAULT);
+
+        final List<UidBatteryConsumer> uidBatteryConsumers =
+                batteryUsageStats.getUidBatteryConsumers();
+        final UidBatteryConsumer uidBatteryConsumer = uidBatteryConsumers.get(0);
+        assertThat(uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND))
+                .isEqualTo(20 * MINUTE_IN_MS);
+        assertThat(uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND))
+                .isEqualTo(10 * MINUTE_IN_MS);
+    }
+
+    @Test
+    public void testWriteAndReadHistory() {
+        MockBatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
+        batteryStats.setRecordAllHistoryLocked(true);
+        batteryStats.forceRecordAllHistory();
+
+        batteryStats.setNoAutoReset(true);
+
+        batteryStats.setBatteryStateLocked(BatteryManager.BATTERY_STATUS_DISCHARGING, 100,
+                /* plugType */ 0, 90, 72, 3700, 3_600_000, 4_000_000, 0, 1_000_000,
+                1_000_000, 1_000_000);
+
+        batteryStats.noteAlarmStartLocked("foo", null, APP_UID, 3_000_000, 2_000_000);
+        batteryStats.noteAlarmFinishLocked("foo", null, APP_UID, 3_001_000, 2_001_000);
+
+        Context context = InstrumentationRegistry.getContext();
+        BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(context, batteryStats);
+
+        final BatteryUsageStats batteryUsageStats =
+                provider.getBatteryUsageStats(
+                        new BatteryUsageStatsQuery.Builder().includeBatteryHistory().build());
+
+        Parcel in = Parcel.obtain();
+        batteryUsageStats.writeToParcel(in, 0);
+        final byte[] bytes = in.marshall();
+
+        Parcel out = Parcel.obtain();
+        out.unmarshall(bytes, 0, bytes.length);
+        out.setDataPosition(0);
+
+        BatteryUsageStats unparceled = BatteryUsageStats.CREATOR.createFromParcel(out);
+
+        final BatteryStatsHistoryIterator iterator =
+                unparceled.iterateBatteryStatsHistory();
+        BatteryStats.HistoryItem item = new BatteryStats.HistoryItem();
+
+        assertThat(iterator.next(item)).isTrue();
+        assertHistoryItem(item,
+                BatteryStats.HistoryItem.CMD_RESET, BatteryStats.HistoryItem.EVENT_NONE,
+                null, 0, 3_600_000, 90, 1_000_000);
+
+        assertThat(iterator.next(item)).isTrue();
+        assertHistoryItem(item,
+                BatteryStats.HistoryItem.CMD_UPDATE, BatteryStats.HistoryItem.EVENT_NONE,
+                null, 0, 3_600_000, 90, 1_000_000);
+
+        assertThat(iterator.next(item)).isTrue();
+        assertHistoryItem(item,
+                BatteryStats.HistoryItem.CMD_UPDATE, BatteryStats.HistoryItem.EVENT_NONE,
+                null, 0, 3_600_000, 90, 2_000_000);
+
+        assertThat(iterator.next(item)).isTrue();
+        assertHistoryItem(item,
+                BatteryStats.HistoryItem.CMD_UPDATE,
+                BatteryStats.HistoryItem.EVENT_ALARM | BatteryStats.HistoryItem.EVENT_FLAG_START,
+                "foo", APP_UID, 3_600_000, 90, 3_000_000);
+
+        assertThat(iterator.next(item)).isTrue();
+        assertHistoryItem(item,
+                BatteryStats.HistoryItem.CMD_UPDATE,
+                BatteryStats.HistoryItem.EVENT_ALARM | BatteryStats.HistoryItem.EVENT_FLAG_FINISH,
+                "foo", APP_UID, 3_600_000, 90, 3_001_000);
+
+        assertThat(iterator.next(item)).isFalse();
+    }
+
+    private void assertHistoryItem(BatteryStats.HistoryItem item, int command, int eventCode,
+            String tag, int uid, int batteryChargeUah, int batteryLevel, long elapsedTimeMs) {
+        assertThat(item.cmd).isEqualTo(command);
+        assertThat(item.eventCode).isEqualTo(eventCode);
+        if (tag == null) {
+            assertThat(item.eventTag).isNull();
+        } else {
+            assertThat(item.eventTag.string).isEqualTo(tag);
+            assertThat(item.eventTag.uid).isEqualTo(uid);
+        }
+        assertThat(item.batteryChargeUah).isEqualTo(batteryChargeUah);
+        assertThat(item.batteryLevel).isEqualTo(batteryLevel);
+
+        assertThat(item.time).isEqualTo(elapsedTimeMs);
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java
index 5edd58f..1679942 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java
@@ -136,17 +136,23 @@
         return mBatteryStats.getUidStatsLocked(uid);
     }
 
-    public void setTime(long realtimeUs, long uptimeUs) {
-        mMockClocks.realtime = realtimeUs;
-        mMockClocks.uptime = uptimeUs;
+    public void setTime(long realtimeMs, long uptimeMs) {
+        mMockClocks.realtime = realtimeMs;
+        mMockClocks.uptime = uptimeMs;
     }
 
-    void apply(PowerCalculator... calculators) {
-        apply(BatteryUsageStatsQuery.DEFAULT, calculators);
+    BatteryUsageStats apply(PowerCalculator... calculators) {
+        return apply(BatteryUsageStatsQuery.DEFAULT, calculators);
     }
 
-    void apply(BatteryUsageStatsQuery query, PowerCalculator... calculators) {
-        BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(0, 0);
+    BatteryUsageStats apply(BatteryUsageStatsQuery query, PowerCalculator... calculators) {
+        final long[] customMeasuredEnergiesMicroJoules =
+                mBatteryStats.getCustomMeasuredEnergiesMicroJoules();
+        final int customMeasuredEnergiesCount = customMeasuredEnergiesMicroJoules != null
+                ? customMeasuredEnergiesMicroJoules.length
+                : 0;
+        BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(
+                customMeasuredEnergiesCount, 0);
         SparseArray<? extends BatteryStats.Uid> uidStats = mBatteryStats.getUidStats();
         for (int i = 0; i < uidStats.size(); i++) {
             builder.getOrCreateUidBatteryConsumerBuilder(uidStats.valueAt(i));
@@ -158,6 +164,7 @@
         }
 
         mBatteryUsageStats = builder.build();
+        return mBatteryUsageStats;
     }
 
     public UidBatteryConsumer getUidBatteryConsumer(int uid) {
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
index 018a810..23ea508 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
@@ -35,6 +35,7 @@
 import java.util.List;
 
 @SmallTest
+@SkipPresubmit("b/180015146")
 @RunWith(AndroidJUnit4.class)
 public class BatteryUsageStatsTest {
 
@@ -66,33 +67,36 @@
         final MockBatteryStatsImpl batteryStats = new MockBatteryStatsImpl(clocks);
         final BatteryStatsImpl.Uid batteryStatsUid = batteryStats.getUidStatsLocked(2000);
 
-        final BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(1, 1);
-        builder.setConsumedPower(100);
-        builder.setDischargePercentage(20);
+        final BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(1, 1)
+                .setDischargePercentage(20)
+                .setDischargedPowerRange(1000, 2000);
 
-        final UidBatteryConsumer.Builder uidBatteryConsumerBuilder =
-                builder.getOrCreateUidBatteryConsumerBuilder(batteryStatsUid);
-        uidBatteryConsumerBuilder.setPackageWithHighestDrain("foo");
-        uidBatteryConsumerBuilder.setConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE, 300);
-        uidBatteryConsumerBuilder.setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, 400);
-        uidBatteryConsumerBuilder.setConsumedPowerForCustomComponent(
-                BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 500);
-        uidBatteryConsumerBuilder.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU, 600);
-        uidBatteryConsumerBuilder.setUsageDurationMillis(
-                BatteryConsumer.TIME_COMPONENT_CPU_FOREGROUND, 700);
-        uidBatteryConsumerBuilder.setUsageDurationForCustomComponentMillis(
-                BatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID, 800);
+        builder.getOrCreateUidBatteryConsumerBuilder(batteryStatsUid)
+                .setPackageWithHighestDrain("foo")
+                .setTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND, 1000)
+                .setTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND, 2000)
+                .setConsumedPower(
+                        BatteryConsumer.POWER_COMPONENT_USAGE, 300)
+                .setConsumedPower(
+                        BatteryConsumer.POWER_COMPONENT_CPU, 400)
+                .setConsumedPowerForCustomComponent(
+                        BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 500)
+                .setUsageDurationMillis(
+                        BatteryConsumer.TIME_COMPONENT_CPU, 600)
+                .setUsageDurationMillis(
+                        BatteryConsumer.TIME_COMPONENT_CPU_FOREGROUND, 700)
+                .setUsageDurationForCustomComponentMillis(
+                        BatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID, 800);
 
-        final SystemBatteryConsumer.Builder systemBatteryConsumerBuilder =
-                builder.getOrCreateSystemBatteryConsumerBuilder(
-                        SystemBatteryConsumer.DRAIN_TYPE_CAMERA);
-        systemBatteryConsumerBuilder.setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, 10100);
-        systemBatteryConsumerBuilder.setConsumedPowerForCustomComponent(
-                BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 10200);
-        systemBatteryConsumerBuilder.setUsageDurationMillis(
-                BatteryConsumer.TIME_COMPONENT_CPU, 10300);
-        systemBatteryConsumerBuilder.setUsageDurationForCustomComponentMillis(
-                BatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID, 10400);
+        builder.getOrCreateSystemBatteryConsumerBuilder(SystemBatteryConsumer.DRAIN_TYPE_CAMERA)
+                .setConsumedPower(
+                        BatteryConsumer.POWER_COMPONENT_CPU, 10100)
+                .setConsumedPowerForCustomComponent(
+                        BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 10200)
+                .setUsageDurationMillis(
+                        BatteryConsumer.TIME_COMPONENT_CPU, 10300)
+                .setUsageDurationForCustomComponentMillis(
+                        BatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID, 10400);
 
         return builder.build();
     }
@@ -100,12 +104,18 @@
     public void validateBatteryUsageStats(BatteryUsageStats batteryUsageStats) {
         assertThat(batteryUsageStats.getConsumedPower()).isEqualTo(100);
         assertThat(batteryUsageStats.getDischargePercentage()).isEqualTo(20);
+        assertThat(batteryUsageStats.getDischargedPowerRange().getLower()).isEqualTo(1000);
+        assertThat(batteryUsageStats.getDischargedPowerRange().getUpper()).isEqualTo(2000);
 
         final List<UidBatteryConsumer> uidBatteryConsumers =
                 batteryUsageStats.getUidBatteryConsumers();
         for (UidBatteryConsumer uidBatteryConsumer : uidBatteryConsumers) {
             if (uidBatteryConsumer.getUid() == 2000) {
                 assertThat(uidBatteryConsumer.getPackageWithHighestDrain()).isEqualTo("foo");
+                assertThat(uidBatteryConsumer.getTimeInStateMs(
+                        UidBatteryConsumer.STATE_FOREGROUND)).isEqualTo(1000);
+                assertThat(uidBatteryConsumer.getTimeInStateMs(
+                        UidBatteryConsumer.STATE_BACKGROUND)).isEqualTo(2000);
                 assertThat(uidBatteryConsumer.getConsumedPower(
                         BatteryConsumer.POWER_COMPONENT_USAGE)).isEqualTo(300);
                 assertThat(uidBatteryConsumer.getConsumedPower(
diff --git a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
index e559471..f6aa08b 100644
--- a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
@@ -43,6 +43,7 @@
             .setAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_TX, 100.0);
 
     @Test
+    @SkipPresubmit("b/180015146")
     public void testTimerBasedModel() {
         setDurationsAndPower(mStatsRule.getUidStats(Process.BLUETOOTH_UID)
                         .getOrCreateBluetoothControllerActivityLocked(),
@@ -73,6 +74,7 @@
     }
 
     @Test
+    @SkipPresubmit("b/180015146")
     public void testReportedPowerBasedModel() {
         setDurationsAndPower(mStatsRule.getUidStats(Process.BLUETOOTH_UID)
                         .getOrCreateBluetoothControllerActivityLocked(),
diff --git a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
index a80f5a0..4fe7d70 100644
--- a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
@@ -382,6 +382,7 @@
     }
 
     @Test
+    @SkipPresubmit("b/180015146 flakey")
     public void testCpuFreqTimes_stateFgService() throws Exception {
         if (!sCpuFreqTimesAvailable || !sPerProcStateTimesAvailable) {
             Log.w(TAG, "Skipping " + testName.getMethodName()
@@ -514,6 +515,7 @@
     }
 
     @Test
+    @SkipPresubmit("b/180015146")
     public void testCpuFreqTimes_trackingDisabled() throws Exception {
         if (!sCpuFreqTimesAvailable || !sPerProcStateTimesAvailable) {
             Log.w(TAG, "Skipping " + testName.getMethodName()
diff --git a/core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java
index 9cf0d37..e691beb 100644
--- a/core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java
@@ -92,6 +92,7 @@
     }
 
     @Test
+    @SkipPresubmit("b/180015146")
     public void testTimerBasedModel() {
         when(mMockUserInfoProvider.exists(anyInt())).thenReturn(true);
 
diff --git a/core/tests/coretests/src/com/android/internal/os/CustomMeasuredPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/CustomMeasuredPowerCalculatorTest.java
new file mode 100644
index 0000000..f298f59
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/CustomMeasuredPowerCalculatorTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.BatteryConsumer;
+import android.os.Process;
+import android.os.SystemBatteryConsumer;
+import android.os.UidBatteryConsumer;
+import android.util.SparseLongArray;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class CustomMeasuredPowerCalculatorTest {
+    private static final double PRECISION = 0.00001;
+
+    private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
+
+    @Rule
+    public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule();
+
+    @Test
+    @SkipPresubmit("b/180015146")
+    public void testMeasuredEnergyCopiedIntoBatteryConsumers() {
+        final BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
+        SparseLongArray uidEnergies = new SparseLongArray();
+        uidEnergies.put(APP_UID, 30_000_000);
+        batteryStats.updateCustomMeasuredEnergyDataLocked(0, 100_000_000, uidEnergies);
+
+        uidEnergies.put(APP_UID, 120_000_000);
+        batteryStats.updateCustomMeasuredEnergyDataLocked(1, 200_000_000, uidEnergies);
+
+        CustomMeasuredPowerCalculator calculator =
+                new CustomMeasuredPowerCalculator(mStatsRule.getPowerProfile());
+
+        mStatsRule.apply(calculator);
+
+        UidBatteryConsumer uid = mStatsRule.getUidBatteryConsumer(APP_UID);
+        assertThat(uid.getConsumedPowerForCustomComponent(
+                BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID))
+                .isWithin(PRECISION).of(2.252252);
+        assertThat(uid.getConsumedPowerForCustomComponent(
+                BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + 1))
+                .isWithin(PRECISION).of(9.009009);
+
+        SystemBatteryConsumer systemConsumer = mStatsRule.getSystemBatteryConsumer(
+                SystemBatteryConsumer.DRAIN_TYPE_CUSTOM);
+        assertThat(systemConsumer.getConsumedPowerForCustomComponent(
+                BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID))
+                .isWithin(PRECISION).of(7.5075075);
+        assertThat(systemConsumer.getConsumedPowerForCustomComponent(
+                BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + 1))
+                .isWithin(PRECISION).of(15.015015);
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/DischargedPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/DischargedPowerCalculatorTest.java
new file mode 100644
index 0000000..bec3d16
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/DischargedPowerCalculatorTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.BatteryManager;
+import android.os.BatteryUsageStats;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class DischargedPowerCalculatorTest {
+    private static final double PRECISION = 0.00001;
+
+    @Rule
+    public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
+            .setAveragePower(PowerProfile.POWER_BATTERY_CAPACITY, 4000.0);
+
+    @Test
+    public void testDischargeTotals() {
+        final BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
+
+        mStatsRule.setTime(1000, 1000);
+        batteryStats.resetAllStatsCmdLocked();
+        batteryStats.setNoAutoReset(true);
+        batteryStats.setBatteryStateLocked(BatteryManager.BATTERY_STATUS_DISCHARGING, 100,
+                /* plugType */ 0, 90, 72, 3700, 3_600_000, 4_000_000, 0, 1_000_000,
+                1_000_000, 1_000_000);
+        batteryStats.setBatteryStateLocked(BatteryManager.BATTERY_STATUS_DISCHARGING, 100,
+                /* plugType */ 0, 80, 72, 3700, 2_400_000, 4_000_000, 0, 2_000_000,
+                2_000_000, 2_000_000);
+
+        DischargedPowerCalculator calculator =
+                new DischargedPowerCalculator(mStatsRule.getPowerProfile());
+
+        final BatteryUsageStats batteryUsageStats = mStatsRule.apply(calculator);
+
+        assertThat(batteryUsageStats.getDischargePercentage()).isEqualTo(10);
+        assertThat(batteryUsageStats.getDischargedPowerRange().getLower())
+                .isWithin(PRECISION).of(360.0);
+        assertThat(batteryUsageStats.getDischargedPowerRange().getUpper())
+                .isWithin(PRECISION).of(400.0);
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidUserSysTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidUserSysTimeReaderTest.java
index 7dca0cb..177f348 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidUserSysTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidUserSysTimeReaderTest.java
@@ -87,6 +87,7 @@
     }
 
     @Test
+    @SkipPresubmit("b/180015146")
     public void testThrottler() throws Exception {
         mReader = new KernelCpuUidUserSysTimeReader(
                 new KernelCpuProcStringReader(mTestFile.getAbsolutePath()), true);
diff --git a/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java
index 717fac0..86e615c 100644
--- a/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java
@@ -48,7 +48,7 @@
             .setAveragePower(PowerProfile.POWER_SCREEN_FULL, 48.0);
 
     @Test
-    public void testEnergyBasedModel() {
+    public void testMeasuredEnergyBasedModel() {
         BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
 
         batteryStats.noteScreenStateLocked(Display.STATE_ON, 0, 0, 0);
diff --git a/core/tests/coretests/src/com/android/internal/os/SkipPresubmit.java b/core/tests/coretests/src/com/android/internal/os/SkipPresubmit.java
new file mode 100644
index 0000000..d03ed66
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/SkipPresubmit.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/** Annotation to skip a test from TEST_MAPPING presubmit. */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface SkipPresubmit {
+    /** The optional reason why the test is ignored. */
+    String value() default "";
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java
index dfbf28b..b5282e9 100644
--- a/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java
@@ -78,6 +78,7 @@
     }
 
     @Test
+    @SkipPresubmit("b/180015146")
     public void testPowerProfileBasedModel() {
         when(mMockUserInfoProvider.exists(anyInt())).thenReturn(true);
 
diff --git a/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java
new file mode 100644
index 0000000..e100545
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.net.NetworkCapabilities;
+import android.net.NetworkStats;
+import android.os.BatteryConsumer;
+import android.os.Process;
+import android.os.SystemBatteryConsumer;
+import android.os.UidBatteryConsumer;
+import android.os.WorkSource;
+import android.os.connectivity.WifiActivityEnergyInfo;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class WifiPowerCalculatorTest {
+    private static final double PRECISION = 0.00001;
+
+    private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
+
+    @Rule
+    public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
+            .setAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_IDLE, 360.0)
+            .setAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_RX, 480.0)
+            .setAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_TX, 720.0)
+            .setAveragePower(PowerProfile.POWER_WIFI_ON, 360.0)
+            .setAveragePower(PowerProfile.POWER_WIFI_SCAN, 480.0)
+            .setAveragePower(PowerProfile.POWER_WIFI_BATCHED_SCAN, 720.0)
+            .setAveragePower(PowerProfile.POWER_WIFI_ACTIVE, 1080.0);
+
+    @Test
+    public void testPowerControllerBasedModel() {
+        BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
+
+        batteryStats.noteNetworkInterfaceForTransports("wifi",
+                new int[]{NetworkCapabilities.TRANSPORT_WIFI});
+
+        NetworkStats networkStats = new NetworkStats(10000, 1)
+                .insertEntry("wifi", APP_UID, 0, 0, 1000, 100, 2000, 20, 100)
+                .insertEntry("wifi", Process.WIFI_UID, 0, 0, 1111, 111, 2222, 22, 111);
+        mStatsRule.setNetworkStats(networkStats);
+
+        WifiActivityEnergyInfo energyInfo = new WifiActivityEnergyInfo(10000,
+                WifiActivityEnergyInfo.STACK_STATE_STATE_ACTIVE, 1000, 2000, 3000, 4000);
+
+        batteryStats.updateWifiState(energyInfo, 1000, 1000);
+
+        WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
+        mStatsRule.apply(calculator);
+
+        UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
+        assertThat(uidConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
+                .isEqualTo(1423);
+        assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
+                .isWithin(PRECISION).of(0.2214666);
+
+        SystemBatteryConsumer systemConsumer =
+                mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_WIFI);
+        assertThat(systemConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
+                .isEqualTo(5577);
+        assertThat(systemConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
+                .isWithin(PRECISION).of(0.645200);
+    }
+
+    @Test
+    public void testTimerBasedModel() {
+        BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
+
+        batteryStats.noteNetworkInterfaceForTransports("wifi",
+                new int[]{NetworkCapabilities.TRANSPORT_WIFI});
+
+        NetworkStats networkStats = new NetworkStats(10000, 1)
+                .insertEntry("wifi", APP_UID, 0, 0, 1000, 100, 2000, 20, 100)
+                .insertEntry("wifi", Process.WIFI_UID, 0, 0, 1111, 111, 2222, 22, 111);
+        mStatsRule.setNetworkStats(networkStats);
+
+        batteryStats.noteWifiScanStartedLocked(APP_UID, 1000, 1000);
+        batteryStats.noteWifiScanStoppedLocked(APP_UID, 2000, 2000);
+        batteryStats.noteWifiRunningLocked(new WorkSource(APP_UID), 3000, 3000);
+        batteryStats.noteWifiStoppedLocked(new WorkSource(APP_UID), 4000, 4000);
+        batteryStats.noteWifiRunningLocked(new WorkSource(Process.WIFI_UID), 1111, 2222);
+        batteryStats.noteWifiStoppedLocked(new WorkSource(Process.WIFI_UID), 3333, 4444);
+
+        // Don't pass WifiActivityEnergyInfo, making WifiPowerCalculator rely exclusively
+        // on the packet counts.
+        batteryStats.updateWifiState(/* energyInfo */ null, 1000, 1000);
+
+        WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
+        mStatsRule.apply(calculator);
+
+        UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
+        assertThat(uidConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
+                .isEqualTo(1000);
+        assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
+                .isWithin(PRECISION).of(0.8231573);
+
+        SystemBatteryConsumer systemConsumer =
+                mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_WIFI);
+        assertThat(systemConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
+                .isEqualTo(2222);
+        assertThat(systemConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
+                .isWithin(PRECISION).of(0.8759216);
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java b/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java
index 5fd5a78..d217bce 100644
--- a/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java
@@ -81,11 +81,11 @@
 
         final MeasuredEnergyStats stats
                 = new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
-        stats.updateCustomBucket(0, 50, true);
-        stats.updateCustomBucket(1, 60, true);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40);
+        stats.updateCustomBucket(0, 50);
+        stats.updateCustomBucket(1, 60);
 
         final MeasuredEnergyStats newStats = MeasuredEnergyStats.createFromTemplate(stats);
 
@@ -114,11 +114,11 @@
 
         final MeasuredEnergyStats stats
                 = new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
-        stats.updateCustomBucket(0, 50, true);
-        stats.updateCustomBucket(1, 60, true);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40);
+        stats.updateCustomBucket(0, 50);
+        stats.updateCustomBucket(1, 60);
 
         final Parcel parcel = Parcel.obtain();
         stats.writeToParcel(parcel);
@@ -149,11 +149,11 @@
 
         final MeasuredEnergyStats stats
                 = new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
-        stats.updateCustomBucket(0, 50, true);
-        stats.updateCustomBucket(1, 60, true);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40);
+        stats.updateCustomBucket(0, 50);
+        stats.updateCustomBucket(1, 60);
 
         final Parcel parcel = Parcel.obtain();
         MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false);
@@ -185,17 +185,17 @@
 
         final MeasuredEnergyStats template
                 = new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
-        template.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
-        template.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
-        template.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
-        template.updateCustomBucket(0, 50, true);
+        template.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10);
+        template.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5);
+        template.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40);
+        template.updateCustomBucket(0, 50);
 
         final MeasuredEnergyStats stats = MeasuredEnergyStats.createFromTemplate(template);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 200, true);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 7, true);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 63, true);
-        stats.updateCustomBucket(0, 315, true);
-        stats.updateCustomBucket(1, 316, true);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 200);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 7);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 63);
+        stats.updateCustomBucket(0, 315);
+        stats.updateCustomBucket(1, 316);
 
         final Parcel parcel = Parcel.obtain();
         MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false);
@@ -243,8 +243,8 @@
         final MeasuredEnergyStats stats
                 = new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
         // Accumulate energy in one bucket and one custom bucket, the rest should be zero
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 200, true);
-        stats.updateCustomBucket(1, 60, true);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 200);
+        stats.updateCustomBucket(1, 60);
 
         // Let's try parcelling with including zeros
         final Parcel includeZerosParcel = Parcel.obtain();
@@ -305,11 +305,11 @@
 
         final MeasuredEnergyStats stats
                 = new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
-        stats.updateCustomBucket(0, 50, true);
-        stats.updateCustomBucket(1, 60, true);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40);
+        stats.updateCustomBucket(0, 50);
+        stats.updateCustomBucket(1, 60);
 
         final Parcel parcel = Parcel.obtain();
         MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false);
@@ -331,14 +331,14 @@
 
         final MeasuredEnergyStats template
                 = new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
-        template.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
-        template.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
-        template.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
-        template.updateCustomBucket(0, 50, true);
+        template.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10);
+        template.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5);
+        template.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40);
+        template.updateCustomBucket(0, 50);
 
         final MeasuredEnergyStats stats = MeasuredEnergyStats.createFromTemplate(template);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 0L, true);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 7L, true);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 0L);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 7L);
 
         final Parcel parcel = Parcel.obtain();
         MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false);
@@ -369,14 +369,14 @@
 
         final MeasuredEnergyStats stats
                 = new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_DOZE, 30, true);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_DOZE, 30);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5);
 
-        stats.updateCustomBucket(0, 50, true);
-        stats.updateCustomBucket(1, 60, true);
-        stats.updateCustomBucket(0, 3, true);
+        stats.updateCustomBucket(0, 50);
+        stats.updateCustomBucket(1, 60);
+        stats.updateCustomBucket(0, 3);
 
         assertEquals(15, stats.getAccumulatedStandardBucketEnergy(ENERGY_BUCKET_SCREEN_ON));
         assertEquals(ENERGY_DATA_UNAVAILABLE,
@@ -409,10 +409,10 @@
         final MeasuredEnergyStats stats
                 = new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_ENERGY_BUCKETS], 3);
 
-        stats.updateCustomBucket(0, 50, true);
-        stats.updateCustomBucket(1, 60, true);
-        stats.updateCustomBucket(2, 13, true);
-        stats.updateCustomBucket(1, 70, true);
+        stats.updateCustomBucket(0, 50);
+        stats.updateCustomBucket(1, 60);
+        stats.updateCustomBucket(2, 13);
+        stats.updateCustomBucket(1, 70);
 
         final long[] output = stats.getAccumulatedCustomBucketEnergies();
         assertEquals(3, output.length);
@@ -449,11 +449,11 @@
 
         final MeasuredEnergyStats stats
                 = new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
-        stats.updateCustomBucket(0, 50, true);
-        stats.updateCustomBucket(1, 60, true);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40);
+        stats.updateCustomBucket(0, 50);
+        stats.updateCustomBucket(1, 60);
 
         MeasuredEnergyStats.resetIfNotNull(stats);
         // All energy should be reset to 0
@@ -471,10 +471,10 @@
         }
 
         // Values should increase as usual.
-        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 70, true);
+        stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 70);
         assertEquals(70L, stats.getAccumulatedStandardBucketEnergy(ENERGY_BUCKET_SCREEN_ON));
 
-        stats.updateCustomBucket(1, 12, true);
+        stats.updateCustomBucket(1, 12);
         assertEquals(12L, stats.getAccumulatedCustomBucketEnergy(1));
     }
 
diff --git a/core/tests/devicestatetests/Android.bp b/core/tests/devicestatetests/Android.bp
index 409b77b..7748de5 100644
--- a/core/tests/devicestatetests/Android.bp
+++ b/core/tests/devicestatetests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworksCoreDeviceStateManagerTests",
     // Include all test java files
@@ -19,6 +28,7 @@
     static_libs: [
         "androidx.test.rules",
         "frameworks-base-testutils",
+        "mockito-target-minus-junit4",
     ],
     libs: ["android.test.runner"],
     platform_apis: true,
diff --git a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateInfoTest.java b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateInfoTest.java
new file mode 100644
index 0000000..dcef0a7
--- /dev/null
+++ b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateInfoTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.devicestate;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Unit tests for {@link DeviceStateInfo}.
+ * <p/>
+ * Run with <code>atest DeviceStateInfoTest</code>.
+ */
+@RunWith(JUnit4.class)
+@SmallTest
+public final class DeviceStateInfoTest {
+    @Test
+    public void create() {
+        final int[] supportedStates = new int[] { 0, 1, 2 };
+        final int baseState = 0;
+        final int currentState = 2;
+
+        final DeviceStateInfo info = new DeviceStateInfo(supportedStates, baseState, currentState);
+        assertNotNull(info.supportedStates);
+        assertEquals(supportedStates, info.supportedStates);
+        assertEquals(baseState, info.baseState);
+        assertEquals(currentState, info.currentState);
+    }
+
+    @Test
+    public void equals() {
+        final int[] supportedStates = new int[] { 0, 1, 2 };
+        final int baseState = 0;
+        final int currentState = 2;
+
+        final DeviceStateInfo info = new DeviceStateInfo(supportedStates, baseState, currentState);
+        assertTrue(info.equals(info));
+
+        final DeviceStateInfo sameInfo = new DeviceStateInfo(supportedStates, baseState,
+                currentState);
+        assertTrue(info.equals(sameInfo));
+
+        final DeviceStateInfo differentInfo = new DeviceStateInfo(new int[]{ 0, 2}, baseState,
+                currentState);
+        assertFalse(info.equals(differentInfo));
+    }
+
+    @Test
+    public void diff_sameObject() {
+        final int[] supportedStates = new int[] { 0, 1, 2 };
+        final int baseState = 0;
+        final int currentState = 2;
+
+        final DeviceStateInfo info = new DeviceStateInfo(supportedStates, baseState, currentState);
+        assertEquals(0, info.diff(info));
+    }
+
+    @Test
+    public void diff_differentSupportedStates() {
+        final DeviceStateInfo info = new DeviceStateInfo(new int[] { 1 }, 0, 0);
+        final DeviceStateInfo otherInfo = new DeviceStateInfo(new int[] { 2 }, 0, 0);
+        final int diff = info.diff(otherInfo);
+        assertTrue((diff & DeviceStateInfo.CHANGED_SUPPORTED_STATES) > 0);
+        assertFalse((diff & DeviceStateInfo.CHANGED_BASE_STATE) > 0);
+        assertFalse((diff & DeviceStateInfo.CHANGED_CURRENT_STATE) > 0);
+    }
+
+    @Test
+    public void diff_differentNonOverrideState() {
+        final DeviceStateInfo info = new DeviceStateInfo(new int[] { 1 }, 1, 0);
+        final DeviceStateInfo otherInfo = new DeviceStateInfo(new int[] { 1 }, 2, 0);
+        final int diff = info.diff(otherInfo);
+        assertFalse((diff & DeviceStateInfo.CHANGED_SUPPORTED_STATES) > 0);
+        assertTrue((diff & DeviceStateInfo.CHANGED_BASE_STATE) > 0);
+        assertFalse((diff & DeviceStateInfo.CHANGED_CURRENT_STATE) > 0);
+    }
+
+    @Test
+    public void diff_differentState() {
+        final DeviceStateInfo info = new DeviceStateInfo(new int[] { 1 }, 0, 1);
+        final DeviceStateInfo otherInfo = new DeviceStateInfo(new int[] { 1 }, 0, 2);
+        final int diff = info.diff(otherInfo);
+        assertFalse((diff & DeviceStateInfo.CHANGED_SUPPORTED_STATES) > 0);
+        assertFalse((diff & DeviceStateInfo.CHANGED_BASE_STATE) > 0);
+        assertTrue((diff & DeviceStateInfo.CHANGED_CURRENT_STATE) > 0);
+    }
+
+    @Test
+    public void writeToParcel() {
+        final int[] supportedStates = new int[] { 0, 1, 2 };
+        final int nonOverrideState = 0;
+        final int state = 2;
+        final DeviceStateInfo originalInfo =
+                new DeviceStateInfo(supportedStates, nonOverrideState, state);
+
+        final Parcel parcel = Parcel.obtain();
+        originalInfo.writeToParcel(parcel, 0 /* flags */);
+        parcel.setDataPosition(0);
+
+        final DeviceStateInfo info = DeviceStateInfo.CREATOR.createFromParcel(parcel);
+        assertEquals(originalInfo, info);
+    }
+}
diff --git a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java
index e7fdfb8..79b4d8b 100644
--- a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java
+++ b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java
@@ -16,11 +16,15 @@
 
 package android.hardware.devicestate;
 
-import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
 
-import android.annotation.Nullable;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import android.hardware.devicestate.DeviceStateManager.DeviceStateCallback;
 import android.os.IBinder;
 import android.os.RemoteException;
 
@@ -32,6 +36,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.Mockito;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -58,42 +63,75 @@
     }
 
     @Test
-    public void registerListener() {
-        mService.setBaseState(DEFAULT_DEVICE_STATE);
+    public void registerCallback() {
+        DeviceStateCallback callback1 = mock(DeviceStateCallback.class);
+        DeviceStateCallback callback2 = mock(DeviceStateCallback.class);
 
-        TestDeviceStateListener listener1 = new TestDeviceStateListener();
-        TestDeviceStateListener listener2 = new TestDeviceStateListener();
-
-        mDeviceStateManagerGlobal.registerDeviceStateListener(listener1,
+        mDeviceStateManagerGlobal.registerDeviceStateCallback(callback1,
                 ConcurrentUtils.DIRECT_EXECUTOR);
-        mDeviceStateManagerGlobal.registerDeviceStateListener(listener2,
+        mDeviceStateManagerGlobal.registerDeviceStateCallback(callback2,
                 ConcurrentUtils.DIRECT_EXECUTOR);
-        assertEquals(DEFAULT_DEVICE_STATE, listener1.getLastReportedState().intValue());
-        assertEquals(DEFAULT_DEVICE_STATE, listener2.getLastReportedState().intValue());
 
+        // Verify initial callbacks
+        verify(callback1).onSupportedStatesChanged(eq(mService.getSupportedStates()));
+        verify(callback1).onBaseStateChanged(eq(mService.getBaseState()));
+        verify(callback1).onStateChanged(eq(mService.getMergedState()));
+        verify(callback2).onSupportedStatesChanged(eq(mService.getSupportedStates()));
+        verify(callback2).onBaseStateChanged(eq(mService.getBaseState()));
+        verify(callback2).onStateChanged(eq(mService.getMergedState()));
+
+        Mockito.reset(callback1);
+        Mockito.reset(callback2);
+
+        // Change the supported states and verify callback
+        mService.setSupportedStates(new int[]{ DEFAULT_DEVICE_STATE });
+        verify(callback1).onSupportedStatesChanged(eq(mService.getSupportedStates()));
+        verify(callback2).onSupportedStatesChanged(eq(mService.getSupportedStates()));
+        mService.setSupportedStates(new int[]{ DEFAULT_DEVICE_STATE, OTHER_DEVICE_STATE });
+
+        Mockito.reset(callback1);
+        Mockito.reset(callback2);
+
+        // Change the base state and verify callback
         mService.setBaseState(OTHER_DEVICE_STATE);
-        assertEquals(OTHER_DEVICE_STATE, listener1.getLastReportedState().intValue());
-        assertEquals(OTHER_DEVICE_STATE, listener2.getLastReportedState().intValue());
+        verify(callback1).onBaseStateChanged(eq(mService.getBaseState()));
+        verify(callback1).onStateChanged(eq(mService.getMergedState()));
+        verify(callback2).onBaseStateChanged(eq(mService.getBaseState()));
+        verify(callback2).onStateChanged(eq(mService.getMergedState()));
+
+        Mockito.reset(callback1);
+        Mockito.reset(callback2);
+
+        // Change the requested state and verify callback
+        DeviceStateRequest request = DeviceStateRequest.newBuilder(DEFAULT_DEVICE_STATE).build();
+        mDeviceStateManagerGlobal.requestState(request, null /* executor */, null /* callback */);
+
+        verify(callback1).onStateChanged(eq(mService.getMergedState()));
+        verify(callback2).onStateChanged(eq(mService.getMergedState()));
     }
 
     @Test
-    public void unregisterListener() {
-        mService.setBaseState(DEFAULT_DEVICE_STATE);
+    public void unregisterCallback() {
+        DeviceStateCallback callback = mock(DeviceStateCallback.class);
 
-        TestDeviceStateListener listener = new TestDeviceStateListener();
-
-        mDeviceStateManagerGlobal.registerDeviceStateListener(listener,
+        mDeviceStateManagerGlobal.registerDeviceStateCallback(callback,
                 ConcurrentUtils.DIRECT_EXECUTOR);
-        assertEquals(DEFAULT_DEVICE_STATE, listener.getLastReportedState().intValue());
 
-        mDeviceStateManagerGlobal.unregisterDeviceStateListener(listener);
+        // Verify initial callbacks
+        verify(callback).onSupportedStatesChanged(eq(mService.getSupportedStates()));
+        verify(callback).onBaseStateChanged(eq(mService.getBaseState()));
+        verify(callback).onStateChanged(eq(mService.getMergedState()));
+        Mockito.reset(callback);
 
+        mDeviceStateManagerGlobal.unregisterDeviceStateCallback(callback);
+
+        mService.setSupportedStates(new int[]{OTHER_DEVICE_STATE});
         mService.setBaseState(OTHER_DEVICE_STATE);
-        assertEquals(DEFAULT_DEVICE_STATE, listener.getLastReportedState().intValue());
+        verifyZeroInteractions(callback);
     }
 
     @Test
-    public void submittingRequestRegisteredCallback() {
+    public void submittingRequestRegistersCallback() {
         assertTrue(mService.mCallbacks.isEmpty());
 
         DeviceStateRequest request = DeviceStateRequest.newBuilder(DEFAULT_DEVICE_STATE).build();
@@ -104,37 +142,22 @@
 
     @Test
     public void submitRequest() {
-        mService.setBaseState(DEFAULT_DEVICE_STATE);
-
-        TestDeviceStateListener listener = new TestDeviceStateListener();
-        mDeviceStateManagerGlobal.registerDeviceStateListener(listener,
+        DeviceStateCallback callback = mock(DeviceStateCallback.class);
+        mDeviceStateManagerGlobal.registerDeviceStateCallback(callback,
                 ConcurrentUtils.DIRECT_EXECUTOR);
 
-        assertEquals(DEFAULT_DEVICE_STATE, listener.getLastReportedState().intValue());
+        verify(callback).onStateChanged(eq(mService.getBaseState()));
+        Mockito.reset(callback);
 
         DeviceStateRequest request = DeviceStateRequest.newBuilder(OTHER_DEVICE_STATE).build();
         mDeviceStateManagerGlobal.requestState(request, null /* executor */, null /* callback */);
 
-        assertEquals(OTHER_DEVICE_STATE, listener.getLastReportedState().intValue());
+        verify(callback).onStateChanged(eq(OTHER_DEVICE_STATE));
+        Mockito.reset(callback);
 
         mDeviceStateManagerGlobal.cancelRequest(request);
 
-        assertEquals(DEFAULT_DEVICE_STATE, listener.getLastReportedState().intValue());
-    }
-
-    private final class TestDeviceStateListener implements DeviceStateManager.DeviceStateListener {
-        @Nullable
-        private Integer mLastReportedDeviceState;
-
-        @Override
-        public void onDeviceStateChanged(int deviceState) {
-            mLastReportedDeviceState = deviceState;
-        }
-
-        @Nullable
-        public Integer getLastReportedState() {
-            return mLastReportedDeviceState;
-        }
+        verify(callback).onStateChanged(eq(mService.getBaseState()));
     }
 
     private static final class TestDeviceStateManagerService extends IDeviceStateManager.Stub {
@@ -150,12 +173,34 @@
             }
         }
 
+        private int[] mSupportedStates = new int[] { DEFAULT_DEVICE_STATE, OTHER_DEVICE_STATE };
         private int mBaseState = DEFAULT_DEVICE_STATE;
-        private int mMergedState = DEFAULT_DEVICE_STATE;
         private ArrayList<Request> mRequests = new ArrayList<>();
 
         private Set<IDeviceStateManagerCallback> mCallbacks = new HashSet<>();
 
+        private DeviceStateInfo getInfo() {
+            final int mergedState = mRequests.isEmpty()
+                    ? mBaseState : mRequests.get(mRequests.size() - 1).state;
+            return new DeviceStateInfo(mSupportedStates, mBaseState, mergedState);
+        }
+
+        private void notifyDeviceStateInfoChanged() {
+            final DeviceStateInfo info = getInfo();
+            for (IDeviceStateManagerCallback callback : mCallbacks) {
+                try {
+                    callback.onDeviceStateInfoChanged(info);
+                } catch (RemoteException e) {
+                    // Do nothing. Should never happen.
+                }
+            }
+        }
+
+        @Override
+        public DeviceStateInfo getDeviceStateInfo() {
+            return getInfo();
+        }
+
         @Override
         public void registerCallback(IDeviceStateManagerCallback callback) {
             if (mCallbacks.contains(callback)) {
@@ -163,16 +208,6 @@
             }
 
             mCallbacks.add(callback);
-            try {
-                callback.onDeviceStateChanged(mMergedState);
-            } catch (RemoteException e) {
-                // Do nothing. Should never happen.
-            }
-        }
-
-        @Override
-        public int[] getSupportedDeviceStates() {
-            return new int[] { DEFAULT_DEVICE_STATE, OTHER_DEVICE_STATE };
         }
 
         @Override
@@ -190,7 +225,7 @@
 
             final Request request = new Request(token, state, flags);
             mRequests.add(request);
-            notifyStateChangedIfNeeded();
+            notifyDeviceStateInfoChanged();
 
             for (IDeviceStateManagerCallback callback : mCallbacks) {
                 try {
@@ -223,32 +258,29 @@
                     // Do nothing. Should never happen.
                 }
             }
-            notifyStateChangedIfNeeded();
+            notifyDeviceStateInfoChanged();
+        }
+
+        public void setSupportedStates(int[] states) {
+            mSupportedStates = states;
+            notifyDeviceStateInfoChanged();
+        }
+
+        public int[] getSupportedStates() {
+            return mSupportedStates;
         }
 
         public void setBaseState(int state) {
             mBaseState = state;
-            notifyStateChangedIfNeeded();
+            notifyDeviceStateInfoChanged();
         }
 
-        private void notifyStateChangedIfNeeded() {
-            final int originalMergedState = mMergedState;
+        public int getBaseState() {
+            return mBaseState;
+        }
 
-            if (!mRequests.isEmpty()) {
-                mMergedState = mRequests.get(mRequests.size() - 1).state;
-            } else {
-                mMergedState = mBaseState;
-            }
-
-            if (mMergedState != originalMergedState) {
-                for (IDeviceStateManagerCallback callback : mCallbacks) {
-                    try {
-                        callback.onDeviceStateChanged(mMergedState);
-                    } catch (RemoteException e) {
-                        // Do nothing. Should never happen.
-                    }
-                }
-            }
+        public int getMergedState() {
+            return getInfo().currentState;
         }
     }
 }
diff --git a/core/tests/featureflagtests/Android.bp b/core/tests/featureflagtests/Android.bp
index 8730b70..d9f608e 100644
--- a/core/tests/featureflagtests/Android.bp
+++ b/core/tests/featureflagtests/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworksCoreFeatureFlagTests",
     // We only want this apk build for tests.
diff --git a/core/tests/hdmitests/Android.bp b/core/tests/hdmitests/Android.bp
index 4755e0e..f49e053 100644
--- a/core/tests/hdmitests/Android.bp
+++ b/core/tests/hdmitests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "HdmiCecTests",
     // Include all test java files
diff --git a/core/tests/hosttests/test-apps/AutoLocTestApp/Android.bp b/core/tests/hosttests/test-apps/AutoLocTestApp/Android.bp
index 1442481..b4efce2 100644
--- a/core/tests/hosttests/test-apps/AutoLocTestApp/Android.bp
+++ b/core/tests/hosttests/test-apps/AutoLocTestApp/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "AutoLocTestApp",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/AutoLocVersionedTestApp_v1/Android.bp b/core/tests/hosttests/test-apps/AutoLocVersionedTestApp_v1/Android.bp
index 438ed25..0e07ddc 100644
--- a/core/tests/hosttests/test-apps/AutoLocVersionedTestApp_v1/Android.bp
+++ b/core/tests/hosttests/test-apps/AutoLocVersionedTestApp_v1/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "AutoLocVersionedTestApp_v1",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/AutoLocVersionedTestApp_v2/Android.bp b/core/tests/hosttests/test-apps/AutoLocVersionedTestApp_v2/Android.bp
index 2ac72a1..f408700 100644
--- a/core/tests/hosttests/test-apps/AutoLocVersionedTestApp_v2/Android.bp
+++ b/core/tests/hosttests/test-apps/AutoLocVersionedTestApp_v2/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "AutoLocVersionedTestApp_v2",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/ExternalLocAllPermsTestApp/Android.bp b/core/tests/hosttests/test-apps/ExternalLocAllPermsTestApp/Android.bp
index e06e82e..964401d 100644
--- a/core/tests/hosttests/test-apps/ExternalLocAllPermsTestApp/Android.bp
+++ b/core/tests/hosttests/test-apps/ExternalLocAllPermsTestApp/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ExternalLocAllPermsTestApp",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/ExternalLocPermsFLTestApp/Android.bp b/core/tests/hosttests/test-apps/ExternalLocPermsFLTestApp/Android.bp
index c48dcd5..297ed57 100644
--- a/core/tests/hosttests/test-apps/ExternalLocPermsFLTestApp/Android.bp
+++ b/core/tests/hosttests/test-apps/ExternalLocPermsFLTestApp/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ExternalLocPermFLTestApp",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/ExternalLocTestApp/Android.bp b/core/tests/hosttests/test-apps/ExternalLocTestApp/Android.bp
index 5c1c15a..cf8c7e1 100644
--- a/core/tests/hosttests/test-apps/ExternalLocTestApp/Android.bp
+++ b/core/tests/hosttests/test-apps/ExternalLocTestApp/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ExternalLocTestApp",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/ExternalLocVersionedTestApp_v1/Android.bp b/core/tests/hosttests/test-apps/ExternalLocVersionedTestApp_v1/Android.bp
index 13f5066..909bd7f 100644
--- a/core/tests/hosttests/test-apps/ExternalLocVersionedTestApp_v1/Android.bp
+++ b/core/tests/hosttests/test-apps/ExternalLocVersionedTestApp_v1/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ExternalLocVersionedTestApp_v1",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/ExternalLocVersionedTestApp_v2/Android.bp b/core/tests/hosttests/test-apps/ExternalLocVersionedTestApp_v2/Android.bp
index e02ffb3..c5f9192 100644
--- a/core/tests/hosttests/test-apps/ExternalLocVersionedTestApp_v2/Android.bp
+++ b/core/tests/hosttests/test-apps/ExternalLocVersionedTestApp_v2/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ExternalLocVersionedTestApp_v2",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/ExternalSharedPerms/Android.bp b/core/tests/hosttests/test-apps/ExternalSharedPerms/Android.bp
index de09800..1545f4d 100644
--- a/core/tests/hosttests/test-apps/ExternalSharedPerms/Android.bp
+++ b/core/tests/hosttests/test-apps/ExternalSharedPerms/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ExternalSharedPermsTestApp",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/ExternalSharedPermsBT/Android.bp b/core/tests/hosttests/test-apps/ExternalSharedPermsBT/Android.bp
index 435144f..8690bdf 100644
--- a/core/tests/hosttests/test-apps/ExternalSharedPermsBT/Android.bp
+++ b/core/tests/hosttests/test-apps/ExternalSharedPermsBT/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ExternalSharedPermsBTTestApp",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/ExternalSharedPermsDiffKey/Android.bp b/core/tests/hosttests/test-apps/ExternalSharedPermsDiffKey/Android.bp
index 445bac9..21b7c4c 100644
--- a/core/tests/hosttests/test-apps/ExternalSharedPermsDiffKey/Android.bp
+++ b/core/tests/hosttests/test-apps/ExternalSharedPermsDiffKey/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ExternalSharedPermsDiffKeyTestApp",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/ExternalSharedPermsFL/Android.bp b/core/tests/hosttests/test-apps/ExternalSharedPermsFL/Android.bp
index d1da399..63bf8dc 100644
--- a/core/tests/hosttests/test-apps/ExternalSharedPermsFL/Android.bp
+++ b/core/tests/hosttests/test-apps/ExternalSharedPermsFL/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ExternalSharedPermsFLTestApp",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/InternalLocTestApp/Android.bp b/core/tests/hosttests/test-apps/InternalLocTestApp/Android.bp
index fab9d43..f05cde4 100644
--- a/core/tests/hosttests/test-apps/InternalLocTestApp/Android.bp
+++ b/core/tests/hosttests/test-apps/InternalLocTestApp/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "InternalLocTestApp",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests/Android.bp b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests/Android.bp
index dcf1687..56f10fe 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests/Android.bp
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "MultiDexLegacyTestServicesTests",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/NoLocTestApp/Android.bp b/core/tests/hosttests/test-apps/NoLocTestApp/Android.bp
index 50a2de4..88e3722 100644
--- a/core/tests/hosttests/test-apps/NoLocTestApp/Android.bp
+++ b/core/tests/hosttests/test-apps/NoLocTestApp/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "NoLocTestApp",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/NoLocVersionedTestApp_v1/Android.bp b/core/tests/hosttests/test-apps/NoLocVersionedTestApp_v1/Android.bp
index 4bc9edc..fd5ab26 100644
--- a/core/tests/hosttests/test-apps/NoLocVersionedTestApp_v1/Android.bp
+++ b/core/tests/hosttests/test-apps/NoLocVersionedTestApp_v1/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "NoLocVersionedTestApp_v1",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/NoLocVersionedTestApp_v2/Android.bp b/core/tests/hosttests/test-apps/NoLocVersionedTestApp_v2/Android.bp
index dd2952b..fa821d8 100644
--- a/core/tests/hosttests/test-apps/NoLocVersionedTestApp_v2/Android.bp
+++ b/core/tests/hosttests/test-apps/NoLocVersionedTestApp_v2/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "NoLocVersionedTestApp_v2",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/SharedUid/32/Android.bp b/core/tests/hosttests/test-apps/SharedUid/32/Android.bp
index f3e3ede..6f3d4cf 100644
--- a/core/tests/hosttests/test-apps/SharedUid/32/Android.bp
+++ b/core/tests/hosttests/test-apps/SharedUid/32/Android.bp
@@ -19,6 +19,15 @@
 
 // Build activity
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "PMTest_Java32",
     srcs: ["**/*.java"],
diff --git a/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.bp b/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.bp
index 9e6c17f..867d65c 100644
--- a/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.bp
+++ b/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.bp
@@ -17,6 +17,15 @@
 // This makefile supplies the rules for building a library of JNI code for
 // use by our example of how to bundle a shared library with an APK.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_test_library {
 
     // This is the target being built.
diff --git a/core/tests/hosttests/test-apps/SharedUid/64/Android.bp b/core/tests/hosttests/test-apps/SharedUid/64/Android.bp
index 5d9c0b5..6bb25a8 100644
--- a/core/tests/hosttests/test-apps/SharedUid/64/Android.bp
+++ b/core/tests/hosttests/test-apps/SharedUid/64/Android.bp
@@ -19,6 +19,15 @@
 
 // Build activity
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "PMTest_Java64",
     srcs: ["**/*.java"],
diff --git a/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.bp b/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.bp
index 91da6e4..c032ba1 100644
--- a/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.bp
+++ b/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.bp
@@ -17,6 +17,15 @@
 // This Android.bp supplies the rules for building a library of JNI code for
 // use by our example of how to bundle a shared library with an APK.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_test_library {
     // This is the target being built.
     name: "libpmtest64",
diff --git a/core/tests/hosttests/test-apps/SharedUid/dual/Android.bp b/core/tests/hosttests/test-apps/SharedUid/dual/Android.bp
index c42192d..94dd0c6 100644
--- a/core/tests/hosttests/test-apps/SharedUid/dual/Android.bp
+++ b/core/tests/hosttests/test-apps/SharedUid/dual/Android.bp
@@ -19,6 +19,15 @@
 
 // Build activity
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "PMTest_Java_dual",
     srcs: ["**/*.java"],
diff --git a/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.bp b/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.bp
index 662755d..6b9d7f3 100644
--- a/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.bp
+++ b/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.bp
@@ -17,6 +17,15 @@
 // This Android.bp supplies the rules for building a library of JNI code for
 // use by our example of how to bundle a shared library with an APK.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_test_library {
 
     // This is the target being built.
diff --git a/core/tests/hosttests/test-apps/SharedUid/java_only/Android.bp b/core/tests/hosttests/test-apps/SharedUid/java_only/Android.bp
index baedc6e..6d63267 100644
--- a/core/tests/hosttests/test-apps/SharedUid/java_only/Android.bp
+++ b/core/tests/hosttests/test-apps/SharedUid/java_only/Android.bp
@@ -19,6 +19,15 @@
 
 // Build activity
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "PMTest_Java",
     srcs: ["**/*.java"],
diff --git a/core/tests/hosttests/test-apps/SimpleTestApp/Android.bp b/core/tests/hosttests/test-apps/SimpleTestApp/Android.bp
index 5f443bd..b022bda 100644
--- a/core/tests/hosttests/test-apps/SimpleTestApp/Android.bp
+++ b/core/tests/hosttests/test-apps/SimpleTestApp/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "SimpleTestApp",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/UpdateExtToIntLocTestApp_v1_ext/Android.bp b/core/tests/hosttests/test-apps/UpdateExtToIntLocTestApp_v1_ext/Android.bp
index 800e083..0ac825b 100644
--- a/core/tests/hosttests/test-apps/UpdateExtToIntLocTestApp_v1_ext/Android.bp
+++ b/core/tests/hosttests/test-apps/UpdateExtToIntLocTestApp_v1_ext/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "UpdateExtToIntLocTestApp_v1_ext",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/UpdateExtToIntLocTestApp_v2_int/Android.bp b/core/tests/hosttests/test-apps/UpdateExtToIntLocTestApp_v2_int/Android.bp
index 299887c..6f66a51 100644
--- a/core/tests/hosttests/test-apps/UpdateExtToIntLocTestApp_v2_int/Android.bp
+++ b/core/tests/hosttests/test-apps/UpdateExtToIntLocTestApp_v2_int/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "UpdateExtToIntLocTestApp_v2_int",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/UpdateExternalLocTestApp_v1_ext/Android.bp b/core/tests/hosttests/test-apps/UpdateExternalLocTestApp_v1_ext/Android.bp
index 1530422..d88bce0 100644
--- a/core/tests/hosttests/test-apps/UpdateExternalLocTestApp_v1_ext/Android.bp
+++ b/core/tests/hosttests/test-apps/UpdateExternalLocTestApp_v1_ext/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "UpdateExternalLocTestApp_v1_ext",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/UpdateExternalLocTestApp_v2_none/Android.bp b/core/tests/hosttests/test-apps/UpdateExternalLocTestApp_v2_none/Android.bp
index 4c7975e..d1240df 100644
--- a/core/tests/hosttests/test-apps/UpdateExternalLocTestApp_v2_none/Android.bp
+++ b/core/tests/hosttests/test-apps/UpdateExternalLocTestApp_v2_none/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "UpdateExternalLocTestApp_v2_none",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/VersatileTestApp_Auto/Android.bp b/core/tests/hosttests/test-apps/VersatileTestApp_Auto/Android.bp
index c6b60c3..751071c 100644
--- a/core/tests/hosttests/test-apps/VersatileTestApp_Auto/Android.bp
+++ b/core/tests/hosttests/test-apps/VersatileTestApp_Auto/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "VersatileTestApp_Auto",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/VersatileTestApp_External/Android.bp b/core/tests/hosttests/test-apps/VersatileTestApp_External/Android.bp
index db521ef..b9ed015 100644
--- a/core/tests/hosttests/test-apps/VersatileTestApp_External/Android.bp
+++ b/core/tests/hosttests/test-apps/VersatileTestApp_External/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "VersatileTestApp_External",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/VersatileTestApp_Internal/Android.bp b/core/tests/hosttests/test-apps/VersatileTestApp_Internal/Android.bp
index ca059302..7b72570 100644
--- a/core/tests/hosttests/test-apps/VersatileTestApp_Internal/Android.bp
+++ b/core/tests/hosttests/test-apps/VersatileTestApp_Internal/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "VersatileTestApp_Internal",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/hosttests/test-apps/VersatileTestApp_None/Android.bp b/core/tests/hosttests/test-apps/VersatileTestApp_None/Android.bp
index 6e1aac7..5f67bce 100644
--- a/core/tests/hosttests/test-apps/VersatileTestApp_None/Android.bp
+++ b/core/tests/hosttests/test-apps/VersatileTestApp_None/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "VersatileTestApp_None",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/mockingcoretests/Android.bp b/core/tests/mockingcoretests/Android.bp
index ae3ff86..96811be 100644
--- a/core/tests/mockingcoretests/Android.bp
+++ b/core/tests/mockingcoretests/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworksMockingCoreTests",
 
diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
index d2b20b4..0808186 100644
--- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
+++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
@@ -298,7 +298,7 @@
                     null /* pendingResults */, null /* pendingNewIntents */,
                     null /* activityOptions */, true /* isForward */, null /* profilerInfo */,
                     mThread /* client */, null /* asssitToken */,
-                    null /* fixedRotationAdjustments */);
+                    null /* fixedRotationAdjustments */, null /* shareableActivityToken */);
         }
 
         @Override
diff --git a/core/tests/notificationtests/Android.bp b/core/tests/notificationtests/Android.bp
index e744d5a..1c0e39d 100644
--- a/core/tests/notificationtests/Android.bp
+++ b/core/tests/notificationtests/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "NotificationStressTests",
     // Include all test java files.
diff --git a/core/tests/overlaytests/device/Android.bp b/core/tests/overlaytests/device/Android.bp
index f86ac9c..0d3b15a 100644
--- a/core/tests/overlaytests/device/Android.bp
+++ b/core/tests/overlaytests/device/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "OverlayDeviceTests",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayOne/Android.bp b/core/tests/overlaytests/device/test-apps/AppOverlayOne/Android.bp
index 847b491..4ff59fa 100644
--- a/core/tests/overlaytests/device/test-apps/AppOverlayOne/Android.bp
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "OverlayDeviceTests_AppOverlayOne",
     sdk_version: "current",
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayTwo/Android.bp b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/Android.bp
index 7d5f82a..1f5763e 100644
--- a/core/tests/overlaytests/device/test-apps/AppOverlayTwo/Android.bp
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "OverlayDeviceTests_AppOverlayTwo",
     sdk_version: "current",
diff --git a/core/tests/overlaytests/device/test-apps/FrameworkOverlay/Android.bp b/core/tests/overlaytests/device/test-apps/FrameworkOverlay/Android.bp
index 50dbc6f..178a020 100644
--- a/core/tests/overlaytests/device/test-apps/FrameworkOverlay/Android.bp
+++ b/core/tests/overlaytests/device/test-apps/FrameworkOverlay/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "OverlayDeviceTests_FrameworkOverlay",
     sdk_version: "current",
diff --git a/core/tests/overlaytests/host/Android.bp b/core/tests/overlaytests/host/Android.bp
index a2fcef5..e4c3fbe 100644
--- a/core/tests/overlaytests/host/Android.bp
+++ b/core/tests/overlaytests/host/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_test_host {
     name: "OverlayHostTests",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/overlaytests/remount/Android.bp b/core/tests/overlaytests/remount/Android.bp
index 939334c..0a6b88b 100644
--- a/core/tests/overlaytests/remount/Android.bp
+++ b/core/tests/overlaytests/remount/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_test_host {
     name: "OverlayRemountedTest",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/overlaytests/remount/test-apps/Overlay/Android.bp b/core/tests/overlaytests/remount/test-apps/Overlay/Android.bp
index 032a0cd..a341c9a 100644
--- a/core/tests/overlaytests/remount/test-apps/Overlay/Android.bp
+++ b/core/tests/overlaytests/remount/test-apps/Overlay/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "OverlayRemountedTest_Overlay",
     sdk_version: "current",
@@ -24,4 +33,4 @@
     name: "OverlayRemountedTest_Overlay_SameCert",
     certificate: ":rro-remounted-test-a",
     sdk_version: "current",
-}
\ No newline at end of file
+}
diff --git a/core/tests/overlaytests/remount/test-apps/SharedLibrary/Android.bp b/core/tests/overlaytests/remount/test-apps/SharedLibrary/Android.bp
index ffb0572..bc88d61 100644
--- a/core/tests/overlaytests/remount/test-apps/SharedLibrary/Android.bp
+++ b/core/tests/overlaytests/remount/test-apps/SharedLibrary/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "OverlayRemountedTest_SharedLibrary",
     sdk_version: "current",
diff --git a/core/tests/overlaytests/remount/test-apps/SharedLibraryOverlay/Android.bp b/core/tests/overlaytests/remount/test-apps/SharedLibraryOverlay/Android.bp
index 0d29aec..88a05ab 100644
--- a/core/tests/overlaytests/remount/test-apps/SharedLibraryOverlay/Android.bp
+++ b/core/tests/overlaytests/remount/test-apps/SharedLibraryOverlay/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "OverlayRemountedTest_SharedLibraryOverlay",
     sdk_version: "current",
diff --git a/core/tests/overlaytests/remount/test-apps/Target/Android.bp b/core/tests/overlaytests/remount/test-apps/Target/Android.bp
index e4b4eaa..869a75f 100644
--- a/core/tests/overlaytests/remount/test-apps/Target/Android.bp
+++ b/core/tests/overlaytests/remount/test-apps/Target/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "OverlayRemountedTest_Target",
     sdk_version: "test_current",
diff --git a/core/tests/overlaytests/remount/test-apps/certs/Android.bp b/core/tests/overlaytests/remount/test-apps/certs/Android.bp
index 06114ef..f5d89bc 100644
--- a/core/tests/overlaytests/remount/test-apps/certs/Android.bp
+++ b/core/tests/overlaytests/remount/test-apps/certs/Android.bp
@@ -13,6 +13,17 @@
 // limitations under the License.
 
 // development/tools/make_key rro-remounted-test-a '/CN=rro_test_a'
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app_certificate {
     name: "rro-remounted-test-a",
     certificate: "rro-remounted-test-a",
diff --git a/core/tests/overlaytests/remount/test-apps/overlaid_apex/Android.bp b/core/tests/overlaytests/remount/test-apps/overlaid_apex/Android.bp
index e6ebd5e..3536c40 100644
--- a/core/tests/overlaytests/remount/test-apps/overlaid_apex/Android.bp
+++ b/core/tests/overlaytests/remount/test-apps/overlaid_apex/Android.bp
@@ -12,6 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 genrule {
   name: "com.android.overlaytest.overlaid.pem",
   out: ["com.android.overlaytest.overlaid.pem"],
@@ -39,4 +50,5 @@
     key: "com.android.overlaytest.overlaid.key",
     apps: ["OverlayRemountedTest_Target"],
     installable: false,
+    updatable: false,
 }
diff --git a/core/tests/overlaytests/remount/test-apps/overlay_apex/Android.bp b/core/tests/overlaytests/remount/test-apps/overlay_apex/Android.bp
index 07f27ee..f041404 100644
--- a/core/tests/overlaytests/remount/test-apps/overlay_apex/Android.bp
+++ b/core/tests/overlaytests/remount/test-apps/overlay_apex/Android.bp
@@ -12,6 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 genrule {
   name: "com.android.overlaytest.overlay.pem",
   out: ["com.android.overlaytest.overlay.pem"],
@@ -39,4 +50,5 @@
     key: "com.android.overlaytest.overlay.key",
     apps: ["OverlayRemountedTest_Overlay"],
     installable: false,
+    updatable: false,
 }
diff --git a/core/tests/packagemanagertests/Android.bp b/core/tests/packagemanagertests/Android.bp
index 6f39af8..5ce71c9 100644
--- a/core/tests/packagemanagertests/Android.bp
+++ b/core/tests/packagemanagertests/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworksCorePackageManagerTests",
     // We only want this apk build for tests.
diff --git a/core/tests/privacytests/Android.bp b/core/tests/privacytests/Android.bp
index 7f56992..bc3dd81 100644
--- a/core/tests/privacytests/Android.bp
+++ b/core/tests/privacytests/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworksPrivacyLibraryTests",
     srcs: ["src/**/*.java"],
diff --git a/core/tests/screenshothelpertests/Android.bp b/core/tests/screenshothelpertests/Android.bp
index 3d54b68..37af99c 100644
--- a/core/tests/screenshothelpertests/Android.bp
+++ b/core/tests/screenshothelpertests/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ScreenshotHelperTests",
 
@@ -25,4 +34,3 @@
 
     certificate: "platform",
 }
-
diff --git a/core/tests/systemproperties/Android.bp b/core/tests/systemproperties/Android.bp
index 7ef1b9b..765ca3e 100644
--- a/core/tests/systemproperties/Android.bp
+++ b/core/tests/systemproperties/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworksCoreSystemPropertiesTests",
     // Include all test java files.
diff --git a/core/tests/utillib/Android.bp b/core/tests/utillib/Android.bp
index 1f742c2..d40d1d2 100644
--- a/core/tests/utillib/Android.bp
+++ b/core/tests/utillib/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library {
     name: "frameworks-core-util-lib",
 
diff --git a/core/tests/utiltests/Android.bp b/core/tests/utiltests/Android.bp
index a9b9c41..72d6a2c 100644
--- a/core/tests/utiltests/Android.bp
+++ b/core/tests/utiltests/Android.bp
@@ -2,6 +2,15 @@
 // Build FrameworksUtilTests package
 //########################################################################
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworksUtilTests",
 
diff --git a/core/tests/utiltests/jni/Android.bp b/core/tests/utiltests/jni/Android.bp
index 6b75471..a9c695e 100644
--- a/core/tests/utiltests/jni/Android.bp
+++ b/core/tests/utiltests/jni/Android.bp
@@ -11,6 +11,15 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 // See the License for the specific language governing permissions and

 // limitations under the License.

+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 

 cc_library_shared {

     name: "libmemoryintarraytest",

diff --git a/core/tests/uwbtests/Android.bp b/core/tests/uwbtests/Android.bp
index 8ee86f4..31f446f 100644
--- a/core/tests/uwbtests/Android.bp
+++ b/core/tests/uwbtests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "UwbManagerTests",
     static_libs: [
diff --git a/core/tests/uwbtests/src/android/uwb/AngleMeasurementTest.java b/core/tests/uwbtests/src/android/uwb/AngleMeasurementTest.java
deleted file mode 100644
index 7769c28..0000000
--- a/core/tests/uwbtests/src/android/uwb/AngleMeasurementTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import android.os.Parcel;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test of {@link AngleMeasurement}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class AngleMeasurementTest {
-    private static final double EPSILON = 0.00000000001;
-
-    @Test
-    public void testBuilder() {
-        double radians = 0.1234;
-        double errorRadians = 0.5678;
-        double confidence = 0.5;
-
-        AngleMeasurement.Builder builder = new AngleMeasurement.Builder();
-        tryBuild(builder, false);
-
-        builder.setRadians(radians);
-        tryBuild(builder, false);
-
-        builder.setErrorRadians(errorRadians);
-        tryBuild(builder, false);
-
-        builder.setConfidenceLevel(confidence);
-        AngleMeasurement measurement = tryBuild(builder, true);
-
-        assertEquals(measurement.getRadians(), radians, 0);
-        assertEquals(measurement.getErrorRadians(), errorRadians, 0);
-        assertEquals(measurement.getConfidenceLevel(), confidence, 0);
-    }
-
-    private AngleMeasurement tryBuild(AngleMeasurement.Builder builder, boolean expectSuccess) {
-        AngleMeasurement measurement = null;
-        try {
-            measurement = builder.build();
-            if (!expectSuccess) {
-                fail("Expected AngleMeasurement.Builder.build() to fail, but it succeeded");
-            }
-        } catch (IllegalStateException e) {
-            if (expectSuccess) {
-                fail("Expected AngleMeasurement.Builder.build() to succeed, but it failed");
-            }
-        }
-        return measurement;
-    }
-
-    @Test
-    public void testParcel() {
-        Parcel parcel = Parcel.obtain();
-        AngleMeasurement measurement = UwbTestUtils.getAngleMeasurement();
-        measurement.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        AngleMeasurement fromParcel = AngleMeasurement.CREATOR.createFromParcel(parcel);
-        assertEquals(measurement, fromParcel);
-    }
-}
diff --git a/core/tests/uwbtests/src/android/uwb/AngleOfArrivalMeasurementTest.java b/core/tests/uwbtests/src/android/uwb/AngleOfArrivalMeasurementTest.java
deleted file mode 100644
index 9394dec..0000000
--- a/core/tests/uwbtests/src/android/uwb/AngleOfArrivalMeasurementTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import android.os.Parcel;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test of {@link AngleOfArrivalMeasurement}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class AngleOfArrivalMeasurementTest {
-
-    @Test
-    public void testBuilder() {
-        AngleMeasurement azimuth = UwbTestUtils.getAngleMeasurement();
-        AngleMeasurement altitude = UwbTestUtils.getAngleMeasurement();
-
-        AngleOfArrivalMeasurement.Builder builder = new AngleOfArrivalMeasurement.Builder();
-        tryBuild(builder, false);
-
-        builder.setAltitude(altitude);
-        tryBuild(builder, false);
-
-        builder.setAzimuth(azimuth);
-        AngleOfArrivalMeasurement measurement = tryBuild(builder, true);
-
-        assertEquals(azimuth, measurement.getAzimuth());
-        assertEquals(altitude, measurement.getAltitude());
-    }
-
-    private AngleMeasurement getAngleMeasurement(double radian, double error, double confidence) {
-        return new AngleMeasurement.Builder()
-                .setRadians(radian)
-                .setErrorRadians(error)
-                .setConfidenceLevel(confidence)
-                .build();
-    }
-
-    private AngleOfArrivalMeasurement tryBuild(AngleOfArrivalMeasurement.Builder builder,
-            boolean expectSuccess) {
-        AngleOfArrivalMeasurement measurement = null;
-        try {
-            measurement = builder.build();
-            if (!expectSuccess) {
-                fail("Expected AngleOfArrivalMeasurement.Builder.build() to fail");
-            }
-        } catch (IllegalStateException e) {
-            if (expectSuccess) {
-                fail("Expected AngleOfArrivalMeasurement.Builder.build() to succeed");
-            }
-        }
-        return measurement;
-    }
-
-    @Test
-    public void testParcel() {
-        Parcel parcel = Parcel.obtain();
-        AngleOfArrivalMeasurement measurement = UwbTestUtils.getAngleOfArrivalMeasurement();
-        measurement.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        AngleOfArrivalMeasurement fromParcel =
-                AngleOfArrivalMeasurement.CREATOR.createFromParcel(parcel);
-        assertEquals(measurement, fromParcel);
-    }
-}
diff --git a/core/tests/uwbtests/src/android/uwb/DistanceMeasurementTest.java b/core/tests/uwbtests/src/android/uwb/DistanceMeasurementTest.java
deleted file mode 100644
index 439c884..0000000
--- a/core/tests/uwbtests/src/android/uwb/DistanceMeasurementTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import android.os.Parcel;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test of {@link DistanceMeasurement}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class DistanceMeasurementTest {
-    private static final double EPSILON = 0.00000000001;
-
-    @Test
-    public void testBuilder() {
-        double meters = 0.12;
-        double error = 0.54;
-        double confidence = 0.99;
-
-        DistanceMeasurement.Builder builder = new DistanceMeasurement.Builder();
-        tryBuild(builder, false);
-
-        builder.setMeters(meters);
-        tryBuild(builder, false);
-
-        builder.setErrorMeters(error);
-        tryBuild(builder, false);
-
-        builder.setConfidenceLevel(confidence);
-        DistanceMeasurement measurement = tryBuild(builder, true);
-
-        assertEquals(meters, measurement.getMeters(), 0);
-        assertEquals(error, measurement.getErrorMeters(), 0);
-        assertEquals(confidence, measurement.getConfidenceLevel(), 0);
-    }
-
-    private DistanceMeasurement tryBuild(DistanceMeasurement.Builder builder,
-            boolean expectSuccess) {
-        DistanceMeasurement measurement = null;
-        try {
-            measurement = builder.build();
-            if (!expectSuccess) {
-                fail("Expected DistanceMeasurement.Builder.build() to fail");
-            }
-        } catch (IllegalStateException e) {
-            if (expectSuccess) {
-                fail("Expected DistanceMeasurement.Builder.build() to succeed");
-            }
-        }
-        return measurement;
-    }
-
-    @Test
-    public void testParcel() {
-        Parcel parcel = Parcel.obtain();
-        DistanceMeasurement measurement = UwbTestUtils.getDistanceMeasurement();
-        measurement.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        DistanceMeasurement fromParcel =
-                DistanceMeasurement.CREATOR.createFromParcel(parcel);
-        assertEquals(measurement, fromParcel);
-    }
-}
diff --git a/core/tests/uwbtests/src/android/uwb/RangingMeasurementTest.java b/core/tests/uwbtests/src/android/uwb/RangingMeasurementTest.java
deleted file mode 100644
index edd4d08..0000000
--- a/core/tests/uwbtests/src/android/uwb/RangingMeasurementTest.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import android.os.Parcel;
-import android.os.SystemClock;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test of {@link RangingMeasurement}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class RangingMeasurementTest {
-
-    @Test
-    public void testBuilder() {
-        int status = RangingMeasurement.RANGING_STATUS_SUCCESS;
-        UwbAddress address = UwbTestUtils.getUwbAddress(false);
-        long time = SystemClock.elapsedRealtimeNanos();
-        AngleOfArrivalMeasurement angleMeasurement = UwbTestUtils.getAngleOfArrivalMeasurement();
-        DistanceMeasurement distanceMeasurement = UwbTestUtils.getDistanceMeasurement();
-
-        RangingMeasurement.Builder builder = new RangingMeasurement.Builder();
-
-        builder.setStatus(status);
-        tryBuild(builder, false);
-
-        builder.setElapsedRealtimeNanos(time);
-        tryBuild(builder, false);
-
-        builder.setAngleOfArrivalMeasurement(angleMeasurement);
-        tryBuild(builder, false);
-
-        builder.setDistanceMeasurement(distanceMeasurement);
-        tryBuild(builder, false);
-
-        builder.setRemoteDeviceAddress(address);
-        RangingMeasurement measurement = tryBuild(builder, true);
-
-        assertEquals(status, measurement.getStatus());
-        assertEquals(address, measurement.getRemoteDeviceAddress());
-        assertEquals(time, measurement.getElapsedRealtimeNanos());
-        assertEquals(angleMeasurement, measurement.getAngleOfArrivalMeasurement());
-        assertEquals(distanceMeasurement, measurement.getDistanceMeasurement());
-    }
-
-    private RangingMeasurement tryBuild(RangingMeasurement.Builder builder,
-            boolean expectSuccess) {
-        RangingMeasurement measurement = null;
-        try {
-            measurement = builder.build();
-            if (!expectSuccess) {
-                fail("Expected RangingMeasurement.Builder.build() to fail");
-            }
-        } catch (IllegalStateException e) {
-            if (expectSuccess) {
-                fail("Expected DistanceMeasurement.Builder.build() to succeed");
-            }
-        }
-        return measurement;
-    }
-
-    @Test
-    public void testParcel() {
-        Parcel parcel = Parcel.obtain();
-        RangingMeasurement measurement = UwbTestUtils.getRangingMeasurement();
-        measurement.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        RangingMeasurement fromParcel = RangingMeasurement.CREATOR.createFromParcel(parcel);
-        assertEquals(measurement, fromParcel);
-    }
-}
diff --git a/core/tests/uwbtests/src/android/uwb/RangingReportTest.java b/core/tests/uwbtests/src/android/uwb/RangingReportTest.java
deleted file mode 100644
index 64c48ba..0000000
--- a/core/tests/uwbtests/src/android/uwb/RangingReportTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import android.os.Parcel;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.List;
-
-/**
- * Test of {@link RangingReport}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class RangingReportTest {
-
-    @Test
-    public void testBuilder() {
-        List<RangingMeasurement> measurements = UwbTestUtils.getRangingMeasurements(5);
-
-        RangingReport.Builder builder = new RangingReport.Builder();
-        builder.addMeasurements(measurements);
-        RangingReport report = tryBuild(builder, true);
-        verifyMeasurementsEqual(measurements, report.getMeasurements());
-
-
-        builder = new RangingReport.Builder();
-        for (RangingMeasurement measurement : measurements) {
-            builder.addMeasurement(measurement);
-        }
-        report = tryBuild(builder, true);
-        verifyMeasurementsEqual(measurements, report.getMeasurements());
-    }
-
-    private void verifyMeasurementsEqual(List<RangingMeasurement> expected,
-            List<RangingMeasurement> actual) {
-        assertEquals(expected.size(), actual.size());
-        for (int i = 0; i < expected.size(); i++) {
-            assertEquals(expected.get(i), actual.get(i));
-        }
-    }
-
-    private RangingReport tryBuild(RangingReport.Builder builder,
-            boolean expectSuccess) {
-        RangingReport report = null;
-        try {
-            report = builder.build();
-            if (!expectSuccess) {
-                fail("Expected RangingReport.Builder.build() to fail");
-            }
-        } catch (IllegalStateException e) {
-            if (expectSuccess) {
-                fail("Expected RangingReport.Builder.build() to succeed");
-            }
-        }
-        return report;
-    }
-
-    @Test
-    public void testParcel() {
-        Parcel parcel = Parcel.obtain();
-        RangingReport report = UwbTestUtils.getRangingReports(5);
-        report.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        RangingReport fromParcel = RangingReport.CREATOR.createFromParcel(parcel);
-        assertEquals(report, fromParcel);
-    }
-}
diff --git a/core/tests/uwbtests/src/android/uwb/RangingSessionTest.java b/core/tests/uwbtests/src/android/uwb/RangingSessionTest.java
deleted file mode 100644
index e5eea26..0000000
--- a/core/tests/uwbtests/src/android/uwb/RangingSessionTest.java
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.os.PersistableBundle;
-import android.os.RemoteException;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-import java.util.concurrent.Executor;
-
-/**
- * Test of {@link RangingSession}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class RangingSessionTest {
-    private static final Executor EXECUTOR = UwbTestUtils.getExecutor();
-    private static final PersistableBundle PARAMS = new PersistableBundle();
-    private static final @RangingSession.Callback.Reason int REASON =
-            RangingSession.Callback.REASON_GENERIC_ERROR;
-
-    @Test
-    public void testOnRangingOpened_OnOpenSuccessCalled() {
-        SessionHandle handle = new SessionHandle(123);
-        RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter adapter = mock(IUwbAdapter.class);
-        RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
-        verifyOpenState(session, false);
-
-        session.onRangingOpened();
-        verifyOpenState(session, true);
-
-        // Verify that the onOpenSuccess callback was invoked
-        verify(callback, times(1)).onOpened(eq(session));
-        verify(callback, times(0)).onClosed(anyInt(), any());
-    }
-
-    @Test
-    public void testOnRangingOpened_CannotOpenClosedSession() {
-        SessionHandle handle = new SessionHandle(123);
-        RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter adapter = mock(IUwbAdapter.class);
-        RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
-
-        session.onRangingOpened();
-        verifyOpenState(session, true);
-        verify(callback, times(1)).onOpened(eq(session));
-        verify(callback, times(0)).onClosed(anyInt(), any());
-
-        session.onRangingClosed(REASON, PARAMS);
-        verifyOpenState(session, false);
-        verify(callback, times(1)).onOpened(eq(session));
-        verify(callback, times(1)).onClosed(anyInt(), any());
-
-        // Now invoke the ranging started callback and ensure the session remains closed
-        session.onRangingOpened();
-        verifyOpenState(session, false);
-        verify(callback, times(1)).onOpened(eq(session));
-        verify(callback, times(1)).onClosed(anyInt(), any());
-    }
-
-    @Test
-    public void testOnRangingClosed_OnClosedCalledWhenSessionNotOpen() {
-        SessionHandle handle = new SessionHandle(123);
-        RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter adapter = mock(IUwbAdapter.class);
-        RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
-        verifyOpenState(session, false);
-
-        session.onRangingClosed(REASON, PARAMS);
-        verifyOpenState(session, false);
-
-        // Verify that the onOpenSuccess callback was invoked
-        verify(callback, times(0)).onOpened(eq(session));
-        verify(callback, times(1)).onClosed(anyInt(), any());
-    }
-
-    @Test
-    public void testOnRangingClosed_OnClosedCalled() {
-        SessionHandle handle = new SessionHandle(123);
-        RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter adapter = mock(IUwbAdapter.class);
-        RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
-        session.onRangingStarted(PARAMS);
-        session.onRangingClosed(REASON, PARAMS);
-        verify(callback, times(1)).onClosed(anyInt(), any());
-
-        verifyOpenState(session, false);
-        session.onRangingClosed(REASON, PARAMS);
-        verify(callback, times(2)).onClosed(anyInt(), any());
-    }
-
-    @Test
-    public void testOnRangingResult_OnReportReceivedCalled() {
-        SessionHandle handle = new SessionHandle(123);
-        RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter adapter = mock(IUwbAdapter.class);
-        RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
-        verifyOpenState(session, false);
-
-        session.onRangingStarted(PARAMS);
-        verifyOpenState(session, true);
-
-        RangingReport report = UwbTestUtils.getRangingReports(1);
-        session.onRangingResult(report);
-        verify(callback, times(1)).onReportReceived(eq(report));
-    }
-
-    @Test
-    public void testStart_CannotStartIfAlreadyStarted() throws RemoteException {
-        SessionHandle handle = new SessionHandle(123);
-        RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter adapter = mock(IUwbAdapter.class);
-        RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
-        doAnswer(new StartAnswer(session)).when(adapter).startRanging(any(), any());
-        session.onRangingOpened();
-
-        session.start(PARAMS);
-        verify(callback, times(1)).onStarted(any());
-
-        // Calling start again should throw an illegal state
-        verifyThrowIllegalState(() -> session.start(PARAMS));
-        verify(callback, times(1)).onStarted(any());
-    }
-
-    @Test
-    public void testStop_CannotStopIfAlreadyStopped() throws RemoteException {
-        SessionHandle handle = new SessionHandle(123);
-        RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter adapter = mock(IUwbAdapter.class);
-        RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
-        doAnswer(new StartAnswer(session)).when(adapter).startRanging(any(), any());
-        doAnswer(new StopAnswer(session)).when(adapter).stopRanging(any());
-        session.onRangingOpened();
-        session.start(PARAMS);
-
-        verifyNoThrowIllegalState(session::stop);
-        verify(callback, times(1)).onStopped();
-
-        // Calling stop again should throw an illegal state
-        verifyThrowIllegalState(session::stop);
-        verify(callback, times(1)).onStopped();
-    }
-
-    @Test
-    public void testReconfigure_OnlyWhenOpened() throws RemoteException {
-        SessionHandle handle = new SessionHandle(123);
-        RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter adapter = mock(IUwbAdapter.class);
-        RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
-        doAnswer(new StartAnswer(session)).when(adapter).startRanging(any(), any());
-        doAnswer(new ReconfigureAnswer(session)).when(adapter).reconfigureRanging(any(), any());
-
-        verifyThrowIllegalState(() -> session.reconfigure(PARAMS));
-        verify(callback, times(0)).onReconfigured(any());
-        verifyOpenState(session, false);
-
-        session.onRangingOpened();
-        verifyNoThrowIllegalState(() -> session.reconfigure(PARAMS));
-        verify(callback, times(1)).onReconfigured(any());
-        verifyOpenState(session, true);
-
-        session.onRangingStarted(PARAMS);
-        verifyNoThrowIllegalState(() -> session.reconfigure(PARAMS));
-        verify(callback, times(2)).onReconfigured(any());
-        verifyOpenState(session, true);
-
-        session.onRangingStopped();
-        verifyNoThrowIllegalState(() -> session.reconfigure(PARAMS));
-        verify(callback, times(3)).onReconfigured(any());
-        verifyOpenState(session, true);
-
-
-        session.onRangingClosed(REASON, PARAMS);
-        verifyThrowIllegalState(() -> session.reconfigure(PARAMS));
-        verify(callback, times(3)).onReconfigured(any());
-        verifyOpenState(session, false);
-    }
-
-    @Test
-    public void testClose_NoCallbackUntilInvoked() throws RemoteException {
-        SessionHandle handle = new SessionHandle(123);
-        RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter adapter = mock(IUwbAdapter.class);
-        RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
-        session.onRangingOpened();
-
-        // Calling close multiple times should invoke closeRanging until the session receives
-        // the onClosed callback.
-        int totalCallsBeforeOnRangingClosed = 3;
-        for (int i = 1; i <= totalCallsBeforeOnRangingClosed; i++) {
-            session.close();
-            verifyOpenState(session, true);
-            verify(adapter, times(i)).closeRanging(handle);
-            verify(callback, times(0)).onClosed(anyInt(), any());
-        }
-
-        // After onClosed is invoked, then the adapter should no longer be called for each call to
-        // the session's close.
-        final int totalCallsAfterOnRangingClosed = 2;
-        for (int i = 1; i <= totalCallsAfterOnRangingClosed; i++) {
-            session.onRangingClosed(REASON, PARAMS);
-            verifyOpenState(session, false);
-            verify(adapter, times(totalCallsBeforeOnRangingClosed)).closeRanging(handle);
-            verify(callback, times(i)).onClosed(anyInt(), any());
-        }
-    }
-
-    @Test
-    public void testClose_OnClosedCalled() throws RemoteException {
-        SessionHandle handle = new SessionHandle(123);
-        RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter adapter = mock(IUwbAdapter.class);
-        RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
-        doAnswer(new CloseAnswer(session)).when(adapter).closeRanging(any());
-        session.onRangingOpened();
-
-        session.close();
-        verify(callback, times(1)).onClosed(anyInt(), any());
-    }
-
-    @Test
-    public void testClose_CannotInteractFurther() throws RemoteException {
-        SessionHandle handle = new SessionHandle(123);
-        RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter adapter = mock(IUwbAdapter.class);
-        RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
-        doAnswer(new CloseAnswer(session)).when(adapter).closeRanging(any());
-        session.close();
-
-        verifyThrowIllegalState(() -> session.start(PARAMS));
-        verifyThrowIllegalState(() -> session.reconfigure(PARAMS));
-        verifyThrowIllegalState(() -> session.stop());
-        verifyNoThrowIllegalState(() -> session.close());
-    }
-
-    @Test
-    public void testOnRangingResult_OnReportReceivedCalledWhenOpen() {
-        SessionHandle handle = new SessionHandle(123);
-        RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter adapter = mock(IUwbAdapter.class);
-        RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
-
-        assertFalse(session.isOpen());
-        session.onRangingStarted(PARAMS);
-        assertTrue(session.isOpen());
-
-        // Verify that the onReportReceived callback was invoked
-        RangingReport report = UwbTestUtils.getRangingReports(1);
-        session.onRangingResult(report);
-        verify(callback, times(1)).onReportReceived(report);
-    }
-
-    @Test
-    public void testOnRangingResult_OnReportReceivedNotCalledWhenNotOpen() {
-        SessionHandle handle = new SessionHandle(123);
-        RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter adapter = mock(IUwbAdapter.class);
-        RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
-
-        assertFalse(session.isOpen());
-
-        // Verify that the onReportReceived callback was invoked
-        RangingReport report = UwbTestUtils.getRangingReports(1);
-        session.onRangingResult(report);
-        verify(callback, times(0)).onReportReceived(report);
-    }
-
-    private void verifyOpenState(RangingSession session, boolean expected) {
-        assertEquals(expected, session.isOpen());
-    }
-
-    private void verifyThrowIllegalState(Runnable runnable) {
-        try {
-            runnable.run();
-            fail();
-        } catch (IllegalStateException e) {
-            // Pass
-        }
-    }
-
-    private void verifyNoThrowIllegalState(Runnable runnable) {
-        try {
-            runnable.run();
-        } catch (IllegalStateException e) {
-            fail();
-        }
-    }
-
-    abstract class AdapterAnswer implements Answer {
-        protected RangingSession mSession;
-
-        protected AdapterAnswer(RangingSession session) {
-            mSession = session;
-        }
-    }
-
-    class StartAnswer extends AdapterAnswer {
-        StartAnswer(RangingSession session) {
-            super(session);
-        }
-
-        @Override
-        public Object answer(InvocationOnMock invocation) {
-            mSession.onRangingStarted(PARAMS);
-            return null;
-        }
-    }
-
-    class ReconfigureAnswer extends AdapterAnswer {
-        ReconfigureAnswer(RangingSession session) {
-            super(session);
-        }
-
-        @Override
-        public Object answer(InvocationOnMock invocation) {
-            mSession.onRangingReconfigured(PARAMS);
-            return null;
-        }
-    }
-
-    class StopAnswer extends AdapterAnswer {
-        StopAnswer(RangingSession session) {
-            super(session);
-        }
-
-        @Override
-        public Object answer(InvocationOnMock invocation) {
-            mSession.onRangingStopped();
-            return null;
-        }
-    }
-
-    class CloseAnswer extends AdapterAnswer {
-        CloseAnswer(RangingSession session) {
-            super(session);
-        }
-
-        @Override
-        public Object answer(InvocationOnMock invocation) {
-            mSession.onRangingClosed(REASON, PARAMS);
-            return null;
-        }
-    }
-}
diff --git a/core/tests/uwbtests/src/android/uwb/SessionHandleTest.java b/core/tests/uwbtests/src/android/uwb/SessionHandleTest.java
deleted file mode 100644
index 8b42ff7..0000000
--- a/core/tests/uwbtests/src/android/uwb/SessionHandleTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import static org.junit.Assert.assertEquals;
-
-import android.os.Parcel;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test of {@link SessionHandle}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class SessionHandleTest {
-
-    @Test
-    public void testBasic() {
-        int handleId = 12;
-        SessionHandle handle = new SessionHandle(handleId);
-        assertEquals(handle.getId(), handleId);
-    }
-
-    @Test
-    public void testParcel() {
-        Parcel parcel = Parcel.obtain();
-        SessionHandle handle = new SessionHandle(10);
-        handle.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        SessionHandle fromParcel = SessionHandle.CREATOR.createFromParcel(parcel);
-        assertEquals(handle, fromParcel);
-    }
-}
diff --git a/core/tests/uwbtests/src/android/uwb/UwbAddressTest.java b/core/tests/uwbtests/src/android/uwb/UwbAddressTest.java
deleted file mode 100644
index ccc88a9..0000000
--- a/core/tests/uwbtests/src/android/uwb/UwbAddressTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import static org.junit.Assert.assertEquals;
-
-import android.os.Parcel;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test of {@link UwbAddress}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class UwbAddressTest {
-
-    @Test
-    public void testFromBytes_Short() {
-        runFromBytes(UwbAddress.SHORT_ADDRESS_BYTE_LENGTH);
-    }
-
-    @Test
-    public void testFromBytes_Extended() {
-        runFromBytes(UwbAddress.EXTENDED_ADDRESS_BYTE_LENGTH);
-    }
-
-    private void runFromBytes(int len) {
-        byte[] addressBytes = getByteArray(len);
-        UwbAddress address = UwbAddress.fromBytes(addressBytes);
-        assertEquals(address.size(), len);
-        assertEquals(addressBytes, address.toBytes());
-    }
-
-    private byte[] getByteArray(int len) {
-        byte[] res = new byte[len];
-        for (int i = 0; i < len; i++) {
-            res[i] = (byte) i;
-        }
-        return res;
-    }
-
-    @Test
-    public void testParcel_Short() {
-        runParcel(true);
-    }
-
-    @Test
-    public void testParcel_Extended() {
-        runParcel(false);
-    }
-
-    private void runParcel(boolean useShortAddress) {
-        Parcel parcel = Parcel.obtain();
-        UwbAddress address = UwbTestUtils.getUwbAddress(useShortAddress);
-        address.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        UwbAddress fromParcel = UwbAddress.CREATOR.createFromParcel(parcel);
-        assertEquals(address, fromParcel);
-    }
-}
diff --git a/core/tests/uwbtests/src/android/uwb/UwbManagerTest.java b/core/tests/uwbtests/src/android/uwb/UwbManagerTest.java
deleted file mode 100644
index 4983bed..0000000
--- a/core/tests/uwbtests/src/android/uwb/UwbManagerTest.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import android.content.Context;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test of {@link UwbManager}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class UwbManagerTest {
-
-    public final Context mContext = InstrumentationRegistry.getContext();
-
-    @Test
-    public void testServiceAvailable() {
-        UwbManager manager = mContext.getSystemService(UwbManager.class);
-        if (UwbTestUtils.isUwbSupported(mContext)) {
-            assertNotNull(manager);
-        } else {
-            assertNull(manager);
-        }
-    }
-}
diff --git a/core/xsd/Android.bp b/core/xsd/Android.bp
index 738f330..5387f85 100644
--- a/core/xsd/Android.bp
+++ b/core/xsd/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 xsd_config {
     name: "permission",
     srcs: ["permission.xsd"],
diff --git a/core/xsd/vts/Android.bp b/core/xsd/vts/Android.bp
index ca655f1..5d8407f 100644
--- a/core/xsd/vts/Android.bp
+++ b/core/xsd/vts/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_test {
     name: "vts_permission_validate_test",
     srcs: [
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index 201f649..85b60f8 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -15,6 +15,15 @@
 
 // Sysconfig files
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 prebuilt_etc {
     name: "framework-sysconfig.xml",
     sub_dir: "sysconfig",
diff --git a/data/etc/car/Android.bp b/data/etc/car/Android.bp
index 41a6fea..2f41b90 100644
--- a/data/etc/car/Android.bp
+++ b/data/etc/car/Android.bp
@@ -16,6 +16,15 @@
 
 // Privapp permission whitelist files
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 prebuilt_etc {
     name: "allowed_privapp_android.car.cluster.loggingrenderer",
     sub_dir: "permissions",
@@ -164,3 +173,10 @@
     src: "com.android.car.shell.xml",
     filename_from_src: true,
 }
+
+prebuilt_etc {
+    name: "allowed_privapp_com.android.car.activityresolver",
+    sub_dir: "permissions",
+    src: "com.android.car.activityresolver.xml",
+    filename_from_src: true,
+}
diff --git a/data/etc/car/android.car.cluster.xml b/data/etc/car/android.car.cluster.xml
index d7f29da..de3acca 100644
--- a/data/etc/car/android.car.cluster.xml
+++ b/data/etc/car/android.car.cluster.xml
@@ -20,5 +20,7 @@
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
         <permission name="android.permission.MANAGE_USERS"/>
         <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+        <permission name="android.car.permission.CAR_ENGINE_DETAILED"/>
+        <permission name="android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL"/>
     </privapp-permissions>
 </permissions>
diff --git a/packages/SystemUI/res/drawable/toast_background.xml b/data/etc/car/com.android.car.activityresolver.xml
similarity index 76%
rename from packages/SystemUI/res/drawable/toast_background.xml
rename to data/etc/car/com.android.car.activityresolver.xml
index 5c45e83..d48bc15 100644
--- a/packages/SystemUI/res/drawable/toast_background.xml
+++ b/data/etc/car/com.android.car.activityresolver.xml
@@ -14,8 +14,8 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-    <solid android:color="#FFFFFFFF" />
-    <corners android:radius="@dimen/toast_bg_radius" />
-</shape>
+<permissions>
+    <privapp-permissions package="com.android.car.activityresolver">
+        <permission name="android.permission.MANAGE_USERS"/>
+    </privapp-permissions>
+</permissions>
diff --git a/data/etc/car/com.android.car.bugreport.xml b/data/etc/car/com.android.car.bugreport.xml
index 432a838..2ff9835 100644
--- a/data/etc/car/com.android.car.bugreport.xml
+++ b/data/etc/car/com.android.car.bugreport.xml
@@ -20,5 +20,7 @@
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
         <permission name="android.permission.READ_LOGS"/>
         <permission name="android.permission.MANAGE_USERS"/>
+        <permission name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS"/>
+        <permission name="android.car.permission.CAR_DRIVING_STATE"/>
     </privapp-permissions>
   </permissions>
diff --git a/data/etc/car/com.android.car.carlauncher.xml b/data/etc/car/com.android.car.carlauncher.xml
index 0e49284..ac16af3 100644
--- a/data/etc/car/com.android.car.carlauncher.xml
+++ b/data/etc/car/com.android.car.carlauncher.xml
@@ -17,9 +17,10 @@
 <permissions>
     <privapp-permissions package="com.android.car.carlauncher">
         <permission name="android.permission.ACTIVITY_EMBEDDING"/>
-	<permission name="android.permission.CONTROL_INCALL_EXPERIENCE"/>
+        <permission name="android.permission.CONTROL_INCALL_EXPERIENCE"/>
         <permission name="android.permission.MANAGE_USERS"/>
         <permission name="android.permission.MEDIA_CONTENT_CONTROL"/>
         <permission name="android.permission.PACKAGE_USAGE_STATS"/>
+        <permission name="android.car.permission.ACCESS_CAR_PROJECTION_STATUS"/>
     </privapp-permissions>
 </permissions>
diff --git a/data/etc/car/com.android.car.dialer.xml b/data/etc/car/com.android.car.dialer.xml
index d44f5a1..61ae53a 100644
--- a/data/etc/car/com.android.car.dialer.xml
+++ b/data/etc/car/com.android.car.dialer.xml
@@ -18,5 +18,6 @@
     <privapp-permissions package="com.android.car.dialer">
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
         <permission name="android.permission.MODIFY_PHONE_STATE"/>
+        <permission name="android.car.permission.ACCESS_CAR_PROJECTION_STATUS"/>
     </privapp-permissions>
 </permissions>
diff --git a/data/etc/car/com.android.car.hvac.xml b/data/etc/car/com.android.car.hvac.xml
index d3631e0..534d44d 100644
--- a/data/etc/car/com.android.car.hvac.xml
+++ b/data/etc/car/com.android.car.hvac.xml
@@ -17,5 +17,6 @@
 <permissions>
     <privapp-permissions package="com.android.car.hvac">
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+        <permission name="android.car.permission.CONTROL_CAR_CLIMATE"/>
     </privapp-permissions>
 </permissions>
diff --git a/data/etc/car/com.android.car.radio.xml b/data/etc/car/com.android.car.radio.xml
index d7853ab..ed8652c 100644
--- a/data/etc/car/com.android.car.radio.xml
+++ b/data/etc/car/com.android.car.radio.xml
@@ -18,5 +18,7 @@
     <privapp-permissions package="com.android.car.radio">
         <permission name="android.permission.ACCESS_BROADCAST_RADIO"/>
         <permission name="android.permission.MEDIA_CONTENT_CONTROL"/>
+        <permission name="android.car.permission.CAR_CONTROL_AUDIO_SETTINGS"/>
+        <permission name="android.car.permission.CAR_CONTROL_AUDIO_VOLUME"/>
     </privapp-permissions>
 </permissions>
diff --git a/data/etc/car/com.google.android.car.kitchensink.xml b/data/etc/car/com.google.android.car.kitchensink.xml
index bd30d7a..e6196c2 100644
--- a/data/etc/car/com.google.android.car.kitchensink.xml
+++ b/data/etc/car/com.google.android.car.kitchensink.xml
@@ -51,5 +51,41 @@
 
         <!-- use for rotary fragment to enable/disable packages related to rotary -->
         <permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
+
+        <!-- CarService permissions -->
+        <!-- TODO: Explain why so many permissions are required -->
+        <permission name="android.car.permission.ACCESS_CAR_PROJECTION_STATUS"/>
+        <permission name="android.car.permission.CAR_CONTROL_AUDIO_SETTINGS"/>
+        <permission name="android.car.permission.CAR_CONTROL_AUDIO_VOLUME"/>
+        <permission name="android.car.permission.CAR_DIAGNOSTICS"/>
+        <permission name="android.car.permission.CAR_DISPLAY_IN_CLUSTER"/>
+        <permission name="android.car.permission.CAR_DRIVING_STATE"/>
+        <permission name="android.car.permission.CAR_DYNAMICS_STATE"/>
+        <permission name="android.car.permission.CAR_EXTERIOR_LIGHTS"/>
+        <permission name="android.car.permission.CAR_IDENTIFICATION"/>
+        <permission name="android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL"/>
+        <permission name="android.car.permission.CAR_MILEAGE"/>
+        <permission name="android.car.permission.CAR_MOCK_VEHICLE_HAL"/>
+        <permission name="android.car.permission.CAR_NAVIGATION_MANAGER"/>
+        <permission name="android.car.permission.CAR_POWER"/>
+        <permission name="android.car.permission.CAR_PROJECTION"/>
+        <permission name="android.car.permission.CAR_TIRES"/>
+        <permission name="android.car.permission.CAR_TEST_SERVICE"/>
+        <permission name="android.car.permission.CAR_UX_RESTRICTIONS_CONFIGURATION"/>
+        <permission name="android.car.permission.CAR_VENDOR_EXTENSION"/>
+        <permission name="android.car.permission.CONTROL_CAR_CLIMATE"/>
+        <permission name="android.car.permission.CONTROL_CAR_DOORS"/>
+        <permission name="android.car.permission.CONTROL_CAR_EXTERIOR_LIGHTS"/>
+        <permission name="android.car.permission.CONTROL_CAR_FEATURES"/>
+        <permission name="android.car.permission.CONTROL_CAR_MIRRORS"/>
+        <permission name="android.car.permission.CONTROL_CAR_SEATS"/>
+        <permission name="android.car.permission.CONTROL_CAR_WINDOWS"/>
+        <permission name="android.car.permission.GET_CAR_VENDOR_CATEGORY_INFO"/>
+        <permission name="android.car.permission.GET_CAR_VENDOR_CATEGORY_SEAT"/>
+        <permission name="android.car.permission.READ_CAR_STEERING"/>
+        <permission name="android.car.permission.SET_CAR_VENDOR_CATEGORY_INFO"/>
+        <permission name="android.car.permission.STORAGE_MONITORING"/>
+        <permission name="android.car.permission.VMS_PUBLISHER"/>
+        <permission name="android.car.permission.VMS_SUBSCRIBER"/>
     </privapp-permissions>
 </permissions>
diff --git a/data/etc/car/com.google.android.car.networking.preferenceupdater.xml b/data/etc/car/com.google.android.car.networking.preferenceupdater.xml
index 489ce1b..cdeb8e4 100644
--- a/data/etc/car/com.google.android.car.networking.preferenceupdater.xml
+++ b/data/etc/car/com.google.android.car.networking.preferenceupdater.xml
@@ -16,12 +16,21 @@
   -->
 <permissions>
     <privapp-permissions package="com.google.android.car.networking.preferenceupdater">
-        <permission name="android.permission.ACCESS_NETWORK_STATE"/>
+        <permission name="android.permission.ACCESS_NETWORK_STATE" />
         <permission name="android.permission.ACCESS_WIFI_STATE"/>
         <permission name="android.permission.ACTIVITY_EMBEDDING"/>
+        <permission name="android.permission.CHANGE_NETWORK_STATE" />
+        <permission name="android.permission.CONNECTIVITY_INTERNAL" />
+        <permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/>
+        <permission name="android.permission.CONTROL_OEM_PAID_NETWORK_PREFERNCE" />
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
         <permission name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
-        <permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/>
+        <permission name="android.permission.INTERNET" />
         <permission name="android.permission.LOCATION_HARDWARE"/>
+        <permission name="android.permission.PACKAGE_USAGE_STATS" />
+        <permission name="android.permission.RECEIVE_BOOT_COMPLETED" />
+        <permission name="android.permission.WAKE_LOCK" />
+        <permission name="android.permission.WRITE_SETTINGS" />
+        <permission name="android.car.permission.CAR_DRIVING_STATE" />
     </privapp-permissions>
 </permissions>
diff --git a/data/etc/com.android.emergency.xml b/data/etc/com.android.emergency.xml
index fa92b6d..2d6ae2e 100644
--- a/data/etc/com.android.emergency.xml
+++ b/data/etc/com.android.emergency.xml
@@ -21,5 +21,7 @@
         <permission name="android.permission.MANAGE_USERS"/>
         <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
         <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
+        <!-- Required to update emergency gesture settings -->
+        <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
     </privapp-permissions>
 </permissions>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 1871e08..48b297d 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -68,6 +68,11 @@
         <permission name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
     </privapp-permissions>
 
+    <privapp-permissions package="com.android.imsserviceentitlement">
+        <permission name="android.permission.MODIFY_PHONE_STATE" />
+        <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
+    </privapp-permissions>
+
     <privapp-permissions package="com.android.launcher3">
         <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
     </privapp-permissions>
@@ -406,8 +411,6 @@
         <permission name="android.permission.SET_WALLPAPER" />
         <permission name="android.permission.SET_WALLPAPER_COMPONENT" />
         <permission name="android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE" />
-        <!-- Permissions required for Incremental CTS tests -->
-        <permission name="com.android.permission.USE_INSTALLER_V2"/>
         <permission name="android.permission.LOADER_USAGE_STATS"/>
         <!-- Permission required to test system only camera devices. -->
         <permission name="android.permission.SYSTEM_CAMERA" />
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 84da930..cabfad4 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -259,6 +259,12 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "-1834214907": {
+      "message": "createNonAppWindowAnimations()",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
+      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
+    },
     "-1824578273": {
       "message": "Reporting new frame to %s: %s",
       "level": "VERBOSE",
@@ -811,6 +817,18 @@
       "group": "WM_DEBUG_RECENTS_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RecentsAnimation.java"
     },
+    "-1153814764": {
+      "message": "onAnimationCancelled",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
+      "at": "com\/android\/server\/wm\/NonAppWindowAnimationAdapter.java"
+    },
+    "-1144293044": {
+      "message": "SURFACE SET FREEZE LAYER: %s",
+      "level": "INFO",
+      "group": "WM_SHOW_TRANSACTIONS",
+      "at": "com\/android\/server\/wm\/WindowStateAnimator.java"
+    },
     "-1142279614": {
       "message": "Looking for focus: %s, flags=%d, canReceive=%b, reason=%s",
       "level": "VERBOSE",
@@ -1303,6 +1321,12 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/DisplayRotation.java"
     },
+    "-567946587": {
+      "message": "Requested redraw for orientation change: %s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ORIENTATION",
+      "at": "com\/android\/server\/wm\/WindowState.java"
+    },
     "-561092364": {
       "message": "onPointerDownOutsideFocusLocked called on %s",
       "level": "INFO",
diff --git a/data/fonts/Android.bp b/data/fonts/Android.bp
index ee5c5b0..f90a74d 100644
--- a/data/fonts/Android.bp
+++ b/data/fonts/Android.bp
@@ -12,6 +12,23 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: ["frameworks_base_data_fonts_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_data_fonts_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 prebuilt_font {
     name: "DroidSansMono.ttf",
     src: "DroidSansMono.ttf",
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 2db4c5d..66b8eae 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -223,7 +223,7 @@
     <alias name="sans-serif-condensed-medium" to="sans-serif-condensed" weight="500" />
 
     <family name="serif">
-        <font weight="400" style="normal">NotoSerif-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSerif.ttf</font>
         <font weight="700" style="normal">NotoSerif-Bold.ttf</font>
         <font weight="400" style="italic">NotoSerif-Italic.ttf</font>
         <font weight="700" style="italic">NotoSerif-BoldItalic.ttf</font>
@@ -245,7 +245,7 @@
     <alias name="monaco" to="monospace" />
 
     <family name="serif-monospace">
-        <font weight="400" style="normal">CutiveMono.ttf</font>
+        <font weight="400" style="normal">CutiveMono-Regular.ttf</font>
     </family>
     <alias name="courier" to="serif-monospace" />
     <alias name="courier new" to="serif-monospace" />
@@ -255,7 +255,7 @@
     </family>
 
     <family name="cursive">
-        <font weight="400" style="normal">DancingScript-Regular.ttf</font>
+        <font weight="400" style="normal">DancingScript.ttf</font>
         <font weight="700" style="normal">DancingScript-Bold.ttf</font>
     </family>
 
@@ -275,144 +275,144 @@
 
     <!-- fallback fonts -->
     <family lang="und-Arab" variant="elegant">
-        <font weight="400" style="normal">NotoNaskhArabic-Regular.ttf</font>
+        <font weight="400" style="normal">NotoNaskhArabic.ttf</font>
         <font weight="700" style="normal">NotoNaskhArabic-Bold.ttf</font>
     </family>
     <family lang="und-Arab" variant="compact">
-        <font weight="400" style="normal">NotoNaskhArabicUI-Regular.ttf</font>
+        <font weight="400" style="normal">NotoNaskhArabicUI.ttf</font>
         <font weight="700" style="normal">NotoNaskhArabicUI-Bold.ttf</font>
     </family>
     <family lang="und-Ethi">
-	      <font weight="400" style="normal">NotoSansEthiopic-VF.ttf
+	      <font weight="400" style="normal">NotoSansEthiopic-Regular.ttf
 	          <axis tag="wght" stylevalue="400"/>
 	      </font>
-	      <font weight="500" style="normal">NotoSansEthiopic-VF.ttf
+	      <font weight="500" style="normal">NotoSansEthiopic-Regular.ttf
 	          <axis tag="wght" stylevalue="500"/>
 	      </font>
-	      <font weight="600" style="normal">NotoSansEthiopic-VF.ttf
+	      <font weight="600" style="normal">NotoSansEthiopic-Regular.ttf
 	          <axis tag="wght" stylevalue="600"/>
 	      </font>
-	      <font weight="700" style="normal">NotoSansEthiopic-VF.ttf
+	      <font weight="700" style="normal">NotoSansEthiopic-Regular.ttf
 	          <axis tag="wght" stylevalue="700"/>
 	      </font>
-	      <font weight="400" style="normal" fallbackFor="serif">NotoSerifEthiopic-VF.ttf
+	      <font weight="400" style="normal" fallbackFor="serif">NotoSerifEthiopic-Regular.ttf
 	          <axis tag="wght" stylevalue="400"/>
 	      </font>
-	      <font weight="500" style="normal" fallbackFor="serif">NotoSerifEthiopic-VF.ttf
+	      <font weight="500" style="normal" fallbackFor="serif">NotoSerifEthiopic-Regular.ttf
 	          <axis tag="wght" stylevalue="500"/>
 	      </font>
-	      <font weight="600" style="normal" fallbackFor="serif">NotoSerifEthiopic-VF.ttf
+	      <font weight="600" style="normal" fallbackFor="serif">NotoSerifEthiopic-Regular.ttf
 	          <axis tag="wght" stylevalue="600"/>
 	      </font>
-	      <font weight="700" style="normal" fallbackFor="serif">NotoSerifEthiopic-VF.ttf
+	      <font weight="700" style="normal" fallbackFor="serif">NotoSerifEthiopic-Regular.ttf
 	          <axis tag="wght" stylevalue="700"/>
 	      </font>
     </family>
     <family lang="und-Hebr">
-        <font weight="400" style="normal">NotoSansHebrew-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansHebrew.ttf</font>
         <font weight="700" style="normal">NotoSansHebrew-Bold.ttf</font>
         <font weight="400" style="normal" fallbackFor="serif">NotoSerifHebrew-Regular.ttf</font>
         <font weight="700" style="normal" fallbackFor="serif">NotoSerifHebrew-Bold.ttf</font>
     </family>
     <family lang="und-Thai" variant="elegant">
-        <font weight="400" style="normal">NotoSansThai-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansThai.ttf</font>
         <font weight="700" style="normal">NotoSansThai-Bold.ttf</font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifThai-Regular.ttf</font>
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifThai.ttf</font>
         <font weight="700" style="normal" fallbackFor="serif">NotoSerifThai-Bold.ttf</font>
     </family>
     <family lang="und-Thai" variant="compact">
-        <font weight="400" style="normal">NotoSansThaiUI-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansThaiUI.ttf</font>
         <font weight="700" style="normal">NotoSansThaiUI-Bold.ttf</font>
     </family>
     <family lang="und-Armn">
-        <font weight="400" style="normal">NotoSansArmenian-VF.ttf
+        <font weight="400" style="normal">NotoSansArmenian-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansArmenian-VF.ttf
+        <font weight="500" style="normal">NotoSansArmenian-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansArmenian-VF.ttf
+        <font weight="600" style="normal">NotoSansArmenian-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansArmenian-VF.ttf
+        <font weight="700" style="normal">NotoSansArmenian-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifArmenian-VF.ttf
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifArmenian-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal" fallbackFor="serif">NotoSerifArmenian-VF.ttf
+        <font weight="500" style="normal" fallbackFor="serif">NotoSerifArmenian-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal" fallbackFor="serif">NotoSerifArmenian-VF.ttf
+        <font weight="600" style="normal" fallbackFor="serif">NotoSerifArmenian-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal" fallbackFor="serif">NotoSerifArmenian-VF.ttf
+        <font weight="700" style="normal" fallbackFor="serif">NotoSerifArmenian-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Geor,und-Geok">
-        <font weight="400" style="normal">NotoSansGeorgian-VF.ttf
+        <font weight="400" style="normal">NotoSansGeorgian-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansGeorgian-VF.ttf
+        <font weight="500" style="normal">NotoSansGeorgian-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansGeorgian-VF.ttf
+        <font weight="600" style="normal">NotoSansGeorgian-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansGeorgian-VF.ttf
+        <font weight="700" style="normal">NotoSansGeorgian-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifGeorgian-VF.ttf
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifGeorgian-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal" fallbackFor="serif">NotoSerifGeorgian-VF.ttf
+        <font weight="500" style="normal" fallbackFor="serif">NotoSerifGeorgian-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal" fallbackFor="serif">NotoSerifGeorgian-VF.ttf
+        <font weight="600" style="normal" fallbackFor="serif">NotoSerifGeorgian-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal" fallbackFor="serif">NotoSerifGeorgian-VF.ttf
+        <font weight="700" style="normal" fallbackFor="serif">NotoSerifGeorgian-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Deva" variant="elegant">
-        <font weight="400" style="normal">NotoSansDevanagari-VF.ttf
+        <font weight="400" style="normal">NotoSansDevanagari-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansDevanagari-VF.ttf
+        <font weight="500" style="normal">NotoSansDevanagari-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansDevanagari-VF.ttf
+        <font weight="600" style="normal">NotoSansDevanagari-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansDevanagari-VF.ttf
+        <font weight="700" style="normal">NotoSansDevanagari-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifDevanagari-VF.ttf
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifDevanagari-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal" fallbackFor="serif">NotoSerifDevanagari-VF.ttf
+        <font weight="500" style="normal" fallbackFor="serif">NotoSerifDevanagari-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal" fallbackFor="serif">NotoSerifDevanagari-VF.ttf
+        <font weight="600" style="normal" fallbackFor="serif">NotoSerifDevanagari-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal" fallbackFor="serif">NotoSerifDevanagari-VF.ttf
+        <font weight="700" style="normal" fallbackFor="serif">NotoSerifDevanagari-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Deva" variant="compact">
-        <font weight="400" style="normal">NotoSansDevanagariUI-VF.ttf
+        <font weight="400" style="normal">NotoSansDevanagariUI-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansDevanagariUI-VF.ttf
+        <font weight="500" style="normal">NotoSansDevanagariUI-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansDevanagariUI-VF.ttf
+        <font weight="600" style="normal">NotoSansDevanagariUI-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansDevanagariUI-VF.ttf
+        <font weight="700" style="normal">NotoSansDevanagariUI-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
@@ -421,347 +421,347 @@
          danda characters.
     -->
     <family lang="und-Gujr" variant="elegant">
-        <font weight="400" style="normal">NotoSansGujarati-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansGujarati.ttf</font>
         <font weight="700" style="normal">NotoSansGujarati-Bold.ttf</font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifGujarati-VF.ttf
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifGujarati-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal" fallbackFor="serif">NotoSerifGujarati-VF.ttf
+        <font weight="500" style="normal" fallbackFor="serif">NotoSerifGujarati-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal" fallbackFor="serif">NotoSerifGujarati-VF.ttf
+        <font weight="600" style="normal" fallbackFor="serif">NotoSerifGujarati-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal" fallbackFor="serif">NotoSerifGujarati-VF.ttf
+        <font weight="700" style="normal" fallbackFor="serif">NotoSerifGujarati-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Gujr" variant="compact">
-        <font weight="400" style="normal">NotoSansGujaratiUI-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansGujaratiUI.ttf</font>
         <font weight="700" style="normal">NotoSansGujaratiUI-Bold.ttf</font>
     </family>
     <family lang="und-Guru" variant="elegant">
-        <font weight="400" style="normal">NotoSansGurmukhi-VF.ttf
+        <font weight="400" style="normal">NotoSansGurmukhi-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansGurmukhi-VF.ttf
+        <font weight="500" style="normal">NotoSansGurmukhi-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansGurmukhi-VF.ttf
+        <font weight="600" style="normal">NotoSansGurmukhi-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansGurmukhi-VF.ttf
+        <font weight="700" style="normal">NotoSansGurmukhi-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifGurmukhi-VF.ttf
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifGurmukhi-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal" fallbackFor="serif">NotoSerifGurmukhi-VF.ttf
+        <font weight="500" style="normal" fallbackFor="serif">NotoSerifGurmukhi-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal" fallbackFor="serif">NotoSerifGurmukhi-VF.ttf
+        <font weight="600" style="normal" fallbackFor="serif">NotoSerifGurmukhi-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal" fallbackFor="serif">NotoSerifGurmukhi-VF.ttf
+        <font weight="700" style="normal" fallbackFor="serif">NotoSerifGurmukhi-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Guru" variant="compact">
-        <font weight="400" style="normal">NotoSansGurmukhiUI-VF.ttf
+        <font weight="400" style="normal">NotoSansGurmukhiUI-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansGurmukhiUI-VF.ttf
+        <font weight="500" style="normal">NotoSansGurmukhiUI-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansGurmukhiUI-VF.ttf
+        <font weight="600" style="normal">NotoSansGurmukhiUI-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansGurmukhiUI-VF.ttf
+        <font weight="700" style="normal">NotoSansGurmukhiUI-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Taml" variant="elegant">
-        <font weight="400" style="normal">NotoSansTamil-VF.ttf
+        <font weight="400" style="normal">NotoSansTamil-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansTamil-VF.ttf
+        <font weight="500" style="normal">NotoSansTamil-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansTamil-VF.ttf
+        <font weight="600" style="normal">NotoSansTamil-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansTamil-VF.ttf
+        <font weight="700" style="normal">NotoSansTamil-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifTamil-VF.ttf
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifTamil-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal" fallbackFor="serif">NotoSerifTamil-VF.ttf
+        <font weight="500" style="normal" fallbackFor="serif">NotoSerifTamil-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal" fallbackFor="serif">NotoSerifTamil-VF.ttf
+        <font weight="600" style="normal" fallbackFor="serif">NotoSerifTamil-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal" fallbackFor="serif">NotoSerifTamil-VF.ttf
+        <font weight="700" style="normal" fallbackFor="serif">NotoSerifTamil-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Taml" variant="compact">
-        <font weight="400" style="normal">NotoSansTamilUI-VF.ttf
+        <font weight="400" style="normal">NotoSansTamilUI-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansTamilUI-VF.ttf
+        <font weight="500" style="normal">NotoSansTamilUI-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansTamilUI-VF.ttf
+        <font weight="600" style="normal">NotoSansTamilUI-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansTamilUI-VF.ttf
+        <font weight="700" style="normal">NotoSansTamilUI-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Mlym" variant="elegant">
-        <font weight="400" style="normal">NotoSansMalayalam-VF.ttf
+        <font weight="400" style="normal">NotoSansMalayalam-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansMalayalam-VF.ttf
+        <font weight="500" style="normal">NotoSansMalayalam-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansMalayalam-VF.ttf
+        <font weight="600" style="normal">NotoSansMalayalam-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansMalayalam-VF.ttf
+        <font weight="700" style="normal">NotoSansMalayalam-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifMalayalam-VF.ttf
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifMalayalam-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal" fallbackFor="serif">NotoSerifMalayalam-VF.ttf
+        <font weight="500" style="normal" fallbackFor="serif">NotoSerifMalayalam-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal" fallbackFor="serif">NotoSerifMalayalam-VF.ttf
+        <font weight="600" style="normal" fallbackFor="serif">NotoSerifMalayalam-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal" fallbackFor="serif">NotoSerifMalayalam-VF.ttf
+        <font weight="700" style="normal" fallbackFor="serif">NotoSerifMalayalam-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Mlym" variant="compact">
-        <font weight="400" style="normal">NotoSansMalayalamUI-VF.ttf
+        <font weight="400" style="normal">NotoSansMalayalamUI-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansMalayalamUI-VF.ttf
+        <font weight="500" style="normal">NotoSansMalayalamUI-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansMalayalamUI-VF.ttf
+        <font weight="600" style="normal">NotoSansMalayalamUI-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansMalayalamUI-VF.ttf
+        <font weight="700" style="normal">NotoSansMalayalamUI-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Beng" variant="elegant">
-        <font weight="400" style="normal">NotoSansBengali-VF.ttf
+        <font weight="400" style="normal">NotoSansBengali-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansBengali-VF.ttf
+        <font weight="500" style="normal">NotoSansBengali-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansBengali-VF.ttf
+        <font weight="600" style="normal">NotoSansBengali-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansBengali-VF.ttf
+        <font weight="700" style="normal">NotoSansBengali-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifBengali-VF.ttf
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifBengali-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal" fallbackFor="serif">NotoSerifBengali-VF.ttf
+        <font weight="500" style="normal" fallbackFor="serif">NotoSerifBengali-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal" fallbackFor="serif">NotoSerifBengali-VF.ttf
+        <font weight="600" style="normal" fallbackFor="serif">NotoSerifBengali-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal" fallbackFor="serif">NotoSerifBengali-VF.ttf
+        <font weight="700" style="normal" fallbackFor="serif">NotoSerifBengali-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Beng" variant="compact">
-        <font weight="400" style="normal">NotoSansBengaliUI-VF.ttf
+        <font weight="400" style="normal">NotoSansBengaliUI-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansBengaliUI-VF.ttf
+        <font weight="500" style="normal">NotoSansBengaliUI-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansBengaliUI-VF.ttf
+        <font weight="600" style="normal">NotoSansBengaliUI-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansBengaliUI-VF.ttf
+        <font weight="700" style="normal">NotoSansBengaliUI-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Telu" variant="elegant">
-        <font weight="400" style="normal">NotoSansTelugu-VF.ttf
+        <font weight="400" style="normal">NotoSansTelugu-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansTelugu-VF.ttf
+        <font weight="500" style="normal">NotoSansTelugu-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansTelugu-VF.ttf
+        <font weight="600" style="normal">NotoSansTelugu-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansTelugu-VF.ttf
+        <font weight="700" style="normal">NotoSansTelugu-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifTelugu-VF.ttf
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifTelugu-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal" fallbackFor="serif">NotoSerifTelugu-VF.ttf
+        <font weight="500" style="normal" fallbackFor="serif">NotoSerifTelugu-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal" fallbackFor="serif">NotoSerifTelugu-VF.ttf
+        <font weight="600" style="normal" fallbackFor="serif">NotoSerifTelugu-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal" fallbackFor="serif">NotoSerifTelugu-VF.ttf
+        <font weight="700" style="normal" fallbackFor="serif">NotoSerifTelugu-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Telu" variant="compact">
-        <font weight="400" style="normal">NotoSansTeluguUI-VF.ttf
+        <font weight="400" style="normal">NotoSansTeluguUI-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansTeluguUI-VF.ttf
+        <font weight="500" style="normal">NotoSansTeluguUI-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansTeluguUI-VF.ttf
+        <font weight="600" style="normal">NotoSansTeluguUI-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansTeluguUI-VF.ttf
+        <font weight="700" style="normal">NotoSansTeluguUI-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Knda" variant="elegant">
-        <font weight="400" style="normal">NotoSansKannada-VF.ttf
+        <font weight="400" style="normal">NotoSansKannada-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansKannada-VF.ttf
+        <font weight="500" style="normal">NotoSansKannada-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansKannada-VF.ttf
+        <font weight="600" style="normal">NotoSansKannada-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansKannada-VF.ttf
+        <font weight="700" style="normal">NotoSansKannada-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifKannada-VF.ttf
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifKannada-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal" fallbackFor="serif">NotoSerifKannada-VF.ttf
+        <font weight="500" style="normal" fallbackFor="serif">NotoSerifKannada-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal" fallbackFor="serif">NotoSerifKannada-VF.ttf
+        <font weight="600" style="normal" fallbackFor="serif">NotoSerifKannada-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal" fallbackFor="serif">NotoSerifKannada-VF.ttf
+        <font weight="700" style="normal" fallbackFor="serif">NotoSerifKannada-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Knda" variant="compact">
-        <font weight="400" style="normal">NotoSansKannadaUI-VF.ttf
+        <font weight="400" style="normal">NotoSansKannadaUI-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansKannadaUI-VF.ttf
+        <font weight="500" style="normal">NotoSansKannadaUI-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansKannadaUI-VF.ttf
+        <font weight="600" style="normal">NotoSansKannadaUI-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansKannadaUI-VF.ttf
+        <font weight="700" style="normal">NotoSansKannadaUI-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Orya" variant="elegant">
-        <font weight="400" style="normal">NotoSansOriya-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansOriya.ttf</font>
         <font weight="700" style="normal">NotoSansOriya-Bold.ttf</font>
     </family>
     <family lang="und-Orya" variant="compact">
-        <font weight="400" style="normal">NotoSansOriyaUI-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansOriyaUI.ttf</font>
         <font weight="700" style="normal">NotoSansOriyaUI-Bold.ttf</font>
     </family>
     <family lang="und-Sinh" variant="elegant">
-        <font weight="400" style="normal">NotoSansSinhala-VF.ttf
+        <font weight="400" style="normal">NotoSansSinhala-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansSinhala-VF.ttf
+        <font weight="500" style="normal">NotoSansSinhala-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansSinhala-VF.ttf
+        <font weight="600" style="normal">NotoSansSinhala-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansSinhala-VF.ttf
+        <font weight="700" style="normal">NotoSansSinhala-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifSinhala-VF.ttf
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifSinhala-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal" fallbackFor="serif">NotoSerifSinhala-VF.ttf
+        <font weight="500" style="normal" fallbackFor="serif">NotoSerifSinhala-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal" fallbackFor="serif">NotoSerifSinhala-VF.ttf
+        <font weight="600" style="normal" fallbackFor="serif">NotoSerifSinhala-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal" fallbackFor="serif">NotoSerifSinhala-VF.ttf
+        <font weight="700" style="normal" fallbackFor="serif">NotoSerifSinhala-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Sinh" variant="compact">
-        <font weight="400" style="normal">NotoSansSinhalaUI-VF.ttf
+        <font weight="400" style="normal">NotoSansSinhalaUI-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansSinhalaUI-VF.ttf
+        <font weight="500" style="normal">NotoSansSinhalaUI-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansSinhalaUI-VF.ttf
+        <font weight="600" style="normal">NotoSansSinhalaUI-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansSinhalaUI-VF.ttf
+        <font weight="700" style="normal">NotoSansSinhalaUI-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Khmr" variant="elegant">
-        <font weight="100" style="normal">NotoSansKhmer-VF.ttf
+        <font weight="100" style="normal">NotoSansKhmer-Regular.ttf
             <axis tag="wdth" stylevalue="100.0"/>
             <axis tag="wght" stylevalue="26.0"/>
         </font>
-        <font weight="200" style="normal">NotoSansKhmer-VF.ttf
+        <font weight="200" style="normal">NotoSansKhmer-Regular.ttf
             <axis tag="wdth" stylevalue="100.0"/>
             <axis tag="wght" stylevalue="39.0"/>
         </font>
-        <font weight="300" style="normal">NotoSansKhmer-VF.ttf
+        <font weight="300" style="normal">NotoSansKhmer-Regular.ttf
             <axis tag="wdth" stylevalue="100.0"/>
             <axis tag="wght" stylevalue="58.0"/>
         </font>
-        <font weight="400" style="normal">NotoSansKhmer-VF.ttf
+        <font weight="400" style="normal">NotoSansKhmer-Regular.ttf
             <axis tag="wdth" stylevalue="100.0"/>
             <axis tag="wght" stylevalue="90.0"/>
         </font>
-        <font weight="500" style="normal">NotoSansKhmer-VF.ttf
+        <font weight="500" style="normal">NotoSansKhmer-Regular.ttf
             <axis tag="wdth" stylevalue="100.0"/>
             <axis tag="wght" stylevalue="108.0"/>
         </font>
-        <font weight="600" style="normal">NotoSansKhmer-VF.ttf
+        <font weight="600" style="normal">NotoSansKhmer-Regular.ttf
             <axis tag="wdth" stylevalue="100.0"/>
             <axis tag="wght" stylevalue="128.0"/>
         </font>
-        <font weight="700" style="normal">NotoSansKhmer-VF.ttf
+        <font weight="700" style="normal">NotoSansKhmer-Regular.ttf
             <axis tag="wdth" stylevalue="100.0"/>
             <axis tag="wght" stylevalue="151.0"/>
         </font>
-        <font weight="800" style="normal">NotoSansKhmer-VF.ttf
+        <font weight="800" style="normal">NotoSansKhmer-Regular.ttf
             <axis tag="wdth" stylevalue="100.0"/>
             <axis tag="wght" stylevalue="169.0"/>
         </font>
-        <font weight="900" style="normal">NotoSansKhmer-VF.ttf
+        <font weight="900" style="normal">NotoSansKhmer-Regular.ttf
             <axis tag="wdth" stylevalue="100.0"/>
             <axis tag="wght" stylevalue="190.0"/>
         </font>
@@ -769,17 +769,17 @@
         <font weight="700" style="normal" fallbackFor="serif">NotoSerifKhmer-Bold.otf</font>
     </family>
     <family lang="und-Khmr" variant="compact">
-        <font weight="400" style="normal">NotoSansKhmerUI-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansKhmerUI.ttf</font>
         <font weight="700" style="normal">NotoSansKhmerUI-Bold.ttf</font>
     </family>
     <family lang="und-Laoo" variant="elegant">
-        <font weight="400" style="normal">NotoSansLao-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansLao.ttf</font>
         <font weight="700" style="normal">NotoSansLao-Bold.ttf</font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifLao-Regular.ttf</font>
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifLao.ttf</font>
         <font weight="700" style="normal" fallbackFor="serif">NotoSerifLao-Bold.ttf</font>
     </family>
     <family lang="und-Laoo" variant="compact">
-        <font weight="400" style="normal">NotoSansLaoUI-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansLaoUI.ttf</font>
         <font weight="700" style="normal">NotoSansLaoUI-Bold.ttf</font>
     </family>
     <family lang="und-Mymr" variant="elegant">
@@ -795,56 +795,56 @@
         <font weight="700" style="normal">NotoSansMyanmarUI-Bold.otf</font>
     </family>
     <family lang="und-Thaa">
-        <font weight="400" style="normal">NotoSansThaana-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansThaana.ttf</font>
         <font weight="700" style="normal">NotoSansThaana-Bold.ttf</font>
     </family>
     <family lang="und-Cham">
-        <font weight="400" style="normal">NotoSansCham-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansCham.ttf</font>
         <font weight="700" style="normal">NotoSansCham-Bold.ttf</font>
     </family>
     <family lang="und-Ahom">
         <font weight="400" style="normal">NotoSansAhom-Regular.otf</font>
     </family>
     <family lang="und-Adlm">
-        <font weight="400" style="normal">NotoSansAdlam-VF.ttf
+        <font weight="400" style="normal">NotoSansAdlam-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansAdlam-VF.ttf
+        <font weight="500" style="normal">NotoSansAdlam-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansAdlam-VF.ttf
+        <font weight="600" style="normal">NotoSansAdlam-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansAdlam-VF.ttf
+        <font weight="700" style="normal">NotoSansAdlam-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Avst">
-        <font weight="400" style="normal">NotoSansAvestan-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansAvestan.ttf</font>
     </family>
     <family lang="und-Bali">
-        <font weight="400" style="normal">NotoSansBalinese-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansBalinese.ttf</font>
     </family>
     <family lang="und-Bamu">
-        <font weight="400" style="normal">NotoSansBamum-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansBamum.ttf</font>
     </family>
     <family lang="und-Batk">
-        <font weight="400" style="normal">NotoSansBatak-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansBatak.ttf</font>
     </family>
     <family lang="und-Brah">
-        <font weight="400" style="normal">NotoSansBrahmi-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansBrahmi.ttf</font>
     </family>
     <family lang="und-Bugi">
-        <font weight="400" style="normal">NotoSansBuginese-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansBuginese.ttf</font>
     </family>
     <family lang="und-Buhd">
-        <font weight="400" style="normal">NotoSansBuhid-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansBuhid.ttf</font>
     </family>
     <family lang="und-Cans">
-        <font weight="400" style="normal">NotoSansCanadianAboriginal-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansCanadianAboriginal.ttf</font>
     </family>
     <family lang="und-Cari">
-        <font weight="400" style="normal">NotoSansCarian-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansCarian.ttf</font>
     </family>
     <family lang="und-Cakm">
         <font weight="400" style="normal">NotoSansChakma-Regular.otf</font>
@@ -853,164 +853,164 @@
         <font weight="400" style="normal">NotoSansCherokee-Regular.ttf</font>
     </family>
     <family lang="und-Copt">
-        <font weight="400" style="normal">NotoSansCoptic-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansCoptic.ttf</font>
     </family>
     <family lang="und-Xsux">
-        <font weight="400" style="normal">NotoSansCuneiform-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansCuneiform.ttf</font>
     </family>
     <family lang="und-Cprt">
-        <font weight="400" style="normal">NotoSansCypriot-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansCypriot.ttf</font>
     </family>
     <family lang="und-Dsrt">
-        <font weight="400" style="normal">NotoSansDeseret-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansDeseret.ttf</font>
     </family>
     <family lang="und-Egyp">
-        <font weight="400" style="normal">NotoSansEgyptianHieroglyphs-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansEgyptianHieroglyphs.ttf</font>
     </family>
     <family lang="und-Elba">
         <font weight="400" style="normal">NotoSansElbasan-Regular.otf</font>
     </family>
     <family lang="und-Glag">
-        <font weight="400" style="normal">NotoSansGlagolitic-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansGlagolitic.ttf</font>
     </family>
     <family lang="und-Goth">
-        <font weight="400" style="normal">NotoSansGothic-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansGothic.ttf</font>
     </family>
     <family lang="und-Hano">
-        <font weight="400" style="normal">NotoSansHanunoo-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansHanunoo.ttf</font>
     </family>
     <family lang="und-Armi">
-        <font weight="400" style="normal">NotoSansImperialAramaic-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansImperialAramaic.ttf</font>
     </family>
     <family lang="und-Phli">
-        <font weight="400" style="normal">NotoSansInscriptionalPahlavi-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansInscriptionalPahlavi.ttf</font>
     </family>
     <family lang="und-Prti">
-        <font weight="400" style="normal">NotoSansInscriptionalParthian-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansInscriptionalParthian.ttf</font>
     </family>
     <family lang="und-Java">
         <font weight="400" style="normal">NotoSansJavanese-Regular.otf</font>
     </family>
     <family lang="und-Kthi">
-        <font weight="400" style="normal">NotoSansKaithi-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansKaithi.ttf</font>
     </family>
     <family lang="und-Kali">
-        <font weight="400" style="normal">NotoSansKayahLi-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansKayahLi.ttf</font>
     </family>
     <family lang="und-Khar">
-        <font weight="400" style="normal">NotoSansKharoshthi-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansKharoshthi.ttf</font>
     </family>
     <family lang="und-Lepc">
-        <font weight="400" style="normal">NotoSansLepcha-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansLepcha.ttf</font>
     </family>
     <family lang="und-Limb">
-        <font weight="400" style="normal">NotoSansLimbu-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansLimbu.ttf</font>
     </family>
     <family lang="und-Linb">
-        <font weight="400" style="normal">NotoSansLinearB-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansLinearB.ttf</font>
     </family>
     <family lang="und-Lisu">
-        <font weight="400" style="normal">NotoSansLisu-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansLisu.ttf</font>
     </family>
     <family lang="und-Lyci">
-        <font weight="400" style="normal">NotoSansLycian-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansLycian.ttf</font>
     </family>
     <family lang="und-Lydi">
-        <font weight="400" style="normal">NotoSansLydian-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansLydian.ttf</font>
     </family>
     <family lang="und-Mand">
-        <font weight="400" style="normal">NotoSansMandaic-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansMandaic.ttf</font>
     </family>
     <family lang="und-Mtei">
-        <font weight="400" style="normal">NotoSansMeeteiMayek-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansMeeteiMayek.ttf</font>
     </family>
     <family lang="und-Talu">
-        <font weight="400" style="normal">NotoSansNewTaiLue-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansNewTaiLue.ttf</font>
     </family>
     <family lang="und-Nkoo">
-        <font weight="400" style="normal">NotoSansNKo-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansNKo.ttf</font>
     </family>
     <family lang="und-Ogam">
-        <font weight="400" style="normal">NotoSansOgham-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansOgham.ttf</font>
     </family>
     <family lang="und-Olck">
-        <font weight="400" style="normal">NotoSansOlChiki-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansOlChiki.ttf</font>
     </family>
     <family lang="und-Ital">
-        <font weight="400" style="normal">NotoSansOldItalic-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansOldItalic.ttf</font>
     </family>
     <family lang="und-Xpeo">
-        <font weight="400" style="normal">NotoSansOldPersian-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansOldPersian.ttf</font>
     </family>
     <family lang="und-Sarb">
-        <font weight="400" style="normal">NotoSansOldSouthArabian-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansOldSouthArabian.ttf</font>
     </family>
     <family lang="und-Orkh">
-        <font weight="400" style="normal">NotoSansOldTurkic-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansOldTurkic.ttf</font>
     </family>
     <family lang="und-Osge">
         <font weight="400" style="normal">NotoSansOsage-Regular.ttf</font>
     </family>
     <family lang="und-Osma">
-        <font weight="400" style="normal">NotoSansOsmanya-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansOsmanya.ttf</font>
     </family>
     <family lang="und-Phnx">
-        <font weight="400" style="normal">NotoSansPhoenician-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansPhoenician.ttf</font>
     </family>
     <family lang="und-Rjng">
-        <font weight="400" style="normal">NotoSansRejang-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansRejang.ttf</font>
     </family>
     <family lang="und-Runr">
-        <font weight="400" style="normal">NotoSansRunic-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansRunic.ttf</font>
     </family>
     <family lang="und-Samr">
-        <font weight="400" style="normal">NotoSansSamaritan-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansSamaritan.ttf</font>
     </family>
     <family lang="und-Saur">
-        <font weight="400" style="normal">NotoSansSaurashtra-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansSaurashtra.ttf</font>
     </family>
     <family lang="und-Shaw">
-        <font weight="400" style="normal">NotoSansShavian-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansShavian.ttf</font>
     </family>
     <family lang="und-Sund">
-        <font weight="400" style="normal">NotoSansSundanese-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansSundanese.ttf</font>
     </family>
     <family lang="und-Sylo">
-        <font weight="400" style="normal">NotoSansSylotiNagri-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansSylotiNagri.ttf</font>
     </family>
     <!-- Esrangela should precede Eastern and Western Syriac, since it's our default form. -->
     <family lang="und-Syre">
-        <font weight="400" style="normal">NotoSansSyriacEstrangela-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansSyriacEstrangela.ttf</font>
     </family>
     <family lang="und-Syrn">
-        <font weight="400" style="normal">NotoSansSyriacEastern-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansSyriacEastern.ttf</font>
     </family>
     <family lang="und-Syrj">
-        <font weight="400" style="normal">NotoSansSyriacWestern-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansSyriacWestern.ttf</font>
     </family>
     <family lang="und-Tglg">
-        <font weight="400" style="normal">NotoSansTagalog-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansTagalog.ttf</font>
     </family>
     <family lang="und-Tagb">
-        <font weight="400" style="normal">NotoSansTagbanwa-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansTagbanwa.ttf</font>
     </family>
     <family lang="und-Lana">
-        <font weight="400" style="normal">NotoSansTaiTham-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansTaiTham.ttf</font>
     </family>
     <family lang="und-Tavt">
-        <font weight="400" style="normal">NotoSansTaiViet-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansTaiViet.ttf</font>
     </family>
     <family lang="und-Tibt">
-        <font weight="400" style="normal">NotoSerifTibetan-VF.ttf
+        <font weight="400" style="normal">NotoSerifTibetan-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSerifTibetan-VF.ttf
+        <font weight="500" style="normal">NotoSerifTibetan-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSerifTibetan-VF.ttf
+        <font weight="600" style="normal">NotoSerifTibetan-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSerifTibetan-VF.ttf
+        <font weight="700" style="normal">NotoSerifTibetan-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
@@ -1018,29 +1018,29 @@
         <font weight="400" style="normal">NotoSansTifinagh-Regular.otf</font>
     </family>
     <family lang="und-Ugar">
-        <font weight="400" style="normal">NotoSansUgaritic-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansUgaritic.ttf</font>
     </family>
     <family lang="und-Vaii">
-        <font weight="400" style="normal">NotoSansVai-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansVai.ttf</font>
     </family>
     <family>
         <font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted.ttf</font>
     </family>
     <family lang="zh-Hans">
-        <font weight="400" style="normal" index="2">NotoSansCJK-Regular.ttc</font>
-        <font weight="400" style="normal" index="2" fallbackFor="serif">NotoSerifCJK-Regular.ttc</font>
+        <font weight="400" style="normal" index="2">NotoSansCJKjp-Regular.otc</font>
+        <font weight="400" style="normal" index="2" fallbackFor="serif">NotoSerifCJKjp-Regular.otc</font>
     </family>
     <family lang="zh-Hant,zh-Bopo">
-        <font weight="400" style="normal" index="3">NotoSansCJK-Regular.ttc</font>
-        <font weight="400" style="normal" index="3" fallbackFor="serif">NotoSerifCJK-Regular.ttc</font>
+        <font weight="400" style="normal" index="3">NotoSansCJKjp-Regular.otc</font>
+        <font weight="400" style="normal" index="3" fallbackFor="serif">NotoSerifCJKjp-Regular.otc</font>
     </family>
     <family lang="ja">
-        <font weight="400" style="normal" index="0">NotoSansCJK-Regular.ttc</font>
-        <font weight="400" style="normal" index="0" fallbackFor="serif">NotoSerifCJK-Regular.ttc</font>
+        <font weight="400" style="normal" index="0">NotoSansCJKjp-Regular.otc</font>
+        <font weight="400" style="normal" index="0" fallbackFor="serif">NotoSerifCJKjp-Regular.otc</font>
     </family>
     <family lang="ko">
-        <font weight="400" style="normal" index="1">NotoSansCJK-Regular.ttc</font>
-        <font weight="400" style="normal" index="1" fallbackFor="serif">NotoSerifCJK-Regular.ttc</font>
+        <font weight="400" style="normal" index="1">NotoSansCJKjp-Regular.otc</font>
+        <font weight="400" style="normal" index="1" fallbackFor="serif">NotoSerifCJKjp-Regular.otc</font>
     </family>
     <family lang="und-Zsye">
         <font weight="400" style="normal">NotoColorEmoji.ttf</font>
@@ -1053,16 +1053,16 @@
         override the East Asian punctuation for Chinese.
     -->
     <family lang="und-Tale">
-        <font weight="400" style="normal">NotoSansTaiLe-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansTaiLe.ttf</font>
     </family>
     <family lang="und-Yiii">
-        <font weight="400" style="normal">NotoSansYi-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansYi.ttf</font>
     </family>
     <family lang="und-Mong">
-        <font weight="400" style="normal">NotoSansMongolian-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansMongolian.ttf</font>
     </family>
     <family lang="und-Phag">
-        <font weight="400" style="normal">NotoSansPhagsPa-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansPhagsPa.ttf</font>
     </family>
     <family lang="und-Hluw">
         <font weight="400" style="normal">NotoSansAnatolianHieroglyphs-Regular.otf</font>
@@ -1152,72 +1152,72 @@
         <font weight="400" style="normal">NotoSerifDogra-Regular.ttf</font>
     </family>
     <family lang="und-Medf">
-        <font weight="400" style="normal">NotoSansMedefaidrin-VF.ttf
+        <font weight="400" style="normal">NotoSansMedefaidrin-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansMedefaidrin-VF.ttf
+        <font weight="500" style="normal">NotoSansMedefaidrin-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansMedefaidrin-VF.ttf
+        <font weight="600" style="normal">NotoSansMedefaidrin-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansMedefaidrin-VF.ttf
+        <font weight="700" style="normal">NotoSansMedefaidrin-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Soyo">
-        <font weight="400" style="normal">NotoSansSoyombo-VF.ttf
+        <font weight="400" style="normal">NotoSansSoyombo-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansSoyombo-VF.ttf
+        <font weight="500" style="normal">NotoSansSoyombo-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansSoyombo-VF.ttf
+        <font weight="600" style="normal">NotoSansSoyombo-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansSoyombo-VF.ttf
+        <font weight="700" style="normal">NotoSansSoyombo-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Takr">
-        <font weight="400" style="normal">NotoSansTakri-VF.ttf
+        <font weight="400" style="normal">NotoSansTakri-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSansTakri-VF.ttf
+        <font weight="500" style="normal">NotoSansTakri-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSansTakri-VF.ttf
+        <font weight="600" style="normal">NotoSansTakri-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSansTakri-VF.ttf
+        <font weight="700" style="normal">NotoSansTakri-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Hmnp">
-        <font weight="400" style="normal">NotoSerifNyiakengPuachueHmong-VF.ttf
+        <font weight="400" style="normal">NotoSerifHmongNyiakeng-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSerifNyiakengPuachueHmong-VF.ttf
+        <font weight="500" style="normal">NotoSerifHmongNyiakeng-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSerifNyiakengPuachueHmong-VF.ttf
+        <font weight="600" style="normal">NotoSerifHmongNyiakeng-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSerifNyiakengPuachueHmong-VF.ttf
+        <font weight="700" style="normal">NotoSerifHmongNyiakeng-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
     <family lang="und-Yezi">
-        <font weight="400" style="normal">NotoSerifYezidi-VF.ttf
+        <font weight="400" style="normal">NotoSerifYezidi-Regular.ttf
             <axis tag="wght" stylevalue="400"/>
         </font>
-        <font weight="500" style="normal">NotoSerifYezidi-VF.ttf
+        <font weight="500" style="normal">NotoSerifYezidi-Regular.ttf
             <axis tag="wght" stylevalue="500"/>
         </font>
-        <font weight="600" style="normal">NotoSerifYezidi-VF.ttf
+        <font weight="600" style="normal">NotoSerifYezidi-Regular.ttf
             <axis tag="wght" stylevalue="600"/>
         </font>
-        <font weight="700" style="normal">NotoSerifYezidi-VF.ttf
+        <font weight="700" style="normal">NotoSerifYezidi-Regular.ttf
             <axis tag="wght" stylevalue="700"/>
         </font>
     </family>
diff --git a/data/keyboards/Android.mk b/data/keyboards/Android.mk
index 7949c77..6ae8800 100644
--- a/data/keyboards/Android.mk
+++ b/data/keyboards/Android.mk
@@ -22,6 +22,9 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := validate_framework_keymaps
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
 intermediates := $(call intermediates-dir-for,ETC,$(LOCAL_MODULE),,COMMON)
 LOCAL_BUILT_MODULE := $(intermediates)/stamp
 
diff --git a/data/keyboards/OWNERS b/data/keyboards/OWNERS
index c4f6df8..0ce8350 100644
--- a/data/keyboards/OWNERS
+++ b/data/keyboards/OWNERS
@@ -1,5 +1,3 @@
 set noparent
 
-michaelwr@google.com
-svv@google.com
-lzye@google.com
+include /services/core/java/com/android/server/input/OWNERS
diff --git a/data/keyboards/Vendor_057e_Product_2009.kl b/data/keyboards/Vendor_057e_Product_2009.kl
index 3c6b11e..7491ee5 100644
--- a/data/keyboards/Vendor_057e_Product_2009.kl
+++ b/data/keyboards/Vendor_057e_Product_2009.kl
@@ -74,3 +74,11 @@
 
 # Home key
 key 0x13c    HOME
+
+# SENSORs
+sensor 0x00 ACCELEROMETER X
+sensor 0x01 ACCELEROMETER Y
+sensor 0x02 ACCELEROMETER Z
+sensor 0x03 GYROSCOPE X
+sensor 0x04 GYROSCOPE Y
+sensor 0x05 GYROSCOPE Z
diff --git a/drm/jni/Android.bp b/drm/jni/Android.bp
index 68757d8..669f109 100644
--- a/drm/jni/Android.bp
+++ b/drm/jni/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_library_shared {
     name: "libdrmframework_jni",
 
diff --git a/errorprone/Android.bp b/errorprone/Android.bp
index c60191c..d1e94df 100644
--- a/errorprone/Android.bp
+++ b/errorprone/Android.bp
@@ -1,4 +1,13 @@
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_plugin {
     name: "error_prone_android_framework",
 
diff --git a/graphics/java/android/graphics/BlurShader.java b/graphics/java/android/graphics/BlurShader.java
deleted file mode 100644
index 2e4bd7d..0000000
--- a/graphics/java/android/graphics/BlurShader.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-/**
- * A subclass of shader that blurs input from another {@link android.graphics.Shader} instance
- * or all the drawing commands with the {@link android.graphics.Paint} that this shader is
- * attached to.
- */
-public final class BlurShader extends Shader {
-
-    private final float mRadiusX;
-    private final float mRadiusY;
-    private final Shader mInputShader;
-    private final TileMode mEdgeTreatment;
-
-    private long mNativeInputShader = 0;
-
-    /**
-     * Create a {@link BlurShader} that blurs the contents of the optional input shader
-     * with the specified radius along the x and y axis. If no input shader is provided
-     * then all drawing commands issued with a {@link android.graphics.Paint} that this
-     * shader is installed in will be blurred.
-     *
-     * This uses a default {@link TileMode#DECAL} for edge treatment
-     *
-     * @param radiusX Radius of blur along the X axis
-     * @param radiusY Radius of blur along the Y axis
-     * @param inputShader Input shader that provides the content to be blurred
-     */
-    public BlurShader(float radiusX, float radiusY, @Nullable Shader inputShader) {
-        this(radiusX, radiusY, inputShader, TileMode.DECAL);
-    }
-
-    /**
-     * Create a {@link BlurShader} that blurs the contents of the optional input shader
-     * with the specified radius along the x and y axis. If no input shader is provided
-     * then all drawing commands issued with a {@link android.graphics.Paint} that this
-     * shader is installed in will be blurred
-     * @param radiusX Radius of blur along the X axis
-     * @param radiusY Radius of blur along the Y axis
-     * @param inputShader Input shader that provides the content to be blurred
-     * @param edgeTreatment Policy for how to blur content near edges of the blur shader
-     */
-    public BlurShader(float radiusX, float radiusY, @Nullable Shader inputShader,
-            @NonNull TileMode edgeTreatment) {
-        mRadiusX = radiusX;
-        mRadiusY = radiusY;
-        mInputShader = inputShader;
-        mEdgeTreatment = edgeTreatment;
-    }
-
-    /** @hide **/
-    @Override
-    protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
-        mNativeInputShader = mInputShader != null
-                ? mInputShader.getNativeInstance(filterFromPaint) : 0;
-        return nativeCreate(nativeMatrix, mRadiusX, mRadiusY, mNativeInputShader,
-                mEdgeTreatment.nativeInt);
-    }
-
-    /** @hide **/
-    @Override
-    protected boolean shouldDiscardNativeInstance(boolean filterFromPaint) {
-        long currentNativeInstance = mInputShader != null
-                ? mInputShader.getNativeInstance(filterFromPaint) : 0;
-        return mNativeInputShader != currentNativeInstance;
-    }
-
-    private static native long nativeCreate(long nativeMatrix, float radiusX, float radiusY,
-            long inputShader, int edgeTreatment);
-}
diff --git a/graphics/java/android/graphics/FrameInfo.java b/graphics/java/android/graphics/FrameInfo.java
index d59abb5..189be53 100644
--- a/graphics/java/android/graphics/FrameInfo.java
+++ b/graphics/java/android/graphics/FrameInfo.java
@@ -69,28 +69,26 @@
     // animation & drawing system
     public static final int VSYNC = 3;
 
-    // The time of the oldest input event
-    public static final int OLDEST_INPUT_EVENT = 4;
-
-    // The time of the newest input event
-    public static final int NEWEST_INPUT_EVENT = 5;
+    // The id of the input event that caused the current frame
+    public static final int INPUT_EVENT_ID = 4;
 
     // When input event handling started
-    public static final int HANDLE_INPUT_START = 6;
+    public static final int HANDLE_INPUT_START = 5;
 
     // When animation evaluations started
-    public static final int ANIMATION_START = 7;
+    public static final int ANIMATION_START = 6;
 
     // When ViewRootImpl#performTraversals() started
-    public static final int PERFORM_TRAVERSALS_START = 8;
+    public static final int PERFORM_TRAVERSALS_START = 7;
 
     // When View:draw() started
-    public static final int DRAW_START = 9;
+    public static final int DRAW_START = 8;
 
     // When the frame needs to be ready by
-    public static final int FRAME_DEADLINE = 10;
+    public static final int FRAME_DEADLINE = 9;
 
     // Must be the last one
+    // This value must be in sync with `UI_THREAD_FRAME_INFO_SIZE` in FrameInfo.h
     private static final int FRAME_INFO_SIZE = FRAME_DEADLINE + 1;
 
     /** checkstyle */
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index f1f9a5f..e222570 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -153,6 +153,13 @@
      * resource bitmaps often are) the filtering will already have been
      * done.</p>
      *
+     * <p>On devices running {@link Build.VERSION_CODES#O} and below, hardware
+     * accelerated drawing always uses bilinear sampling on scaled bitmaps,
+     * regardless of this flag. On devices running {@link Build.VERSION_CODES#Q}
+     * and above, this flag defaults to being set on a new {@code Paint}. It can
+     * be cleared with {@link #setFlags} or {@link #setFilterBitmap}.</p>
+     *
+     * @see #Paint()
      * @see #Paint(int)
      * @see #setFlags(int)
      */
@@ -558,6 +565,12 @@
 
     /**
      * Create a new paint with default settings.
+     *
+     * <p>On devices running {@link Build.VERSION_CODES#O} and below, hardware
+     * accelerated drawing always acts as if {@link #FILTER_BITMAP_FLAG} is set.
+     * On devices running {@link Build.VERSION_CODES#Q} and above,
+     * {@code FILTER_BITMAP_FLAG} is set by this constructor, and it can be
+     * cleared with {@link #setFlags} or {@link #setFilterBitmap}.</p>
      */
     public Paint() {
         this(0);
@@ -567,6 +580,13 @@
      * Create a new paint with the specified flags. Use setFlags() to change
      * these after the paint is created.
      *
+     * <p>On devices running {@link Build.VERSION_CODES#O} and below, hardware
+     * accelerated drawing always acts as if {@link #FILTER_BITMAP_FLAG} is set.
+     * On devices running {@link Build.VERSION_CODES#Q} and above,
+     * {@code FILTER_BITMAP_FLAG} is always set by this constructor, regardless
+     * of the value of {@code flags}. It can be cleared with {@link #setFlags} or
+     * {@link #setFilterBitmap}.</p>
+     *
      * @param flags initial flag bits, as if they were passed via setFlags().
      */
     public Paint(int flags) {
@@ -991,6 +1011,7 @@
      * device pixels. That is dependent on dithering and xfermodes.
      *
      * @see #setFilterBitmap(boolean) setFilterBitmap()
+     * @see #FILTER_BITMAP_FLAG
      */
     public final boolean isFilterBitmap() {
         return (getFlags() & FILTER_BITMAP_FLAG) != 0;
@@ -1004,6 +1025,7 @@
      *
      * @param filter true to set the FILTER_BITMAP_FLAG bit in the paint's
      *               flags, false to clear it.
+     * @see #FILTER_BITMAP_FLAG
      */
     public void setFilterBitmap(boolean filter) {
         nSetFilterBitmap(mNativePaint, filter);
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index 4a92cf1..f6f770b 100644
--- a/graphics/java/android/graphics/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -272,6 +272,16 @@
         void positionChanged(long frameNumber, int left, int top, int right, int bottom);
 
         /**
+         * Call to apply a stretch effect to any child SurfaceControl layers
+         *
+         * TODO: Fold this into positionChanged & have HWUI do the ASurfaceControl calls?
+         *
+         * @hide
+         */
+        default void applyStretch(long frameNumber, float left, float top, float right,
+                float bottom, float vecX, float vecY, float maxStretch) { }
+
+        /**
          * Called by native on RenderThread to notify that the view is no longer in the
          * draw tree. UI thread is blocked at this point.
          *
@@ -312,6 +322,14 @@
                 pul.positionLost(frameNumber);
             }
         }
+
+        @Override
+        public void applyStretch(long frameNumber, float left, float top, float right, float bottom,
+                float vecX, float vecY, float maxStretch) {
+            for (PositionUpdateListener pul : mListeners) {
+                pul.applyStretch(frameNumber, left, top, right, bottom, vecX, vecY, maxStretch);
+            }
+        }
     }
 
     /**
@@ -707,7 +725,7 @@
         if (1.0 < vecY || vecY < -1.0) {
             throw new IllegalArgumentException("vecY must be in the range [-1, 1], was " + vecY);
         }
-        if (top <= bottom || right <= left) {
+        if (top >= bottom || left >= right) {
             throw new IllegalArgumentException(
                     "Stretch region must not be empty, got "
                             + new RectF(left, top, right, bottom).toString());
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 32c777c..c807882 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -172,9 +172,9 @@
      * @hide
      */
     @UnsupportedAppUsage
-    public long native_instance;
+    public final long native_instance;
 
-    private Runnable mCleaner;
+    private final Runnable mCleaner;
 
     /** @hide */
     @IntDef(value = {NORMAL, BOLD, ITALIC, BOLD_ITALIC})
@@ -189,9 +189,9 @@
     /** @hide */ public static final int STYLE_MASK = 0x03;
 
     @UnsupportedAppUsage
-    private @Style int mStyle = 0;
+    private @Style final int mStyle;
 
-    private @IntRange(from = 0, to = FontStyle.FONT_WEIGHT_MAX) int mWeight = 0;
+    private @IntRange(from = 0, to = FontStyle.FONT_WEIGHT_MAX) final int mWeight;
 
     // Value for weight and italic. Indicates the value is resolved by font metadata.
     // Must be the same as the C++ constant in core/jni/android/graphics/FontFamily.cpp
@@ -207,6 +207,7 @@
     private static final int STYLE_NORMAL = 0;
     private static final int STYLE_ITALIC = 1;
 
+    @GuardedBy("this")
     private int[] mSupportedAxes;
     private static final int[] EMPTY_AXES = {};
 
diff --git a/graphics/proto/Android.bp b/graphics/proto/Android.bp
index ea79b73..1b19266 100644
--- a/graphics/proto/Android.bp
+++ b/graphics/proto/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library_static {
     name: "updatable-driver-protos",
     host_supported: true,
diff --git a/keystore/Android.bp b/keystore/Android.bp
new file mode 100644
index 0000000..5db668e
--- /dev/null
+++ b/keystore/Android.bp
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["frameworks_base_keystore_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_keystore_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
diff --git a/keystore/java/android/security/AndroidKeyStoreMaintenance.java b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
new file mode 100644
index 0000000..ed789f0
--- /dev/null
+++ b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
+import android.security.usermanager.IKeystoreUserManager;
+import android.system.keystore2.Domain;
+import android.system.keystore2.ResponseCode;
+import android.util.Log;
+
+/**
+ * @hide This is the client side for IKeystoreUserManager AIDL.
+ * It shall only be used by the LockSettingsService.
+ */
+public class AndroidKeyStoreMaintenance {
+    private static final String TAG = "AndroidKeyStoreMaintenance";
+
+    public static final int SYSTEM_ERROR = ResponseCode.SYSTEM_ERROR;
+
+    private static IKeystoreUserManager getService() {
+        return IKeystoreUserManager.Stub.asInterface(
+                ServiceManager.checkService("android.security.usermanager"));
+    }
+
+    /**
+     * Informs Keystore 2.0 about adding a user
+     *
+     * @param userId - Android user id of the user being added
+     * @return 0 if successful or a {@code ResponseCode}
+     * @hide
+     */
+    public static int onUserAdded(@NonNull int userId) {
+        if (!android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) return 0;
+        try {
+            getService().onUserAdded(userId);
+            return 0;
+        } catch (ServiceSpecificException e) {
+            Log.e(TAG, "onUserAdded failed", e);
+            return e.errorCode;
+        } catch (Exception e) {
+            Log.e(TAG, "Can not connect to keystore", e);
+            return SYSTEM_ERROR;
+        }
+    }
+
+    /**
+     * Informs Keystore 2.0 about removing a usergit mer
+     *
+     * @param userId - Android user id of the user being removed
+     * @return 0 if successful or a {@code ResponseCode}
+     * @hide
+     */
+    public static int onUserRemoved(int userId) {
+        if (!android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) return 0;
+        try {
+            getService().onUserRemoved(userId);
+            return 0;
+        } catch (ServiceSpecificException e) {
+            Log.e(TAG, "onUserRemoved failed", e);
+            return e.errorCode;
+        } catch (Exception e) {
+            Log.e(TAG, "Can not connect to keystore", e);
+            return SYSTEM_ERROR;
+        }
+    }
+
+    /**
+     * Informs Keystore 2.0 about changing user's password
+     *
+     * @param userId   - Android user id of the user
+     * @param password - a secret derived from the synthetic password provided by the
+     *                 LockSettingService
+     * @return 0 if successful or a {@code ResponseCode}
+     * @hide
+     */
+    public static int onUserPasswordChanged(int userId, @Nullable byte[] password) {
+        if (!android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) return 0;
+        try {
+            getService().onUserPasswordChanged(userId, password);
+            return 0;
+        } catch (ServiceSpecificException e) {
+            Log.e(TAG, "onUserPasswordChanged failed", e);
+            return e.errorCode;
+        } catch (Exception e) {
+            Log.e(TAG, "Can not connect to keystore", e);
+            return SYSTEM_ERROR;
+        }
+    }
+
+    /**
+     * Informs Keystore 2.0 that an app was uninstalled and the corresponding namspace is to
+     * be cleared.
+     */
+    public static int clearNamespace(@Domain int domain, long namespace) {
+        if (!android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) return 0;
+        try {
+            getService().clearNamespace(domain, namespace);
+            return 0;
+        } catch (ServiceSpecificException e) {
+            Log.e(TAG, "clearNamespace failed", e);
+            return e.errorCode;
+        } catch (Exception e) {
+            Log.e(TAG, "Can not connect to keystore", e);
+            return SYSTEM_ERROR;
+        }
+    }
+}
diff --git a/keystore/java/android/security/Authorization.java b/keystore/java/android/security/Authorization.java
index 21d23b1..50a9082 100644
--- a/keystore/java/android/security/Authorization.java
+++ b/keystore/java/android/security/Authorization.java
@@ -33,20 +33,12 @@
  */
 public class Authorization {
     private static final String TAG = "KeystoreAuthorization";
-    private static IKeystoreAuthorization sIKeystoreAuthorization;
 
     public static final int SYSTEM_ERROR = ResponseCode.SYSTEM_ERROR;
 
-    public Authorization() {
-        sIKeystoreAuthorization = null;
-    }
-
-    private static synchronized IKeystoreAuthorization getService() {
-        if (sIKeystoreAuthorization == null) {
-            sIKeystoreAuthorization = IKeystoreAuthorization.Stub.asInterface(
+    private static IKeystoreAuthorization getService() {
+        return IKeystoreAuthorization.Stub.asInterface(
                     ServiceManager.checkService("android.security.authorization"));
-        }
-        return sIKeystoreAuthorization;
     }
 
     /**
@@ -55,12 +47,12 @@
      * @param authToken created by Android authenticators.
      * @return 0 if successful or {@code ResponseCode.SYSTEM_ERROR}.
      */
-    public int addAuthToken(@NonNull HardwareAuthToken authToken) {
+    public static int addAuthToken(@NonNull HardwareAuthToken authToken) {
         if (!android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) return 0;
         try {
             getService().addAuthToken(authToken);
             return 0;
-        } catch (RemoteException e) {
+        } catch (RemoteException | NullPointerException e) {
             Log.w(TAG, "Can not connect to keystore", e);
             return SYSTEM_ERROR;
         } catch (ServiceSpecificException e) {
@@ -73,7 +65,7 @@
      * @param authToken
      * @return 0 if successful or a {@code ResponseCode}.
      */
-    public int addAuthToken(@NonNull byte[] authToken) {
+    public static int addAuthToken(@NonNull byte[] authToken) {
         return addAuthToken(AuthTokenUtils.toHardwareAuthToken(authToken));
     }
 
@@ -86,7 +78,7 @@
      *
      * @return 0 if successful or a {@code ResponseCode}.
      */
-    public int onLockScreenEvent(@NonNull boolean locked, @NonNull int userId,
+    public static int onLockScreenEvent(@NonNull boolean locked, @NonNull int userId,
             @Nullable byte[] syntheticPassword) {
         if (!android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) return 0;
         try {
@@ -96,7 +88,7 @@
                 getService().onLockScreenEvent(LockScreenEvent.UNLOCK, userId, syntheticPassword);
             }
             return 0;
-        } catch (RemoteException e) {
+        } catch (RemoteException | NullPointerException e) {
             Log.w(TAG, "Can not connect to keystore", e);
             return SYSTEM_ERROR;
         } catch (ServiceSpecificException e) {
diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl
index f708298..684eebe 100644
--- a/keystore/java/android/security/IKeyChainService.aidl
+++ b/keystore/java/android/security/IKeyChainService.aidl
@@ -37,8 +37,6 @@
     void setUserSelectable(String alias, boolean isUserSelectable);
 
     int generateKeyPair(in String algorithm, in ParcelableKeyGenParameterSpec spec);
-    int attestKey(in String alias, in byte[] challenge, in int[] idAttestationFlags,
-            out KeymasterCertificateChain chain);
     boolean setKeyPairCertificate(String alias, in byte[] userCert, in byte[] certChain);
 
     // APIs used by CertInstaller and DevicePolicyManager
@@ -65,6 +63,7 @@
     AppUriAuthenticationPolicy getCredentialManagementAppPolicy();
     String getPredefinedAliasForPackageAndUri(String packageName, in Uri uri);
     void removeCredentialManagementApp();
+    boolean isCredentialManagementApp(String packageName);
 
     // APIs used by KeyChainActivity
     void setGrant(int uid, String alias, boolean value);
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 97819c5..65a81cd 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -44,6 +44,8 @@
 import android.security.keystore.AndroidKeyStoreProvider;
 import android.security.keystore.KeyPermanentlyInvalidatedException;
 import android.security.keystore.KeyProperties;
+import android.system.keystore2.Domain;
+import android.system.keystore2.KeyDescriptor;
 import android.util.Log;
 
 import com.android.org.conscrypt.TrustedCertificateStore;
@@ -421,6 +423,15 @@
      * credentials. This is limited to unmanaged devices. The authentication policy must be
      * provided to be able to make this request successfully.
      *
+     * <p> This intent should be started using {@link Activity#startActivityForResult(Intent, int)}
+     * to verify whether the request was successful and whether the user accepted or denied the
+     * request. If the user successfully receives and accepts the request, the result code will be
+     * {@link Activity#RESULT_OK}, otherwise the result code will be
+     * {@link Activity#RESULT_CANCELED}.
+     *
+     * <p> {@link KeyChain#isCredentialManagementApp(Context)} should be used to determine whether
+     * an app is already the credential management app.
+     *
      * @param policy The authentication policy determines which alias for a private key and
      *               certificate pair should be used for authentication.
      */
@@ -589,6 +600,55 @@
     }
 
     /**
+     * Check whether the caller is the credential management app {@link CredentialManagementApp}.
+     * The credential management app has the ability to manage the user's KeyChain credentials
+     * on unmanaged devices.
+     *
+     * <p> {@link KeyChain#createManageCredentialsIntent} should be used by an app to request to
+     * become the credential management app. The user must approve this request before the app can
+     * manage the user's credentials. There can only be one credential management on the device.
+     *
+     * @return {@code true} if the caller is the credential management app.
+     */
+    public static boolean isCredentialManagementApp(@NonNull Context context) {
+        boolean isCredentialManagementApp = false;
+        try (KeyChainConnection keyChainConnection = KeyChain.bind(context)) {
+            isCredentialManagementApp = keyChainConnection.getService()
+                    .isCredentialManagementApp(context.getPackageName());
+        } catch (RemoteException e) {
+            e.rethrowAsRuntimeException();
+        } catch (InterruptedException e) {
+            throw new RuntimeException("Interrupted while checking whether the caller is the "
+                    + "credential management app.", e);
+        } catch (SecurityException e) {
+            isCredentialManagementApp = false;
+        }
+        return isCredentialManagementApp;
+    }
+
+    /**
+     * Called by the credential management app to get the authentication policy
+     * {@link AppUriAuthenticationPolicy}.
+     *
+     * @return the credential management app's authentication policy.
+     * @throws SecurityException if the caller is not the credential management app.
+     */
+    @NonNull
+    public static AppUriAuthenticationPolicy getCredentialManagementAppPolicy(
+            @NonNull Context context) throws SecurityException {
+        AppUriAuthenticationPolicy policy = null;
+        try (KeyChainConnection keyChainConnection = KeyChain.bind(context)) {
+            policy = keyChainConnection.getService().getCredentialManagementAppPolicy();
+        } catch (RemoteException e) {
+            e.rethrowAsRuntimeException();
+        } catch (InterruptedException e) {
+            throw new RuntimeException(
+                    "Interrupted while getting credential management app policy.", e);
+        }
+        return policy;
+    }
+
+    /**
      * Set a credential management app. The credential management app has the ability to manage
      * the user's KeyChain credentials on unmanaged devices.
      *
@@ -682,6 +742,33 @@
         return null;
     }
 
+    /**
+     * This prefix is used to disambiguate grant aliase strings from normal key alias strings.
+     * Technically, a key alias string can use the same prefix. However, a collision does not
+     * lead to privilege escalation, because grants are access controlled in the Keystore daemon.
+     * @hide
+     */
+    public static final String GRANT_ALIAS_PREFIX = "ks2_keychain_grant_id:";
+
+    private static KeyDescriptor getGrantDescriptor(String keyid) {
+        KeyDescriptor result = new KeyDescriptor();
+        result.domain = Domain.GRANT;
+        result.blob = null;
+        result.alias = null;
+        try {
+            result.nspace = Long.parseUnsignedLong(
+                    keyid.substring(GRANT_ALIAS_PREFIX.length()), 16 /* radix */);
+        } catch (NumberFormatException e) {
+            return null;
+        }
+        return result;
+    }
+
+    /** @hide */
+    public static String getGrantString(KeyDescriptor key) {
+        return String.format(GRANT_ALIAS_PREFIX + "%016X", key.nspace);
+    }
+
     /** @hide */
     @Nullable @WorkerThread
     public static KeyPair getKeyPair(@NonNull Context context, @NonNull String alias)
@@ -705,11 +792,23 @@
 
         if (keyId == null) {
             return null;
+        }
+
+        if (AndroidKeyStoreProvider.isKeystore2Enabled()) {
+            try {
+                return android.security.keystore2.AndroidKeyStoreProvider
+                        .loadAndroidKeyStoreKeyPairFromKeystore(
+                                KeyStore2.getInstance(),
+                                getGrantDescriptor(keyId));
+            } catch (UnrecoverableKeyException | KeyPermanentlyInvalidatedException e) {
+                throw new KeyChainException(e);
+            }
         } else {
             try {
                 return AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore(
                         KeyStore.getInstance(), keyId, KeyStore.UID_SELF);
-            } catch (RuntimeException | UnrecoverableKeyException | KeyPermanentlyInvalidatedException e) {
+            } catch (RuntimeException | UnrecoverableKeyException
+                    | KeyPermanentlyInvalidatedException e) {
                 throw new KeyChainException(e);
             }
         }
@@ -827,11 +926,8 @@
     @Deprecated
     public static boolean isBoundKeyAlgorithm(
             @NonNull @KeyProperties.KeyAlgorithmEnum String algorithm) {
-        if (!isKeyAlgorithmSupported(algorithm)) {
-            return false;
-        }
-
-        return KeyStore.getInstance().isHardwareBacked(algorithm);
+        // All supported algorithms are hardware backed. Individual keys may not be.
+        return true;
     }
 
     /** @hide */
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index e19d88c..93658e6 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -43,6 +43,7 @@
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeystoreResponse;
 import android.security.keystore.UserNotAuthenticatedException;
+import android.system.keystore2.Domain;
 import android.util.Log;
 
 import com.android.internal.org.bouncycastle.asn1.ASN1InputStream;
@@ -466,6 +467,9 @@
 
     public boolean clearUid(int uid) {
         try {
+            if (android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) {
+                return AndroidKeyStoreMaintenance.clearNamespace(Domain.APP, uid) == 0;
+            }
             return mBinder.clear_uid(uid) == NO_ERROR;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
@@ -996,7 +1000,7 @@
      */
     public int addAuthToken(byte[] authToken) {
         try {
-            new Authorization().addAuthToken(authToken);
+            Authorization.addAuthToken(authToken);
             return mBinder.addAuthToken(authToken);
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
diff --git a/keystore/java/android/security/KeyStore2.java b/keystore/java/android/security/KeyStore2.java
index f7477bf..6ac3821 100644
--- a/keystore/java/android/security/KeyStore2.java
+++ b/keystore/java/android/security/KeyStore2.java
@@ -24,6 +24,7 @@
 import android.os.ServiceManager;
 import android.os.ServiceSpecificException;
 import android.security.keymaster.KeymasterDefs;
+import android.system.keystore2.Domain;
 import android.system.keystore2.IKeystoreService;
 import android.system.keystore2.KeyDescriptor;
 import android.system.keystore2.KeyEntryResponse;
@@ -107,7 +108,6 @@
             try {
                 return request.execute(service);
             } catch (ServiceSpecificException e) {
-                Log.e(TAG, "KeyStore exception", e);
                 throw getKeyStoreException(e.errorCode);
             } catch (RemoteException e) {
                 if (firstTry) {
@@ -158,6 +158,50 @@
     }
 
     /**
+     * Grant string prefix as used by the keystore boringssl engine. Must be kept in sync
+     * with system/security/keystore-engine. Note: The prefix here includes the 0x which
+     * std::stringstream used in keystore-engine needs to identify the number as hex represented.
+     * Here we include it in the prefix, because Long#parseUnsignedLong does not understand it
+     * and gets the radix as explicit argument.
+     * @hide
+     */
+    private static final String KEYSTORE_ENGINE_GRANT_ALIAS_PREFIX =
+            "ks2_keystore-engine_grant_id:0x";
+
+    /**
+     * This function turns a grant identifier into a specific string that is understood by the
+     * keystore-engine in system/security/keystore-engine. Is only used by VPN and WI-FI components
+     * to allow certain system components like racoon or vendor components like WPA supplicant
+     * to use keystore keys with boring ssl.
+     *
+     * @param grantId the grant id as returned by {@link #grant} in the {@code nspace} filed of
+     *                the resulting {@code KeyDescriptor}.
+     * @return The grant descriptor string.
+     * @hide
+     */
+    public static String makeKeystoreEngineGrantString(long grantId) {
+        return String.format("%s%016X", KEYSTORE_ENGINE_GRANT_ALIAS_PREFIX, grantId);
+    }
+
+    /**
+     * Convenience function to turn a keystore engine grant string as returned by
+     * {@link #makeKeystoreEngineGrantString(long)} back into a grant KeyDescriptor.
+     *
+     * @param grantString As string returned by {@link #makeKeystoreEngineGrantString(long)}
+     * @return The grant key descriptor.
+     * @hide
+     */
+    public static KeyDescriptor keystoreEngineGrantString2KeyDescriptor(String grantString) {
+        KeyDescriptor key = new KeyDescriptor();
+        key.domain = Domain.GRANT;
+        key.nspace = Long.parseUnsignedLong(
+                grantString.substring(KEYSTORE_ENGINE_GRANT_ALIAS_PREFIX.length()), 16);
+        key.alias = null;
+        key.blob = null;
+        return key;
+    }
+
+    /**
      * Create a grant that allows the grantee identified by {@code granteeUid} to use
      * the key specified by {@code descriptor} withint the restrictions given by
      * {@code accessVectore}.
diff --git a/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java b/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java
index c20cf01..a6e3366 100644
--- a/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java
@@ -59,7 +59,7 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeString(mSpec.getKeystoreAlias());
         out.writeInt(mSpec.getPurposes());
-        out.writeInt(mSpec.getUid());
+        out.writeInt(mSpec.getNamespace());
         out.writeInt(mSpec.getKeySize());
 
         // Only needs to support RSAKeyGenParameterSpec and ECGenParameterSpec.
@@ -125,7 +125,7 @@
     private ParcelableKeyGenParameterSpec(Parcel in) {
         final String keystoreAlias = in.readString();
         final int purposes = in.readInt();
-        final int uid = in.readInt();
+        final int namespace = in.readInt();
         final int keySize = in.readInt();
 
         final int keySpecType = in.readInt();
@@ -177,7 +177,7 @@
         // KeyGenParameterSpec constructor (whereas using a builder would silently drop them).
         mSpec = new KeyGenParameterSpec(
                 keystoreAlias,
-                uid,
+                namespace,
                 keySize,
                 algorithmSpec,
                 certificateSubject,
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
index b3bfd6a..e401add 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -154,7 +154,7 @@
     private KeyGenParameterSpec mSpec;
 
     private String mEntryAlias;
-    private int mEntryUid;
+    private int mEntryNamespace;
     private @KeyProperties.KeyAlgorithmEnum String mJcaKeyAlgorithm;
     private int mKeymasterAlgorithm = -1;
     private int mKeySizeBits;
@@ -218,7 +218,7 @@
             }
 
             mEntryAlias = spec.getKeystoreAlias();
-            mEntryUid = spec.getUid();
+            mEntryNamespace = spec.getNamespace();
             mSpec = spec;
             mKeymasterAlgorithm = keymasterAlgorithm;
             mKeySizeBits = spec.getKeySize();
@@ -439,7 +439,7 @@
 
     private void resetAll() {
         mEntryAlias = null;
-        mEntryUid = KeyProperties.NAMESPACE_APPLICATION;
+        mEntryNamespace = KeyProperties.NAMESPACE_APPLICATION;
         mJcaKeyAlgorithm = null;
         mKeymasterAlgorithm = -1;
         mKeymasterPurposes = null;
@@ -541,10 +541,10 @@
 
         KeyDescriptor descriptor = new KeyDescriptor();
         descriptor.alias = mEntryAlias;
-        descriptor.domain = mEntryUid == KeyProperties.NAMESPACE_APPLICATION
+        descriptor.domain = mEntryNamespace == KeyProperties.NAMESPACE_APPLICATION
                 ? Domain.APP
                 : Domain.SELINUX;
-        descriptor.nspace = mEntryUid;
+        descriptor.nspace = mEntryNamespace;
         descriptor.blob = null;
 
         boolean success = false;
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
index e101115..d36695b 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
@@ -43,6 +43,7 @@
 
 import javax.crypto.Cipher;
 import javax.crypto.Mac;
+import javax.crypto.SecretKey;
 
 /**
  * A provider focused on providing JCA interfaces for the Android KeyStore.
@@ -273,10 +274,10 @@
     /** @hide **/
     @NonNull
     public static KeyPair loadAndroidKeyStoreKeyPairFromKeystore(
-            @NonNull KeyStore2 keyStore, @NonNull String privateKeyAlias, int namespace)
+            @NonNull KeyStore2 keyStore, @NonNull KeyDescriptor descriptor)
             throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
         AndroidKeyStoreKey key =
-                loadAndroidKeyStoreKeyFromKeystore(keyStore, privateKeyAlias, namespace);
+                loadAndroidKeyStoreKeyFromKeystore(keyStore, descriptor);
         if (key instanceof AndroidKeyStorePublicKey) {
             AndroidKeyStorePublicKey publicKey = (AndroidKeyStorePublicKey) key;
             return new KeyPair(publicKey, publicKey.getPrivateKey());
@@ -299,13 +300,26 @@
         }
     }
 
+    /** @hide **/
+    @NonNull
+    public static SecretKey loadAndroidKeyStoreSecretKeyFromKeystore(
+            @NonNull KeyStore2 keyStore, @NonNull KeyDescriptor descriptor)
+            throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
+
+        AndroidKeyStoreKey key =
+                loadAndroidKeyStoreKeyFromKeystore(keyStore, descriptor);
+        if (key instanceof SecretKey) {
+            return (SecretKey) key;
+        } else {
+            throw new UnrecoverableKeyException("No secret key found by the given alias.");
+        }
+    }
 
     @NonNull
     private static AndroidKeyStoreSecretKey makeAndroidKeyStoreSecretKeyFromKeyEntryResponse(
             @NonNull KeyDescriptor descriptor,
             @NonNull KeyEntryResponse response, int algorithm, int digest)
             throws UnrecoverableKeyException {
-
         @KeyProperties.KeyAlgorithmEnum String keyAlgorithmString;
         try {
             keyAlgorithmString = KeyProperties.KeyAlgorithm.fromKeymasterSecretKeyAlgorithm(
@@ -336,8 +350,7 @@
     @NonNull
     public static AndroidKeyStoreKey loadAndroidKeyStoreKeyFromKeystore(
             @NonNull KeyStore2 keyStore, @NonNull String alias, int namespace)
-            throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException  {
-
+            throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
         KeyDescriptor descriptor = new KeyDescriptor();
         if (namespace == KeyProperties.NAMESPACE_APPLICATION) {
             descriptor.nspace = KeyProperties.NAMESPACE_APPLICATION; // ignored;
@@ -348,6 +361,18 @@
         }
         descriptor.alias = alias;
         descriptor.blob = null;
+
+        final AndroidKeyStoreKey key = loadAndroidKeyStoreKeyFromKeystore(keyStore, descriptor);
+        if (key instanceof AndroidKeyStorePublicKey) {
+            return ((AndroidKeyStorePublicKey) key).getPrivateKey();
+        } else {
+            return key;
+        }
+    }
+
+    private static AndroidKeyStoreKey loadAndroidKeyStoreKeyFromKeystore(
+            @NonNull KeyStore2 keyStore, @NonNull KeyDescriptor descriptor)
+            throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
         KeyEntryResponse response = null;
         try {
             response = keyStore.getKeyEntry(descriptor);
@@ -397,7 +422,7 @@
                 keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_EC) {
             return makeAndroidKeyStorePublicKeyFromKeyEntryResponse(descriptor, response.metadata,
                     new KeyStoreSecurityLevel(response.iSecurityLevel),
-                    keymasterAlgorithm).getPrivateKey();
+                    keymasterAlgorithm);
         } else {
             throw new UnrecoverableKeyException("Key algorithm unknown");
         }
diff --git a/keystore/tests/Android.bp b/keystore/tests/Android.bp
index e9b22c1..2315a85 100644
--- a/keystore/tests/Android.bp
+++ b/keystore/tests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_keystore_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_keystore_license"],
+}
+
 android_test {
     name: "KeystoreTests",
     // LOCAL_MODULE := keystore
diff --git a/libs/WindowManager/Jetpack/Android.bp b/libs/WindowManager/Jetpack/Android.bp
index 4612ba2..d8f00bb 100644
--- a/libs/WindowManager/Jetpack/Android.bp
+++ b/libs/WindowManager/Jetpack/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 // Sidecar
 android_library_import {
     name: "window-sidecar",
diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp
index 0540aee..1b5dc8b 100644
--- a/libs/WindowManager/Shell/Android.bp
+++ b/libs/WindowManager/Shell/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 // Begin ProtoLog
 java_library {
     name: "wm_shell_protolog-groups",
diff --git a/libs/WindowManager/Shell/res/drawable/pip_expand.xml b/libs/WindowManager/Shell/res/drawable/pip_expand.xml
index c99d819..d36c4f7 100644
--- a/libs/WindowManager/Shell/res/drawable/pip_expand.xml
+++ b/libs/WindowManager/Shell/res/drawable/pip_expand.xml
@@ -14,8 +14,8 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="36dp"
-    android:height="36dp"
+    android:width="@dimen/pip_expand_action_inner_size"
+    android:height="@dimen/pip_expand_action_inner_size"
     android:viewportWidth="36"
     android:viewportHeight="36">
 
@@ -25,4 +25,4 @@
         android:fillColor="#FFFFFF"
         android:pathData="M10 21H7v8h8v-3h-5v-5zm-3-6h3v-5h5V7H7v8zm19 11h-5v3h8v-8h-3v5zM21
 7v3h5v5h3V7h-8z" />
-</vector>
\ No newline at end of file
+</vector>
diff --git a/libs/WindowManager/Shell/res/drawable/pip_ic_close_white.xml b/libs/WindowManager/Shell/res/drawable/pip_ic_close_white.xml
index bcc850a..6045626 100644
--- a/libs/WindowManager/Shell/res/drawable/pip_ic_close_white.xml
+++ b/libs/WindowManager/Shell/res/drawable/pip_ic_close_white.xml
@@ -15,8 +15,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
+        android:width="@dimen/pip_action_inner_size"
+        android:height="@dimen/pip_action_inner_size"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
diff --git a/libs/WindowManager/Shell/res/drawable/pip_ic_pause_white.xml b/libs/WindowManager/Shell/res/drawable/pip_ic_pause_white.xml
index ef9b2d9..0c469f7 100644
--- a/libs/WindowManager/Shell/res/drawable/pip_ic_pause_white.xml
+++ b/libs/WindowManager/Shell/res/drawable/pip_ic_pause_white.xml
@@ -15,8 +15,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
+    android:width="@dimen/pip_action_inner_size"
+    android:height="@dimen/pip_action_inner_size"
     android:viewportWidth="24"
     android:viewportHeight="24">
 
diff --git a/libs/WindowManager/Shell/res/drawable/pip_ic_play_arrow_white.xml b/libs/WindowManager/Shell/res/drawable/pip_ic_play_arrow_white.xml
index f12d2cb..8567afa 100644
--- a/libs/WindowManager/Shell/res/drawable/pip_ic_play_arrow_white.xml
+++ b/libs/WindowManager/Shell/res/drawable/pip_ic_play_arrow_white.xml
@@ -15,8 +15,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
+    android:width="@dimen/pip_action_inner_size"
+    android:height="@dimen/pip_action_inner_size"
     android:viewportWidth="24"
     android:viewportHeight="24">
 
diff --git a/libs/WindowManager/Shell/res/drawable/pip_ic_settings.xml b/libs/WindowManager/Shell/res/drawable/pip_ic_settings.xml
index b61e98ce..73ec167 100644
--- a/libs/WindowManager/Shell/res/drawable/pip_ic_settings.xml
+++ b/libs/WindowManager/Shell/res/drawable/pip_ic_settings.xml
@@ -15,8 +15,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
+    android:width="@dimen/pip_action_inner_size"
+    android:height="@dimen/pip_action_inner_size"
     android:viewportWidth="24.0"
     android:viewportHeight="24.0">
     <path
diff --git a/libs/WindowManager/Shell/res/drawable/pip_ic_skip_next_white.xml b/libs/WindowManager/Shell/res/drawable/pip_ic_skip_next_white.xml
index 040c7e6..6c55421 100644
--- a/libs/WindowManager/Shell/res/drawable/pip_ic_skip_next_white.xml
+++ b/libs/WindowManager/Shell/res/drawable/pip_ic_skip_next_white.xml
@@ -15,8 +15,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
+    android:width="@dimen/pip_action_inner_size"
+    android:height="@dimen/pip_action_inner_size"
     android:viewportWidth="24"
     android:viewportHeight="24">
 
@@ -25,4 +25,4 @@
         android:pathData="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z" />
     <path
         android:pathData="M0 0h24v24H0z" />
-</vector>
\ No newline at end of file
+</vector>
diff --git a/libs/WindowManager/Shell/res/drawable/pip_ic_skip_previous_white.xml b/libs/WindowManager/Shell/res/drawable/pip_ic_skip_previous_white.xml
index b9b94b7..6b5382b 100644
--- a/libs/WindowManager/Shell/res/drawable/pip_ic_skip_previous_white.xml
+++ b/libs/WindowManager/Shell/res/drawable/pip_ic_skip_previous_white.xml
@@ -15,8 +15,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
+    android:width="@dimen/pip_action_inner_size"
+    android:height="@dimen/pip_action_inner_size"
     android:viewportWidth="24"
     android:viewportHeight="24">
 
@@ -25,4 +25,4 @@
         android:pathData="M6 6h2v12H6zm3.5 6l8.5 6V6z" />
     <path
         android:pathData="M0 0h24v24H0z" />
-</vector>
\ No newline at end of file
+</vector>
diff --git a/libs/WindowManager/Shell/res/layout/one_handed_tutorial.xml b/libs/WindowManager/Shell/res/layout/one_handed_tutorial.xml
index dc54caf..0190aad 100644
--- a/libs/WindowManager/Shell/res/layout/one_handed_tutorial.xml
+++ b/libs/WindowManager/Shell/res/layout/one_handed_tutorial.xml
@@ -54,8 +54,8 @@
         android:layout_height="wrap_content"
         android:layout_marginTop="6dp"
         android:layout_marginBottom="0dp"
-        android:layout_marginStart="86dp"
-        android:layout_marginEnd="86dp"
+        android:layout_marginStart="46dp"
+        android:layout_marginEnd="46dp"
         android:gravity="center_horizontal"
         android:fontFamily="roboto-regular"
         android:text="@string/one_handed_tutorial_description"
diff --git a/libs/WindowManager/Shell/res/layout/pip_menu.xml b/libs/WindowManager/Shell/res/layout/pip_menu.xml
index b581f55..9fe0247 100644
--- a/libs/WindowManager/Shell/res/layout/pip_menu.xml
+++ b/libs/WindowManager/Shell/res/layout/pip_menu.xml
@@ -40,7 +40,7 @@
                 android:layout_height="@dimen/pip_expand_action_size"
                 android:layout_gravity="center"
                 android:contentDescription="@string/pip_phone_expand"
-                android:padding="10dp"
+                android:gravity="center"
                 android:src="@drawable/pip_expand"
                 android:background="?android:selectableItemBackgroundBorderless" />
         </FrameLayout>
@@ -72,8 +72,8 @@
             android:id="@+id/settings"
             android:layout_width="@dimen/pip_action_size"
             android:layout_height="@dimen/pip_action_size"
-            android:padding="@dimen/pip_action_padding"
             android:contentDescription="@string/pip_phone_settings"
+            android:gravity="center"
             android:src="@drawable/pip_ic_settings"
             android:background="?android:selectableItemBackgroundBorderless" />
 
@@ -81,8 +81,8 @@
             android:id="@+id/dismiss"
             android:layout_width="@dimen/pip_action_size"
             android:layout_height="@dimen/pip_action_size"
-            android:padding="@dimen/pip_action_padding"
             android:contentDescription="@string/pip_phone_close"
+            android:gravity="center"
             android:src="@drawable/pip_ic_close_white"
             android:background="?android:selectableItemBackgroundBorderless" />
     </LinearLayout>
diff --git a/libs/WindowManager/Shell/res/layout/pip_menu_action.xml b/libs/WindowManager/Shell/res/layout/pip_menu_action.xml
index 7a026ca..a733b31 100644
--- a/libs/WindowManager/Shell/res/layout/pip_menu_action.xml
+++ b/libs/WindowManager/Shell/res/layout/pip_menu_action.xml
@@ -14,10 +14,18 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 -->
-<ImageButton
+<com.android.wm.shell.pip.phone.PipMenuActionView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="@dimen/pip_action_size"
     android:layout_height="@dimen/pip_action_size"
-    android:padding="@dimen/pip_action_padding"
     android:background="?android:selectableItemBackgroundBorderless"
-    android:forceHasOverlappingRendering="false" />
+    android:forceHasOverlappingRendering="false">
+
+    <ImageView
+        android:id="@+id/image"
+        android:layout_width="@dimen/pip_action_inner_size"
+        android:layout_height="@dimen/pip_action_inner_size"
+        android:layout_gravity="center"
+        android:scaleType="fitXY"/>
+
+</com.android.wm.shell.pip.phone.PipMenuActionView>
diff --git a/libs/WindowManager/Shell/res/layout/size_compat_mode_hint.xml b/libs/WindowManager/Shell/res/layout/size_compat_mode_hint.xml
index 347c2b4..0dea87c 100644
--- a/libs/WindowManager/Shell/res/layout/size_compat_mode_hint.xml
+++ b/libs/WindowManager/Shell/res/layout/size_compat_mode_hint.xml
@@ -14,35 +14,52 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.wm.shell.sizecompatui.SizeCompatHintPopup
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:background="@android:color/background_light"
-    android:orientation="vertical">
+    android:layout_height="wrap_content">
 
-    <TextView
-        android:layout_width="180dp"
-        android:layout_height="wrap_content"
-        android:paddingLeft="10dp"
-        android:paddingRight="10dp"
-        android:paddingTop="10dp"
-        android:text="@string/restart_button_description"
-        android:textAlignment="viewStart"
-        android:textColor="@android:color/primary_text_light"
-        android:textSize="16sp" />
-
-    <Button
-        android:id="@+id/got_it"
+    <FrameLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:includeFontPadding="false"
-        android:layout_gravity="end"
-        android:minHeight="36dp"
-        android:background="?android:attr/selectableItemBackground"
-        android:text="@string/got_it"
-        android:textAllCaps="true"
-        android:textColor="#3c78d8"
-        android:textSize="16sp"
-        android:textStyle="bold" />
+        android:gravity="center"
+        android:clipToPadding="false"
+        android:padding="@dimen/bubble_elevation">
 
-</LinearLayout>
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:background="@android:color/background_light"
+            android:elevation="@dimen/bubble_elevation"
+            android:orientation="vertical">
+
+            <TextView
+                android:layout_width="180dp"
+                android:layout_height="wrap_content"
+                android:paddingLeft="10dp"
+                android:paddingRight="10dp"
+                android:paddingTop="10dp"
+                android:text="@string/restart_button_description"
+                android:textAlignment="viewStart"
+                android:textColor="@android:color/primary_text_light"
+                android:textSize="16sp"/>
+
+            <Button
+                android:id="@+id/got_it"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:includeFontPadding="false"
+                android:layout_gravity="end"
+                android:minHeight="36dp"
+                android:background="?android:attr/selectableItemBackground"
+                android:text="@string/got_it"
+                android:textAllCaps="true"
+                android:textColor="#3c78d8"
+                android:textSize="16sp"
+                android:textStyle="bold"/>
+
+        </LinearLayout>
+
+    </FrameLayout>
+
+</com.android.wm.shell.sizecompatui.SizeCompatHintPopup>
diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml
index ea634cf..c3ae053 100644
--- a/libs/WindowManager/Shell/res/values-af/strings.xml
+++ b/libs/WindowManager/Shell/res/values-af/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Borrel"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Bestuur"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Borrel is toegemaak."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Tik om hierdie program te herbegin en maak volskerm oop."</string>
+    <string name="got_it" msgid="4428750913636945527">"Het dit"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml
index e4628d7..c889039 100644
--- a/libs/WindowManager/Shell/res/values-am/strings.xml
+++ b/libs/WindowManager/Shell/res/values-am/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"አረፋ"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"ያቀናብሩ"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"አረፋ ተሰናብቷል።"</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"ይህን መተግበሪያ ዳግም ለማስነሳት መታ ያድርጉ እና ወደ ሙሉ ማያ ገጽ ይሂዱ።"</string>
+    <string name="got_it" msgid="4428750913636945527">"ገባኝ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml
index 7b5bda7..2c89b1d 100644
--- a/libs/WindowManager/Shell/res/values-ar/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ar/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"فقاعة"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"إدارة"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"تم إغلاق الفقاعة."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"انقر لإعادة تشغيل هذا التطبيق والانتقال إلى وضع ملء الشاشة."</string>
+    <string name="got_it" msgid="4428750913636945527">"حسنًا"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml
index 47294c4..0a74ac6 100644
--- a/libs/WindowManager/Shell/res/values-as/strings.xml
+++ b/libs/WindowManager/Shell/res/values-as/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"বাবল"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"পৰিচালনা কৰক"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"বাবল অগ্ৰাহ্য কৰা হৈছে"</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"এপ্‌টো ৰিষ্টাৰ্ট কৰিবলৈ আৰু পূৰ্ণ স্ক্ৰীন ব্যৱহাৰ কৰিবলৈ টিপক।"</string>
+    <string name="got_it" msgid="4428750913636945527">"বুজি পালোঁ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml
index 923ff79..54483bf 100644
--- a/libs/WindowManager/Shell/res/values-az/strings.xml
+++ b/libs/WindowManager/Shell/res/values-az/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Qabarcıq"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"İdarə edin"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Qabarcıqdan imtina edilib."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Bu tətbiqi sıfırlayaraq tam ekrana keçmək üçün toxunun."</string>
+    <string name="got_it" msgid="4428750913636945527">"Anladım"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
index 02e609cd..5ed79c4 100644
--- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Oblačić"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Upravljajte"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Oblačić je odbačen."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Dodirnite da biste restartovali aplikaciju i prešli u režim celog ekrana."</string>
+    <string name="got_it" msgid="4428750913636945527">"Važi"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml
index ccea318..a9a62de 100644
--- a/libs/WindowManager/Shell/res/values-be/strings.xml
+++ b/libs/WindowManager/Shell/res/values-be/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Усплывальнае апавяшчэнне"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Кіраваць"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Усплывальнае апавяшчэнне адхілена."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Націсніце, каб перазапусціць гэту праграму і перайсці ў поўнаэкранны рэжым."</string>
+    <string name="got_it" msgid="4428750913636945527">"Зразумела"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml
index d29660b..80895dc 100644
--- a/libs/WindowManager/Shell/res/values-bg/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bg/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Балонче"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Управление"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Балончето е отхвърлено."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Докоснете, за да рестартирате това приложение в режим на цял екран."</string>
+    <string name="got_it" msgid="4428750913636945527">"Разбрах"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml
index 84bcaf9..bdda799 100644
--- a/libs/WindowManager/Shell/res/values-bn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bn/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"বাবল"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"ম্যানেজ করুন"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"বাবল বাতিল করা হয়েছে।"</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"এই অ্যাপ রিস্টার্ট করতে ট্যাপ করুন ও \'ফুল-স্ক্রিন\' মোড ব্যবহার করুন।"</string>
+    <string name="got_it" msgid="4428750913636945527">"বুঝেছি"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml
index 85e08d7..759e9b8 100644
--- a/libs/WindowManager/Shell/res/values-bs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bs/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Oblačić"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Upravljaj"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Oblačić je odbačen."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Dodirnite da ponovo pokrenete ovu aplikaciju i aktivirate prikaz preko cijelog ekrana."</string>
+    <string name="got_it" msgid="4428750913636945527">"Razumijem"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml
index a80b7fb..202ea20 100644
--- a/libs/WindowManager/Shell/res/values-ca/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ca/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Bombolla"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Gestiona"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"La bombolla s\'ha ignorat."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Toca per reiniciar aquesta aplicació i passar a pantalla completa."</string>
+    <string name="got_it" msgid="4428750913636945527">"Entesos"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml
index e8257bc..08a4201 100644
--- a/libs/WindowManager/Shell/res/values-cs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-cs/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Bublina"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Spravovat"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bublina byla zavřena."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Klepnutím aplikaci restartujete a přejdete na režim celé obrazovky"</string>
+    <string name="got_it" msgid="4428750913636945527">"Rozumím"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml
index 17f8286..395f6e7 100644
--- a/libs/WindowManager/Shell/res/values-da/strings.xml
+++ b/libs/WindowManager/Shell/res/values-da/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Boble"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Administrer"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Boblen blev lukket."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Tryk for at genstarte denne app, og gå til fuld skærm."</string>
+    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml
index f04796a..ab3461a 100644
--- a/libs/WindowManager/Shell/res/values-de/strings.xml
+++ b/libs/WindowManager/Shell/res/values-de/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Bubble"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Verwalten"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bubble verworfen."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Tippe, um die App im Vollbildmodus neu zu starten."</string>
+    <string name="got_it" msgid="4428750913636945527">"Ok"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml
index cc329e8..75e4379 100644
--- a/libs/WindowManager/Shell/res/values-el/strings.xml
+++ b/libs/WindowManager/Shell/res/values-el/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Συννεφάκι"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Διαχείριση"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Το συννεφάκι παραβλέφθηκε."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Πατήστε για επανεκκίνηση αυτής της εφαρμογής και ενεργοποίηση πλήρους οθόνης."</string>
+    <string name="got_it" msgid="4428750913636945527">"Το κατάλαβα"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
index 90c71c0..0d7b60f 100644
--- a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Bubble"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Manage"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bubble dismissed."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Tap to restart this app and go full screen."</string>
+    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
index 90c71c0..0d7b60f 100644
--- a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Bubble"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Manage"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bubble dismissed."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Tap to restart this app and go full screen."</string>
+    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
index 90c71c0..0d7b60f 100644
--- a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Bubble"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Manage"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bubble dismissed."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Tap to restart this app and go full screen."</string>
+    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
index 90c71c0..0d7b60f 100644
--- a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Bubble"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Manage"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bubble dismissed."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Tap to restart this app and go full screen."</string>
+    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
index d8b5b400..4bff89d 100644
--- a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‏‎‏‎‏‏‎‏‎‏‏‎‏‎‎‏‏‏‏‎‏‏‎‏‏‎‏‏‎‎‏‏‎‏‏‎‏‏‎‎‎‏‏‏‏‏‎‎‎‎‏‎‎Bubble‎‏‎‎‏‎"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‎‎‏‎‏‏‎‎‎‏‏‏‎‏‎‎‎‎‏‎‎‎‏‏‎‎‏‎‎‎‏‎‎‏‏‎‎‎‏‎‏‎‎‏‏‏‎‎‏‏‎Manage‎‏‎‎‏‎"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‎‎‎‏‎‏‏‎‏‏‎‏‎‏‎‏‎‏‏‏‏‏‎‏‎Bubble dismissed.‎‏‎‎‏‎"</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‏‎‏‎‏‎‎‏‎‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‏‏‎‏‏‏‎Tap to restart this app and go full screen.‎‏‎‎‏‎"</string>
+    <string name="got_it" msgid="4428750913636945527">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‎‏‏‎‎‎‎‏‎‏‎‏‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‎‎‏‏‏‎‎‏‏‏‎‏‏‏‎Got it‎‏‎‎‏‎"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
index 7244b1a..90c4d51 100644
--- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Cuadro"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Administrar"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Se descartó el cuadro."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Presiona para reiniciar esta app y acceder al modo de pantalla completa."</string>
+    <string name="got_it" msgid="4428750913636945527">"Entendido"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml
index 65e75bd..f3baad7 100644
--- a/libs/WindowManager/Shell/res/values-es/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Burbuja"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Gestionar"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Burbuja cerrada."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Toca para reiniciar esta aplicación e ir a la pantalla completa."</string>
+    <string name="got_it" msgid="4428750913636945527">"Listo"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml
index 0ccfcfe..9222a91 100644
--- a/libs/WindowManager/Shell/res/values-et/strings.xml
+++ b/libs/WindowManager/Shell/res/values-et/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Mull"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Halda"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Mullist loobuti."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Puudutage rakenduse taaskäivitamiseks ja täisekraanrežiimi aktiveerimiseks."</string>
+    <string name="got_it" msgid="4428750913636945527">"Selge"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml
index 6682ea8..4a59b59 100644
--- a/libs/WindowManager/Shell/res/values-eu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-eu/strings.xml
@@ -25,8 +25,8 @@
     <string name="pip_notification_message" msgid="8854051911700302620">"Ez baduzu nahi <xliff:g id="NAME">%s</xliff:g> zerbitzuak eginbide hori erabiltzea, sakatu hau ezarpenak ireki eta aukera desaktibatzeko."</string>
     <string name="pip_play" msgid="3496151081459417097">"Erreproduzitu"</string>
     <string name="pip_pause" msgid="690688849510295232">"Pausatu"</string>
-    <string name="pip_skip_to_next" msgid="8403429188794867653">"Saltatu hurrengora"</string>
-    <string name="pip_skip_to_prev" msgid="7172158111196394092">"Saltatu aurrekora"</string>
+    <string name="pip_skip_to_next" msgid="8403429188794867653">"Joan hurrengora"</string>
+    <string name="pip_skip_to_prev" msgid="7172158111196394092">"Joan aurrekora"</string>
     <string name="accessibility_action_pip_resize" msgid="4623966104749543182">"Aldatu tamaina"</string>
     <string name="dock_forced_resizable" msgid="1749750436092293116">"Baliteke aplikazioak ez funtzionatzea pantaila zatituan."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Aplikazioak ez du onartzen pantaila zatitua"</string>
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Burbuila"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Kudeatu"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Baztertu da globoa."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Saka ezazu aplikazioa berrabiarazteko, eta ezarri pantaila osoko modua."</string>
+    <string name="got_it" msgid="4428750913636945527">"Ados"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml
index a41811d..fed3ea9 100644
--- a/libs/WindowManager/Shell/res/values-fa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fa/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"حباب"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"مدیریت"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"حبابک رد شد."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"برای بازراه‌اندازی این برنامه و تغییر به حالت تمام‌صفحه، ضربه بزنید."</string>
+    <string name="got_it" msgid="4428750913636945527">"متوجه‌ام"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml
index fcdc70f..332dc9b 100644
--- a/libs/WindowManager/Shell/res/values-fi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fi/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Kupla"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Ylläpidä"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Kupla ohitettu."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Napauta, niin sovellus käynnistyy uudelleen ja siirtyy koko näytön tilaan."</string>
+    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
index ed82237..f51fc66 100644
--- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Bulle"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Gérer"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bulle ignorée."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Touchez pour redémarrer cette application et passer en plein écran."</string>
+    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml
index ad98b85..8fa06e8 100644
--- a/libs/WindowManager/Shell/res/values-fr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Bulle"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Gérer"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bulle fermée."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Appuyez pour redémarrer cette application et activer le mode plein écran."</string>
+    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml
index 529825e..56188d4 100644
--- a/libs/WindowManager/Shell/res/values-gl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gl/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Burbulla"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Xestionar"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Ignorouse a burbulla."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Toca o botón para reiniciar esta aplicación e abrila en pantalla completa."</string>
+    <string name="got_it" msgid="4428750913636945527">"Entendido"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml
index ee23e1e9..b76e910 100644
--- a/libs/WindowManager/Shell/res/values-gu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gu/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"બબલ"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"મેનેજ કરો"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"બબલ છોડી દેવાયો."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"આ ઍપ ફરીથી ચાલુ કરવા માટે ટૅપ કરીને પૂર્ણ સ્ક્રીન કરો."</string>
+    <string name="got_it" msgid="4428750913636945527">"સમજાઈ ગયું"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml
index 34c1c85..a969386 100644
--- a/libs/WindowManager/Shell/res/values-hi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hi/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"बबल"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"प्रबंधित करें"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"बबल खारिज किया गया."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"इस ऐप्लिकेशन को रीस्टार्ट करने और फ़ुल स्क्रीन पर देखने के लिए टैप करें."</string>
+    <string name="got_it" msgid="4428750913636945527">"ठीक है"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml
index 32b21aa..769d1d2 100644
--- a/libs/WindowManager/Shell/res/values-hr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hr/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Oblačić"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Upravljanje"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Oblačić odbačen."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Dodirnite da biste ponovo pokrenuli tu aplikaciju i prikazali je na cijelom zaslonu."</string>
+    <string name="got_it" msgid="4428750913636945527">"Shvaćam"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml
index 123b127..05655f1 100644
--- a/libs/WindowManager/Shell/res/values-hu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hu/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Buborék"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Kezelés"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Buborék elvetve."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Koppintson az alkalmazás újraindításához és a teljes képernyős mód elindításához."</string>
+    <string name="got_it" msgid="4428750913636945527">"Rendben"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml
index b047cf1..5f7495e 100644
--- a/libs/WindowManager/Shell/res/values-hy/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hy/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Պղպջակ"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Կառավարել"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Ամպիկը փակվեց։"</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Հպեք՝ հավելվածը վերագործարկելու և լիաէկրան ռեժիմին անցնելու համար։"</string>
+    <string name="got_it" msgid="4428750913636945527">"Եղավ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml
index a75cdb4..2cf50c0 100644
--- a/libs/WindowManager/Shell/res/values-in/strings.xml
+++ b/libs/WindowManager/Shell/res/values-in/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Balon"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Kelola"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Balon ditutup."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Ketuk untuk memulai ulang aplikasi ini dan membuka layar penuh."</string>
+    <string name="got_it" msgid="4428750913636945527">"Oke"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml
index 3b28148..7a3b6a6 100644
--- a/libs/WindowManager/Shell/res/values-is/strings.xml
+++ b/libs/WindowManager/Shell/res/values-is/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Blaðra"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Stjórna"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Blöðru lokað."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Ýttu til að endurræsa forritið og sýna það á öllum skjánum."</string>
+    <string name="got_it" msgid="4428750913636945527">"Ég skil"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml
index 8a2b9db..b061d1f 100644
--- a/libs/WindowManager/Shell/res/values-it/strings.xml
+++ b/libs/WindowManager/Shell/res/values-it/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Fumetto"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Gestisci"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Fumetto ignorato."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Tocca per riavviare l\'app e passare alla modalità a schermo intero."</string>
+    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml
index 20114a7..b75ee45 100644
--- a/libs/WindowManager/Shell/res/values-iw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-iw/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"בועה"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"ניהול"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"הבועה נסגרה."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"צריך להקיש כדי להפעיל מחדש את האפליקציה הזו ולעבור למסך מלא."</string>
+    <string name="got_it" msgid="4428750913636945527">"הבנתי"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml
index fbb2951..ab693d2 100644
--- a/libs/WindowManager/Shell/res/values-ja/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ja/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"バブル"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"管理"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ふきだしが非表示になっています。"</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"タップしてこのアプリを再起動すると、全画面表示になります。"</string>
+    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml
index f978481..ef9a84f 100644
--- a/libs/WindowManager/Shell/res/values-ka/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ka/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"ბუშტი"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"მართვა"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ბუშტი დაიხურა."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"შეეხეთ ამ აპის გადასატვირთად და გადადით სრულ ეკრანზე."</string>
+    <string name="got_it" msgid="4428750913636945527">"გასაგებია"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml
index 2d27faf..13f3a4e 100644
--- a/libs/WindowManager/Shell/res/values-kk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kk/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Көпіршік"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Басқару"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Қалқымалы анықтама өшірілді."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Бұл қолданбаны қайта қосып, толық экранға өту үшін түртіңіз."</string>
+    <string name="got_it" msgid="4428750913636945527">"Түсінікті"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml
index d503b7a..134d3c2 100644
--- a/libs/WindowManager/Shell/res/values-km/strings.xml
+++ b/libs/WindowManager/Shell/res/values-km/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"ពពុះ"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"គ្រប់គ្រង"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"បានច្រានចោល​សារលេចឡើង។"</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"ចុចដើម្បី​ចាប់ផ្ដើម​កម្មវិធី​នេះឡើងវិញ រួចចូលប្រើ​ពេញអេក្រង់។"</string>
+    <string name="got_it" msgid="4428750913636945527">"យល់ហើយ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml
index 3d61d84..c8b3389 100644
--- a/libs/WindowManager/Shell/res/values-kn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kn/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"ಬಬಲ್"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"ನಿರ್ವಹಿಸಿ"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ಬಬಲ್ ವಜಾಗೊಳಿಸಲಾಗಿದೆ."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"ಈ ಆ್ಯಪ್ ಅನ್ನು ಮರುಪ್ರಾರಂಭಿಸಲು ಮತ್ತು ಪೂರ್ಣ ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿ ನೋಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
+    <string name="got_it" msgid="4428750913636945527">"ಅರ್ಥವಾಯಿತು"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml
index ea7ad56..b29612e 100644
--- a/libs/WindowManager/Shell/res/values-ko/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ko/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"버블"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"관리"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"대화창을 닫았습니다."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"탭하여 이 앱을 다시 시작하고 전체 화면으로 이동합니다."</string>
+    <string name="got_it" msgid="4428750913636945527">"확인"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml
index 611b2d6..530d40a 100644
--- a/libs/WindowManager/Shell/res/values-ky/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ky/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Көбүк"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Башкаруу"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Калкып чыкма билдирме жабылды."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Бул колдонмону өчүрүп күйгүзүп, толук экранга өтүү үчүн таптап коюңуз."</string>
+    <string name="got_it" msgid="4428750913636945527">"Түшүндүм"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml
index a1c998c..5ccf164 100644
--- a/libs/WindowManager/Shell/res/values-lo/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lo/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"ຟອງ"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"ຈັດການ"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ປິດ Bubble ໄສ້ແລ້ວ."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"ແຕະເພື່ອຣີສະຕາດແອັບນີ້ ແລະ ໃຊ້ແບບເຕັມຈໍ."</string>
+    <string name="got_it" msgid="4428750913636945527">"ເຂົ້າໃຈແລ້ວ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml
index b2ccd57..1433312 100644
--- a/libs/WindowManager/Shell/res/values-lt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lt/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Debesėlis"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Tvarkyti"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Debesėlio atsisakyta."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Palieskite, kad paleistumėte iš naujo šią programą ir įjungtumėte viso ekrano režimą."</string>
+    <string name="got_it" msgid="4428750913636945527">"Supratau"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml
index e6d0c77..fb297b8 100644
--- a/libs/WindowManager/Shell/res/values-lv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lv/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Burbulis"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Pārvaldīt"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Burbulis ir noraidīts."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Pieskarieties, lai restartētu šo lietotni un pārietu pilnekrāna režīmā."</string>
+    <string name="got_it" msgid="4428750913636945527">"Labi"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml
index 43f2881..80b3329 100644
--- a/libs/WindowManager/Shell/res/values-mk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mk/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Балонче"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Управувајте"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Балончето е отфрлено."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Допрете за да ја рестартирате апликацијава и да ја отворите на цел екран."</string>
+    <string name="got_it" msgid="4428750913636945527">"Сфатив"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml
index e675861..5d47911 100644
--- a/libs/WindowManager/Shell/res/values-ml/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ml/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"ബബ്ൾ"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"മാനേജ് ചെയ്യുക"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ബബ്ൾ ഡിസ്മിസ് ചെയ്തു."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"ഈ ആപ്പ് റീസ്‌റ്റാർട്ട് ചെയ്‌ത് പൂർണ്ണ സ്ക്രീനിലേക്ക് മാറാൻ ടാപ്പ് ചെയ്യുക."</string>
+    <string name="got_it" msgid="4428750913636945527">"മനസ്സിലായി"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml
index 044fd9f..a5e7f95 100644
--- a/libs/WindowManager/Shell/res/values-mn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mn/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Бөмбөлөг"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Удирдах"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Бөмбөлгийг үл хэрэгссэн."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Энэ аппыг дахин эхлүүлж, бүтэн дэлгэцэд орохын тулд товшино уу."</string>
+    <string name="got_it" msgid="4428750913636945527">"Ойлголоо"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml
index e838cf5..0450189 100644
--- a/libs/WindowManager/Shell/res/values-mr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mr/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"बबल"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"व्यवस्थापित करा"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"बबल डिसमिस केला."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"हे अ‍ॅप रीस्टार्ट करण्यासाठी आणि फुल स्क्रीन करण्यासाठी टॅप करा."</string>
+    <string name="got_it" msgid="4428750913636945527">"समजले"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml
index 6664f38..c0c1cbd 100644
--- a/libs/WindowManager/Shell/res/values-ms/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ms/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Gelembung"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Urus"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Gelembung diketepikan."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Ketik untuk memulakan semula apl ini dan menggunakan skrin penuh."</string>
+    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml
index 9681d14..0d78f89 100644
--- a/libs/WindowManager/Shell/res/values-my/strings.xml
+++ b/libs/WindowManager/Shell/res/values-my/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"ပူဖောင်းဖောက်သံ"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"စီမံရန်"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ပူဖောင်းကွက် ဖယ်လိုက်သည်။"</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"ဤအက်ပ်ကို ပြန်စပြီး ဖန်သားပြင်အပြည့်လုပ်ရန် တို့ပါ။"</string>
+    <string name="got_it" msgid="4428750913636945527">"ရပြီ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml
index 986e890..fab0c0c 100644
--- a/libs/WindowManager/Shell/res/values-nb/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nb/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Boble"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Administrer"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Boblen er avvist."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Trykk for å starte denne appen på nytt og vise den i fullskjerm."</string>
+    <string name="got_it" msgid="4428750913636945527">"Greit"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml
index 0369c6d..882ac37 100644
--- a/libs/WindowManager/Shell/res/values-ne/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ne/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"बबल"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"व्यवस्थापन गर्नुहोस्"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"बबल हटाइयो।"</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"यो एप रिस्टार्ट गर्न ट्याप गर्नुहोस् र फुल स्क्रिन मोडमा जानुहोस्।"</string>
+    <string name="got_it" msgid="4428750913636945527">"बुझेँ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml
index 26c276e..1527e89 100644
--- a/libs/WindowManager/Shell/res/values-nl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nl/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Bubbel"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Beheren"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bubbel gesloten."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Tik om deze app opnieuw te starten en te openen op het volledige scherm."</string>
+    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml
index 27f1622..50d2007 100644
--- a/libs/WindowManager/Shell/res/values-or/strings.xml
+++ b/libs/WindowManager/Shell/res/values-or/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"ବବଲ୍"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"ପରିଚାଳନା କରନ୍ତୁ"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ବବଲ୍ ଖାରଜ କରାଯାଇଛି।"</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"ଏହି ଆପକୁ ରିଷ୍ଟାର୍ଟ କରି ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନ୍ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ।"</string>
+    <string name="got_it" msgid="4428750913636945527">"ବୁଝିଗଲି"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml
index 96688b9..dd3d26e 100644
--- a/libs/WindowManager/Shell/res/values-pa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pa/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"ਬੁਲਬੁਲਾ"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ਬਬਲ ਨੂੰ ਖਾਰਜ ਕੀਤਾ ਗਿਆ।"</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"ਇਸ ਐਪ ਨੂੰ ਮੁੜ-ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ ਅਤੇ ਪੂਰੀ ਸਕ੍ਰੀਨ ਮੋਡ \'ਤੇ ਜਾਓ।"</string>
+    <string name="got_it" msgid="4428750913636945527">"ਸਮਝ ਲਿਆ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml
index 6b640b5..ca2bdcb 100644
--- a/libs/WindowManager/Shell/res/values-pl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pl/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Dymek"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Zarządzaj"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Zamknięto dymek"</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Kliknij, by uruchomić tę aplikację ponownie i przejść w tryb pełnoekranowy."</string>
+    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
index 465d2d1..bdd0d4b 100644
--- a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Bolha"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Gerenciar"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Balão dispensado."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Toque para reiniciar o app e usar tela cheia."</string>
+    <string name="got_it" msgid="4428750913636945527">"Ok"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
index df841bf..6661b05 100644
--- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Balão"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Gerir"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Balão ignorado."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Toque para reiniciar esta app e ficar em ecrã inteiro."</string>
+    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-pt/strings.xml b/libs/WindowManager/Shell/res/values-pt/strings.xml
index 465d2d1..bdd0d4b 100644
--- a/libs/WindowManager/Shell/res/values-pt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Bolha"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Gerenciar"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Balão dispensado."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Toque para reiniciar o app e usar tela cheia."</string>
+    <string name="got_it" msgid="4428750913636945527">"Ok"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml
index 55a4376..9112543 100644
--- a/libs/WindowManager/Shell/res/values-ro/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ro/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Balon"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Gestionați"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Balonul a fost respins."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Atingeți ca să reporniți aplicația și să treceți în modul ecran complet."</string>
+    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml
index 8ae00d2..5120136 100644
--- a/libs/WindowManager/Shell/res/values-ru/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ru/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Всплывающая подсказка"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Настроить"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Всплывающий чат закрыт."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Нажмите, чтобы перезапустить приложение и перейти в полноэкранный режим."</string>
+    <string name="got_it" msgid="4428750913636945527">"ОК"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml
index 081926f..e1d9a82 100644
--- a/libs/WindowManager/Shell/res/values-si/strings.xml
+++ b/libs/WindowManager/Shell/res/values-si/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"බුබුළු"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"කළමනා කරන්න"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"බුබුල ඉවත දමා ඇත."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"මෙම යෙදුම යළි ඇරඹීමට සහ පූර්ණ තිරයට යාමට තට්ටු කරන්න."</string>
+    <string name="got_it" msgid="4428750913636945527">"තේරුණා"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sk/strings.xml b/libs/WindowManager/Shell/res/values-sk/strings.xml
index 24fded7..c88099b 100644
--- a/libs/WindowManager/Shell/res/values-sk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sk/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Bublina"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Spravovať"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bublina bola zavretá."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Klepnutím reštartujete túto aplikáciu a prejdete do režimu celej obrazovky."</string>
+    <string name="got_it" msgid="4428750913636945527">"Dobre"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml
index 3f42530..42d7be7 100644
--- a/libs/WindowManager/Shell/res/values-sl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sl/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Mehurček"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Upravljanje"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Oblaček je bil opuščen."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Dotaknite se za vnovični zagon te aplikacije in preklop v celozaslonski način."</string>
+    <string name="got_it" msgid="4428750913636945527">"Razumem"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml
index ddae724..1f373b5 100644
--- a/libs/WindowManager/Shell/res/values-sq/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sq/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Flluskë"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Menaxho"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Flluska u hoq."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Trokit për ta rinisur këtë aplikacion dhe për të kaluar në ekranin e plotë."</string>
+    <string name="got_it" msgid="4428750913636945527">"E kuptova"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml
index 74c9ac0..2bbbbf9 100644
--- a/libs/WindowManager/Shell/res/values-sr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sr/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Облачић"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Управљајте"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Облачић је одбачен."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Додирните да бисте рестартовали апликацију и прешли у режим целог екрана."</string>
+    <string name="got_it" msgid="4428750913636945527">"Важи"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml
index 81328a8..692b5ed 100644
--- a/libs/WindowManager/Shell/res/values-sv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sv/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Bubbla"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Hantera"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bubblan ignorerades."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Tryck för att starta om appen i helskärmsläge."</string>
+    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml
index 4559832..61c95ee 100644
--- a/libs/WindowManager/Shell/res/values-sw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sw/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Kiputo"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Dhibiti"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Umeondoa kiputo."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Gusa ili uzime na uwashe programu hii, kisha nenda kwenye skrini nzima."</string>
+    <string name="got_it" msgid="4428750913636945527">"Nimeelewa"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml
index 586ee94..32a925a 100644
--- a/libs/WindowManager/Shell/res/values-ta/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ta/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"பபிள்"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"நிர்வகி"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"குமிழ் நிராகரிக்கப்பட்டது."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"தட்டுவதன் மூலம் இந்த ஆப்ஸை மீண்டும் தொடங்கலாம், முழுத்திரையில் பார்க்கலாம்."</string>
+    <string name="got_it" msgid="4428750913636945527">"சரி"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml
index 4e85b43..3db12e7 100644
--- a/libs/WindowManager/Shell/res/values-te/strings.xml
+++ b/libs/WindowManager/Shell/res/values-te/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"బబుల్"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"మేనేజ్ చేయండి"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"బబుల్ విస్మరించబడింది."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"ఈ యాప్‌ను రీస్టార్ట్ చేయడానికి ట్యాప్ చేసి, ఆపై పూర్తి స్క్రీన్‌లోకి వెళ్లండి."</string>
+    <string name="got_it" msgid="4428750913636945527">"అర్థమైంది"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-th/strings.xml b/libs/WindowManager/Shell/res/values-th/strings.xml
index 66c7018..7df76e8 100644
--- a/libs/WindowManager/Shell/res/values-th/strings.xml
+++ b/libs/WindowManager/Shell/res/values-th/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"บับเบิล"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"จัดการ"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ปิดบับเบิลแล้ว"</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"แตะเพื่อรีสตาร์ทแอปนี้และแสดงแบบเต็มหน้าจอ"</string>
+    <string name="got_it" msgid="4428750913636945527">"รับทราบ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml
index a76bf6f..d6c2784 100644
--- a/libs/WindowManager/Shell/res/values-tl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tl/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Bubble"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Pamahalaan"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Na-dismiss na ang bubble."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"I-tap para i-restart ang app na ito at mag-full screen."</string>
+    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml
index b3276da..47d5966 100644
--- a/libs/WindowManager/Shell/res/values-tr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tr/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Baloncuk"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Yönet"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Balon kapatıldı."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Bu uygulamayı yeniden başlatmak ve tam ekrana geçmek için dokunun."</string>
+    <string name="got_it" msgid="4428750913636945527">"Anladım"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml
index 8e303cf..c57f16f 100644
--- a/libs/WindowManager/Shell/res/values-uk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uk/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Спливаюче сповіщення"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Налаштувати"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Спливаюче сповіщення закрито."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Натисніть, щоб перезапустити додаток і перейти в повноекранний режим."</string>
+    <string name="got_it" msgid="4428750913636945527">"Зрозуміло"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml
index 4b0adc6..97a22e7 100644
--- a/libs/WindowManager/Shell/res/values-ur/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ur/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"بلبلہ"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"نظم کریں"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"بلبلہ برخاست کر دیا گیا۔"</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"یہ ایپ دوبارہ شروع کرنے کے لیے تھپتھپائیں اور پوری اسکرین پر جائیں۔"</string>
+    <string name="got_it" msgid="4428750913636945527">"سمجھ آ گئی"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml
index 74b135d..4e91e76 100644
--- a/libs/WindowManager/Shell/res/values-uz/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uz/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Pufaklar"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Boshqarish"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bulutcha yopildi."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Bu ilovani qaytadan ishga tushirish va butun ekranda ochish uchun bosing."</string>
+    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml
index ce37231..169e986f 100644
--- a/libs/WindowManager/Shell/res/values-vi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-vi/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Bong bóng"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Quản lý"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Đã đóng bong bóng."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Nhấn để khởi động lại ứng dụng này và xem ở chế độ toàn màn hình."</string>
+    <string name="got_it" msgid="4428750913636945527">"Tôi hiểu"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
index 3143130..1999703 100644
--- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"气泡"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"管理"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"已关闭对话泡。"</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"点按即可重启此应用并进入全屏模式。"</string>
+    <string name="got_it" msgid="4428750913636945527">"知道了"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
index 4f8bfe0..f82d6d5 100644
--- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"氣泡"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"管理"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"對話氣泡已關閉。"</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"輕按即可重新開啟此應用程式並放大至全螢幕。"</string>
+    <string name="got_it" msgid="4428750913636945527">"知道了"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
index 6fb8ed9..596e7c7 100644
--- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"泡泡"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"管理"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"已關閉泡泡。"</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"輕觸即可重新啟動這個應用程式並進入全螢幕模式。"</string>
+    <string name="got_it" msgid="4428750913636945527">"我知道了"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml
index cab2776..3fed41f 100644
--- a/libs/WindowManager/Shell/res/values-zu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zu/strings.xml
@@ -69,4 +69,6 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Ibhamuza"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Phatha"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Ibhamuza licashisiwe."</string>
+    <string name="restart_button_description" msgid="5887656107651190519">"Thepha ukuze uqale kabusha lolu hlelo lokusebenza uphinde uye kusikrini esigcwele."</string>
+    <string name="got_it" msgid="4428750913636945527">"Ngiyezwa"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 583964b..75bed37 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -21,14 +21,20 @@
     <dimen name="floating_dismiss_gradient_height">250dp</dimen>
 
     <!-- The padding around a PiP actions. -->
-    <dimen name="pip_action_padding">12dp</dimen>
+    <dimen name="pip_action_padding">16dp</dimen>
 
     <!-- The height of the PiP actions container in which the actions are vertically centered. -->
     <dimen name="pip_action_size">48dp</dimen>
 
-    <!-- The width and height of the PiP expand action. -->
+    <!-- The width and height of the PiP action asset drawn within the container. -->
+    <dimen name="pip_action_inner_size">20dp</dimen>
+
+    <!-- The width and height of the PiP expand action container. -->
     <dimen name="pip_expand_action_size">60dp</dimen>
 
+    <!-- The width and height of the PiP expand action asset drawn within the container. -->
+    <dimen name="pip_expand_action_inner_size">28dp</dimen>
+
     <!-- The padding between actions in the PiP in landscape  Note that the PiP does not reflect
          the configuration of the device, so we can't use -land resources. -->
     <dimen name="pip_between_action_padding_land">8dp</dimen>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
index 7376d98..cc353dc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
@@ -25,6 +25,7 @@
 import com.android.wm.shell.draganddrop.DragAndDropController;
 import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
 import com.android.wm.shell.splitscreen.SplitScreenController;
+import com.android.wm.shell.startingsurface.StartingSurface;
 import com.android.wm.shell.transition.Transitions;
 
 import java.util.Optional;
@@ -44,6 +45,7 @@
     private final FullscreenTaskListener mFullscreenTaskListener;
     private final ShellExecutor mMainExecutor;
     private final Transitions mTransitions;
+    private final Optional<StartingSurface> mStartingSurfaceOptional;
 
     private final InitImpl mImpl = new InitImpl();
 
@@ -53,6 +55,7 @@
             Optional<LegacySplitScreenController> legacySplitScreenOptional,
             Optional<SplitScreenController> splitScreenOptional,
             Optional<AppPairsController> appPairsOptional,
+            Optional<StartingSurface> startingSurfaceOptional,
             FullscreenTaskListener fullscreenTaskListener,
             Transitions transitions,
             ShellExecutor mainExecutor) {
@@ -62,6 +65,7 @@
                 legacySplitScreenOptional,
                 splitScreenOptional,
                 appPairsOptional,
+                startingSurfaceOptional,
                 fullscreenTaskListener,
                 transitions,
                 mainExecutor).mImpl;
@@ -73,6 +77,7 @@
             Optional<LegacySplitScreenController> legacySplitScreenOptional,
             Optional<SplitScreenController> splitScreenOptional,
             Optional<AppPairsController> appPairsOptional,
+            Optional<StartingSurface> startingSurfaceOptional,
             FullscreenTaskListener fullscreenTaskListener,
             Transitions transitions,
             ShellExecutor mainExecutor) {
@@ -85,6 +90,7 @@
         mFullscreenTaskListener = fullscreenTaskListener;
         mTransitions = transitions;
         mMainExecutor = mainExecutor;
+        mStartingSurfaceOptional = startingSurfaceOptional;
     }
 
     private void init() {
@@ -93,6 +99,7 @@
 
         mShellTaskOrganizer.addListenerForType(
                 mFullscreenTaskListener, TASK_LISTENER_TYPE_FULLSCREEN);
+        mStartingSurfaceOptional.ifPresent(mShellTaskOrganizer::initStartingSurface);
         // Register the shell organizer
         mShellTaskOrganizer.registerOrganizer();
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index efc55c4..9ddeb2f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -44,7 +44,7 @@
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.sizecompatui.SizeCompatUIController;
-import com.android.wm.shell.startingsurface.StartingSurfaceDrawer;
+import com.android.wm.shell.startingsurface.StartingSurface;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -110,7 +110,7 @@
     private final ArrayMap<IBinder, TaskListener> mLaunchCookieToListener = new ArrayMap<>();
 
     private final Object mLock = new Object();
-    private final StartingSurfaceDrawer mStartingSurfaceDrawer;
+    private StartingSurface mStartingSurface;
 
     /**
      * In charge of showing size compat UI. Can be {@code null} if device doesn't support size
@@ -120,23 +120,19 @@
     private final SizeCompatUIController mSizeCompatUI;
 
     public ShellTaskOrganizer(ShellExecutor mainExecutor, Context context) {
-        this(null /* taskOrganizerController */, mainExecutor, context, null /* sizeCompatUI */,
-                new StartingSurfaceDrawer(context, mainExecutor));
+        this(null /* taskOrganizerController */, mainExecutor, context, null /* sizeCompatUI */);
     }
 
     public ShellTaskOrganizer(ShellExecutor mainExecutor, Context context, @Nullable
             SizeCompatUIController sizeCompatUI) {
-        this(null /* taskOrganizerController */, mainExecutor, context, sizeCompatUI,
-                new StartingSurfaceDrawer(context, mainExecutor));
+        this(null /* taskOrganizerController */, mainExecutor, context, sizeCompatUI);
     }
 
     @VisibleForTesting
     ShellTaskOrganizer(ITaskOrganizerController taskOrganizerController, ShellExecutor mainExecutor,
-            Context context, @Nullable SizeCompatUIController sizeCompatUI,
-            StartingSurfaceDrawer startingSurfaceDrawer) {
+            Context context, @Nullable SizeCompatUIController sizeCompatUI) {
         super(taskOrganizerController, mainExecutor);
         mSizeCompatUI = sizeCompatUI;
-        mStartingSurfaceDrawer = startingSurfaceDrawer;
     }
 
     @Override
@@ -163,6 +159,15 @@
     }
 
     /**
+     * @hide
+     */
+    public void initStartingSurface(StartingSurface startingSurface) {
+        synchronized (mLock) {
+            mStartingSurface = startingSurface;
+        }
+    }
+
+    /**
      * Adds a listener for a specific task id.
      */
     public void addListenerForTaskId(TaskListener listener, int taskId) {
@@ -254,17 +259,23 @@
 
     @Override
     public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
-        mStartingSurfaceDrawer.addStartingWindow(info, appToken);
+        if (mStartingSurface != null) {
+            mStartingSurface.addStartingWindow(info, appToken);
+        }
     }
 
     @Override
     public void removeStartingWindow(int taskId) {
-        mStartingSurfaceDrawer.removeStartingWindow(taskId);
+        if (mStartingSurface != null) {
+            mStartingSurface.removeStartingWindow(taskId);
+        }
     }
 
     @Override
     public void copySplashScreenView(int taskId) {
-        mStartingSurfaceDrawer.copySplashScreenView(taskId);
+        if (mStartingSurface != null) {
+            mStartingSurface.copySplashScreenView(taskId);
+        }
     }
 
     @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
index 5992447..46884fe 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
@@ -157,6 +157,7 @@
         });
         options.setLaunchCookie(launchCookie);
         options.setLaunchWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
+        options.setRemoveWithTaskOrganizer(true);
     }
 
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/WindowManagerShellWrapper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/WindowManagerShellWrapper.java
index 59271e9..e6e6d4a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/WindowManagerShellWrapper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/WindowManagerShellWrapper.java
@@ -22,7 +22,7 @@
 
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.pip.PinnedStackListenerForwarder;
-import com.android.wm.shell.pip.PinnedStackListenerForwarder.PinnedStackListener;
+import com.android.wm.shell.pip.PinnedStackListenerForwarder.PinnedTaskListener;
 
 /**
  * The singleton wrapper to communicate between WindowManagerService and WMShell features
@@ -46,7 +46,7 @@
      * Adds a pinned stack listener, which will receive updates from the window manager service
      * along with any other pinned stack listeners that were added via this method.
      */
-    public void addPinnedStackListener(PinnedStackListener listener)
+    public void addPinnedStackListener(PinnedTaskListener listener)
             throws RemoteException {
         mPinnedStackListenerForwarder.addListener(listener);
         mPinnedStackListenerForwarder.register(DEFAULT_DISPLAY);
@@ -55,7 +55,7 @@
     /**
      * Removes a pinned stack listener.
      */
-    public void removePinnedStackListener(PinnedStackListener listener) {
+    public void removePinnedStackListener(PinnedTaskListener listener) {
         mPinnedStackListenerForwarder.removeListener(listener);
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
index 79f9dcd..562b32b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
@@ -34,6 +34,7 @@
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayImeController;
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.common.split.SplitLayout;
 
@@ -57,12 +58,14 @@
     private final AppPairsController mController;
     private final SyncTransactionQueue mSyncQueue;
     private final DisplayController mDisplayController;
+    private final DisplayImeController mDisplayImeController;
     private SplitLayout mSplitLayout;
 
     AppPair(AppPairsController controller) {
         mController = controller;
         mSyncQueue = controller.getSyncTransactionQueue();
         mDisplayController = controller.getDisplayController();
+        mDisplayImeController = controller.getDisplayImeController();
     }
 
     int getRootTaskId() {
@@ -97,7 +100,7 @@
         mSplitLayout = new SplitLayout(TAG + "SplitDivider",
                 mDisplayController.getDisplayContext(mRootTaskInfo.displayId),
                 mRootTaskInfo.configuration, this /* layoutChangeListener */,
-                b -> b.setParent(mRootTaskLeash));
+                b -> b.setParent(mRootTaskLeash), mDisplayImeController);
 
         final WindowContainerToken token1 = task1.token;
         final WindowContainerToken token2 = task2.token;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPairsController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPairsController.java
index 0415f12..b159333 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPairsController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPairsController.java
@@ -23,17 +23,16 @@
 import android.util.SparseArray;
 
 import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayImeController;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
 
 import java.io.PrintWriter;
-import java.util.concurrent.TimeUnit;
 
 /**
  * Class manages app-pairs multitasking mode and implements the main interface {@link AppPairs}.
@@ -50,12 +49,15 @@
     // Active app-pairs mapped by root task id key.
     private final SparseArray<AppPair> mActiveAppPairs = new SparseArray<>();
     private final DisplayController mDisplayController;
+    private final DisplayImeController mDisplayImeController;
 
     public AppPairsController(ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue,
-                DisplayController displayController, ShellExecutor mainExecutor) {
+            DisplayController displayController, ShellExecutor mainExecutor,
+            DisplayImeController displayImeController) {
         mTaskOrganizer = organizer;
         mSyncQueue = syncQueue;
         mDisplayController = displayController;
+        mDisplayImeController = displayImeController;
         mMainExecutor = mainExecutor;
     }
 
@@ -130,18 +132,22 @@
         }
     }
 
-    public ShellTaskOrganizer getTaskOrganizer() {
+    ShellTaskOrganizer getTaskOrganizer() {
         return mTaskOrganizer;
     }
 
-    public SyncTransactionQueue getSyncTransactionQueue() {
+    SyncTransactionQueue getSyncTransactionQueue() {
         return mSyncQueue;
     }
 
-    public DisplayController getDisplayController() {
+    DisplayController getDisplayController() {
         return mDisplayController;
     }
 
+    DisplayImeController getDisplayImeController() {
+        return mDisplayImeController;
+    }
+
     public void dump(@NonNull PrintWriter pw, String prefix) {
         final String innerPrefix = prefix + "  ";
         final String childPrefix = innerPrefix + "  ";
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index 0ee1f06..8697be9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -124,6 +124,7 @@
     private int mDesiredHeight;
     @DimenRes
     private int mDesiredHeightResId;
+    private int mTaskId;
 
     /** for logging **/
     @Nullable
@@ -162,7 +163,7 @@
      */
     Bubble(@NonNull final String key, @NonNull final ShortcutInfo shortcutInfo,
             final int desiredHeight, final int desiredHeightResId, @Nullable final String title,
-            Executor mainExecutor) {
+            int taskId, Executor mainExecutor) {
         Objects.requireNonNull(key);
         Objects.requireNonNull(shortcutInfo);
         mMetadataShortcutId = shortcutInfo.getId();
@@ -178,6 +179,7 @@
         mTitle = title;
         mShowBubbleUpdateDot = false;
         mMainExecutor = mainExecutor;
+        mTaskId = taskId;
     }
 
     @VisibleForTesting(visibility = PRIVATE)
@@ -197,6 +199,7 @@
             });
         };
         mMainExecutor = mainExecutor;
+        mTaskId = INVALID_TASK_ID;
         setEntry(entry);
     }
 
@@ -520,7 +523,7 @@
      */
     @Override
     public int getTaskId() {
-        return mExpandedView != null ? mExpandedView.getTaskId() : INVALID_TASK_ID;
+        return mExpandedView != null ? mExpandedView.getTaskId() : mTaskId;
     }
 
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 047df5b..1320780 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -1213,7 +1213,7 @@
 
     /** PinnedStackListener that dispatches IME visibility updates to the stack. */
     //TODO(b/170442945): Better way to do this / insets listener?
-    private class BubblesImeListener extends PinnedStackListenerForwarder.PinnedStackListener {
+    private class BubblesImeListener extends PinnedStackListenerForwarder.PinnedTaskListener {
         @Override
         public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
             if (mStackView != null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt
index 3108b02..2417552 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt
@@ -28,7 +28,6 @@
 import com.android.wm.shell.bubbles.storage.BubblePersistentRepository
 import com.android.wm.shell.bubbles.storage.BubbleVolatileRepository
 import com.android.wm.shell.common.ShellExecutor
-import com.android.wm.shell.common.annotations.ExternalThread
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.Job
@@ -36,8 +35,11 @@
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.yield
 
-internal class BubbleDataRepository(context: Context, private val launcherApps: LauncherApps,
-        private val mainExecutor : ShellExecutor) {
+internal class BubbleDataRepository(
+    context: Context,
+    private val launcherApps: LauncherApps,
+    private val mainExecutor: ShellExecutor
+) {
     private val volatileRepository = BubbleVolatileRepository(launcherApps)
     private val persistentRepository = BubblePersistentRepository(context)
 
@@ -78,7 +80,8 @@
                     b.key,
                     b.rawDesiredHeight,
                     b.rawDesiredHeightResId,
-                    b.title
+                    b.title,
+                    b.taskId
             )
         }
     }
@@ -168,6 +171,7 @@
                             entity.desiredHeight,
                             entity.desiredHeightResId,
                             entity.title,
+                            entity.taskId,
                             mainExecutor
                     ) }
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
index 19c3cf9..57a2b6c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
@@ -227,24 +227,30 @@
     /*
      * Fade animation for consecutive flyouts.
      */
-    void animateUpdate(Bubble.FlyoutMessage flyoutMessage, float parentWidth, float stackY) {
+    void animateUpdate(Bubble.FlyoutMessage flyoutMessage, float parentWidth, PointF stackPos,
+            boolean hideDot) {
         final Runnable afterFadeOut = () -> {
             updateFlyoutMessage(flyoutMessage, parentWidth);
             // Wait for TextViews to layout with updated height.
             post(() -> {
-                mFlyoutY = stackY + (mBubbleSize - mFlyoutTextContainer.getHeight()) / 2f;
-                fade(true /* in */, () -> {} /* after */);
+                fade(true /* in */, stackPos, hideDot, () -> {} /* after */);
             } /* after */ );
         };
-        fade(false /* in */, afterFadeOut);
+        fade(false /* in */, stackPos, hideDot, afterFadeOut);
     }
 
     /*
      * Fade-out above or fade-in from below.
      */
-    private void fade(boolean in, Runnable afterFade) {
+    private void fade(boolean in, PointF stackPos, boolean hideDot, Runnable afterFade) {
+        mFlyoutY = stackPos.y + (mBubbleSize - mFlyoutTextContainer.getHeight()) / 2f;
+
         setAlpha(in ? 0f : 1f);
         setTranslationY(in ? mFlyoutY + FLYOUT_FADE_Y : mFlyoutY);
+        updateFlyoutX(stackPos.x);
+        setTranslationX(mRestingTranslationX);
+        updateDot(stackPos, hideDot);
+
         animate()
                 .alpha(in ? 1f : 0f)
                 .setDuration(in ? FLYOUT_FADE_IN_DURATION : FLYOUT_FADE_OUT_DURATION)
@@ -287,6 +293,33 @@
         mMessageText.setText(flyoutMessage.message);
     }
 
+    void updateFlyoutX(float stackX) {
+        // Calculate the translation required to position the flyout next to the bubble stack,
+        // with the desired padding.
+        mRestingTranslationX = mArrowPointingLeft
+                ? stackX + mBubbleSize + mFlyoutSpaceFromBubble
+                : stackX - getWidth() - mFlyoutSpaceFromBubble;
+    }
+
+    void updateDot(PointF stackPos, boolean hideDot) {
+        // Calculate the difference in size between the flyout and the 'dot' so that we can
+        // transform into the dot later.
+        final float newDotSize = hideDot ? 0f : mNewDotSize;
+        mFlyoutToDotWidthDelta = getWidth() - newDotSize;
+        mFlyoutToDotHeightDelta = getHeight() - newDotSize;
+
+        // Calculate the translation values needed to be in the correct 'new dot' position.
+        final float adjustmentForScaleAway = hideDot ? 0f : (mOriginalDotSize / 2f);
+        final float dotPositionX = stackPos.x + mDotCenter[0] - adjustmentForScaleAway;
+        final float dotPositionY = stackPos.y + mDotCenter[1] - adjustmentForScaleAway;
+
+        final float distanceFromFlyoutLeftToDotCenterX = mRestingTranslationX - dotPositionX;
+        final float distanceFromLayoutTopToDotCenterY = mFlyoutY - dotPositionY;
+
+        mTranslationXWhenDot = -distanceFromFlyoutLeftToDotCenterX;
+        mTranslationYWhenDot = -distanceFromLayoutTopToDotCenterY;
+    }
+
     /** Configures the flyout, collapsed into dot form. */
     void setupFlyoutStartingAsDot(
             Bubble.FlyoutMessage flyoutMessage,
@@ -322,29 +355,8 @@
             mFlyoutY =
                     stackPos.y + (mBubbleSize - mFlyoutTextContainer.getHeight()) / 2f;
             setTranslationY(mFlyoutY);
-
-            // Calculate the translation required to position the flyout next to the bubble stack,
-            // with the desired padding.
-            mRestingTranslationX = mArrowPointingLeft
-                    ? stackPos.x + mBubbleSize + mFlyoutSpaceFromBubble
-                    : stackPos.x - getWidth() - mFlyoutSpaceFromBubble;
-
-            // Calculate the difference in size between the flyout and the 'dot' so that we can
-            // transform into the dot later.
-            final float newDotSize = hideDot ? 0f : mNewDotSize;
-            mFlyoutToDotWidthDelta = getWidth() - newDotSize;
-            mFlyoutToDotHeightDelta = getHeight() - newDotSize;
-
-            // Calculate the translation values needed to be in the correct 'new dot' position.
-            final float adjustmentForScaleAway = hideDot ? 0f : (mOriginalDotSize / 2f);
-            final float dotPositionX = stackPos.x + mDotCenter[0] - adjustmentForScaleAway;
-            final float dotPositionY = stackPos.y + mDotCenter[1] - adjustmentForScaleAway;
-
-            final float distanceFromFlyoutLeftToDotCenterX = mRestingTranslationX - dotPositionX;
-            final float distanceFromLayoutTopToDotCenterY = mFlyoutY - dotPositionY;
-
-            mTranslationXWhenDot = -distanceFromFlyoutLeftToDotCenterX;
-            mTranslationYWhenDot = -distanceFromLayoutTopToDotCenterY;
+            updateFlyoutX(stackPos.x);
+            updateDot(stackPos, hideDot);
             if (onLayoutComplete != null) {
                 onLayoutComplete.run();
             }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index a3edc20..78820a8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -1539,19 +1539,16 @@
      * Update bubble order and pointer position.
      */
     public void updateBubbleOrder(List<Bubble> bubbles) {
-        if (isExpansionAnimating()) {
-            return;
-        }
         final Runnable reorder = () -> {
             for (int i = 0; i < bubbles.size(); i++) {
                 Bubble bubble = bubbles.get(i);
                 mBubbleContainer.reorderView(bubble.getIconView(), i);
             }
         };
-        if (mIsExpanded) {
+        if (mIsExpanded || isExpansionAnimating()) {
             reorder.run();
             updateBadgesAndZOrder(false /* setBadgeForCollapsedStack */);
-        } else {
+        } else if (!isExpansionAnimating()) {
             List<View> bubbleViews = bubbles.stream()
                     .map(b -> b.getIconView()).collect(Collectors.toList());
             mStackAnimationController.animateReorder(bubbleViews, reorder);
@@ -2434,7 +2431,7 @@
 
             if (mFlyout.getVisibility() == View.VISIBLE) {
                 mFlyout.animateUpdate(bubble.getFlyoutMessage(), getWidth(),
-                        mStackAnimationController.getStackPosition().y);
+                        mStackAnimationController.getStackPosition(), !bubble.showDot());
             } else {
                 mFlyout.setVisibility(INVISIBLE);
                 mFlyout.setupFlyoutStartingAsDot(bubble.getFlyoutMessage(),
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleEntity.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleEntity.kt
index aeba302..d5cab5a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleEntity.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleEntity.kt
@@ -25,5 +25,6 @@
     val key: String,
     val desiredHeight: Int,
     @DimenRes val desiredHeightResId: Int,
-    val title: String? = null
+    val title: String? = null,
+    val taskId: Int
 )
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelper.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelper.kt
index fe72bd3..470011b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelper.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelper.kt
@@ -15,6 +15,7 @@
  */
 package com.android.wm.shell.bubbles.storage
 
+import android.app.ActivityTaskManager.INVALID_TASK_ID
 import android.util.Xml
 import com.android.internal.util.FastXmlSerializer
 import com.android.internal.util.XmlUtils
@@ -38,6 +39,7 @@
 private const val ATTR_DESIRED_HEIGHT = "h"
 private const val ATTR_DESIRED_HEIGHT_RES_ID = "hid"
 private const val ATTR_TITLE = "t"
+private const val ATTR_TASK_ID = "tid"
 
 /**
  * Writes the bubbles in xml format into given output stream.
@@ -70,6 +72,7 @@
         serializer.attribute(null, ATTR_DESIRED_HEIGHT, bubble.desiredHeight.toString())
         serializer.attribute(null, ATTR_DESIRED_HEIGHT_RES_ID, bubble.desiredHeightResId.toString())
         bubble.title?.let { serializer.attribute(null, ATTR_TITLE, it) }
+        serializer.attribute(null, ATTR_TASK_ID, bubble.taskId.toString())
         serializer.endTag(null, TAG_BUBBLE)
     } catch (e: IOException) {
         throw RuntimeException(e)
@@ -103,7 +106,8 @@
             parser.getAttributeWithName(ATTR_KEY) ?: return null,
             parser.getAttributeWithName(ATTR_DESIRED_HEIGHT)?.toInt() ?: return null,
             parser.getAttributeWithName(ATTR_DESIRED_HEIGHT_RES_ID)?.toInt() ?: return null,
-            parser.getAttributeWithName(ATTR_TITLE)
+            parser.getAttributeWithName(ATTR_TITLE),
+            parser.getAttributeWithName(ATTR_TASK_ID)?.toInt() ?: INVALID_TASK_ID
     )
 }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
index 58a4baf..f118b1e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
@@ -22,6 +22,8 @@
 import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
 import static android.os.Process.SYSTEM_UID;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
+import static android.util.RotationUtils.rotateBounds;
+import static android.util.RotationUtils.rotateInsets;
 import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
 import static android.view.Surface.ROTATION_0;
 import static android.view.Surface.ROTATION_270;
@@ -37,7 +39,6 @@
 import android.os.SystemProperties;
 import android.provider.Settings;
 import android.util.DisplayMetrics;
-import android.util.RotationUtils;
 import android.util.Size;
 import android.view.Display;
 import android.view.DisplayCutout;
@@ -49,6 +50,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
 
 /**
  * Contains information about the layout-properties of a display. This refers to internal layout
@@ -81,6 +83,31 @@
     private boolean mHasStatusBar = false;
     private int mNavBarFrameHeight = 0;
 
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof DisplayLayout)) return false;
+        final DisplayLayout other = (DisplayLayout) o;
+        return mUiMode == other.mUiMode
+                && mWidth == other.mWidth
+                && mHeight == other.mHeight
+                && Objects.equals(mCutout, other.mCutout)
+                && mRotation == other.mRotation
+                && mDensityDpi == other.mDensityDpi
+                && Objects.equals(mNonDecorInsets, other.mNonDecorInsets)
+                && Objects.equals(mStableInsets, other.mStableInsets)
+                && mHasNavigationBar == other.mHasNavigationBar
+                && mHasStatusBar == other.mHasStatusBar
+                && mNavBarFrameHeight == other.mNavBarFrameHeight;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mUiMode, mWidth, mHeight, mCutout, mRotation, mDensityDpi,
+                mNonDecorInsets, mStableInsets, mHasNavigationBar, mHasStatusBar,
+                mNavBarFrameHeight);
+    }
+
     /**
      * Create empty layout.
      */
@@ -241,38 +268,6 @@
     }
 
     /**
-     * Rotates bounds as if parentBounds and bounds are a group. The group is rotated by `delta`
-     * 90-degree counter-clockwise increments. This assumes that parentBounds is at 0,0 and
-     * remains at 0,0 after rotation.
-     *
-     * Only 'bounds' is mutated.
-     */
-    public static void rotateBounds(Rect inOutBounds, Rect parentBounds, int delta) {
-        int rdelta = ((delta % 4) + 4) % 4;
-        int origLeft = inOutBounds.left;
-        switch (rdelta) {
-            case 0:
-                return;
-            case 1:
-                inOutBounds.left = inOutBounds.top;
-                inOutBounds.top = parentBounds.right - inOutBounds.right;
-                inOutBounds.right = inOutBounds.bottom;
-                inOutBounds.bottom = parentBounds.right - origLeft;
-                return;
-            case 2:
-                inOutBounds.left = parentBounds.right - inOutBounds.right;
-                inOutBounds.right = parentBounds.right - origLeft;
-                return;
-            case 3:
-                inOutBounds.left = parentBounds.bottom - inOutBounds.bottom;
-                inOutBounds.bottom = inOutBounds.right;
-                inOutBounds.right = parentBounds.bottom - inOutBounds.top;
-                inOutBounds.top = origLeft;
-                return;
-        }
-    }
-
-    /**
      * Calculates the stable insets if we already have the non-decor insets.
      */
     private static void convertNonDecorInsetsToStableInsets(Resources res, Rect inOutInsets,
@@ -359,8 +354,7 @@
         if (rotation == ROTATION_0) {
             return computeSafeInsets(cutout, displayWidth, displayHeight);
         }
-        final Insets waterfallInsets =
-                RotationUtils.rotateInsets(cutout.getWaterfallInsets(), rotation);
+        final Insets waterfallInsets = rotateInsets(cutout.getWaterfallInsets(), rotation);
         final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
         Rect[] cutoutRects = cutout.getBoundingRectsAll();
         final Rect[] newBounds = new Rect[cutoutRects.length];
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
index fb70cbe5..4bb8e9b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
@@ -39,12 +39,12 @@
 import android.view.IWindowSessionCallback;
 import android.view.InsetsSourceControl;
 import android.view.InsetsState;
+import android.view.ScrollCaptureResponse;
 import android.view.SurfaceControl;
-import android.view.SurfaceSession;
 import android.view.SurfaceControlViewHost;
+import android.view.SurfaceSession;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewRootImpl;
 import android.view.WindowManager;
 import android.view.WindowlessWindowManager;
 import android.window.ClientWindowFrames;
@@ -371,7 +371,11 @@
         @Override
         public void requestScrollCapture(IScrollCaptureCallbacks callbacks) {
             try {
-                callbacks.onUnavailable();
+                callbacks.onScrollCaptureResponse(
+                        new ScrollCaptureResponse.Builder()
+                                .setDescription("Not Implemented")
+                                .build());
+
             } catch (RemoteException ex) {
                 // ignore
             }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java
index e94080a..3b67005 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java
@@ -227,7 +227,7 @@
     }
 
     @Override
-    public void onActivityDismissingDockedStack() {
+    public void onActivityDismissingDockedTask() {
         mMainHandler.sendEmptyMessage(ON_ACTIVITY_DISMISSING_DOCKED_STACK);
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
index c27c929..b9fdaa1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
@@ -36,11 +36,13 @@
 import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.wm.shell.R;
 import com.android.wm.shell.animation.Interpolators;
+import com.android.wm.shell.common.DisplayImeController;
 
 /**
- * Stack divider for app pair.
+ * Divider for multi window splits.
  */
-public class DividerView extends FrameLayout implements View.OnTouchListener {
+public class DividerView extends FrameLayout implements View.OnTouchListener,
+        DisplayImeController.ImePositionProcessor {
     public static final long TOUCH_ANIMATION_DURATION = 150;
     public static final long TOUCH_RELEASE_ANIMATION_DURATION = 200;
 
@@ -56,6 +58,7 @@
     private boolean mMoving;
     private int mStartPos;
     private GestureDetector mDoubleTapDetector;
+    private boolean mInteractive;
 
     public DividerView(@NonNull Context context) {
         super(context);
@@ -91,12 +94,19 @@
         mTouchElevation = getResources().getDimensionPixelSize(
                 R.dimen.docked_stack_divider_lift_elevation);
         mDoubleTapDetector = new GestureDetector(getContext(), new DoubleTapListener());
+        mInteractive = true;
         setOnTouchListener(this);
     }
 
     @Override
+    public void onImeVisibilityChanged(int displayId, boolean isShowing) {
+        if (displayId != getDisplay().getDisplayId()) return;
+        setInteractive(!isShowing);
+    }
+
+    @Override
     public boolean onTouch(View v, MotionEvent event) {
-        if (mSplitLayout == null) {
+        if (mSplitLayout == null || !mInteractive) {
             return false;
         }
 
@@ -202,6 +212,13 @@
         mViewHost.relayout(lp);
     }
 
+    private void setInteractive(boolean interactive) {
+        if (interactive == mInteractive) return;
+        mInteractive = interactive;
+        releaseTouching();
+        mHandle.setVisibility(mInteractive ? View.VISIBLE : View.INVISIBLE);
+    }
+
     private boolean isLandscape() {
         return getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE;
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 60231df..bacff78 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -35,6 +35,7 @@
 
 import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.wm.shell.animation.Interpolators;
+import com.android.wm.shell.common.DisplayImeController;
 
 /**
  * Records and handles layout of splits. Helps to calculate proper bounds when configuration or
@@ -59,11 +60,13 @@
 
     public SplitLayout(String windowName, Context context, Configuration configuration,
             LayoutChangeListener layoutChangeListener,
-            SplitWindowManager.ParentContainerCallbacks parentContainerCallbacks) {
+            SplitWindowManager.ParentContainerCallbacks parentContainerCallbacks,
+            DisplayImeController displayImeController) {
         mContext = context.createConfigurationContext(configuration);
         mLayoutChangeListener = layoutChangeListener;
         mSplitWindowManager = new SplitWindowManager(
-                windowName, mContext, configuration, parentContainerCallbacks);
+                windowName, mContext, configuration, parentContainerCallbacks,
+                displayImeController);
 
         mDividerWindowWidth = context.getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.docked_stack_divider_thickness);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
index 87f0c25..f6efb01 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
@@ -46,6 +46,7 @@
 import androidx.annotation.Nullable;
 
 import com.android.wm.shell.R;
+import com.android.wm.shell.common.DisplayImeController;
 
 /**
  * Holds view hierarchy of a root surface and helps to inflate {@link DividerView} for a split.
@@ -53,23 +54,27 @@
 public final class SplitWindowManager extends WindowlessWindowManager {
     private static final String TAG = SplitWindowManager.class.getSimpleName();
 
+    private final String mWindowName;
+    private final DisplayImeController mDisplayImeController;
     private final ParentContainerCallbacks mParentContainerCallbacks;
     private Context mContext;
     private SurfaceControlViewHost mViewHost;
     private SurfaceControl mLeash;
     private boolean mResizingSplits;
-    private final String mWindowName;
+    private DividerView mDividerView;
 
     public interface ParentContainerCallbacks {
         void attachToParentSurface(SurfaceControl.Builder b);
     }
 
     public SplitWindowManager(String windowName, Context context, Configuration config,
-            ParentContainerCallbacks parentContainerCallbacks) {
+            ParentContainerCallbacks parentContainerCallbacks,
+            DisplayImeController displayImeController) {
         super(config, null /* rootSurface */, null /* hostInputToken */);
         mContext = context.createConfigurationContext(config);
         mParentContainerCallbacks = parentContainerCallbacks;
         mWindowName = windowName;
+        mDisplayImeController = displayImeController;
     }
 
     @Override
@@ -103,14 +108,16 @@
 
     /** Inflates {@link DividerView} on to the root surface. */
     void init(SplitLayout splitLayout) {
-        if (mViewHost == null) {
-            mViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(), this);
+        if (mDividerView != null || mViewHost != null) {
+            throw new UnsupportedOperationException(
+                    "Try to inflate divider view again without release first");
         }
 
-        final Rect dividerBounds = splitLayout.getDividerBounds();
-        final DividerView dividerView = (DividerView) LayoutInflater.from(mContext)
+        mViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(), this);
+        mDividerView = (DividerView) LayoutInflater.from(mContext)
                 .inflate(R.layout.split_divider, null /* root */);
 
+        final Rect dividerBounds = splitLayout.getDividerBounds();
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 dividerBounds.width(), dividerBounds.height(), TYPE_DOCK_DIVIDER,
                 FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL | FLAG_WATCH_OUTSIDE_TOUCH
@@ -119,8 +126,9 @@
         lp.token = new Binder();
         lp.setTitle(mWindowName);
         lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
-        mViewHost.setView(dividerView, lp);
-        dividerView.setup(splitLayout, mViewHost);
+        mViewHost.setView(mDividerView, lp);
+        mDividerView.setup(splitLayout, mViewHost);
+        mDisplayImeController.addPositionProcessor(mDividerView);
     }
 
     /**
@@ -128,6 +136,11 @@
      * hierarchy.
      */
     void release() {
+        if (mDividerView != null) {
+            mDisplayImeController.removePositionProcessor(mDividerView);
+            mDividerView = null;
+        }
+
         if (mViewHost != null){
             mViewHost.release();
             mViewHost = null;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java
index 477ec33..40244fb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java
@@ -18,6 +18,7 @@
 
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.util.RotationUtils.rotateBounds;
 import static android.view.WindowManager.DOCKED_BOTTOM;
 import static android.view.WindowManager.DOCKED_INVALID;
 import static android.view.WindowManager.DOCKED_LEFT;
@@ -244,7 +245,7 @@
             DividerSnapAlgorithm snap = initSnapAlgorithmForRotation(context, tmpDL, dividerSize);
 
             tmpRect.set(bounds);
-            DisplayLayout.rotateBounds(tmpRect, displayRect, rotation - dl.rotation());
+            rotateBounds(tmpRect, displayRect, dl.rotation(), rotation);
             rotatedDisplayRect.set(0, 0, tmpDL.width(), tmpDL.height());
             final int dockSide = getPrimarySplitSide(tmpRect, rotatedDisplayRect,
                     tmpDL.getOrientation());
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java
index c8f8987..82468ad 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java
@@ -105,7 +105,7 @@
             synchronized (mDockedRect) {
                 mTouchableRegion.set(region);
             }
-            WindowManagerGlobal.getWindowManagerService().setDockedStackDividerTouchRegion(
+            WindowManagerGlobal.getWindowManagerService().setDockedTaskDividerTouchRegion(
                     mTouchableRegion);
         } catch (RemoteException e) {
             Log.w(TAG, "Failed to set touchable region: " + e);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java
index 11c11f4..4f31c37 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java
@@ -16,13 +16,11 @@
 
 package com.android.wm.shell.onehanded;
 
-import androidx.annotation.NonNull;
+import android.content.res.Configuration;
 
 import com.android.wm.shell.common.annotations.ExternalThread;
 import com.android.wm.shell.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
 
-import java.io.PrintWriter;
-
 /**
  * Interface to engage one handed feature.
  */
@@ -54,19 +52,33 @@
     void stopOneHanded(int uiEvent);
 
     /**
-     * Set navigation 3 button mode enabled or disabled by users.
+     * Sets navigation 3 button mode enabled or disabled by users.
      */
     void setThreeButtonModeEnabled(boolean enabled);
 
     /**
-     * Register callback to be notified after {@link OneHandedDisplayAreaOrganizer}
+     * Sets one handed feature temporary locked in enabled or disabled state, this won't change
+     * settings configuration.
+     *
+     * @param locked locked function in disabled(can not trigger) or enabled state.
+     * @param enabled function in disabled(can not trigger) or enabled state.
+     */
+    void setLockedDisabled(boolean locked, boolean enabled);
+
+    /**
+     * Registers callback to be notified after {@link OneHandedDisplayAreaOrganizer}
      * transition start or finish
      */
     void registerTransitionCallback(OneHandedTransitionCallback callback);
 
     /**
-     * Register callback for one handed gesture, this gesture callbcak will be activated on
+     * Registers callback for one handed gesture, this gesture callback will be activated on
      * 3 button navigation mode only
      */
     void registerGestureCallback(OneHandedGestureEventCallback callback);
+
+    /**
+     * Receive onConfigurationChanged() events
+     */
+    void onConfigChanged(Configuration newConfig);
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
index 5a3c38b..a1b1de3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.content.om.IOverlayManager;
 import android.content.om.OverlayInfo;
+import android.content.res.Configuration;
 import android.database.ContentObserver;
 import android.graphics.Point;
 import android.os.Handler;
@@ -31,6 +32,7 @@
 import android.os.SystemProperties;
 import android.provider.Settings;
 import android.util.Slog;
+import android.view.ViewConfiguration;
 import android.view.accessibility.AccessibilityManager;
 
 import androidx.annotation.NonNull;
@@ -65,6 +67,7 @@
     private volatile boolean mIsOneHandedEnabled;
     private volatile boolean mIsSwipeToNotificationEnabled;
     private boolean mTaskChangeToExit;
+    private boolean mLockedDisabled;
     private float mOffSetFraction;
 
     private final Context mContext;
@@ -154,7 +157,7 @@
         OneHandedTouchHandler touchHandler = new OneHandedTouchHandler(timeoutHandler,
                 mainExecutor);
         OneHandedGestureHandler gestureHandler = new OneHandedGestureHandler(
-                context, displayController, mainExecutor);
+                context, displayController, ViewConfiguration.get(context), mainExecutor);
         OneHandedBackgroundPanelOrganizer oneHandedBackgroundPanelOrganizer =
                 new OneHandedBackgroundPanelOrganizer(context, displayController, mainExecutor);
         OneHandedDisplayAreaOrganizer organizer = new OneHandedDisplayAreaOrganizer(
@@ -222,8 +225,7 @@
         setupGesturalOverlay();
         updateSettings();
 
-        mAccessibilityManager = (AccessibilityManager)
-                context.getSystemService(Context.ACCESSIBILITY_SERVICE);
+        mAccessibilityManager = AccessibilityManager.getInstance(context);
         mAccessibilityManager.addAccessibilityStateChangeListener(
                 mAccessibilityStateChangeListener);
     }
@@ -262,6 +264,10 @@
 
     @VisibleForTesting
     void startOneHanded() {
+        if (isLockedDisabled()) {
+            Slog.d(TAG, "Temporary lock disabled");
+            return;
+        }
         if (!mDisplayAreaOrganizer.isInOneHanded()) {
             final int yOffSet = Math.round(getDisplaySize().y * mOffSetFraction);
             mDisplayAreaOrganizer.scheduleOffset(0, yOffSet);
@@ -345,7 +351,8 @@
         };
     }
 
-    private void onEnabledSettingChanged() {
+    @VisibleForTesting
+    void onEnabledSettingChanged() {
         final boolean enabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
                 mContext.getContentResolver());
         mOneHandedUiEventLogger.writeEvent(enabled
@@ -360,7 +367,8 @@
                         mContext.getContentResolver()));
     }
 
-    private void onTimeoutSettingChanged() {
+    @VisibleForTesting
+    void onTimeoutSettingChanged() {
         final int newTimeout = OneHandedSettingsUtil.getSettingsOneHandedModeTimeout(
                 mContext.getContentResolver());
         int metricsId = OneHandedUiEventLogger.OneHandedSettingsTogglesEvent.INVALID.getId();
@@ -388,7 +396,8 @@
         }
     }
 
-    private void onTaskChangeExitSettingChanged() {
+    @VisibleForTesting
+    void onTaskChangeExitSettingChanged() {
         final boolean enabled = OneHandedSettingsUtil.getSettingsTapsAppToExit(
                 mContext.getContentResolver());
         mOneHandedUiEventLogger.writeEvent(enabled
@@ -398,7 +407,8 @@
         setTaskChangeToExit(enabled);
     }
 
-    private void onSwipeToNotificationEnabledSettingChanged() {
+    @VisibleForTesting
+    void onSwipeToNotificationEnabledSettingChanged() {
         final boolean enabled =
                 OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
                         mContext.getContentResolver());
@@ -428,21 +438,35 @@
         return displaySize;
     }
 
+    @VisibleForTesting
+    boolean isLockedDisabled() {
+        return mLockedDisabled;
+    }
+
     private void updateOneHandedEnabled() {
         if (mDisplayAreaOrganizer.isInOneHanded()) {
             stopOneHanded();
         }
-        // TODO Be aware to unregisterOrganizer() after animation finished
-        mDisplayAreaOrganizer.unregisterOrganizer();
-        mBackgroundPanelOrganizer.unregisterOrganizer();
-        if (mIsOneHandedEnabled) {
+
+        mTouchHandler.onOneHandedEnabled(mIsOneHandedEnabled);
+        mGestureHandler.onOneHandedEnabled(mIsOneHandedEnabled || mIsSwipeToNotificationEnabled);
+
+        if (!mIsOneHandedEnabled) {
+            mDisplayAreaOrganizer.unregisterOrganizer();
+            mBackgroundPanelOrganizer.unregisterOrganizer();
+            // Do NOT register + unRegister DA in the same call
+            return;
+        }
+
+        if (mDisplayAreaOrganizer.getDisplayAreaTokenMap().isEmpty()) {
             mDisplayAreaOrganizer.registerOrganizer(
                     OneHandedDisplayAreaOrganizer.FEATURE_ONE_HANDED);
+        }
+
+        if (mBackgroundPanelOrganizer.getBackgroundSurface() == null) {
             mBackgroundPanelOrganizer.registerOrganizer(
                     OneHandedBackgroundPanelOrganizer.FEATURE_ONE_HANDED_BACKGROUND_PANEL);
         }
-        mTouchHandler.onOneHandedEnabled(mIsOneHandedEnabled);
-        mGestureHandler.onOneHandedEnabled(mIsOneHandedEnabled || mIsSwipeToNotificationEnabled);
     }
 
     private void setupGesturalOverlay() {
@@ -452,7 +476,6 @@
 
         OverlayInfo info = null;
         try {
-            // TODO(b/157958539) migrate new RRO config file after S+
             mOverlayManager.setHighestPriority(ONE_HANDED_MODE_GESTURAL_OVERLAY, USER_CURRENT);
             info = mOverlayManager.getOverlayInfo(ONE_HANDED_MODE_GESTURAL_OVERLAY, USER_CURRENT);
         } catch (RemoteException e) { /* Do nothing */ }
@@ -472,11 +495,31 @@
         }
     }
 
+    @VisibleForTesting
+    void setLockedDisabled(boolean locked, boolean enabled) {
+        if (enabled == mIsOneHandedEnabled) {
+            return;
+        }
+        mLockedDisabled = locked && !enabled;
+    }
+
+    private void onConfigChanged(Configuration newConfig) {
+        if (mTutorialHandler != null) {
+            if (!mIsOneHandedEnabled
+                    || newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+                return;
+            }
+            mTutorialHandler.onConfigurationChanged(newConfig);
+        }
+    }
+
     public void dump(@NonNull PrintWriter pw) {
         final String innerPrefix = "  ";
         pw.println(TAG + "states: ");
         pw.print(innerPrefix + "mOffSetFraction=");
         pw.println(mOffSetFraction);
+        pw.print(innerPrefix + "mLockedDisabled=");
+        pw.println(mLockedDisabled);
 
         if (mDisplayAreaOrganizer != null) {
             mDisplayAreaOrganizer.dump(pw);
@@ -553,6 +596,13 @@
         }
 
         @Override
+        public void setLockedDisabled(boolean locked, boolean enabled) {
+            mMainExecutor.execute(() -> {
+                OneHandedController.this.setLockedDisabled(locked, enabled);
+            });
+        }
+
+        @Override
         public void registerTransitionCallback(OneHandedTransitionCallback callback) {
             mMainExecutor.execute(() -> {
                 OneHandedController.this.registerTransitionCallback(callback);
@@ -565,5 +615,12 @@
                 OneHandedController.this.registerGestureCallback(callback);
             });
         }
+
+        @Override
+        public void onConfigChanged(Configuration newConfig) {
+            mMainExecutor.execute(() -> {
+                OneHandedController.this.onConfigChanged(newConfig);
+            });
+        }
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
index 04d1264..4c5cc22 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
@@ -66,8 +66,7 @@
     private boolean mIsInOneHanded;
     private int mEnterExitAnimationDurationMs;
 
-    @VisibleForTesting
-    ArrayMap<WindowContainerToken, SurfaceControl> mDisplayAreaTokenMap = new ArrayMap();
+    private ArrayMap<WindowContainerToken, SurfaceControl> mDisplayAreaTokenMap = new ArrayMap();
     private DisplayController mDisplayController;
     private OneHandedAnimationController mAnimationController;
     private OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory
@@ -203,6 +202,7 @@
                     animateWindows(token, leash, fromBounds, toBounds, direction,
                             mEnterExitAnimationDurationMs);
                     wct.setBounds(token, toBounds);
+                    wct.setAppBounds(token, toBounds);
                 });
         applyTransaction(wct);
     }
@@ -232,6 +232,7 @@
                     // DisplayRotationController will applyTransaction() after finish rotating
                     if (wct != null) {
                         wct.setBounds(token, null/* reset */);
+                        wct.setAppBounds(token, null/* reset */);
                     }
                 });
         tx.apply();
@@ -298,6 +299,11 @@
         return new Rect(0, 0, realSize.x, realSize.y);
     }
 
+    @VisibleForTesting
+    ArrayMap<WindowContainerToken, SurfaceControl> getDisplayAreaTokenMap() {
+        return mDisplayAreaTokenMap;
+    }
+
     /**
      * Register transition callback
      */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
index 49b7e05..91e649f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
@@ -87,6 +87,7 @@
      * @param displayController        {@link DisplayController}
      */
     public OneHandedGestureHandler(Context context, DisplayController displayController,
+            ViewConfiguration viewConfig,
             ShellExecutor mainExecutor) {
         mDisplayController = displayController;
         mMainExecutor = mainExecutor;
@@ -95,7 +96,7 @@
                 com.android.internal.R.dimen.navigation_bar_gesture_larger_height);
         mDragDistThreshold = context.getResources().getDimensionPixelSize(
                 R.dimen.gestures_onehanded_drag_threshold);
-        final float slop = ViewConfiguration.get(context).getScaledTouchSlop();
+        final float slop = viewConfig.getScaledTouchSlop();
         mSquaredSlop = slop * slop;
 
         updateIsEnabled();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
index 492130b..3f72b80 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
@@ -18,6 +18,7 @@
 
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -55,12 +56,14 @@
     private final AccessibilityManager mAccessibilityManager;
     private final String mPackageName;
 
+    private Context mContext;
     private View mTutorialView;
     private Point mDisplaySize = new Point();
     private ContentResolver mContentResolver;
     private boolean mCanShowTutorial;
     private String mStartOneHandedDescription;
     private String mStopOneHandedDescription;
+    private boolean mIsOneHandedMode;
 
     private enum ONE_HANDED_TRIGGER_STATE {
         UNSET, ENTERING, EXITING
@@ -92,19 +95,19 @@
                 mTriggerState = (startValue.top == 0)
                         ? ONE_HANDED_TRIGGER_STATE.ENTERING : ONE_HANDED_TRIGGER_STATE.EXITING;
                 if (mCanShowTutorial && mTriggerState == ONE_HANDED_TRIGGER_STATE.ENTERING) {
-                    createTutorialTarget();
+                    attachTurtorialTarget();
                 }
             }
         }
     };
 
     public OneHandedTutorialHandler(Context context, ShellExecutor mainExecutor) {
+        mContext = context;
         context.getDisplay().getRealSize(mDisplaySize);
         mPackageName = context.getPackageName();
         mContentResolver = context.getContentResolver();
         mWindowManager = context.getSystemService(WindowManager.class);
-        mAccessibilityManager = (AccessibilityManager)
-                context.getSystemService(Context.ACCESSIBILITY_SERVICE);
+        mAccessibilityManager = AccessibilityManager.getInstance(context);
 
         mStartOneHandedDescription = context.getResources().getString(
                 R.string.accessibility_action_start_one_handed);
@@ -113,6 +116,7 @@
         mCanShowTutorial = (Settings.Secure.getInt(mContentResolver,
                 Settings.Secure.ONE_HANDED_TUTORIAL_SHOW_COUNT, 0) >= MAX_TUTORIAL_SHOW_COUNT)
                 ? false : true;
+        mIsOneHandedMode = false;
         final float offsetPercentageConfig = context.getResources().getFraction(
                 R.fraction.config_one_handed_offset, 1, 1);
         final int sysPropPercentageConfig = SystemProperties.getInt(
@@ -120,11 +124,7 @@
         mTutorialAreaHeight = Math.round(mDisplaySize.y * (sysPropPercentageConfig / 100.0f));
 
         mainExecutor.execute(() -> {
-            mTutorialView = LayoutInflater.from(context).inflate(R.layout.one_handed_tutorial,
-                    null);
-            mTargetViewContainer = new FrameLayout(context);
-            mTargetViewContainer.setClipChildren(false);
-            mTargetViewContainer.addView(mTutorialView);
+            recreateTutorialView(mContext);
         });
     }
 
@@ -144,10 +144,20 @@
         mTriggerState = ONE_HANDED_TRIGGER_STATE.UNSET;
     }
 
+    private void recreateTutorialView(Context context) {
+        mTutorialView = LayoutInflater.from(context).inflate(R.layout.one_handed_tutorial,
+                null);
+        mTargetViewContainer = new FrameLayout(context);
+        mTargetViewContainer.setClipChildren(false);
+        mTargetViewContainer.addView(mTutorialView);
+        mTargetViewContainer.setVisibility(mIsOneHandedMode ? View.VISIBLE : View.GONE);
+    }
+
     private void updateFinished(int visible, float finalPosition) {
         if (!canShowTutorial()) {
             return;
         }
+        mIsOneHandedMode = (finalPosition == 0f) ? true : false;
         mTargetViewContainer.setVisibility(visible);
         mTargetViewContainer.setTranslationY(finalPosition);
     }
@@ -176,7 +186,7 @@
      * Adds the tutorial target view to the WindowManager and update its layout, so it's ready
      * to be animated in.
      */
-    private void createTutorialTarget() {
+    private void attachTurtorialTarget() {
         if (!mTargetViewContainer.isAttachedToWindow()) {
             try {
                 mWindowManager.addView(mTargetViewContainer, getTutorialTargetLayoutParams());
@@ -242,4 +252,17 @@
         mTargetViewContainer.setTransitionGroup(true);
         mTargetViewContainer.setTranslationY(value - mTargetViewContainer.getHeight());
     }
+
+    /**
+     * onConfigurationChanged events for updating tutorial text.
+     * @param newConfig
+     */
+    public void onConfigurationChanged(Configuration newConfig) {
+        if (!mCanShowTutorial) {
+            return;
+        }
+        removeTutorialFromWindowManager();
+        recreateTutorialView(mContext.createConfigurationContext(newConfig));
+        attachTurtorialTarget();
+    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java
index 8f8ec47..b3b1ba7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java
@@ -20,7 +20,7 @@
 import android.content.ComponentName;
 import android.content.pm.ParceledListSlice;
 import android.os.RemoteException;
-import android.view.IPinnedStackListener;
+import android.view.IPinnedTaskListener;
 import android.view.WindowManagerGlobal;
 
 import androidx.annotation.BinderThread;
@@ -32,66 +32,66 @@
 /**
  * PinnedStackListener that simply forwards all calls to each listener added via
  * {@link #addListener}. This is necessary since calling
- * {@link com.android.server.wm.WindowManagerService#registerPinnedStackListener} replaces any
+ * {@link com.android.server.wm.WindowManagerService#registerPinnedTaskListener} replaces any
  * previously set listener.
  */
 public class PinnedStackListenerForwarder {
 
-    private final IPinnedStackListener mListenerImpl = new PinnedStackListenerImpl();
+    private final IPinnedTaskListener mListenerImpl = new PinnedTaskListenerImpl();
     private final ShellExecutor mMainExecutor;
-    private final ArrayList<PinnedStackListener> mListeners = new ArrayList<>();
+    private final ArrayList<PinnedTaskListener> mListeners = new ArrayList<>();
 
     public PinnedStackListenerForwarder(ShellExecutor mainExecutor) {
         mMainExecutor = mainExecutor;
     }
 
     /** Adds a listener to receive updates from the WindowManagerService. */
-    public void addListener(PinnedStackListener listener) {
+    public void addListener(PinnedTaskListener listener) {
         mListeners.add(listener);
     }
 
     /** Removes a listener so it will no longer receive updates from the WindowManagerService. */
-    public void removeListener(PinnedStackListener listener) {
+    public void removeListener(PinnedTaskListener listener) {
         mListeners.remove(listener);
     }
 
     public void register(int displayId) throws RemoteException {
-        WindowManagerGlobal.getWindowManagerService().registerPinnedStackListener(
+        WindowManagerGlobal.getWindowManagerService().registerPinnedTaskListener(
                 displayId, mListenerImpl);
     }
 
     private void onMovementBoundsChanged(boolean fromImeAdjustment) {
-        for (PinnedStackListener listener : mListeners) {
+        for (PinnedTaskListener listener : mListeners) {
             listener.onMovementBoundsChanged(fromImeAdjustment);
         }
     }
 
     private void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
-        for (PinnedStackListener listener : mListeners) {
+        for (PinnedTaskListener listener : mListeners) {
             listener.onImeVisibilityChanged(imeVisible, imeHeight);
         }
     }
 
     private void onActionsChanged(ParceledListSlice<RemoteAction> actions) {
-        for (PinnedStackListener listener : mListeners) {
+        for (PinnedTaskListener listener : mListeners) {
             listener.onActionsChanged(actions);
         }
     }
 
     private void onActivityHidden(ComponentName componentName) {
-        for (PinnedStackListener listener : mListeners) {
+        for (PinnedTaskListener listener : mListeners) {
             listener.onActivityHidden(componentName);
         }
     }
 
     private void onAspectRatioChanged(float aspectRatio) {
-        for (PinnedStackListener listener : mListeners) {
+        for (PinnedTaskListener listener : mListeners) {
             listener.onAspectRatioChanged(aspectRatio);
         }
     }
 
     @BinderThread
-    private class PinnedStackListenerImpl extends IPinnedStackListener.Stub {
+    private class PinnedTaskListenerImpl extends IPinnedTaskListener.Stub {
         @Override
         public void onMovementBoundsChanged(boolean fromImeAdjustment) {
             mMainExecutor.execute(() -> {
@@ -129,10 +129,10 @@
     }
 
     /**
-     * A counterpart of {@link IPinnedStackListener} with empty implementations.
+     * A counterpart of {@link IPinnedTaskListener} with empty implementations.
      * Subclasses can ignore those methods they do not intend to take action upon.
      */
-    public static class PinnedStackListener {
+    public static class PinnedTaskListener {
         public void onMovementBoundsChanged(boolean fromImeAdjustment) {}
 
         public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
index 5ffa988..a52db24 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.pip;
 
+import static android.util.RotationUtils.rotateBounds;
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
 
@@ -33,7 +34,6 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
 import com.android.wm.shell.animation.Interpolators;
-import com.android.wm.shell.common.DisplayLayout;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -90,15 +90,15 @@
 
     private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
 
-    private PipTransitionAnimator mCurrentAnimator;
-
-    private ThreadLocal<AnimationHandler> mSfAnimationHandlerThreadLocal =
+    private final ThreadLocal<AnimationHandler> mSfAnimationHandlerThreadLocal =
             ThreadLocal.withInitial(() -> {
                 AnimationHandler handler = new AnimationHandler();
                 handler.setProvider(new SfVsyncFrameCallbackProvider());
                 return handler;
             });
 
+    private PipTransitionAnimator mCurrentAnimator;
+
     public PipAnimationController(PipSurfaceTransactionHelper helper) {
         mSurfaceTransactionHelper = helper;
     }
@@ -268,6 +268,7 @@
             if (mPipAnimationCallback != null) {
                 mPipAnimationCallback.onPipAnimationEnd(mTaskInfo, tx, this);
             }
+            mTransitionDirection = TRANSITION_DIRECTION_NONE;
         }
 
         @Override
@@ -275,6 +276,7 @@
             if (mPipAnimationCallback != null) {
                 mPipAnimationCallback.onPipAnimationCancel(mTaskInfo, this);
             }
+            mTransitionDirection = TRANSITION_DIRECTION_NONE;
         }
 
         @Override public void onAnimationRepeat(Animator animation) {}
@@ -448,7 +450,7 @@
                 // Rotate the end bounds according to the rotation delta because the display will
                 // be rotated to the same orientation.
                 rotatedEndRect = new Rect(endValue);
-                DisplayLayout.rotateBounds(rotatedEndRect, endValue, rotationDelta);
+                rotateBounds(rotatedEndRect, endValue, rotationDelta);
             } else {
                 rotatedEndRect = null;
             }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMediaController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMediaController.java
index 1a4616c..6afcc06 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMediaController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMediaController.java
@@ -32,6 +32,7 @@
 import android.media.session.MediaSessionManager;
 import android.media.session.PlaybackState;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.UserHandle;
 
 import androidx.annotation.Nullable;
@@ -76,6 +77,7 @@
 
     private final Context mContext;
     private final Handler mMainHandler;
+    private final HandlerExecutor mHandlerExecutor;
 
     private final MediaSessionManager mMediaSessionManager;
     private MediaController mMediaController;
@@ -123,6 +125,7 @@
     public PipMediaController(Context context, Handler mainHandler) {
         mContext = context;
         mMainHandler = mainHandler;
+        mHandlerExecutor = new HandlerExecutor(mMainHandler);
         IntentFilter mediaControlFilter = new IntentFilter();
         mediaControlFilter.addAction(ACTION_PLAY);
         mediaControlFilter.addAction(ACTION_PAUSE);
@@ -247,8 +250,8 @@
      */
     public void registerSessionListenerForCurrentUser() {
         mMediaSessionManager.removeOnActiveSessionsChangedListener(mSessionsChangedListener);
-        mMediaSessionManager.addOnActiveSessionsChangedListener(mSessionsChangedListener, null,
-                UserHandle.CURRENT, mMainHandler);
+        mMediaSessionManager.addOnActiveSessionsChangedListener(null, UserHandle.CURRENT,
+                mHandlerExecutor, mSessionsChangedListener);
     }
 
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipUiEventLogger.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipUiEventLogger.java
index f8b4dd9..a0a76d8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipUiEventLogger.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipUiEventLogger.java
@@ -98,7 +98,16 @@
         PICTURE_IN_PICTURE_CHANGE_ASPECT_RATIO(609),
 
         @UiEvent(doc = "User resize of the picture-in-picture window")
-        PICTURE_IN_PICTURE_RESIZE(610);
+        PICTURE_IN_PICTURE_RESIZE(610),
+
+        @UiEvent(doc = "User unstashed picture-in-picture")
+        PICTURE_IN_PICTURE_STASH_UNSTASHED(709),
+
+        @UiEvent(doc = "User stashed picture-in-picture to the left side")
+        PICTURE_IN_PICTURE_STASH_LEFT(710),
+
+        @UiEvent(doc = "User stashed picture-in-picture to the right side")
+        PICTURE_IN_PICTURE_STASH_RIGHT(711);
 
         private final int mId;
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index 4a2a032..9a584c6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -65,6 +65,7 @@
 import com.android.wm.shell.pip.PipUtils;
 
 import java.io.PrintWriter;
+import java.util.Objects;
 import java.util.function.Consumer;
 
 /**
@@ -93,17 +94,20 @@
 
     protected PhonePipMenuController mMenuController;
     protected PipTaskOrganizer mPipTaskOrganizer;
-    protected PinnedStackListenerForwarder.PinnedStackListener mPinnedStackListener =
-            new PipControllerPinnedStackListener();
+    protected PinnedStackListenerForwarder.PinnedTaskListener mPinnedTaskListener =
+            new PipControllerPinnedTaskListener();
 
     /**
      * Handler for display rotation changes.
      */
     private final DisplayChangeController.OnDisplayChangingListener mRotationController = (
             int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) -> {
-        if (!mPipTaskOrganizer.isInPip() || mPipTaskOrganizer.isDeferringEnterPipAnimation()) {
-            // Skip if we aren't in PIP or haven't actually entered PIP yet. We still need to update
-            // the display layout in the bounds handler in this case.
+        if (!mPipTaskOrganizer.isInPip()
+                || mPipBoundsState.getDisplayLayout().rotation() == toRotation
+                || mPipTaskOrganizer.isDeferringEnterPipAnimation()) {
+            // Skip if the same rotation has been set or we aren't in PIP or haven't actually
+            // entered PIP yet. We still need to update the display layout in the bounds handler
+            // in this case.
             onDisplayRotationChangedNotInPip(mContext, toRotation);
             // do not forget to update the movement bounds as well.
             updateMovementBounds(mPipBoundsState.getNormalBounds(), true /* fromRotation */,
@@ -178,8 +182,8 @@
     /**
      * Handler for messages from the PIP controller.
      */
-    private class PipControllerPinnedStackListener extends
-            PinnedStackListenerForwarder.PinnedStackListener {
+    private class PipControllerPinnedTaskListener extends
+            PinnedStackListenerForwarder.PinnedTaskListener {
         @Override
         public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
             mPipBoundsState.setImeVisibility(imeVisible, imeHeight);
@@ -310,7 +314,7 @@
         mPipBoundsState.setDisplayLayout(new DisplayLayout(context, context.getDisplay()));
 
         try {
-            mWindowManagerShellWrapper.addPinnedStackListener(mPinnedStackListener);
+            mWindowManagerShellWrapper.addPinnedStackListener(mPinnedTaskListener);
         } catch (RemoteException e) {
             Slog.e(TAG, "Failed to register pinned stack listener", e);
         }
@@ -378,6 +382,9 @@
     }
 
     private void onDisplayChanged(DisplayLayout layout, boolean saveRestoreSnapFraction) {
+        if (Objects.equals(layout, mPipBoundsState.getDisplayLayout())) {
+            return;
+        }
         Runnable updateDisplayLayout = () -> {
             mPipBoundsState.setDisplayLayout(layout);
             updateMovementBounds(null /* toBounds */,
@@ -476,8 +483,11 @@
             int launcherRotation, int shelfHeight) {
         setShelfHeightLocked(shelfHeight > 0 /* visible */, shelfHeight);
         onDisplayRotationChangedNotInPip(mContext, launcherRotation);
-        return mPipTaskOrganizer.startSwipePipToHome(componentName, activityInfo,
+        final Rect entryBounds = mPipTaskOrganizer.startSwipePipToHome(componentName, activityInfo,
                 pictureInPictureParams);
+        // sync mPipBoundsState with the newly calculated bounds.
+        mPipBoundsState.setNormalBounds(entryBounds);
+        return entryBounds;
     }
 
     private void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuActionView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuActionView.java
new file mode 100644
index 0000000..f11ae42
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuActionView.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.pip.phone;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import com.android.wm.shell.R;
+
+/**
+ * Container layout wraps single action image view drawn in PiP menu and can restrict the size of
+ * action image view (see pip_menu_action.xml).
+ */
+public class PipMenuActionView extends FrameLayout {
+    private ImageView mImageView;
+
+    public PipMenuActionView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mImageView = findViewById(R.id.image);
+    }
+
+    /** pass through to internal {@link #mImageView} */
+    public void setImageDrawable(Drawable drawable) {
+        mImageView.setImageDrawable(drawable);
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
index 1cf3a48..0d64407 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
@@ -59,7 +59,6 @@
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.FrameLayout;
-import android.widget.ImageButton;
 import android.widget.LinearLayout;
 
 import com.android.wm.shell.R;
@@ -407,7 +406,7 @@
                 // Ensure we have as many buttons as actions
                 final LayoutInflater inflater = LayoutInflater.from(mContext);
                 while (mActionsGroup.getChildCount() < mActions.size()) {
-                    final ImageButton actionView = (ImageButton) inflater.inflate(
+                    final PipMenuActionView actionView = (PipMenuActionView) inflater.inflate(
                             R.layout.pip_menu_action, mActionsGroup, false);
                     mActionsGroup.addView(actionView);
                 }
@@ -424,7 +423,8 @@
                         && (stackBounds.width() > stackBounds.height());
                 for (int i = 0; i < mActions.size(); i++) {
                     final RemoteAction action = mActions.get(i);
-                    final ImageButton actionView = (ImageButton) mActionsGroup.getChildAt(i);
+                    final PipMenuActionView actionView =
+                            (PipMenuActionView) mActionsGroup.getChildAt(i);
 
                     // TODO: Check if the action drawable has changed before we reload it
                     action.getIcon().loadDrawableAsync(mContext, d -> {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
index afc7b52..5e23281 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
@@ -170,6 +170,7 @@
         mPipBoundsAlgorithm = pipBoundsAlgorithm;
         mPipBoundsState = pipBoundsState;
         mMenuController = menuController;
+        mPipUiEventLogger = pipUiEventLogger;
         mMenuController.addListener(new PipMenuListener());
         mGesture = new DefaultPipTouchGesture();
         mMotionHelper = new PipMotionHelper(mContext, pipBoundsState, pipTaskOrganizer,
@@ -186,6 +187,8 @@
                 () -> {
                     if (mPipBoundsState.isStashed()) {
                         animateToUnStashedState();
+                        mPipUiEventLogger.log(
+                                PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_STASH_UNSTASHED);
                         mPipBoundsState.setStashed(STASH_TYPE_NONE);
                     } else {
                         mMenuController.showMenuWithPossibleDelay(MENU_STATE_FULL,
@@ -206,8 +209,6 @@
                 mMotionHelper, pipTaskOrganizer, mPipBoundsAlgorithm.getSnapAlgorithm(),
                 this::onAccessibilityShowMenu, this::updateMovementBounds, mainExecutor);
 
-        mPipUiEventLogger = pipUiEventLogger;
-
         mEnableStash = DeviceConfig.getBoolean(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 PIP_STASHING,
@@ -867,6 +868,8 @@
                 if (mEnableStash && shouldStash(vel, getPossiblyMotionBounds())) {
                     mMotionHelper.stashToEdge(vel.x, vel.y, this::stashEndAction /* endAction */);
                 } else {
+                    mPipUiEventLogger.log(
+                            PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_STASH_UNSTASHED);
                     mPipBoundsState.setStashed(STASH_TYPE_NONE);
                     mMotionHelper.flingToSnapTarget(vel.x, vel.y,
                             this::flingEndAction /* endAction */);
@@ -897,6 +900,8 @@
                 if (!mTouchState.isWaitingForDoubleTap()) {
                     if (mPipBoundsState.isStashed()) {
                         animateToUnStashedState();
+                        mPipUiEventLogger.log(
+                                PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_STASH_UNSTASHED);
                         mPipBoundsState.setStashed(STASH_TYPE_NONE);
                     } else {
                         // User has stalled long enough for this not to be a drag or a double tap,
@@ -921,9 +926,15 @@
                     && mPipExclusionBoundsChangeListener.get() != null) {
                 mPipExclusionBoundsChangeListener.get().accept(mPipBoundsState.getBounds());
             }
-            if (mPipBoundsState.getBounds().left < 0) {
+            if (mPipBoundsState.getBounds().left < 0
+                    && mPipBoundsState.getStashedState() != STASH_TYPE_LEFT) {
+                mPipUiEventLogger.log(
+                        PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_STASH_LEFT);
                 mPipBoundsState.setStashed(STASH_TYPE_LEFT);
-            } else {
+            } else if (mPipBoundsState.getBounds().left >= 0
+                    && mPipBoundsState.getStashedState() != STASH_TYPE_RIGHT) {
+                mPipUiEventLogger.log(
+                        PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_STASH_RIGHT);
                 mPipBoundsState.setStashed(STASH_TYPE_RIGHT);
             }
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
index 56f183f..7098019 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
@@ -377,7 +377,7 @@
 
     private void registerWmShellPinnedStackListener(WindowManagerShellWrapper wmShell) {
         try {
-            wmShell.addPinnedStackListener(new PinnedStackListenerForwarder.PinnedStackListener() {
+            wmShell.addPinnedStackListener(new PinnedStackListenerForwarder.PinnedTaskListener() {
                 @Override
                 public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
                     if (DEBUG) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatHintPopup.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatHintPopup.java
new file mode 100644
index 0000000..78af9df
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatHintPopup.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.sizecompatui;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
+import android.graphics.drawable.RippleDrawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.Button;
+import android.widget.FrameLayout;
+
+import androidx.annotation.Nullable;
+
+import com.android.wm.shell.R;
+
+/** Popup to show the hint about the {@link SizeCompatRestartButton}. */
+public class SizeCompatHintPopup extends FrameLayout implements View.OnClickListener {
+
+    private SizeCompatUILayout mLayout;
+
+    public SizeCompatHintPopup(Context context) {
+        super(context);
+    }
+
+    public SizeCompatHintPopup(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public SizeCompatHintPopup(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public SizeCompatHintPopup(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    void inject(SizeCompatUILayout layout) {
+        mLayout = layout;
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        final Button gotItButton = findViewById(R.id.got_it);
+        gotItButton.setBackground(new RippleDrawable(ColorStateList.valueOf(Color.LTGRAY),
+                null /* content */, null /* mask */));
+        gotItButton.setOnClickListener(this);
+    }
+
+    @Override
+    public void onClick(View v) {
+        mLayout.dismissHint();
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButton.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButton.java
index 9094d7d..08a8402 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButton.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButton.java
@@ -22,19 +22,13 @@
 import android.graphics.drawable.GradientDrawable;
 import android.graphics.drawable.RippleDrawable;
 import android.util.AttributeSet;
-import android.view.LayoutInflater;
 import android.view.View;
-import android.view.WindowManager;
-import android.widget.Button;
 import android.widget.FrameLayout;
 import android.widget.ImageButton;
-import android.widget.LinearLayout;
-import android.widget.PopupWindow;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.wm.shell.R;
 
 /** Button to restart the size compat activity. */
@@ -42,10 +36,6 @@
         View.OnLongClickListener {
 
     private SizeCompatUILayout mLayout;
-    private ImageButton mRestartButton;
-    @VisibleForTesting
-    PopupWindow mShowingHint;
-    private WindowManager.LayoutParams mWinParams;
 
     public SizeCompatRestartButton(@NonNull Context context) {
         super(context);
@@ -67,24 +57,19 @@
 
     void inject(SizeCompatUILayout layout) {
         mLayout = layout;
-        mWinParams = layout.getWindowLayoutParams();
-    }
-
-    void remove() {
-        dismissHint();
     }
 
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mRestartButton = findViewById(R.id.size_compat_restart_button);
+        final ImageButton restartButton = findViewById(R.id.size_compat_restart_button);
         final ColorStateList color = ColorStateList.valueOf(Color.LTGRAY);
         final GradientDrawable mask = new GradientDrawable();
         mask.setShape(GradientDrawable.OVAL);
         mask.setColor(color);
-        mRestartButton.setBackground(new RippleDrawable(color, null /* content */, mask));
-        mRestartButton.setOnClickListener(this);
-        mRestartButton.setOnLongClickListener(this);
+        restartButton.setBackground(new RippleDrawable(color, null /* content */, mask));
+        restartButton.setOnClickListener(this);
+        restartButton.setOnLongClickListener(this);
     }
 
     @Override
@@ -94,69 +79,7 @@
 
     @Override
     public boolean onLongClick(View v) {
-        showHint();
+        mLayout.onRestartButtonLongClicked();
         return true;
     }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        if (mLayout.mShouldShowHint) {
-            mLayout.mShouldShowHint = false;
-            showHint();
-        }
-    }
-
-    @Override
-    public void setVisibility(@Visibility int visibility) {
-        if (visibility == View.GONE && mShowingHint != null) {
-            // Also dismiss the popup.
-            dismissHint();
-        }
-        super.setVisibility(visibility);
-    }
-
-    @Override
-    public void setLayoutDirection(int layoutDirection) {
-        final int gravity = SizeCompatUILayout.getGravity(layoutDirection);
-        if (mWinParams.gravity != gravity) {
-            mWinParams.gravity = gravity;
-            getContext().getSystemService(WindowManager.class).updateViewLayout(this,
-                    mWinParams);
-        }
-        super.setLayoutDirection(layoutDirection);
-    }
-
-    void showHint() {
-        if (mShowingHint != null) {
-            return;
-        }
-
-        // TODO: popup is not attached to the button surface. Need to handle this differently for
-        // non-fullscreen task.
-        final View popupView = LayoutInflater.from(getContext()).inflate(
-                R.layout.size_compat_mode_hint, null);
-        final PopupWindow popupWindow = new PopupWindow(popupView,
-                LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
-        popupWindow.setWindowLayoutType(mWinParams.type);
-        popupWindow.setElevation(getResources().getDimension(R.dimen.bubble_elevation));
-        popupWindow.setAnimationStyle(android.R.style.Animation_InputMethod);
-        popupWindow.setClippingEnabled(false);
-        popupWindow.setOnDismissListener(() -> mShowingHint = null);
-        mShowingHint = popupWindow;
-
-        final Button gotItButton = popupView.findViewById(R.id.got_it);
-        gotItButton.setBackground(new RippleDrawable(ColorStateList.valueOf(Color.LTGRAY),
-                null /* content */, null /* mask */));
-        gotItButton.setOnClickListener(view -> dismissHint());
-        popupWindow.showAtLocation(mRestartButton, mWinParams.gravity, mLayout.mPopupOffsetX,
-                mLayout.mPopupOffsetY);
-    }
-
-    void dismissHint() {
-        if (mShowingHint != null) {
-            mShowingHint.dismiss();
-            mShowingHint = null;
-        }
-    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java
index a3880f4..c981ade 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java
@@ -50,7 +50,7 @@
     /** Whether the IME is shown on display id. */
     private final Set<Integer> mDisplaysWithIme = new ArraySet<>(1);
 
-    /** The showing buttons by task id. */
+    /** The showing UIs by task id. */
     private final SparseArray<SizeCompatUILayout> mActiveLayouts = new SparseArray<>(0);
 
     /** Avoid creating display context frequently for non-default display. */
@@ -77,12 +77,12 @@
     }
 
     /**
-     * Called when the Task info changed. Creates and updates the restart button if there is an
-     * activity in size compat, or removes the restart button if there is no size compat activity.
+     * Called when the Task info changed. Creates and updates the size compat UI if there is an
+     * activity in size compat, or removes the UI if there is no size compat activity.
      *
      * @param displayId display the task and activity are in.
      * @param taskId task the activity is in.
-     * @param taskConfig task config to place the restart button with.
+     * @param taskConfig task config to place the size compat UI with.
      * @param sizeCompatActivity the size compat activity in the task. Can be {@code null} if the
      *                           top activity in this Task is not in size compat.
      * @param taskListener listener to handle the Task Surface placement.
@@ -94,10 +94,10 @@
             // Null token means the current foreground activity is not in size compatibility mode.
             removeLayout(taskId);
         } else if (mActiveLayouts.contains(taskId)) {
-            // Button already exists, update the button layout.
+            // UI already exists, update the UI layout.
             updateLayout(taskId, taskConfig, sizeCompatActivity, taskListener);
         } else {
-            // Create a new restart button.
+            // Create a new size compat UI.
             createLayout(displayId, taskId, taskConfig, sizeCompatActivity, taskListener);
         }
     }
@@ -106,7 +106,7 @@
     public void onDisplayRemoved(int displayId) {
         mDisplayContextCache.remove(displayId);
 
-        // Remove all buttons on the removed display.
+        // Remove all size compat UIs on the removed display.
         final List<Integer> toRemoveTaskIds = new ArrayList<>();
         forAllLayoutsOnDisplay(displayId, layout -> toRemoveTaskIds.add(layout.getTaskId()));
         for (int i = toRemoveTaskIds.size() - 1; i >= 0; i--) {
@@ -128,7 +128,7 @@
             mDisplaysWithIme.remove(displayId);
         }
 
-        // Hide the button when input method is showing.
+        // Hide the size compat UIs when input method is showing.
         forAllLayoutsOnDisplay(displayId, layout -> layout.updateImeVisibility(isShowing));
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java
index 5924b53..32f3648 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java
@@ -30,7 +30,6 @@
 import android.graphics.Rect;
 import android.os.Binder;
 import android.os.IBinder;
-import android.view.Gravity;
 import android.view.SurfaceControl;
 import android.view.View;
 import android.view.WindowManager;
@@ -43,7 +42,7 @@
 
 /**
  * Records and handles layout of size compat UI on a task with size compat activity. Helps to
- * calculate proper bounds when configuration or button position changes.
+ * calculate proper bounds when configuration or UI position changes.
  */
 class SizeCompatUILayout {
     private static final String TAG = "SizeCompatUILayout";
@@ -56,12 +55,18 @@
     private IBinder mActivityToken;
     private ShellTaskOrganizer.TaskListener mTaskListener;
     private DisplayLayout mDisplayLayout;
-    @VisibleForTesting
-    final SizeCompatUIWindowManager mWindowManager;
 
     @VisibleForTesting
+    final SizeCompatUIWindowManager mButtonWindowManager;
+    @VisibleForTesting
+    @Nullable
+    SizeCompatUIWindowManager mHintWindowManager;
+    @VisibleForTesting
     @Nullable
     SizeCompatRestartButton mButton;
+    @VisibleForTesting
+    @Nullable
+    SizeCompatHintPopup mHint;
     final int mButtonSize;
     final int mPopupOffsetX;
     final int mPopupOffsetY;
@@ -79,7 +84,7 @@
         mTaskListener = taskListener;
         mDisplayLayout = displayLayout;
         mShouldShowHint = !hasShownHint;
-        mWindowManager = new SizeCompatUIWindowManager(mContext, taskConfig, this);
+        mButtonWindowManager = new SizeCompatUIWindowManager(mContext, taskConfig, this);
 
         mButtonSize =
                 mContext.getResources().getDimensionPixelSize(R.dimen.size_compat_button_size);
@@ -87,21 +92,52 @@
         mPopupOffsetY = mButtonSize;
     }
 
-    /** Creates the button window. */
+    /** Creates the activity restart button window. */
     void createSizeCompatButton(boolean isImeShowing) {
         if (isImeShowing || mButton != null) {
             // When ime is showing, wait until ime is dismiss to create UI.
             return;
         }
-        mButton = mWindowManager.createSizeCompatUI();
-        updateSurfacePosition();
+        mButton = mButtonWindowManager.createSizeCompatButton();
+        updateButtonSurfacePosition();
+
+        if (mShouldShowHint) {
+            // Only show by default for the first time.
+            mShouldShowHint = false;
+            createSizeCompatHint();
+        }
     }
 
-    /** Releases the button window. */
+    /** Creates the restart button hint window. */
+    private void createSizeCompatHint() {
+        if (mHint != null) {
+            // Hint already shown.
+            return;
+        }
+        mHintWindowManager = createHintWindowManager();
+        mHint = mHintWindowManager.createSizeCompatHint();
+        updateHintSurfacePosition();
+    }
+
+    @VisibleForTesting
+    SizeCompatUIWindowManager createHintWindowManager() {
+        return new SizeCompatUIWindowManager(mContext, mTaskConfig, this);
+    }
+
+    /** Dismisses the hint window. */
+    void dismissHint() {
+        mHint = null;
+        if (mHintWindowManager != null) {
+            mHintWindowManager.release();
+            mHintWindowManager = null;
+        }
+    }
+
+    /** Releases the UI windows. */
     void release() {
-        mButton.remove();
+        dismissHint();
         mButton = null;
-        mWindowManager.release();
+        mButtonWindowManager.release();
     }
 
     /** Called when size compat info changed. */
@@ -115,7 +151,10 @@
 
         // Update configuration.
         mContext = mContext.createConfigurationContext(taskConfig);
-        mWindowManager.setConfiguration(taskConfig);
+        mButtonWindowManager.setConfiguration(taskConfig);
+        if (mHintWindowManager != null) {
+            mHintWindowManager.setConfiguration(taskConfig);
+        }
 
         if (mButton == null || prevTaskListener != taskListener) {
             // TaskListener changed, recreate the button for new surface parent.
@@ -126,14 +165,19 @@
 
         if (!taskConfig.windowConfiguration.getBounds()
                 .equals(prevTaskConfig.windowConfiguration.getBounds())) {
-            // Reposition the button surface.
-            updateSurfacePosition();
+            // Reposition the UI surfaces.
+            updateButtonSurfacePosition();
+            updateHintSurfacePosition();
         }
 
         if (taskConfig.getLayoutDirection() != prevTaskConfig.getLayoutDirection()) {
             // Update layout for RTL.
             mButton.setLayoutDirection(taskConfig.getLayoutDirection());
-            updateSurfacePosition();
+            updateButtonSurfacePosition();
+            if (mHint != null) {
+                mHint.setLayoutDirection(taskConfig.getLayoutDirection());
+                updateHintSurfacePosition();
+            }
         }
     }
 
@@ -149,8 +193,9 @@
         displayLayout.getStableBounds(curStableBounds);
         mDisplayLayout = displayLayout;
         if (!prevStableBounds.equals(curStableBounds)) {
-            // Stable bounds changed, update button surface position.
-            updateSurfacePosition();
+            // Stable bounds changed, update UI surface positions.
+            updateButtonSurfacePosition();
+            updateHintSurfacePosition();
         }
     }
 
@@ -162,27 +207,46 @@
             return;
         }
 
+        // Hide size compat UIs when IME is showing.
         final int newVisibility = isImeShowing ? View.GONE : View.VISIBLE;
         if (mButton.getVisibility() != newVisibility) {
             mButton.setVisibility(newVisibility);
         }
+        if (mHint != null && mHint.getVisibility() != newVisibility) {
+            mHint.setVisibility(newVisibility);
+        }
     }
 
     /** Gets the layout params for restart button. */
-    WindowManager.LayoutParams getWindowLayoutParams() {
+    WindowManager.LayoutParams getButtonWindowLayoutParams() {
         final WindowManager.LayoutParams winParams = new WindowManager.LayoutParams(
+                // Cannot be wrap_content as this determines the actual window size
                 mButtonSize, mButtonSize,
                 TYPE_APPLICATION_OVERLAY,
                 FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL,
                 PixelFormat.TRANSLUCENT);
-        winParams.gravity = getGravity(getLayoutDirection());
         winParams.token = new Binder();
-        winParams.setTitle(SizeCompatRestartButton.class.getSimpleName() + mContext.getDisplayId());
+        winParams.setTitle(SizeCompatRestartButton.class.getSimpleName() + getTaskId());
         winParams.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
         return winParams;
     }
 
-    /** Called when it is ready to be placed button surface button. */
+    /** Gets the layout params for hint popup. */
+    WindowManager.LayoutParams getHintWindowLayoutParams(SizeCompatHintPopup hint) {
+        final WindowManager.LayoutParams winParams = new WindowManager.LayoutParams(
+                // Cannot be wrap_content as this determines the actual window size
+                hint.getMeasuredWidth(), hint.getMeasuredHeight(),
+                TYPE_APPLICATION_OVERLAY,
+                FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL,
+                PixelFormat.TRANSLUCENT);
+        winParams.token = new Binder();
+        winParams.setTitle(SizeCompatHintPopup.class.getSimpleName() + getTaskId());
+        winParams.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
+        winParams.windowAnimations = android.R.style.Animation_InputMethod;
+        return winParams;
+    }
+
+    /** Called when it is ready to be placed size compat UI surface. */
     void attachToParentSurface(SurfaceControl.Builder b) {
         mTaskListener.attachChildSurfaceToTask(mTaskId, b);
     }
@@ -192,13 +256,17 @@
         ActivityClient.getInstance().restartActivityProcessIfVisible(mActivityToken);
     }
 
+    /** Called when the restart button is long clicked. */
+    void onRestartButtonLongClicked() {
+        createSizeCompatHint();
+    }
+
     @VisibleForTesting
-    void updateSurfacePosition() {
-        if (mButton == null || mWindowManager.getSurfaceControl() == null) {
+    void updateButtonSurfacePosition() {
+        if (mButton == null || mButtonWindowManager.getSurfaceControl() == null) {
             return;
         }
-        // The hint popup won't be at the correct position.
-        mButton.dismissHint();
+        final SurfaceControl leash = mButtonWindowManager.getSurfaceControl();
 
         // Use stable bounds to prevent the button from overlapping with system bars.
         final Rect taskBounds = mTaskConfig.windowConfiguration.getBounds();
@@ -212,8 +280,30 @@
                 : stableBounds.right - taskBounds.left - mButtonSize;
         final int positionY = stableBounds.bottom - taskBounds.top - mButtonSize;
 
-        mSyncQueue.runInSync(t ->
-                t.setPosition(mWindowManager.getSurfaceControl(), positionX, positionY));
+        mSyncQueue.runInSync(t -> t.setPosition(leash, positionX, positionY));
+    }
+
+    void updateHintSurfacePosition() {
+        if (mHint == null || mHintWindowManager == null
+                || mHintWindowManager.getSurfaceControl() == null) {
+            return;
+        }
+        final SurfaceControl leash = mHintWindowManager.getSurfaceControl();
+
+        // Use stable bounds to prevent the hint from overlapping with system bars.
+        final Rect taskBounds = mTaskConfig.windowConfiguration.getBounds();
+        final Rect stableBounds = new Rect();
+        mDisplayLayout.getStableBounds(stableBounds);
+        stableBounds.intersect(taskBounds);
+
+        // Position of the hint in the container coordinate.
+        final int positionX = getLayoutDirection() == View.LAYOUT_DIRECTION_RTL
+                ? stableBounds.left - taskBounds.left + mPopupOffsetX
+                : stableBounds.right - taskBounds.left - mPopupOffsetX - mHint.getMeasuredWidth();
+        final int positionY =
+                stableBounds.bottom - taskBounds.top - mPopupOffsetY - mHint.getMeasuredHeight();
+
+        mSyncQueue.runInSync(t -> t.setPosition(leash, positionX, positionY));
     }
 
     int getDisplayId() {
@@ -227,9 +317,4 @@
     private int getLayoutDirection() {
         return mContext.getResources().getConfiguration().getLayoutDirection();
     }
-
-    static int getGravity(int layoutDirection) {
-        return Gravity.BOTTOM
-                | (layoutDirection == View.LAYOUT_DIRECTION_RTL ? Gravity.START : Gravity.END);
-    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIWindowManager.java
index a7ad982..f634c45 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIWindowManager.java
@@ -24,12 +24,14 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceControlViewHost;
 import android.view.SurfaceSession;
+import android.view.View;
 import android.view.WindowlessWindowManager;
 
 import com.android.wm.shell.R;
 
 /**
- * Holds view hierarchy of a root surface and helps to inflate {@link SizeCompatRestartButton}.
+ * Holds view hierarchy of a root surface and helps to inflate {@link SizeCompatRestartButton} or
+ * {@link SizeCompatHintPopup}.
  */
 class SizeCompatUIWindowManager extends WindowlessWindowManager {
 
@@ -67,18 +69,39 @@
     }
 
     /** Inflates {@link SizeCompatRestartButton} on to the root surface. */
-    SizeCompatRestartButton createSizeCompatUI() {
-        if (mViewHost == null) {
-            mViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(), this);
+    SizeCompatRestartButton createSizeCompatButton() {
+        if (mViewHost != null) {
+            throw new IllegalStateException(
+                    "A UI has already been created with this window manager.");
         }
 
+        mViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(), this);
+
         final SizeCompatRestartButton button = (SizeCompatRestartButton)
                 LayoutInflater.from(mContext).inflate(R.layout.size_compat_ui, null);
         button.inject(mLayout);
-        mViewHost.setView(button, mLayout.getWindowLayoutParams());
+        mViewHost.setView(button, mLayout.getButtonWindowLayoutParams());
         return button;
     }
 
+    /** Inflates {@link SizeCompatHintPopup} on to the root surface. */
+    SizeCompatHintPopup createSizeCompatHint() {
+        if (mViewHost != null) {
+            throw new IllegalStateException(
+                    "A UI has already been created with this window manager.");
+        }
+
+        mViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(), this);
+
+        final SizeCompatHintPopup hint = (SizeCompatHintPopup)
+                LayoutInflater.from(mContext).inflate(R.layout.size_compat_mode_hint, null);
+        // Measure how big the hint is.
+        hint.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+        hint.inject(mLayout);
+        mViewHost.setView(hint, mLayout.getHintWindowLayoutParams(hint));
+        return hint;
+    }
+
     /** Releases the surface control and tears down the view hierarchy. */
     void release() {
         if (mViewHost != null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index b0167af..11548ad 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -42,6 +42,7 @@
 
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
 import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayImeController;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.draganddrop.DragAndDropPolicy;
@@ -62,18 +63,20 @@
     private final RootTaskDisplayAreaOrganizer mRootTDAOrganizer;
     private final ShellExecutor mMainExecutor;
     private final SplitScreenImpl mImpl = new SplitScreenImpl();
+    private final DisplayImeController mDisplayImeController;
 
     private StageCoordinator mStageCoordinator;
 
     public SplitScreenController(ShellTaskOrganizer shellTaskOrganizer,
             SyncTransactionQueue syncQueue, Context context,
             RootTaskDisplayAreaOrganizer rootTDAOrganizer,
-            ShellExecutor mainExecutor) {
+            ShellExecutor mainExecutor, DisplayImeController displayImeController) {
         mTaskOrganizer = shellTaskOrganizer;
         mSyncQueue = syncQueue;
         mContext = context;
         mRootTDAOrganizer = rootTDAOrganizer;
         mMainExecutor = mainExecutor;
+        mDisplayImeController = displayImeController;
     }
 
     public SplitScreen asSplitScreen() {
@@ -84,7 +87,7 @@
         if (mStageCoordinator == null) {
             // TODO: Multi-display
             mStageCoordinator = new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue,
-                    mRootTDAOrganizer, mTaskOrganizer);
+                    mRootTDAOrganizer, mTaskOrganizer, mDisplayImeController);
         }
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index e44c820..bbfbc40 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -39,6 +39,7 @@
 
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
 import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayImeController;
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.common.split.SplitLayout;
 
@@ -79,10 +80,12 @@
     private DisplayAreaInfo mDisplayAreaInfo;
     private final Context mContext;
     private final List<SplitScreen.SplitScreenListener> mListeners = new ArrayList<>();
+    private final DisplayImeController mDisplayImeController;
     private boolean mExitSplitScreenOnHide = true;
 
     StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
-            RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer) {
+            RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer,
+            DisplayImeController displayImeController) {
         mContext = context;
         mDisplayId = displayId;
         mSyncQueue = syncQueue;
@@ -90,13 +93,14 @@
         mTaskOrganizer = taskOrganizer;
         mMainStage = new MainStage(mTaskOrganizer, mDisplayId, mMainStageListener, mSyncQueue);
         mSideStage = new SideStage(mTaskOrganizer, mDisplayId, mSideStageListener, mSyncQueue);
+        mDisplayImeController = displayImeController;
         mRootTDAOrganizer.registerListener(displayId, this);
     }
 
     @VisibleForTesting
     StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
             RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer,
-            MainStage mainStage, SideStage sideStage) {
+            MainStage mainStage, SideStage sideStage, DisplayImeController displayImeController) {
         mContext = context;
         mDisplayId = displayId;
         mSyncQueue = syncQueue;
@@ -104,6 +108,7 @@
         mTaskOrganizer = taskOrganizer;
         mMainStage = mainStage;
         mSideStage = sideStage;
+        mDisplayImeController = displayImeController;
         mRootTDAOrganizer.registerListener(displayId, this);
     }
 
@@ -357,8 +362,9 @@
 
     @Override
     public void onSnappedToDismiss(boolean bottomOrRight) {
-        final boolean mainStageToTop = bottomOrRight
-                && mSideStagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT;
+        final boolean mainStageToTop =
+                bottomOrRight ? mSideStagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT
+                        : mSideStagePosition == STAGE_POSITION_TOP_OR_LEFT;
         exitSplitScreen(mainStageToTop ? mMainStage : mSideStage);
     }
 
@@ -420,7 +426,8 @@
         if (mSplitLayout == null) {
             mSplitLayout = new SplitLayout(TAG + "SplitDivider", mContext,
                     mDisplayAreaInfo.configuration, this,
-                    b -> mRootTDAOrganizer.attachToDisplayArea(mDisplayId, b));
+                    b -> mRootTDAOrganizer.attachToDisplayArea(mDisplayId, b),
+                    mDisplayImeController);
         }
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
index 45d5515..7649770 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
@@ -43,6 +43,7 @@
 
 /**
  * Util class to create the view for a splash screen content.
+ *
  * @hide
  */
 public class SplashscreenContentDrawer {
@@ -349,7 +350,7 @@
 
         // Calculate the difference between two colors based on the HSV dimensions.
         final float normalizeH = minAngle / 180f;
-        final double square =  Math.pow(normalizeH, 2)
+        final double square = Math.pow(normalizeH, 2)
                 + Math.pow(aHsv[1] - bHsv[1], 2)
                 + Math.pow(aHsv[2] - bHsv[2], 2);
         final double mean = square / 3;
@@ -433,8 +434,11 @@
          */
         private interface ColorTester {
             float nonTransparentRatio();
+
             boolean isComplexColor();
+
             int getDominantColor();
+
             boolean isGrayscale();
         }
 
@@ -511,14 +515,17 @@
                 // restore to original bounds
                 drawable.setBounds(initialBounds);
 
-                final Palette.Builder builder = new Palette.Builder(bitmap)
-                        .maximumColorCount(5).clearFilters();
+                final Palette.Builder builder;
                 // The Palette API will ignore Alpha, so it cannot handle transparent pixels, but
                 // sometimes we will need this information to know if this Drawable object is
                 // transparent.
                 mFilterTransparent = filterTransparent;
                 if (mFilterTransparent) {
-                    builder.setQuantizer(TRANSPARENT_FILTER_QUANTIZER);
+                    builder = new Palette.Builder(bitmap, TRANSPARENT_FILTER_QUANTIZER)
+                            .maximumColorCount(5);
+                } else {
+                    builder = new Palette.Builder(bitmap, null)
+                            .maximumColorCount(5);
                 }
                 mPalette = builder.generate();
                 bitmap.recycle();
@@ -538,7 +545,7 @@
             public int getDominantColor() {
                 final Palette.Swatch mainSwatch = mPalette.getDominantSwatch();
                 if (mainSwatch != null) {
-                    return mainSwatch.getRgb();
+                    return mainSwatch.getInt();
                 }
                 return Color.BLACK;
             }
@@ -549,7 +556,7 @@
                 if (swatches != null) {
                     for (int i = swatches.size() - 1; i >= 0; i--) {
                         Palette.Swatch swatch = swatches.get(i);
-                        if (!isGrayscaleColor(swatch.getRgb())) {
+                        if (!isGrayscaleColor(swatch.getInt())) {
                             return false;
                         }
                     }
@@ -561,9 +568,9 @@
                 private static final int NON_TRANSPARENT = 0xFF000000;
                 private final Quantizer mInnerQuantizer = new VariationalKMeansQuantizer();
                 private float mNonTransparentRatio;
+
                 @Override
-                public void quantize(final int[] pixels, final int maxColors,
-                        final Palette.Filter[] filters) {
+                public void quantize(final int[] pixels, final int maxColors) {
                     mNonTransparentRatio = 0;
                     int realSize = 0;
                     for (int i = pixels.length - 1; i > 0; i--) {
@@ -575,7 +582,7 @@
                         if (DEBUG) {
                             Slog.d(TAG, "quantize: this is pure transparent image");
                         }
-                        mInnerQuantizer.quantize(pixels, maxColors, filters);
+                        mInnerQuantizer.quantize(pixels, maxColors);
                         return;
                     }
                     mNonTransparentRatio = (float) realSize / pixels.length;
@@ -587,7 +594,7 @@
                             rowIndex++;
                         }
                     }
-                    mInnerQuantizer.quantize(samplePixels, maxColors, filters);
+                    mInnerQuantizer.quantize(samplePixels, maxColors);
                 }
 
                 @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java
new file mode 100644
index 0000000..2c4ceff
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.startingsurface;
+
+import android.os.IBinder;
+import android.window.StartingWindowInfo;
+
+/**
+ * Interface to engage starting window feature.
+ */
+public interface StartingSurface {
+    /**
+     * Called when a task need a starting window.
+     */
+    void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken);
+    /**
+     * Called when the content of a task is ready to show, starting window can be removed.
+     */
+    void removeStartingWindow(int taskId);
+    /**
+     * Called when the Task wants to copy the splash screen.
+     * @param taskId
+     */
+    void copySplashScreenView(int taskId);
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index 5332291..8144071 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -16,15 +16,9 @@
 
 package com.android.wm.shell.startingsurface;
 
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.content.Context.CONTEXT_RESTRICTED;
 import static android.content.res.Configuration.EMPTY;
 import static android.view.Display.DEFAULT_DISPLAY;
-import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED;
-import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
-import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
-import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
-import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
 
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityTaskManager;
@@ -37,7 +31,6 @@
 import android.content.res.TypedArray;
 import android.hardware.display.DisplayManager;
 import android.os.IBinder;
-import android.os.RemoteException;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.Display;
@@ -46,7 +39,6 @@
 import android.window.SplashScreenView;
 import android.window.SplashScreenView.SplashScreenViewParcelable;
 import android.window.StartingWindowInfo;
-import android.window.TaskOrganizer;
 import android.window.TaskSnapshot;
 
 import com.android.internal.R;
@@ -56,19 +48,13 @@
 import java.util.function.Consumer;
 
 /**
- * Implementation to draw the starting window to an application, and remove the starting window
- * until the application displays its own window.
- *
- * When receive {@link TaskOrganizer#addStartingWindow} callback, use this class to create a
- * starting window and attached to the Task, then when the Task want to remove the starting window,
- * the TaskOrganizer will receive {@link TaskOrganizer#removeStartingWindow} callback then use this
- * class to remove the starting window of the Task.
+ * A class which able to draw splash screen or snapshot as the starting window for a task.
  * @hide
  */
 public class StartingSurfaceDrawer {
     static final String TAG = StartingSurfaceDrawer.class.getSimpleName();
-    static final boolean DEBUG_SPLASH_SCREEN = false;
-    static final boolean DEBUG_TASK_SNAPSHOT = false;
+    static final boolean DEBUG_SPLASH_SCREEN = StartingWindowController.DEBUG_SPLASH_SCREEN;
+    static final boolean DEBUG_TASK_SNAPSHOT = StartingWindowController.DEBUG_TASK_SNAPSHOT;
 
     private final Context mContext;
     private final DisplayManager mDisplayManager;
@@ -107,106 +93,10 @@
         return context.createDisplayContext(targetDisplay);
     }
 
-    private static class PreferredStartingTypeHelper {
-        private static final int STARTING_TYPE_NO = 0;
-        private static final int STARTING_TYPE_SPLASH_SCREEN = 1;
-        private static final int STARTING_TYPE_SNAPSHOT = 2;
-
-        TaskSnapshot mSnapshot;
-        int mPreferredType;
-
-        PreferredStartingTypeHelper(StartingWindowInfo taskInfo) {
-            final int parameter = taskInfo.startingWindowTypeParameter;
-            final boolean newTask = (parameter & TYPE_PARAMETER_NEW_TASK) != 0;
-            final boolean taskSwitch = (parameter & TYPE_PARAMETER_TASK_SWITCH) != 0;
-            final boolean processRunning = (parameter & TYPE_PARAMETER_PROCESS_RUNNING) != 0;
-            final boolean allowTaskSnapshot = (parameter & TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT) != 0;
-            final boolean activityCreated = (parameter & TYPE_PARAMETER_ACTIVITY_CREATED) != 0;
-            mPreferredType = preferredStartingWindowType(taskInfo, newTask, taskSwitch,
-                    processRunning, allowTaskSnapshot, activityCreated);
-        }
-
-        // reference from ActivityRecord#getStartingWindowType
-        private int preferredStartingWindowType(StartingWindowInfo windowInfo,
-                boolean newTask, boolean taskSwitch, boolean processRunning,
-                boolean allowTaskSnapshot, boolean activityCreated) {
-            if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
-                Slog.d(TAG, "preferredStartingWindowType newTask " + newTask
-                        + " taskSwitch " + taskSwitch
-                        + " processRunning " + processRunning
-                        + " allowTaskSnapshot " + allowTaskSnapshot
-                        + " activityCreated " + activityCreated);
-            }
-
-            if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
-                return STARTING_TYPE_SPLASH_SCREEN;
-            } else if (taskSwitch && allowTaskSnapshot) {
-                final TaskSnapshot snapshot = getTaskSnapshot(windowInfo.taskInfo.taskId);
-                if (isSnapshotCompatible(windowInfo, snapshot)) {
-                    return STARTING_TYPE_SNAPSHOT;
-                }
-                if (windowInfo.taskInfo.topActivityType != ACTIVITY_TYPE_HOME) {
-                    return STARTING_TYPE_SPLASH_SCREEN;
-                }
-                return STARTING_TYPE_NO;
-            } else {
-                return STARTING_TYPE_NO;
-            }
-        }
-
-        /**
-         * Returns {@code true} if the task snapshot is compatible with this activity (at least the
-         * rotation must be the same).
-         */
-        private boolean isSnapshotCompatible(StartingWindowInfo windowInfo, TaskSnapshot snapshot) {
-            if (snapshot == null) {
-                if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
-                    Slog.d(TAG, "isSnapshotCompatible no snapshot " + windowInfo.taskInfo.taskId);
-                }
-                return false;
-            }
-
-            final int taskRotation = windowInfo.taskInfo.configuration
-                    .windowConfiguration.getRotation();
-            final int snapshotRotation = snapshot.getRotation();
-            if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
-                Slog.d(TAG, "isSnapshotCompatible rotation " + taskRotation
-                        + " snapshot " + snapshotRotation);
-            }
-            return taskRotation == snapshotRotation;
-        }
-
-        private TaskSnapshot getTaskSnapshot(int taskId) {
-            if (mSnapshot != null) {
-                return mSnapshot;
-            }
-            try {
-                mSnapshot = ActivityTaskManager.getService().getTaskSnapshot(taskId,
-                        false/* isLowResolution */);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Unable to get snapshot for task: " + taskId + ", from: " + e);
-                return null;
-            }
-            return mSnapshot;
-        }
-    }
-
     /**
-     * Called when a task need a starting window.
+     * Called when a task need a splash screen starting window.
      */
-    public void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
-        final PreferredStartingTypeHelper helper =
-                new PreferredStartingTypeHelper(windowInfo);
-        if (helper.mPreferredType == PreferredStartingTypeHelper.STARTING_TYPE_SPLASH_SCREEN) {
-            addSplashScreenStartingWindow(windowInfo, appToken);
-        } else if (helper.mPreferredType == PreferredStartingTypeHelper.STARTING_TYPE_SNAPSHOT) {
-            final TaskSnapshot snapshot = helper.mSnapshot;
-            makeTaskSnapshotWindow(windowInfo, appToken, snapshot);
-        }
-        // If prefer don't show, then don't show!
-    }
-
-    private void addSplashScreenStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
+    public void addSplashScreenStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
         final RunningTaskInfo taskInfo = windowInfo.taskInfo;
         final ActivityInfo activityInfo = taskInfo.topActivityInfo;
         if (activityInfo == null) {
@@ -378,8 +268,8 @@
     /**
      * Called when a task need a snapshot starting window.
      */
-    private void makeTaskSnapshotWindow(StartingWindowInfo startingWindowInfo,
-            IBinder appToken, TaskSnapshot snapshot) {
+    void makeTaskSnapshotWindow(StartingWindowInfo startingWindowInfo, IBinder appToken,
+            TaskSnapshot snapshot) {
         final int taskId = startingWindowInfo.taskInfo.taskId;
         final TaskSnapshotWindow surface = TaskSnapshotWindow.create(startingWindowInfo, appToken,
                 snapshot, mMainExecutor, () -> removeWindowSynced(taskId) /* clearWindow */);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
new file mode 100644
index 0000000..73bf8ac
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.wm.shell.startingsurface;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_NONE;
+import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT;
+import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
+
+import android.app.ActivityTaskManager;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.window.StartingWindowInfo;
+import android.window.TaskOrganizer;
+import android.window.TaskSnapshot;
+
+import com.android.wm.shell.common.ShellExecutor;
+
+/**
+ * Implementation to draw the starting window to an application, and remove the starting window
+ * until the application displays its own window.
+ *
+ * When receive {@link TaskOrganizer#addStartingWindow} callback, use this class to create a
+ * starting window and attached to the Task, then when the Task want to remove the starting window,
+ * the TaskOrganizer will receive {@link TaskOrganizer#removeStartingWindow} callback then use this
+ * class to remove the starting window of the Task.
+ * @hide
+ */
+public class StartingWindowController {
+    private static final String TAG = StartingWindowController.class.getSimpleName();
+    static final boolean DEBUG_SPLASH_SCREEN = false;
+    static final boolean DEBUG_TASK_SNAPSHOT = false;
+
+    private final StartingSurfaceDrawer mStartingSurfaceDrawer;
+    private final StartingTypeChecker mStartingTypeChecker = new StartingTypeChecker();
+    private final StartingSurfaceImpl mImpl = new StartingSurfaceImpl();
+
+    public StartingWindowController(Context context, ShellExecutor mainExecutor) {
+        mStartingSurfaceDrawer = new StartingSurfaceDrawer(context, mainExecutor);
+    }
+
+    /**
+     * Provide the implementation for Shell Module.
+     */
+    public StartingSurface asStartingSurface() {
+        return mImpl;
+    }
+
+    private static class StartingTypeChecker {
+        TaskSnapshot mSnapshot;
+
+        StartingTypeChecker() { }
+
+        private void reset() {
+            mSnapshot = null;
+        }
+
+        private @StartingWindowInfo.StartingWindowType int
+                estimateStartingWindowType(StartingWindowInfo windowInfo) {
+            reset();
+            final int parameter = windowInfo.startingWindowTypeParameter;
+            final boolean newTask = (parameter & TYPE_PARAMETER_NEW_TASK) != 0;
+            final boolean taskSwitch = (parameter & TYPE_PARAMETER_TASK_SWITCH) != 0;
+            final boolean processRunning = (parameter & TYPE_PARAMETER_PROCESS_RUNNING) != 0;
+            final boolean allowTaskSnapshot = (parameter & TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT) != 0;
+            final boolean activityCreated = (parameter & TYPE_PARAMETER_ACTIVITY_CREATED) != 0;
+            return estimateStartingWindowType(windowInfo, newTask, taskSwitch,
+                    processRunning, allowTaskSnapshot, activityCreated);
+        }
+
+        // reference from ActivityRecord#getStartingWindowType
+        private int estimateStartingWindowType(StartingWindowInfo windowInfo,
+                boolean newTask, boolean taskSwitch, boolean processRunning,
+                boolean allowTaskSnapshot, boolean activityCreated) {
+            if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
+                Slog.d(TAG, "preferredStartingWindowType newTask " + newTask
+                        + " taskSwitch " + taskSwitch
+                        + " processRunning " + processRunning
+                        + " allowTaskSnapshot " + allowTaskSnapshot
+                        + " activityCreated " + activityCreated);
+            }
+            if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
+                return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+            }
+            if (taskSwitch && allowTaskSnapshot) {
+                final TaskSnapshot snapshot = getTaskSnapshot(windowInfo.taskInfo.taskId);
+                if (isSnapshotCompatible(windowInfo, snapshot)) {
+                    return STARTING_WINDOW_TYPE_SNAPSHOT;
+                }
+                if (windowInfo.taskInfo.topActivityType != ACTIVITY_TYPE_HOME) {
+                    return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+                }
+            }
+            return STARTING_WINDOW_TYPE_NONE;
+        }
+
+        /**
+         * Returns {@code true} if the task snapshot is compatible with this activity (at least the
+         * rotation must be the same).
+         */
+        private boolean isSnapshotCompatible(StartingWindowInfo windowInfo, TaskSnapshot snapshot) {
+            if (snapshot == null) {
+                if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
+                    Slog.d(TAG, "isSnapshotCompatible no snapshot " + windowInfo.taskInfo.taskId);
+                }
+                return false;
+            }
+
+            final int taskRotation = windowInfo.taskInfo.configuration
+                    .windowConfiguration.getRotation();
+            final int snapshotRotation = snapshot.getRotation();
+            if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
+                Slog.d(TAG, "isSnapshotCompatible rotation " + taskRotation
+                        + " snapshot " + snapshotRotation);
+            }
+            return taskRotation == snapshotRotation;
+        }
+
+        private TaskSnapshot getTaskSnapshot(int taskId) {
+            if (mSnapshot != null) {
+                return mSnapshot;
+            }
+            try {
+                mSnapshot = ActivityTaskManager.getService().getTaskSnapshot(taskId,
+                        false/* isLowResolution */);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Unable to get snapshot for task: " + taskId + ", from: " + e);
+                return null;
+            }
+            return mSnapshot;
+        }
+    }
+
+    /**
+     * Called when a task need a starting window.
+     */
+    void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
+        final int suggestionType = mStartingTypeChecker.estimateStartingWindowType(windowInfo);
+        if (suggestionType == STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
+            mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, appToken);
+        } else if (suggestionType == STARTING_WINDOW_TYPE_SNAPSHOT) {
+            final TaskSnapshot snapshot = mStartingTypeChecker.mSnapshot;
+            mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, appToken, snapshot);
+        }
+        // If prefer don't show, then don't show!
+    }
+
+    void copySplashScreenView(int taskId) {
+        mStartingSurfaceDrawer.copySplashScreenView(taskId);
+    }
+
+    /**
+     * Called when the content of a task is ready to show, starting window can be removed.
+     */
+    void removeStartingWindow(int taskId) {
+        mStartingSurfaceDrawer.removeStartingWindow(taskId);
+    }
+
+    private class StartingSurfaceImpl implements StartingSurface {
+
+        @Override
+        public void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
+            StartingWindowController.this.addStartingWindow(windowInfo, appToken);
+        }
+
+        @Override
+        public void removeStartingWindow(int taskId) {
+            StartingWindowController.this.removeStartingWindow(taskId);
+        }
+
+        @Override
+        public void copySplashScreenView(int taskId) {
+            StartingWindowController.this.copySplashScreenView(taskId);
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index 59f8c1d..2182ee5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -16,55 +16,78 @@
 
 package com.android.wm.shell.transition;
 
+import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_OPEN;
 import static android.view.WindowManager.TRANSIT_TO_BACK;
 import static android.view.WindowManager.TRANSIT_TO_FRONT;
 import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
+import static android.window.TransitionInfo.FLAG_TRANSLUCENT;
 
 import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Rect;
 import android.os.IBinder;
 import android.util.ArrayMap;
+import android.view.Choreographer;
 import android.view.SurfaceControl;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+import android.view.animation.Transformation;
 import android.window.TransitionInfo;
 import android.window.TransitionRequestInfo;
 import android.window.WindowContainerTransaction;
 
+import com.android.internal.R;
+import com.android.internal.policy.AttributeCache;
+import com.android.internal.policy.TransitionAnimation;
+import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.TransactionPool;
+import com.android.wm.shell.protolog.ShellProtoLogGroup;
 
 import java.util.ArrayList;
 
 /** The default handler that handles anything not already handled. */
 public class DefaultTransitionHandler implements Transitions.TransitionHandler {
+    private static final int MAX_ANIMATION_DURATION = 3000;
+
     private final TransactionPool mTransactionPool;
     private final ShellExecutor mMainExecutor;
     private final ShellExecutor mAnimExecutor;
+    private final TransitionAnimation mTransitionAnimation;
 
     /** Keeps track of the currently-running animations associated with each transition. */
     private final ArrayMap<IBinder, ArrayList<Animator>> mAnimations = new ArrayMap<>();
 
-    DefaultTransitionHandler(@NonNull TransactionPool transactionPool,
+    private float mTransitionAnimationScaleSetting = 1.0f;
+
+    DefaultTransitionHandler(@NonNull TransactionPool transactionPool, Context context,
             @NonNull ShellExecutor mainExecutor, @NonNull ShellExecutor animExecutor) {
         mTransactionPool = transactionPool;
         mMainExecutor = mainExecutor;
         mAnimExecutor = animExecutor;
+        mTransitionAnimation = new TransitionAnimation(context, false /* debug */, Transitions.TAG);
+
+        AttributeCache.init(context);
     }
 
     @Override
     public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
             @NonNull SurfaceControl.Transaction t,
             @NonNull Transitions.TransitionFinishCallback finishCallback) {
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+                "start default transition animation, info = %s", info);
         if (mAnimations.containsKey(transition)) {
             throw new IllegalStateException("Got a duplicate startAnimation call for "
                     + transition);
         }
         final ArrayList<Animator> animations = new ArrayList<>();
         mAnimations.put(transition, animations);
-        final boolean isOpening = Transitions.isOpeningType(info.getType());
 
         final Runnable onAnimFinish = () -> {
             if (!animations.isEmpty()) return;
@@ -77,19 +100,9 @@
             // Don't animate anything with an animating parent
             if (change.getParent() != null) continue;
 
-            final int mode = change.getMode();
-            if (isOpening && (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT)) {
-                if ((change.getFlags() & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) != 0) {
-                    // This received a transferred starting window, so don't animate
-                    continue;
-                }
-                // fade in
-                startExampleAnimation(
-                        animations, change.getLeash(), true /* show */, onAnimFinish);
-            } else if (!isOpening && (mode == TRANSIT_CLOSE || mode == TRANSIT_TO_BACK)) {
-                // fade out
-                startExampleAnimation(
-                        animations, change.getLeash(), false /* show */, onAnimFinish);
+            Animation a = loadAnimation(info.getType(), change);
+            if (a != null) {
+                startAnimInternal(animations, a, change.getLeash(), onAnimFinish);
             }
         }
         t.apply();
@@ -105,32 +118,93 @@
         return null;
     }
 
-    // TODO(shell-transitions): real animations
-    private void startExampleAnimation(@NonNull ArrayList<Animator> animations,
-            @NonNull SurfaceControl leash, boolean show, @NonNull Runnable finishCallback) {
-        final float end = show ? 1.f : 0.f;
-        final float start = 1.f - end;
+    @Override
+    public void setAnimScaleSetting(float scale) {
+        mTransitionAnimationScaleSetting = scale;
+    }
+
+    @Nullable
+    private Animation loadAnimation(int type, TransitionInfo.Change change) {
+        // TODO(b/178678389): It should handle more type animation here
+        Animation a = null;
+
+        final boolean isOpening = Transitions.isOpeningType(type);
+        final int mode = change.getMode();
+        final int flags = change.getFlags();
+
+        if (mode == TRANSIT_OPEN && isOpening) {
+            if ((flags & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) != 0) {
+                // This received a transferred starting window, so don't animate
+                return null;
+            }
+
+            if (change.getTaskInfo() != null) {
+                a = mTransitionAnimation.loadDefaultAnimationAttr(
+                        R.styleable.WindowAnimation_taskOpenEnterAnimation);
+            } else {
+                a = mTransitionAnimation.loadDefaultAnimationRes((flags & FLAG_TRANSLUCENT) == 0
+                        ? R.anim.activity_open_enter : R.anim.activity_translucent_open_enter);
+            }
+        } else if (mode == TRANSIT_TO_FRONT && isOpening) {
+            if ((flags & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) != 0) {
+                // This received a transferred starting window, so don't animate
+                return null;
+            }
+
+            a = mTransitionAnimation.loadDefaultAnimationAttr(
+                    R.styleable.WindowAnimation_taskToFrontEnterAnimation);
+        } else if (mode == TRANSIT_CLOSE && !isOpening) {
+            if (change.getTaskInfo() != null) {
+                a = mTransitionAnimation.loadDefaultAnimationAttr(
+                        R.styleable.WindowAnimation_taskCloseExitAnimation);
+            } else {
+                a = mTransitionAnimation.loadDefaultAnimationRes((flags & FLAG_TRANSLUCENT) == 0
+                        ? R.anim.activity_close_exit : R.anim.activity_translucent_close_exit);
+            }
+        } else if (mode == TRANSIT_TO_BACK && !isOpening) {
+            a = mTransitionAnimation.loadDefaultAnimationAttr(
+                    R.styleable.WindowAnimation_taskToBackExitAnimation);
+        } else if (mode == TRANSIT_CHANGE) {
+            // In the absence of a specific adapter, we just want to keep everything stationary.
+            a = new AlphaAnimation(1.f, 1.f);
+            a.setDuration(TransitionAnimation.DEFAULT_APP_TRANSITION_DURATION);
+        }
+
+        if (a != null) {
+            Rect start = change.getStartAbsBounds();
+            Rect end = change.getEndAbsBounds();
+            a.restrictDuration(MAX_ANIMATION_DURATION);
+            a.initialize(end.width(), end.height(), start.width(), start.height());
+            a.scaleCurrentDuration(mTransitionAnimationScaleSetting);
+        }
+        return a;
+    }
+
+    private void startAnimInternal(@NonNull ArrayList<Animator> animations, @NonNull Animation anim,
+            @NonNull SurfaceControl leash, @NonNull Runnable finishCallback) {
         final SurfaceControl.Transaction transaction = mTransactionPool.acquire();
-        final ValueAnimator va = ValueAnimator.ofFloat(start, end);
-        va.setDuration(500);
+        final ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
+        final Transformation transformation = new Transformation();
+        final float[] matrix = new float[9];
+        // Animation length is already expected to be scaled.
+        va.overrideDurationScale(1.0f);
+        va.setDuration(anim.computeDurationHint());
         va.addUpdateListener(animation -> {
-            float fraction = animation.getAnimatedFraction();
-            transaction.setAlpha(leash, start * (1.f - fraction) + end * fraction);
-            transaction.apply();
+            final long currentPlayTime = Math.min(va.getDuration(), va.getCurrentPlayTime());
+
+            applyTransformation(currentPlayTime, transaction, leash, anim, transformation, matrix);
         });
+
         final Runnable finisher = () -> {
-            transaction.setAlpha(leash, end);
-            transaction.apply();
+            applyTransformation(va.getDuration(), transaction, leash, anim, transformation, matrix);
+
             mTransactionPool.release(transaction);
             mMainExecutor.execute(() -> {
                 animations.remove(va);
                 finishCallback.run();
             });
         };
-        va.addListener(new Animator.AnimatorListener() {
-            @Override
-            public void onAnimationStart(Animator animation) { }
-
+        va.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
                 finisher.run();
@@ -140,11 +214,17 @@
             public void onAnimationCancel(Animator animation) {
                 finisher.run();
             }
-
-            @Override
-            public void onAnimationRepeat(Animator animation) { }
         });
         animations.add(va);
         mAnimExecutor.execute(va::start);
     }
+
+    private static void applyTransformation(long time, SurfaceControl.Transaction t,
+            SurfaceControl leash, Animation anim, Transformation transformation, float[] matrix) {
+        anim.getTransformation(time, transformation);
+        t.setMatrix(leash, transformation.getMatrix(), matrix);
+        t.setAlpha(leash, transformation.getAlpha());
+        t.setFrameTimelineVsync(Choreographer.getInstance().getVsyncId());
+        t.apply();
+    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 1034489..89eee67 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -25,9 +25,13 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.SystemProperties;
+import android.provider.Settings;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.view.SurfaceControl;
@@ -43,6 +47,7 @@
 
 import androidx.annotation.BinderThread;
 
+import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.ShellTaskOrganizer;
@@ -63,6 +68,7 @@
             SystemProperties.getBoolean("persist.debug.shell_transit", false);
 
     private final WindowOrganizer mOrganizer;
+    private final Context mContext;
     private final ShellExecutor mMainExecutor;
     private final ShellExecutor mAnimExecutor;
     private final TransitionPlayerImpl mPlayerImpl;
@@ -72,6 +78,8 @@
     /** List of possible handlers. Ordered by specificity (eg. tapped back to front). */
     private final ArrayList<TransitionHandler> mHandlers = new ArrayList<>();
 
+    private float mTransitionAnimationScaleSetting = 1.0f;
+
     private static final class ActiveTransition {
         TransitionHandler mFirstHandler = null;
     }
@@ -84,26 +92,46 @@
     }
 
     public Transitions(@NonNull WindowOrganizer organizer, @NonNull TransactionPool pool,
-            @NonNull ShellExecutor mainExecutor, @NonNull ShellExecutor animExecutor) {
+            @NonNull Context context, @NonNull ShellExecutor mainExecutor,
+            @NonNull ShellExecutor animExecutor) {
         mOrganizer = organizer;
+        mContext = context;
         mMainExecutor = mainExecutor;
         mAnimExecutor = animExecutor;
         mPlayerImpl = new TransitionPlayerImpl();
         // The very last handler (0 in the list) should be the default one.
-        mHandlers.add(new DefaultTransitionHandler(pool, mainExecutor, animExecutor));
+        mHandlers.add(new DefaultTransitionHandler(pool, context, mainExecutor, animExecutor));
         // Next lowest priority is remote transitions.
         mRemoteTransitionHandler = new RemoteTransitionHandler(mainExecutor);
         mHandlers.add(mRemoteTransitionHandler);
+
+        ContentResolver resolver = context.getContentResolver();
+        mTransitionAnimationScaleSetting = Settings.Global.getFloat(resolver,
+                Settings.Global.TRANSITION_ANIMATION_SCALE,
+                context.getResources().getFloat(
+                        R.dimen.config_appTransitionAnimationDurationScaleDefault));
+        dispatchAnimScaleSetting(mTransitionAnimationScaleSetting);
+
+        resolver.registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.TRANSITION_ANIMATION_SCALE), false,
+                new SettingsObserver());
     }
 
     private Transitions() {
         mOrganizer = null;
+        mContext = null;
         mMainExecutor = null;
         mAnimExecutor = null;
         mPlayerImpl = null;
         mRemoteTransitionHandler = null;
     }
 
+    private void dispatchAnimScaleSetting(float scale) {
+        for (int i = mHandlers.size() - 1; i >= 0; --i) {
+            mHandlers.get(i).setAnimScaleSetting(scale);
+        }
+    }
+
     /** Create an empty/non-registering transitions object for system-ui tests. */
     @VisibleForTesting
     public static RemoteTransitions createEmptyForTesting() {
@@ -368,6 +396,13 @@
         @Nullable
         WindowContainerTransaction handleRequest(@NonNull IBinder transition,
                 @NonNull TransitionRequestInfo request);
+
+        /**
+         * Sets transition animation scale settings value to handler.
+         *
+         * @param scale The setting value of transition animation scale.
+         */
+        default void setAnimScaleSetting(float scale) {}
     }
 
     @BinderThread
@@ -404,4 +439,21 @@
             });
         }
     }
+
+    private class SettingsObserver extends ContentObserver {
+
+        SettingsObserver() {
+            super(null);
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            super.onChange(selfChange);
+            mTransitionAnimationScaleSetting = Settings.Global.getFloat(
+                    mContext.getContentResolver(), Settings.Global.TRANSITION_ANIMATION_SCALE,
+                    mTransitionAnimationScaleSetting);
+
+            mMainExecutor.execute(() -> dispatchAnimScaleSetting(mTransitionAnimationScaleSetting));
+        }
+    }
 }
diff --git a/libs/WindowManager/Shell/tests/OWNERS b/libs/WindowManager/Shell/tests/OWNERS
index 2c6c7b3..d80699d 100644
--- a/libs/WindowManager/Shell/tests/OWNERS
+++ b/libs/WindowManager/Shell/tests/OWNERS
@@ -1,2 +1,3 @@
+# Bug component: 909476
 # includes OWNERS from parent directories
 natanieljr@google.com
diff --git a/libs/WindowManager/Shell/tests/flicker/Android.bp b/libs/WindowManager/Shell/tests/flicker/Android.bp
index a57ac35..9dd25fe 100644
--- a/libs/WindowManager/Shell/tests/flicker/Android.bp
+++ b/libs/WindowManager/Shell/tests/flicker/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "WMShellFlickerTests",
     srcs: ["src/**/*.java", "src/**/*.kt"],
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
index 3282ece..35bab7a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
@@ -18,241 +18,92 @@
 
 import android.graphics.Region
 import android.view.Surface
-import com.android.server.wm.flicker.dsl.LayersAssertionBuilder
-import com.android.server.wm.flicker.dsl.LayersAssertionBuilderLegacy
-import com.android.server.wm.flicker.APP_PAIR_SPLIT_DIVIDER
-import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER
+import com.android.server.wm.flicker.FlickerTestParameter
 import com.android.server.wm.flicker.helpers.WindowUtils
 import com.android.server.wm.flicker.traces.layers.getVisibleBounds
 
-@JvmOverloads
-fun LayersAssertionBuilder.appPairsDividerIsVisible(bugId: Int = 0) {
-    end("appPairsDividerIsVisible", bugId) {
+fun FlickerTestParameter.appPairsDividerIsVisible() {
+    assertLayersEnd {
         this.isVisible(APP_PAIR_SPLIT_DIVIDER)
     }
 }
 
-@JvmOverloads
-fun LayersAssertionBuilder.appPairsDividerIsInvisible(bugId: Int = 0) {
-    end("appPairsDividerIsInVisible", bugId) {
-        this.notExists(APP_PAIR_SPLIT_DIVIDER)
+fun FlickerTestParameter.appPairsDividerIsInvisible() {
+    assertLayersEnd {
+        this.notContains(APP_PAIR_SPLIT_DIVIDER)
     }
 }
 
-@JvmOverloads
-fun LayersAssertionBuilder.appPairsDividerBecomesVisible(bugId: Int = 0) {
-    all("dividerLayerBecomesVisible", bugId) {
-        this.hidesLayer(DOCKED_STACK_DIVIDER)
+fun FlickerTestParameter.appPairsDividerBecomesVisible() {
+    assertLayers {
+        this.isInvisible(DOCKED_STACK_DIVIDER)
             .then()
-            .showsLayer(DOCKED_STACK_DIVIDER)
+            .isVisible(DOCKED_STACK_DIVIDER)
     }
 }
 
-@JvmOverloads
-fun LayersAssertionBuilder.dockedStackDividerIsVisible(bugId: Int = 0) {
-    end("dockedStackDividerIsVisible", bugId) {
+fun FlickerTestParameter.dockedStackDividerIsVisible() {
+    assertLayersEnd {
         this.isVisible(DOCKED_STACK_DIVIDER)
     }
 }
 
-@JvmOverloads
-fun LayersAssertionBuilder.dockedStackDividerBecomesVisible(bugId: Int = 0) {
-    all("dividerLayerBecomesVisible", bugId) {
-        this.hidesLayer(DOCKED_STACK_DIVIDER)
+fun FlickerTestParameter.dockedStackDividerBecomesVisible() {
+    assertLayers {
+        this.isInvisible(DOCKED_STACK_DIVIDER)
             .then()
-            .showsLayer(DOCKED_STACK_DIVIDER)
+            .isVisible(DOCKED_STACK_DIVIDER)
     }
 }
 
-@JvmOverloads
-fun LayersAssertionBuilder.dockedStackDividerBecomesInvisible(bugId: Int = 0) {
-    all("dividerLayerBecomesInvisible", bugId) {
-        this.showsLayer(DOCKED_STACK_DIVIDER)
-            .then()
-            .hidesLayer(DOCKED_STACK_DIVIDER)
-    }
-}
-
-@JvmOverloads
-fun LayersAssertionBuilder.dockedStackDividerIsInvisible(bugId: Int = 0) {
-    end("dockedStackDividerIsInvisible", bugId) {
-        this.notExists(DOCKED_STACK_DIVIDER)
-    }
-}
-
-@JvmOverloads
-fun LayersAssertionBuilder.appPairsPrimaryBoundsIsVisible(
-    rotation: Int,
-    primaryLayerName: String,
-    bugId: Int = 0
-) {
-    end("PrimaryAppBounds", bugId) {
-        val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER)
-        this.hasVisibleRegion(primaryLayerName, getPrimaryRegion(dividerRegion, rotation))
-    }
-}
-
-@JvmOverloads
-fun LayersAssertionBuilder.appPairsSecondaryBoundsIsVisible(
-    rotation: Int,
-    secondaryLayerName: String,
-    bugId: Int = 0
-) {
-    end("SecondaryAppBounds", bugId) {
-        val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER)
-        this.hasVisibleRegion(secondaryLayerName, getSecondaryRegion(dividerRegion, rotation))
-    }
-}
-
-@JvmOverloads
-fun LayersAssertionBuilder.dockedStackPrimaryBoundsIsVisible(
-    rotation: Int,
-    primaryLayerName: String,
-    bugId: Int = 0
-) {
-    end("PrimaryAppBounds", bugId) {
-        val dividerRegion = entry.getVisibleBounds(DOCKED_STACK_DIVIDER)
-        this.hasVisibleRegion(primaryLayerName, getPrimaryRegion(dividerRegion, rotation))
-    }
-}
-
-@JvmOverloads
-fun LayersAssertionBuilder.dockedStackSecondaryBoundsIsVisible(
-    rotation: Int,
-    secondaryLayerName: String,
-    bugId: Int = 0
-) {
-    end("SecondaryAppBounds", bugId) {
-        val dividerRegion = entry.getVisibleBounds(DOCKED_STACK_DIVIDER)
-        this.hasVisibleRegion(secondaryLayerName, getSecondaryRegion(dividerRegion, rotation))
-    }
-}
-
-@JvmOverloads
-fun LayersAssertionBuilderLegacy.appPairsDividerIsVisible(
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    end("appPairsDividerIsVisible", bugId, enabled) {
-        this.isVisible(APP_PAIR_SPLIT_DIVIDER)
-    }
-}
-
-@JvmOverloads
-fun LayersAssertionBuilderLegacy.appPairsDividerIsInvisible(
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    end("appPairsDividerIsInVisible", bugId, enabled) {
-        this.notExists(APP_PAIR_SPLIT_DIVIDER)
-    }
-}
-
-@JvmOverloads
-fun LayersAssertionBuilderLegacy.appPairsDividerBecomesVisible(
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    all("dividerLayerBecomesVisible", bugId, enabled) {
-        this.hidesLayer(DOCKED_STACK_DIVIDER)
-            .then()
-            .showsLayer(DOCKED_STACK_DIVIDER)
-    }
-}
-
-@JvmOverloads
-fun LayersAssertionBuilderLegacy.dockedStackDividerIsVisible(
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    end("dockedStackDividerIsVisible", bugId, enabled) {
+fun FlickerTestParameter.dockedStackDividerBecomesInvisible() {
+    assertLayers {
         this.isVisible(DOCKED_STACK_DIVIDER)
-    }
-}
-
-@JvmOverloads
-fun LayersAssertionBuilderLegacy.dockedStackDividerBecomesVisible(
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    all("dividerLayerBecomesVisible", bugId, enabled) {
-        this.hidesLayer(DOCKED_STACK_DIVIDER)
             .then()
-            .showsLayer(DOCKED_STACK_DIVIDER)
+            .isInvisible(DOCKED_STACK_DIVIDER)
     }
 }
 
-@JvmOverloads
-fun LayersAssertionBuilderLegacy.dockedStackDividerBecomesInvisible(
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    all("dividerLayerBecomesInvisible", bugId, enabled) {
-        this.showsLayer(DOCKED_STACK_DIVIDER)
-            .then()
-            .hidesLayer(DOCKED_STACK_DIVIDER)
+fun FlickerTestParameter.dockedStackDividerIsInvisible() {
+    assertLayersEnd {
+        this.notContains(DOCKED_STACK_DIVIDER)
     }
 }
 
-@JvmOverloads
-fun LayersAssertionBuilderLegacy.dockedStackDividerIsInvisible(
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    end("dockedStackDividerIsInvisible", bugId, enabled) {
-        this.notExists(DOCKED_STACK_DIVIDER)
-    }
-}
-
-@JvmOverloads
-fun LayersAssertionBuilderLegacy.appPairsPrimaryBoundsIsVisible(
-    rotation: Int,
-    primaryLayerName: String,
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    end("PrimaryAppBounds", bugId, enabled) {
+fun FlickerTestParameter.appPairsPrimaryBoundsIsVisible(rotation: Int, primaryLayerName: String) {
+    assertLayersEnd {
         val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER)
-        this.hasVisibleRegion(primaryLayerName, getPrimaryRegion(dividerRegion, rotation))
+        this.coversExactly(getPrimaryRegion(dividerRegion, rotation), primaryLayerName)
     }
 }
 
-@JvmOverloads
-fun LayersAssertionBuilderLegacy.appPairsSecondaryBoundsIsVisible(
+fun FlickerTestParameter.dockedStackPrimaryBoundsIsVisible(
     rotation: Int,
-    secondaryLayerName: String,
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
+    primaryLayerName: String
 ) {
-    end("SecondaryAppBounds", bugId, enabled) {
+    assertLayersEnd {
+        val dividerRegion = entry.getVisibleBounds(DOCKED_STACK_DIVIDER)
+        this.coversExactly(getPrimaryRegion(dividerRegion, rotation), primaryLayerName)
+    }
+}
+
+fun FlickerTestParameter.appPairsSecondaryBoundsIsVisible(
+    rotation: Int,
+    secondaryLayerName: String
+) {
+    assertLayersEnd {
         val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER)
-        this.hasVisibleRegion(secondaryLayerName, getSecondaryRegion(dividerRegion, rotation))
+        this.coversExactly(getSecondaryRegion(dividerRegion, rotation), secondaryLayerName)
     }
 }
 
-@JvmOverloads
-fun LayersAssertionBuilderLegacy.dockedStackPrimaryBoundsIsVisible(
+fun FlickerTestParameter.dockedStackSecondaryBoundsIsVisible(
     rotation: Int,
-    primaryLayerName: String,
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
+    secondaryLayerName: String
 ) {
-    end("PrimaryAppBounds", bugId, enabled) {
+    assertLayersEnd {
         val dividerRegion = entry.getVisibleBounds(DOCKED_STACK_DIVIDER)
-        this.hasVisibleRegion(primaryLayerName, getPrimaryRegion(dividerRegion, rotation))
-    }
-}
-
-@JvmOverloads
-fun LayersAssertionBuilderLegacy.dockedStackSecondaryBoundsIsVisible(
-    rotation: Int,
-    secondaryLayerName: String,
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    end("SecondaryAppBounds", bugId, enabled) {
-        val dividerRegion = entry.getVisibleBounds(DOCKED_STACK_DIVIDER)
-        this.hasVisibleRegion(secondaryLayerName, getSecondaryRegion(dividerRegion, rotation))
+        this.coversExactly(getSecondaryRegion(dividerRegion, rotation), secondaryLayerName)
     }
 }
 
@@ -260,10 +111,10 @@
     val displayBounds = WindowUtils.getDisplayBounds(rotation)
     return if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
         Region(0, 0, displayBounds.bounds.right,
-                dividerRegion.bounds.bottom - WindowUtils.dockedStackDividerInset)
+            dividerRegion.bounds.bottom - WindowUtils.dockedStackDividerInset)
     } else {
         Region(0, 0, dividerRegion.bounds.left,
-                dividerRegion.bounds.right - WindowUtils.dockedStackDividerInset)
+            dividerRegion.bounds.right - WindowUtils.dockedStackDividerInset)
     }
 }
 
@@ -271,12 +122,12 @@
     val displayBounds = WindowUtils.getDisplayBounds(rotation)
     return if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
         Region(0,
-                dividerRegion.bounds.bottom - WindowUtils.dockedStackDividerInset,
-                displayBounds.bounds.right,
-                displayBounds.bounds.bottom - WindowUtils.dockedStackDividerInset)
+            dividerRegion.bounds.bottom - WindowUtils.dockedStackDividerInset,
+            displayBounds.bounds.right,
+            displayBounds.bounds.bottom - WindowUtils.dockedStackDividerInset)
     } else {
         Region(dividerRegion.bounds.right, 0,
-                displayBounds.bounds.right,
-                displayBounds.bounds.bottom - WindowUtils.dockedStackDividerInset)
+            displayBounds.bounds.right,
+            displayBounds.bounds.bottom - WindowUtils.dockedStackDividerInset)
     }
-}
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
index d2cfb0f..03b93c7 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
@@ -18,3 +18,5 @@
 
 const val IME_WINDOW_NAME = "InputMethod"
 const val SYSTEM_UI_PACKAGE_NAME = "com.android.systemui"
+const val APP_PAIR_SPLIT_DIVIDER = "AppPairSplitDivider"
+const val DOCKED_STACK_DIVIDER = "DockedStackDivider"
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt
index 89bbdb0..9c50630 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt
@@ -16,33 +16,33 @@
 
 package com.android.wm.shell.flicker
 
+import android.app.Instrumentation
 import android.content.pm.PackageManager
 import android.content.pm.PackageManager.FEATURE_LEANBACK
 import android.content.pm.PackageManager.FEATURE_LEANBACK_ONLY
-import android.os.RemoteException
-import android.os.SystemClock
-import android.platform.helpers.IAppHelper
 import android.view.Surface
 import androidx.test.platform.app.InstrumentationRegistry
 import androidx.test.uiautomator.UiDevice
-import com.android.server.wm.flicker.Flicker
 import org.junit.Assume.assumeFalse
 import org.junit.Before
+import org.junit.runners.Parameterized
 
 /**
  * Base class of all Flicker test that performs common functions for all flicker tests:
  *
- *
  * - Caches transitions so that a transition is run once and the transition results are used by
  * tests multiple times. This is needed for parameterized tests which call the BeforeClass methods
  * multiple times.
  * - Keeps track of all test artifacts and deletes ones which do not need to be reviewed.
  * - Fails tests if results are not available for any test due to jank.
  */
-abstract class FlickerTestBase {
-    val instrumentation by lazy { InstrumentationRegistry.getInstrumentation() }
-    val uiDevice by lazy { UiDevice.getInstance(instrumentation) }
-    val packageManager: PackageManager by lazy { instrumentation.context.getPackageManager() }
+abstract class FlickerTestBase(
+    protected val rotationName: String,
+    protected val rotation: Int
+) {
+    val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    val uiDevice = UiDevice.getInstance(instrumentation)
+    val packageManager: PackageManager = instrumentation.context.packageManager
     protected val isTelevision: Boolean by lazy {
         packageManager.run {
             hasSystemFeature(FEATURE_LEANBACK) || hasSystemFeature(FEATURE_LEANBACK_ONLY)
@@ -56,83 +56,12 @@
     @Before
     open fun televisionSetUp() = assumeFalse(isTelevision)
 
-    /**
-     * Build a test tag for the test
-     * @param testName Name of the transition(s) being tested
-     * @param app App being launcher
-     * @param rotation Initial screen rotation
-     *
-     * @return test tag with pattern <NAME>__<APP>__<ROTATION>
-    </ROTATION></APP></NAME> */
-    protected fun buildTestTag(testName: String, app: IAppHelper, rotation: Int): String {
-        return buildTestTag(
-                testName, app, rotation, rotation, app2 = null, extraInfo = "")
-    }
-
-    /**
-     * Build a test tag for the test
-     * @param testName Name of the transition(s) being tested
-     * @param app App being launcher
-     * @param beginRotation Initial screen rotation
-     * @param endRotation End screen rotation (if any, otherwise use same as initial)
-     *
-     * @return test tag with pattern <NAME>__<APP>__<BEGIN_ROTATION>-<END_ROTATION>
-    </END_ROTATION></BEGIN_ROTATION></APP></NAME> */
-    protected fun buildTestTag(
-        testName: String,
-        app: IAppHelper,
-        beginRotation: Int,
-        endRotation: Int
-    ): String {
-        return buildTestTag(
-                testName, app, beginRotation, endRotation, app2 = null, extraInfo = "")
-    }
-
-    /**
-     * Build a test tag for the test
-     * @param testName Name of the transition(s) being tested
-     * @param app App being launcher
-     * @param app2 Second app being launched (if any)
-     * @param beginRotation Initial screen rotation
-     * @param endRotation End screen rotation (if any, otherwise use same as initial)
-     * @param extraInfo Additional information to append to the tag
-     *
-     * @return test tag with pattern <NAME>__<APP></APP>(S)>__<ROTATION></ROTATION>(S)>[__<EXTRA>]
-    </EXTRA></NAME> */
-    protected fun buildTestTag(
-        testName: String,
-        app: IAppHelper,
-        beginRotation: Int,
-        endRotation: Int,
-        app2: IAppHelper?,
-        extraInfo: String
-    ): String {
-        var testTag = "${testName}__${app.launcherName}"
-        if (app2 != null) {
-            testTag += "-${app2.launcherName}"
-        }
-        testTag += "__${Surface.rotationToString(beginRotation)}"
-        if (endRotation != beginRotation) {
-            testTag += "-${Surface.rotationToString(endRotation)}"
-        }
-        if (extraInfo.isNotEmpty()) {
-            testTag += "__$extraInfo"
-        }
-        return testTag
-    }
-
-    protected fun Flicker.setRotation(rotation: Int) {
-        try {
-            when (rotation) {
-                Surface.ROTATION_270 -> device.setOrientationLeft()
-                Surface.ROTATION_90 -> device.setOrientationRight()
-                Surface.ROTATION_0 -> device.setOrientationNatural()
-                else -> device.setOrientationNatural()
-            }
-            // Wait for animation to complete
-            SystemClock.sleep(1000)
-        } catch (e: RemoteException) {
-            throw RuntimeException(e)
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<Array<Any>> {
+            val supportedRotations = intArrayOf(Surface.ROTATION_0, Surface.ROTATION_90)
+            return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
         }
     }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/NonRotationTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/NonRotationTestBase.kt
deleted file mode 100644
index 90334ae..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/NonRotationTestBase.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.flicker
-
-import android.view.Surface
-import org.junit.runners.Parameterized
-
-abstract class NonRotationTestBase(
-    protected val rotationName: String,
-    protected val rotation: Int
-) : FlickerTestBase() {
-    companion object {
-        const val SCREENSHOT_LAYER = "RotationLayer"
-
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val supportedRotations = intArrayOf(Surface.ROTATION_0, Surface.ROTATION_90)
-            return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
-        }
-    }
-}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt
index c3fd663..90e7137 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt
@@ -16,17 +16,17 @@
 
 package com.android.wm.shell.flicker.apppairs
 
-import android.os.Bundle
 import android.os.SystemClock
+import android.platform.test.annotations.Presubmit
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.buildTestTag
-import com.android.wm.shell.flicker.helpers.AppPairsHelper
 import com.android.wm.shell.flicker.appPairsDividerIsInvisible
+import com.android.wm.shell.flicker.helpers.AppPairsHelper
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -41,47 +41,47 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class AppPairsTestCannotPairNonResizeableApps(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : AppPairsTransition(InstrumentationRegistry.getInstrumentation()) {
+    testSpec: FlickerTestParameter
+) : AppPairsTransition(testSpec) {
+
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = {
+            super.transition(this, it)
+            transitions {
+                nonResizeableApp?.launchViaIntent(wmHelper)
+                // TODO pair apps through normal UX flow
+                executeShellCommand(
+                    composePairsCommand(primaryTaskId, nonResizeableTaskId, pair = true))
+                SystemClock.sleep(AppPairsHelper.TIMEOUT_MS)
+            }
+        }
+
+    @Presubmit
+    @Test
+    fun appPairsDividerIsInvisible() = testSpec.appPairsDividerIsInvisible()
+
+    @Presubmit
+    @Test
+    fun onlyResizeableAppWindowVisible() {
+        val nonResizeableApp = nonResizeableApp
+        require(nonResizeableApp != null) {
+            "Non resizeable app not initialized"
+        }
+        testSpec.assertWmEnd {
+            isVisible(nonResizeableApp.defaultWindowName)
+            isInvisible(primaryApp.defaultWindowName)
+        }
+    }
+
+    companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): List<Array<Any>> {
-            val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
-                withTestName {
-                    buildTestTag(configuration)
-                }
-                transitions {
-                    nonResizeableApp?.launchViaIntent(wmHelper)
-                    // TODO pair apps through normal UX flow
-                    executeShellCommand(
-                        composePairsCommand(primaryTaskId, nonResizeableTaskId, pair = true))
-                    SystemClock.sleep(AppPairsHelper.TIMEOUT_MS)
-                }
-                assertions {
-                    presubmit {
-                        layersTrace {
-                            appPairsDividerIsInvisible()
-                        }
-                        windowManagerTrace {
-                            val nonResizeableApp = nonResizeableApp
-                            require(nonResizeableApp != null) {
-                                "Non resizeable app not initialized"
-                            }
-
-                            end("onlyResizeableAppWindowVisible") {
-                                isVisible(nonResizeableApp.defaultWindowName)
-                                isInvisible(primaryApp.defaultWindowName)
-                            }
-                        }
-                    }
-                }
-            }
-
-            return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation,
-                transition, testSpec, repetitions = AppPairsHelper.TEST_REPETITIONS)
+        fun getParams(): List<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
+                repetitions = AppPairsHelper.TEST_REPETITIONS)
         }
     }
 }
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt
index 7a2a5e4..dc51b4f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt
@@ -16,19 +16,20 @@
 
 package com.android.wm.shell.flicker.apppairs
 
-import android.os.Bundle
 import android.os.SystemClock
+import android.platform.test.annotations.Presubmit
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.APP_PAIR_SPLIT_DIVIDER
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.traces.layers.getVisibleBounds
+import com.android.wm.shell.flicker.APP_PAIR_SPLIT_DIVIDER
 import com.android.wm.shell.flicker.appPairsDividerIsVisible
 import com.android.wm.shell.flicker.helpers.AppPairsHelper
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -39,52 +40,53 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class AppPairsTestPairPrimaryAndSecondaryApps(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : AppPairsTransition(InstrumentationRegistry.getInstrumentation()) {
+    testSpec: FlickerTestParameter
+) : AppPairsTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = {
+            super.transition(this, it)
+            transitions {
+                // TODO pair apps through normal UX flow
+                executeShellCommand(
+                    composePairsCommand(primaryTaskId, secondaryTaskId, pair = true))
+                SystemClock.sleep(AppPairsHelper.TIMEOUT_MS)
+            }
+        }
+
+    @Presubmit
+    @Test
+    fun appPairsDividerIsVisible() = testSpec.appPairsDividerIsVisible()
+
+    @Presubmit
+    @Test
+    fun bothAppWindowsVisible() {
+        testSpec.assertWmEnd {
+            isVisible(primaryApp.defaultWindowName)
+            isVisible(secondaryApp.defaultWindowName)
+        }
+    }
+
+    @FlakyTest
+    @Test
+    fun appsEndingBounds() {
+        testSpec.assertLayersEnd {
+            val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER)
+            this.coversExactly(appPairsHelper.getPrimaryBounds(dividerRegion),
+                primaryApp.defaultWindowName)
+                .coversExactly(appPairsHelper.getSecondaryBounds(dividerRegion),
+                    secondaryApp.defaultWindowName)
+        }
+    }
+
+    companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): List<Array<Any>> {
-            val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
-                withTestName {
-                    buildTestTag(configuration)
-                }
-                transitions {
-                    // TODO pair apps through normal UX flow
-                    executeShellCommand(
-                        composePairsCommand(primaryTaskId, secondaryTaskId, pair = true))
-                    SystemClock.sleep(AppPairsHelper.TIMEOUT_MS)
-                }
-                assertions {
-                    presubmit {
-                        layersTrace {
-                            appPairsDividerIsVisible()
-                        }
-                        windowManagerTrace {
-                            end("bothAppWindowsVisible") {
-                                isVisible(primaryApp.defaultWindowName)
-                                isVisible(secondaryApp.defaultWindowName)
-                            }
-                        }
-                    }
-
-                    flaky {
-                        layersTrace {
-                            end("appsEndingBounds") {
-                                val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER)
-                                this.hasVisibleRegion(primaryApp.defaultWindowName,
-                                    appPairsHelper.getPrimaryBounds(dividerRegion))
-                                    .hasVisibleRegion(secondaryApp.defaultWindowName,
-                                        appPairsHelper.getSecondaryBounds(dividerRegion))
-                            }
-                        }
-                    }
-                }
-            }
-            return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation, transition,
-                testSpec, repetitions = AppPairsHelper.TEST_REPETITIONS)
+        fun getParams(): List<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
+                repetitions = AppPairsHelper.TEST_REPETITIONS)
         }
     }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt
index d8dc4c2..5bb9b2f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt
@@ -16,19 +16,20 @@
 
 package com.android.wm.shell.flicker.apppairs
 
-import android.os.Bundle
 import android.os.SystemClock
+import android.platform.test.annotations.Presubmit
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.APP_PAIR_SPLIT_DIVIDER
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.traces.layers.getVisibleBounds
+import com.android.wm.shell.flicker.APP_PAIR_SPLIT_DIVIDER
 import com.android.wm.shell.flicker.appPairsDividerIsInvisible
 import com.android.wm.shell.flicker.helpers.AppPairsHelper
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -39,61 +40,67 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class AppPairsTestUnpairPrimaryAndSecondaryApps(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : AppPairsTransition(InstrumentationRegistry.getInstrumentation()) {
+    testSpec: FlickerTestParameter
+) : AppPairsTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = {
+            super.transition(this, it)
+            setup {
+                executeShellCommand(
+                    composePairsCommand(primaryTaskId, secondaryTaskId, pair = true))
+                SystemClock.sleep(AppPairsHelper.TIMEOUT_MS)
+            }
+            transitions {
+                // TODO pair apps through normal UX flow
+                executeShellCommand(
+                    composePairsCommand(primaryTaskId, secondaryTaskId, pair = false))
+                SystemClock.sleep(AppPairsHelper.TIMEOUT_MS)
+            }
+        }
+
+    @Presubmit
+    @Test
+    fun appPairsDividerIsInvisible() = testSpec.appPairsDividerIsInvisible()
+
+    @Presubmit
+    @Test
+    fun bothAppWindowsInvisible() {
+        testSpec.assertWmEnd {
+            isInvisible(primaryApp.defaultWindowName)
+            isInvisible(secondaryApp.defaultWindowName)
+        }
+    }
+
+    @FlakyTest
+    @Test
+    fun appsStartingBounds() {
+        testSpec.assertLayersStart {
+            val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER)
+            coversExactly(appPairsHelper.getPrimaryBounds(dividerRegion),
+                primaryApp.defaultWindowName)
+            coversExactly(appPairsHelper.getSecondaryBounds(dividerRegion),
+                secondaryApp.defaultWindowName)
+        }
+    }
+
+    @FlakyTest
+    @Test
+    fun appsEndingBounds() {
+        testSpec.assertLayersEnd {
+            notContains(primaryApp.defaultWindowName)
+            notContains(secondaryApp.defaultWindowName)
+        }
+    }
+
+    companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): List<Array<Any>> {
-            val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
-                withTestName {
-                    buildTestTag(configuration)
-                }
-                setup {
-                    executeShellCommand(
-                        composePairsCommand(primaryTaskId, secondaryTaskId, pair = true))
-                    SystemClock.sleep(AppPairsHelper.TIMEOUT_MS)
-                }
-                transitions {
-                    // TODO pair apps through normal UX flow
-                    executeShellCommand(
-                        composePairsCommand(primaryTaskId, secondaryTaskId, pair = false))
-                    SystemClock.sleep(AppPairsHelper.TIMEOUT_MS)
-                }
-                assertions {
-                    presubmit {
-                        layersTrace {
-                            appPairsDividerIsInvisible()
-                        }
-                        windowManagerTrace {
-                            end("bothAppWindowsInvisible") {
-                                isInvisible(primaryApp.defaultWindowName)
-                                isInvisible(secondaryApp.defaultWindowName)
-                            }
-                        }
-                    }
-
-                    flaky {
-                        layersTrace {
-                            start("appsStartingBounds") {
-                                val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER)
-                                this.hasVisibleRegion(primaryApp.defaultWindowName,
-                                    appPairsHelper.getPrimaryBounds(dividerRegion))
-                                    .hasVisibleRegion(secondaryApp.defaultWindowName,
-                                        appPairsHelper.getSecondaryBounds(dividerRegion))
-                            }
-                            end("appsEndingBounds") {
-                                this.notExists(primaryApp.defaultWindowName)
-                                    .notExists(secondaryApp.defaultWindowName)
-                            }
-                        }
-                    }
-                }
-            }
-            return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation, transition,
-                testSpec, repetitions = AppPairsHelper.TEST_REPETITIONS)
+        fun getParams(): List<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
+                repetitions = AppPairsHelper.TEST_REPETITIONS)
         }
     }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTransition.kt
index 78a938a..91e080f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTransition.kt
@@ -17,41 +17,55 @@
 package com.android.wm.shell.flicker.apppairs
 
 import android.app.Instrumentation
-import android.os.Bundle
+import android.platform.test.annotations.Presubmit
 import android.system.helpers.ActivityHelper
 import android.util.Log
+import androidx.test.platform.app.InstrumentationRegistry
 import com.android.compatibility.common.util.SystemUtil
+import com.android.server.wm.flicker.FlickerBuilderProvider
+import com.android.server.wm.flicker.FlickerTestParameter
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isRotated
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
 import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.repetitions
 import com.android.server.wm.flicker.startRotation
 import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
 import com.android.wm.shell.flicker.helpers.AppPairsHelper
 import com.android.wm.shell.flicker.helpers.SplitScreenHelper
 import com.android.wm.shell.flicker.testapp.Components
+import org.junit.Test
 import java.io.IOException
 
-open class AppPairsTransition(
-    protected val instrumentation: Instrumentation
-) {
-    internal val activityHelper = ActivityHelper.getInstance()
-
-    internal val appPairsHelper = AppPairsHelper(instrumentation,
+abstract class AppPairsTransition(protected val testSpec: FlickerTestParameter) {
+    protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    protected val isRotated = testSpec.config.startRotation.isRotated()
+    protected val activityHelper = ActivityHelper.getInstance()
+    protected val appPairsHelper = AppPairsHelper(instrumentation,
         Components.SplitScreenActivity.LABEL,
         Components.SplitScreenActivity.COMPONENT)
 
-    internal val primaryApp = SplitScreenHelper.getPrimary(instrumentation)
-    internal val secondaryApp = SplitScreenHelper.getSecondary(instrumentation)
-    internal open val nonResizeableApp: SplitScreenHelper? =
+    protected val primaryApp = SplitScreenHelper.getPrimary(instrumentation)
+    protected val secondaryApp = SplitScreenHelper.getSecondary(instrumentation)
+    protected open val nonResizeableApp: SplitScreenHelper? =
         SplitScreenHelper.getNonResizeable(instrumentation)
-    internal var primaryTaskId = ""
-    internal var secondaryTaskId = ""
-    internal var nonResizeableTaskId = ""
+    protected var primaryTaskId = ""
+    protected var secondaryTaskId = ""
+    protected var nonResizeableTaskId = ""
 
-    internal open val transition: FlickerBuilder.(Bundle) -> Unit
+    @FlickerBuilderProvider
+    fun buildFlicker(): FlickerBuilder {
+        return FlickerBuilder(instrumentation).apply {
+            withTestName { testSpec.name }
+            repeat { testSpec.config.repetitions }
+            transition(this, testSpec.config)
+        }
+    }
+
+    internal open val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
         get() = { configuration ->
             setup {
                 test {
@@ -71,20 +85,9 @@
                         primaryTaskId, secondaryTaskId, pair = false))
                     executeShellCommand(composePairsCommand(
                         primaryTaskId, nonResizeableTaskId, pair = false))
-                    primaryApp.exit()
-                    secondaryApp.exit()
-                    nonResizeableApp?.exit()
-                }
-            }
-
-            assertions {
-                layersTrace {
-                    navBarLayerIsAlwaysVisible()
-                    statusBarLayerIsAlwaysVisible()
-                }
-                windowManagerTrace {
-                    navBarWindowIsAlwaysVisible()
-                    statusBarWindowIsAlwaysVisible()
+                    primaryApp.exit(wmHelper)
+                    secondaryApp.exit(wmHelper)
+                    nonResizeableApp?.exit(wmHelper)
                 }
             }
         }
@@ -128,4 +131,20 @@
         }
         append("$primaryApp $secondaryApp")
     }
+
+    @Presubmit
+    @Test
+    open fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    open fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    open fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    open fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
 }
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt
index 8aee005..5f003ba 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt
@@ -16,27 +16,26 @@
 
 package com.android.wm.shell.flicker.apppairs
 
-import android.os.Bundle
 import android.os.SystemClock
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.endRotation
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
-import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
-import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
 import com.android.wm.shell.flicker.appPairsDividerIsVisible
 import com.android.wm.shell.flicker.appPairsPrimaryBoundsIsVisible
 import com.android.wm.shell.flicker.appPairsSecondaryBoundsIsVisible
 import com.android.wm.shell.flicker.helpers.AppPairsHelper
 import com.android.wm.shell.flicker.helpers.SplitScreenHelper
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -47,57 +46,65 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class RotateTwoLaunchedAppsInAppPairsMode(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : RotateTwoLaunchedAppsTransition(
-        InstrumentationRegistry.getInstrumentation()) {
+    testSpec: FlickerTestParameter
+) : RotateTwoLaunchedAppsTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = {
+            super.transition(this, it)
+            transitions {
+                executeShellCommand(composePairsCommand(
+                    primaryTaskId, secondaryTaskId, true /* pair */))
+                SystemClock.sleep(AppPairsHelper.TIMEOUT_MS)
+                setRotation(testSpec.config.endRotation)
+            }
+        }
+
+    @Presubmit
+    @Test
+    fun bothAppWindowsVisible() {
+        testSpec.assertWmEnd {
+            isVisible(primaryApp.defaultWindowName)
+                .isVisible(secondaryApp.defaultWindowName)
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun appPairsDividerIsVisible() = testSpec.appPairsDividerIsVisible()
+
+    @Presubmit
+    @Test
+    fun navBarLayerRotatesAndScales() = testSpec.navBarLayerRotatesAndScales(Surface.ROTATION_0,
+        testSpec.config.endRotation)
+
+    @Presubmit
+    @Test
+    fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales(Surface.ROTATION_0,
+        testSpec.config.endRotation)
+
+    @FlakyTest(bugId = 172776659)
+    @Test
+    fun appPairsPrimaryBoundsIsVisible() =
+        testSpec.appPairsPrimaryBoundsIsVisible(testSpec.config.endRotation,
+            primaryApp.defaultWindowName)
+
+    @FlakyTest(bugId = 172776659)
+    @Test
+    fun appPairsSecondaryBoundsIsVisible() =
+        testSpec.appPairsSecondaryBoundsIsVisible(testSpec.config.endRotation,
+            secondaryApp.defaultWindowName)
+
+    companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
-                withTestName {
-                    buildTestTag(configuration)
-                }
-                transitions {
-                    executeShellCommand(composePairsCommand(
-                        primaryTaskId, secondaryTaskId, true /* pair */))
-                    SystemClock.sleep(AppPairsHelper.TIMEOUT_MS)
-                    setRotation(configuration.endRotation)
-                }
-                assertions {
-                    presubmit {
-                        windowManagerTrace {
-                            navBarWindowIsAlwaysVisible()
-                            statusBarWindowIsAlwaysVisible()
-                            end("bothAppWindowsVisible") {
-                                isVisible(primaryApp.defaultWindowName)
-                                    .isVisible(secondaryApp.defaultWindowName)
-                            }
-                        }
-                    }
-
-                    flaky {
-                        layersTrace {
-                            appPairsDividerIsVisible()
-                            navBarLayerRotatesAndScales(Surface.ROTATION_0,
-                                configuration.endRotation)
-                            statusBarLayerRotatesScales(Surface.ROTATION_0,
-                                configuration.endRotation)
-                            appPairsPrimaryBoundsIsVisible(configuration.endRotation,
-                                primaryApp.defaultWindowName, bugId = 172776659)
-                            appPairsSecondaryBoundsIsVisible(configuration.endRotation,
-                                secondaryApp.defaultWindowName, bugId = 172776659)
-                        }
-                    }
-                }
-            }
-
-            return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation,
-                transition, testSpec,
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
                 repetitions = SplitScreenHelper.TEST_REPETITIONS,
-                supportedRotations = listOf(Surface.ROTATION_90, Surface.ROTATION_270))
+                supportedRotations = listOf(Surface.ROTATION_90, Surface.ROTATION_270)
+            )
         }
     }
 }
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt
index bc99c94..d479208 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt
@@ -16,22 +16,19 @@
 
 package com.android.wm.shell.flicker.apppairs
 
-import android.os.Bundle
 import android.os.SystemClock
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.endRotation
-import com.android.server.wm.flicker.helpers.buildTestTag
-import com.android.server.wm.flicker.helpers.isRotated
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
-import com.android.server.wm.flicker.startRotation
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
 import com.android.wm.shell.flicker.appPairsDividerIsVisible
@@ -39,7 +36,9 @@
 import com.android.wm.shell.flicker.appPairsSecondaryBoundsIsVisible
 import com.android.wm.shell.flicker.helpers.AppPairsHelper
 import com.android.wm.shell.flicker.helpers.SplitScreenHelper
+import org.junit.Assume
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -48,70 +47,75 @@
  * Test open apps to app pairs and rotate.
  * To run this test: `atest WMShellFlickerTests:RotateTwoLaunchedAppsRotateAndEnterAppPairsMode`
  */
-@Presubmit
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class RotateTwoLaunchedAppsRotateAndEnterAppPairsMode(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : RotateTwoLaunchedAppsTransition(
-        InstrumentationRegistry.getInstrumentation()) {
+    testSpec: FlickerTestParameter
+) : RotateTwoLaunchedAppsTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = {
+            super.transition(this, it)
+            transitions {
+                this.setRotation(testSpec.config.endRotation)
+                executeShellCommand(
+                    composePairsCommand(primaryTaskId, secondaryTaskId, pair = true))
+                SystemClock.sleep(AppPairsHelper.TIMEOUT_MS)
+            }
+        }
+
+    @Presubmit
+    @Test
+    fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales(Surface.ROTATION_0,
+        testSpec.config.endRotation)
+
+    @Presubmit
+    @Test
+    fun appPairsDividerIsVisible() = testSpec.appPairsDividerIsVisible()
+
+    @Presubmit
+    @Test
+    fun navBarLayerRotatesAndScales() = testSpec.navBarLayerRotatesAndScales(
+        Surface.ROTATION_0, testSpec.config.endRotation)
+
+    @Presubmit
+    @Test
+    override fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    override fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun bothAppWindowsVisible() {
+        testSpec.assertWmEnd {
+            isVisible(primaryApp.defaultWindowName)
+            isVisible(secondaryApp.defaultWindowName)
+        }
+    }
+
+    @FlakyTest(bugId = 172776659)
+    @Test
+    fun appPairsPrimaryBoundsIsVisible() =
+        testSpec.appPairsPrimaryBoundsIsVisible(testSpec.config.endRotation,
+            primaryApp.defaultWindowName)
+
+    @FlakyTest(bugId = 172776659)
+    @Test
+    fun appPairsSecondaryBoundsIsVisible() =
+        testSpec.appPairsSecondaryBoundsIsVisible(testSpec.config.endRotation,
+            secondaryApp.defaultWindowName)
+
+    companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
-                withTestName {
-                    buildTestTag(configuration)
-                }
-                transitions {
-                    this.setRotation(configuration.endRotation)
-                    executeShellCommand(
-                        composePairsCommand(primaryTaskId, secondaryTaskId, pair = true))
-                    SystemClock.sleep(AppPairsHelper.TIMEOUT_MS)
-                }
-                assertions {
-                    val isRotated = configuration.startRotation.isRotated()
-                    presubmit {
-                        layersTrace {
-                            statusBarLayerRotatesScales(Surface.ROTATION_0,
-                                configuration.endRotation)
-                            appPairsDividerIsVisible()
-                            if (!isRotated) {
-                                navBarLayerRotatesAndScales(Surface.ROTATION_0,
-                                    configuration.endRotation)
-                            }
-                        }
-                        windowManagerTrace {
-                            navBarWindowIsAlwaysVisible()
-                            statusBarWindowIsAlwaysVisible()
-                            end("bothAppWindowsVisible") {
-                                isVisible(primaryApp.defaultWindowName)
-                                isVisible(secondaryApp.defaultWindowName)
-                            }
-                        }
-                    }
-                    flaky {
-                        layersTrace {
-                            appPairsPrimaryBoundsIsVisible(configuration.endRotation,
-                                primaryApp.defaultWindowName, 172776659)
-                            appPairsSecondaryBoundsIsVisible(configuration.endRotation,
-                                secondaryApp.defaultWindowName, 172776659)
-
-                            if (isRotated) {
-                                navBarLayerRotatesAndScales(Surface.ROTATION_0,
-                                    configuration.endRotation)
-                            }
-                        }
-                    }
-                }
-            }
-
-            return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation,
-                transition, testSpec,
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
                 repetitions = SplitScreenHelper.TEST_REPETITIONS,
                 supportedRotations = listOf(Surface.ROTATION_90, Surface.ROTATION_270)
             )
         }
     }
-}
\ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsTransition.kt
index 8ea2544..83853e6 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsTransition.kt
@@ -16,21 +16,20 @@
 
 package com.android.wm.shell.flicker.apppairs
 
-import android.app.Instrumentation
-import android.os.Bundle
 import android.view.Surface
+import com.android.server.wm.flicker.FlickerTestParameter
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
 import com.android.wm.shell.flicker.helpers.SplitScreenHelper
 
-open class RotateTwoLaunchedAppsTransition(
-    instrumentation: Instrumentation
-) : AppPairsTransition(instrumentation) {
+abstract class RotateTwoLaunchedAppsTransition(
+    testSpec: FlickerTestParameter
+) : AppPairsTransition(testSpec) {
     override val nonResizeableApp: SplitScreenHelper?
         get() = null
 
-    override val transition: FlickerBuilder.(Bundle) -> Unit
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
         get() = {
             setup {
                 test {
@@ -45,8 +44,8 @@
                 eachRun {
                     executeShellCommand(composePairsCommand(
                         primaryTaskId, secondaryTaskId, pair = false))
-                    primaryApp.exit()
-                    secondaryApp.exit()
+                    primaryApp.exit(wmHelper)
+                    secondaryApp.exit(wmHelper)
                 }
             }
         }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt
index 9f2087f..901b7a3 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt
@@ -18,7 +18,6 @@
 
 import android.app.Instrumentation
 import android.content.ComponentName
-import android.os.SystemClock
 import com.android.wm.shell.flicker.testapp.Components
 
 class SplitScreenHelper(
@@ -27,17 +26,6 @@
     componentsInfo: ComponentName
 ) : BaseAppHelper(instrumentation, activityLabel, componentsInfo) {
 
-    /**
-     * Reopens the first device window from the list of recent apps (overview)
-     */
-    fun reopenAppFromOverview() {
-        val x = uiDevice.displayWidth / 2
-        val y = uiDevice.displayHeight / 2
-        uiDevice.click(x, y)
-        // Wait for animation to complete.
-        SystemClock.sleep(TIMEOUT_MS)
-    }
-
     companion object {
         const val TEST_REPETITIONS = 1
         const val TIMEOUT_MS = 3_000L
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt
index 2c29220..17c51fb 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt
@@ -16,16 +16,15 @@
 
 package com.android.wm.shell.flicker.legacysplitscreen
 
-import android.os.Bundle
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.WALLPAPER_TITLE
 import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.launchSplitScreen
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.startRotation
@@ -36,6 +35,7 @@
 import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible
 import com.android.wm.shell.flicker.helpers.SplitScreenHelper
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -47,56 +47,73 @@
 @Presubmit
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-// @FlakyTest(bugId = 179116910)
 class EnterSplitScreenDockActivity(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) {
+    testSpec: FlickerTestParameter
+) : LegacySplitScreenTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = { configuration ->
+            super.transition(this, configuration)
+            transitions {
+                device.launchSplitScreen(wmHelper)
+            }
+        }
+
+    @FlakyTest(bugId = 169271943)
+    @Test
+    fun dockedStackPrimaryBoundsIsVisible() =
+        testSpec.dockedStackPrimaryBoundsIsVisible(testSpec.config.startRotation,
+            splitScreenApp.defaultWindowName)
+
+    @Presubmit
+    @Test
+    fun dockedStackDividerBecomesVisible() = testSpec.dockedStackDividerBecomesVisible()
+
+    @FlakyTest(bugId = 178531736)
+    @Test
+    // b/178531736
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry(
+            listOf(LAUNCHER_PACKAGE_NAME,
+                WALLPAPER_TITLE, LIVE_WALLPAPER_PACKAGE_NAME,
+                splitScreenApp.defaultWindowName)
+        )
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @FlakyTest(bugId = 178531736)
+    @Test
+    // b/178531736
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry(
+            listOf(LAUNCHER_PACKAGE_NAME,
+                WALLPAPER_TITLE, LIVE_WALLPAPER_PACKAGE_NAME,
+                splitScreenApp.defaultWindowName)
+        )
+
+    @Presubmit
+    @Test
+    fun appWindowIsVisible() {
+        testSpec.assertWmEnd {
+            isVisible(splitScreenApp.defaultWindowName)
+        }
+    }
+
+    companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
-                withTestName {
-                    buildTestTag("testLegacySplitScreenDockActivity", configuration)
-                }
-                repeat { SplitScreenHelper.TEST_REPETITIONS }
-                transitions {
-                    device.launchSplitScreen()
-                }
-                assertions {
-                    layersTrace {
-                        dockedStackPrimaryBoundsIsVisible(
-                            configuration.startRotation,
-                            splitScreenApp.defaultWindowName, bugId = 169271943)
-                        dockedStackDividerBecomesVisible()
-                        visibleLayersShownMoreThanOneConsecutiveEntry(
-                            listOf(LAUNCHER_PACKAGE_NAME,
-                                WALLPAPER_TITLE, LIVE_WALLPAPER_PACKAGE_NAME,
-                                splitScreenApp.defaultWindowName),
-                            bugId = 178531736
-                        )
-                    }
-                    windowManagerTrace {
-                        navBarWindowIsAlwaysVisible()
-                        statusBarWindowIsAlwaysVisible()
-                        visibleWindowsShownMoreThanOneConsecutiveEntry(
-                            listOf(LAUNCHER_PACKAGE_NAME,
-                                WALLPAPER_TITLE, LIVE_WALLPAPER_PACKAGE_NAME,
-                                splitScreenApp.defaultWindowName),
-                            bugId = 178531736
-                        )
-                        end("appWindowIsVisible") {
-                            isVisible(splitScreenApp.defaultWindowName)
-                        }
-                    }
-                }
-            }
-            return FlickerTestRunnerFactory.getInstance().buildTest(
-                instrumentation, defaultTransitionSetup, testSpec,
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
                 repetitions = SplitScreenHelper.TEST_REPETITIONS,
                 supportedRotations = listOf(Surface.ROTATION_0) // bugId = 179116910
             )
         }
     }
-}
\ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt
index 903971e..a94fd46 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt
@@ -16,17 +16,17 @@
 
 package com.android.wm.shell.flicker.legacysplitscreen
 
-import android.os.Bundle
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.appWindowBecomesVisible
 import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.reopenAppFromOverview
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.startRotation
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
@@ -37,6 +37,7 @@
 import com.android.wm.shell.flicker.dockedStackSecondaryBoundsIsVisible
 import com.android.wm.shell.flicker.helpers.SplitScreenHelper
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -45,61 +46,79 @@
  * Test open activity to primary split screen and dock secondary activity to side
  * To run this test: `atest WMShellFlickerTests:EnterSplitScreenLaunchToSide`
  */
-@Presubmit
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class EnterSplitScreenLaunchToSide(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) {
+    testSpec: FlickerTestParameter
+) : LegacySplitScreenTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = { configuration ->
+            super.transition(this, configuration)
+            transitions {
+                device.launchSplitScreen(wmHelper)
+                device.reopenAppFromOverview(wmHelper)
+            }
+        }
+
+    @FlakyTest(bugId = 169271943)
+    @Test
+    fun dockedStackPrimaryBoundsIsVisible() =
+        testSpec.dockedStackPrimaryBoundsIsVisible(testSpec.config.startRotation,
+            splitScreenApp.defaultWindowName)
+
+    @FlakyTest(bugId = 169271943)
+    @Test
+    fun dockedStackSecondaryBoundsIsVisible() =
+        testSpec.dockedStackSecondaryBoundsIsVisible(testSpec.config.startRotation,
+            secondaryApp.defaultWindowName)
+
+    @Presubmit
+    @Test
+    // b/169271943
+    fun dockedStackDividerBecomesVisible() = testSpec.dockedStackDividerBecomesVisible()
+
+    @FlakyTest(bugId = 178447631)
+    @Test
+    // TODO(b/178447631) Remove Splash Screen from white list when flicker lib
+    //                   add a wait for splash screen be gone
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry(
+            listOf(LAUNCHER_PACKAGE_NAME, SPLASH_SCREEN_NAME,
+                splitScreenApp.defaultWindowName,
+                secondaryApp.defaultWindowName)
+        )
+
+    @Presubmit
+    @Test
+    fun appWindowBecomesVisible() = testSpec.appWindowBecomesVisible(secondaryApp.defaultWindowName)
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry(
+            listOf(LAUNCHER_PACKAGE_NAME, SPLASH_SCREEN_NAME,
+                splitScreenApp.defaultWindowName,
+                secondaryApp.defaultWindowName)
+        )
+
+    companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
-                withTestName {
-                    buildTestTag("testLegacySplitScreenLaunchToSide", configuration)
-                }
-                repeat { SplitScreenHelper.TEST_REPETITIONS }
-                transitions {
-                    device.launchSplitScreen()
-                    secondaryApp.reopenAppFromOverview()
-                }
-                assertions {
-                    layersTrace {
-                        dockedStackPrimaryBoundsIsVisible(
-                            configuration.startRotation,
-                            splitScreenApp.defaultWindowName, bugId = 169271943)
-                        dockedStackSecondaryBoundsIsVisible(
-                            configuration.startRotation,
-                            secondaryApp.defaultWindowName, bugId = 169271943)
-                        dockedStackDividerBecomesVisible()
-                        // TODO(b/178447631) Remove Splash Screen from white list when flicker lib
-                        //                   add a wait for splash screen be gone
-                        visibleLayersShownMoreThanOneConsecutiveEntry(
-                            listOf(LAUNCHER_PACKAGE_NAME, SPLASH_SCREEN_NAME,
-                                splitScreenApp.defaultWindowName,
-                                secondaryApp.defaultWindowName),
-                            bugId = 178447631
-                        )
-                    }
-                    windowManagerTrace {
-                        appWindowBecomesVisible(secondaryApp.defaultWindowName)
-                        navBarWindowIsAlwaysVisible()
-                        statusBarWindowIsAlwaysVisible()
-                        visibleWindowsShownMoreThanOneConsecutiveEntry(
-                            listOf(LAUNCHER_PACKAGE_NAME, SPLASH_SCREEN_NAME,
-                                splitScreenApp.defaultWindowName,
-                                secondaryApp.defaultWindowName)
-                        )
-                    }
-                }
-            }
-            return FlickerTestRunnerFactory.getInstance().buildTest(
-                instrumentation, defaultTransitionSetup, testSpec,
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
                 repetitions = SplitScreenHelper.TEST_REPETITIONS,
                 supportedRotations = listOf(Surface.ROTATION_0) // bugId = 175687842
             )
         }
     }
-}
\ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNonResizableNotDock.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNonResizableNotDock.kt
index e361923..238059b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNonResizableNotDock.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNonResizableNotDock.kt
@@ -16,17 +16,14 @@
 
 package com.android.wm.shell.flicker.legacysplitscreen
 
-import android.os.Bundle
-import android.platform.test.annotations.Presubmit
 import android.view.Surface
 import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.WALLPAPER_TITLE
 import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.canSplitScreen
 import com.android.server.wm.flicker.helpers.openQuickstep
 import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
@@ -35,6 +32,7 @@
 import com.android.wm.shell.flicker.helpers.SplitScreenHelper
 import org.junit.Assert
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -43,59 +41,68 @@
  * Test open non-resizable activity will auto exit split screen mode
  * To run this test: `atest WMShellFlickerTests:EnterSplitScreenNonResizableNotDock`
  */
-@Presubmit
 @RequiresDevice
 @RunWith(Parameterized::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FlakyTest(bugId = 173875043)
 class EnterSplitScreenNonResizableNotDock(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) {
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
-                withTestName {
-                    buildTestTag("testLegacySplitScreenNonResizeableActivityNotDock", configuration)
-                }
-                repeat { SplitScreenHelper.TEST_REPETITIONS }
-                transitions {
-                    nonResizeableApp.launchViaIntent(wmHelper)
-                    device.openQuickstep()
-                    if (device.canSplitScreen()) {
-                        Assert.fail("Non-resizeable app should not enter split screen")
-                    }
-                }
-                assertions {
-                    layersTrace {
-                        dockedStackDividerIsInvisible()
-                        visibleLayersShownMoreThanOneConsecutiveEntry(
-                            listOf(LAUNCHER_PACKAGE_NAME,
-                                SPLASH_SCREEN_NAME,
-                                nonResizeableApp.defaultWindowName,
-                                splitScreenApp.defaultWindowName),
-                            bugId = 178447631
-                        )
-                    }
-                    windowManagerTrace {
-                        visibleWindowsShownMoreThanOneConsecutiveEntry(
-                            listOf(WALLPAPER_TITLE,
-                                LAUNCHER_PACKAGE_NAME,
-                                SPLASH_SCREEN_NAME,
-                                nonResizeableApp.defaultWindowName,
-                                splitScreenApp.defaultWindowName)
-                        )
-                        end("appWindowIsVisible") {
-                            isInvisible(nonResizeableApp.defaultWindowName)
-                        }
-                    }
+    testSpec: FlickerTestParameter
+) : LegacySplitScreenTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = { configuration ->
+            super.transition(this, configuration)
+            teardown {
+                eachRun {
+                    nonResizeableApp.exit(wmHelper)
                 }
             }
-            return FlickerTestRunnerFactory.getInstance().buildTest(
-                instrumentation, defaultTransitionSetup, testSpec,
+            transitions {
+                nonResizeableApp.launchViaIntent(wmHelper)
+                device.openQuickstep(wmHelper)
+                if (device.canSplitScreen(wmHelper)) {
+                    Assert.fail("Non-resizeable app should not enter split screen")
+                }
+            }
+        }
+
+    @Test
+    fun dockedStackDividerIsInvisible() = testSpec.dockedStackDividerIsInvisible()
+
+    @FlakyTest(bugId = 178447631)
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry(
+            listOf(LAUNCHER_PACKAGE_NAME,
+                SPLASH_SCREEN_NAME,
+                nonResizeableApp.defaultWindowName,
+                splitScreenApp.defaultWindowName)
+        )
+
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry(
+            listOf(WALLPAPER_TITLE,
+                LAUNCHER_PACKAGE_NAME,
+                SPLASH_SCREEN_NAME,
+                nonResizeableApp.defaultWindowName,
+                splitScreenApp.defaultWindowName)
+        )
+
+    @Test
+    fun appWindowIsVisible() {
+        testSpec.assertWmEnd {
+            isInvisible(nonResizeableApp.defaultWindowName)
+        }
+    }
+
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
                 repetitions = SplitScreenHelper.TEST_REPETITIONS,
-                supportedRotations = listOf(Surface.ROTATION_0 /* bugId = 178685668 */))
+                supportedRotations = listOf(Surface.ROTATION_0)) // b/178685668
         }
     }
 }
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottom.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottom.kt
index 4933665..acd570a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottom.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottom.kt
@@ -16,17 +16,15 @@
 
 package com.android.wm.shell.flicker.legacysplitscreen
 
-import android.os.Bundle
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.appWindowBecomesInVisible
 import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.exitSplitScreenFromBottom
 import com.android.server.wm.flicker.helpers.launchSplitScreen
 import com.android.server.wm.flicker.layerBecomesInvisible
@@ -34,8 +32,10 @@
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.wm.shell.flicker.DOCKED_STACK_DIVIDER
 import com.android.wm.shell.flicker.helpers.SplitScreenHelper
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -44,51 +44,72 @@
  * Test open resizeable activity split in primary, and drag divider to bottom exit split screen
  * To run this test: `atest WMShellFlickerTests:ExitLegacySplitScreenFromBottom`
  */
-@Presubmit
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class ExitLegacySplitScreenFromBottom(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) {
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
-                withTestName {
-                    buildTestTag("testExitLegacySplitScreenFromBottom", configuration)
-                }
-                repeat { SplitScreenHelper.TEST_REPETITIONS }
-                transitions {
-                    device.launchSplitScreen()
-                    device.exitSplitScreenFromBottom()
-                }
-                assertions {
-                    layersTrace {
-                        layerBecomesInvisible(DOCKED_STACK_DIVIDER)
-                        visibleLayersShownMoreThanOneConsecutiveEntry(
-                            listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName,
-                                secondaryApp.defaultWindowName),
-                            bugId = 178447631
-                        )
-                    }
-                    windowManagerTrace {
-                        appWindowBecomesInVisible(secondaryApp.defaultWindowName)
-                        navBarWindowIsAlwaysVisible()
-                        statusBarWindowIsAlwaysVisible()
-                        visibleWindowsShownMoreThanOneConsecutiveEntry(
-                            listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName,
-                                secondaryApp.defaultWindowName),
-                            bugId = 178447631
-                        )
-                    }
+    testSpec: FlickerTestParameter
+) : LegacySplitScreenTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = { configuration ->
+            super.transition(this, configuration)
+            setup {
+                eachRun {
+                    splitScreenApp.launchViaIntent(wmHelper)
+                    device.launchSplitScreen(wmHelper)
                 }
             }
-            return FlickerTestRunnerFactory.getInstance().buildTest(
-                instrumentation, defaultTransitionSetup, testSpec,
+            teardown {
+                eachRun {
+                    splitScreenApp.exit(wmHelper)
+                }
+            }
+            transitions {
+                device.exitSplitScreenFromBottom()
+            }
+        }
+
+    @Presubmit
+    @Test
+    fun layerBecomesInvisible() = testSpec.layerBecomesInvisible(DOCKED_STACK_DIVIDER)
+
+    @FlakyTest(bugId = 178447631)
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry(
+            listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName,
+                secondaryApp.defaultWindowName)
+        )
+
+    @Presubmit
+    @Test
+    fun appWindowBecomesInVisible() =
+        testSpec.appWindowBecomesInVisible(secondaryApp.defaultWindowName)
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @FlakyTest(bugId = 178447631)
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry(
+            listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName,
+                secondaryApp.defaultWindowName)
+        )
+
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
                 repetitions = SplitScreenHelper.TEST_REPETITIONS,
-                supportedRotations = listOf(Surface.ROTATION_0) // bugId = 175687842
+                supportedRotations = listOf(Surface.ROTATION_0) // b/175687842
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitPrimarySplitScreenShowSecondaryFullscreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitPrimarySplitScreenShowSecondaryFullscreen.kt
index ff3a979..cef1886 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitPrimarySplitScreenShowSecondaryFullscreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitPrimarySplitScreenShowSecondaryFullscreen.kt
@@ -16,16 +16,17 @@
 
 package com.android.wm.shell.flicker.legacysplitscreen
 
-import android.os.Bundle
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.appWindowBecomesInVisible
 import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.reopenAppFromOverview
 import com.android.server.wm.flicker.layerBecomesInvisible
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
@@ -34,6 +35,7 @@
 import com.android.wm.shell.flicker.dockedStackDividerIsInvisible
 import com.android.wm.shell.flicker.helpers.SplitScreenHelper
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -45,49 +47,71 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class ExitPrimarySplitScreenShowSecondaryFullscreen(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) {
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
-                withTestName {
-                    buildTestTag("testExitPrimarySplitScreenShowSecondaryFullscreen", configuration)
-                }
-                repeat { SplitScreenHelper.TEST_REPETITIONS }
-                transitions {
-                    device.launchSplitScreen()
-                    secondaryApp.reopenAppFromOverview()
-                    // TODO(b/175687842) Can not find Split screen divider, use exit() instead
-                    splitScreenApp.exit()
-                }
-                assertions {
-                    layersTrace {
-                        dockedStackDividerIsInvisible(bugId = 175687842)
-                        layerBecomesInvisible(splitScreenApp.defaultWindowName)
-                        visibleLayersShownMoreThanOneConsecutiveEntry(
-                            listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName,
-                                secondaryApp.defaultWindowName),
-                            bugId = 178447631
-                        )
-                    }
-                    windowManagerTrace {
-                        appWindowBecomesInVisible(splitScreenApp.defaultWindowName)
-                        navBarWindowIsAlwaysVisible()
-                        statusBarWindowIsAlwaysVisible()
-                        visibleWindowsShownMoreThanOneConsecutiveEntry(
-                            listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName,
-                                secondaryApp.defaultWindowName),
-                            bugId = 178447631
-                        )
-                    }
+    testSpec: FlickerTestParameter
+) : LegacySplitScreenTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = { configuration ->
+            super.transition(this, configuration)
+            teardown {
+                eachRun {
+                    secondaryApp.exit(wmHelper)
                 }
             }
-            return FlickerTestRunnerFactory.getInstance().buildTest(
-                instrumentation, defaultTransitionSetup, testSpec,
+            transitions {
+                splitScreenApp.launchViaIntent(wmHelper)
+                secondaryApp.launchViaIntent(wmHelper)
+                device.launchSplitScreen(wmHelper)
+                device.reopenAppFromOverview(wmHelper)
+                // TODO(b/175687842) Can not find Split screen divider, use exit() instead
+                splitScreenApp.exit(wmHelper)
+            }
+        }
+
+    @FlakyTest(bugId = 175687842)
+    @Test
+    fun dockedStackDividerIsInvisible() = testSpec.dockedStackDividerIsInvisible()
+
+    @Presubmit
+    @Test
+    fun layerBecomesInvisible() = testSpec.layerBecomesInvisible(splitScreenApp.defaultWindowName)
+
+    @FlakyTest(bugId = 178447631)
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry(
+            listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName,
+                secondaryApp.defaultWindowName)
+        )
+
+    @Presubmit
+    @Test
+    fun appWindowBecomesInVisible() =
+        testSpec.appWindowBecomesInVisible(splitScreenApp.defaultWindowName)
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @FlakyTest(bugId = 178447631)
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry(
+            listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName,
+                secondaryApp.defaultWindowName)
+        )
+
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
                 repetitions = SplitScreenHelper.TEST_REPETITIONS,
                 supportedRotations = listOf(Surface.ROTATION_0) // bugId = 179116910
             )
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenRotateTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenRotateTransition.kt
new file mode 100644
index 0000000..1e89a25
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenRotateTransition.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.legacysplitscreen
+
+import android.view.Surface
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.openQuickStepAndClearRecentAppsFromOverview
+import com.android.server.wm.flicker.helpers.setRotation
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+
+abstract class LegacySplitScreenRotateTransition(
+    testSpec: FlickerTestParameter
+) : LegacySplitScreenTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = {
+            setup {
+                eachRun {
+                    device.wakeUpAndGoToHomeScreen()
+                    device.openQuickStepAndClearRecentAppsFromOverview(wmHelper)
+                    secondaryApp.launchViaIntent(wmHelper)
+                    splitScreenApp.launchViaIntent(wmHelper)
+                }
+            }
+            teardown {
+                eachRun {
+                    splitScreenApp.exit(wmHelper)
+                    secondaryApp.exit(wmHelper)
+                    this.setRotation(Surface.ROTATION_0)
+                }
+            }
+        }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt
index 03b6edf..7f69a66 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt
@@ -19,15 +19,15 @@
 import android.platform.test.annotations.Presubmit
 import android.support.test.launcherhelper.LauncherStrategyFactory
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.endRotation
 import com.android.server.wm.flicker.focusDoesNotChange
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.exitSplitScreen
-import com.android.server.wm.flicker.helpers.isInSplitScreen
 import com.android.server.wm.flicker.helpers.launchSplitScreen
 import com.android.server.wm.flicker.helpers.openQuickStepAndClearRecentAppsFromOverview
 import com.android.server.wm.flicker.helpers.setRotation
@@ -39,13 +39,13 @@
 import com.android.server.wm.flicker.layerBecomesInvisible
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.noUncoveredRegions
-import com.android.server.wm.flicker.repetitions
 import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
 import com.android.wm.shell.flicker.dockedStackDividerBecomesInvisible
 import com.android.wm.shell.flicker.helpers.SimpleAppHelper
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -54,81 +54,100 @@
  * Test open app to split screen.
  * To run this test: `atest WMShellFlickerTests:LegacySplitScreenToLauncher`
  */
-@Presubmit
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class LegacySplitScreenToLauncher(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
+    testSpec: FlickerTestParameter
+) : LegacySplitScreenTransition(testSpec) {
+    private val launcherPackageName = LauncherStrategyFactory.getInstance(instrumentation)
+        .launcherStrategy.supportedLauncherPackage
+    private val testApp = SimpleAppHelper(instrumentation)
+
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = { configuration ->
+            setup {
+                test {
+                    device.wakeUpAndGoToHomeScreen()
+                    device.openQuickStepAndClearRecentAppsFromOverview(wmHelper)
+                }
+                eachRun {
+                    testApp.launchViaIntent(wmHelper)
+                    this.setRotation(configuration.endRotation)
+                    device.launchSplitScreen(wmHelper)
+                    device.waitForIdle()
+                }
+            }
+            teardown {
+                eachRun {
+                    testApp.exit(wmHelper)
+                }
+            }
+            transitions {
+                device.exitSplitScreen()
+            }
+        }
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry()
+
+    @Presubmit
+    @Test
+    fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun noUncoveredRegions() = testSpec.noUncoveredRegions(testSpec.config.endRotation)
+
+    @Presubmit
+    @Test
+    fun navBarLayerRotatesAndScales() =
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.endRotation)
+
+    @Presubmit
+    @Test
+    fun statusBarLayerRotatesScales() =
+        testSpec.statusBarLayerRotatesScales(testSpec.config.endRotation)
+
+    @Presubmit
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry(listOf(launcherPackageName))
+
+    @Presubmit
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun dockedStackDividerBecomesInvisible() = testSpec.dockedStackDividerBecomesInvisible()
+
+    @Presubmit
+    @Test
+    fun layerBecomesInvisible() = testSpec.layerBecomesInvisible(testApp.getPackage())
+
+    @FlakyTest(bugId = 151179149)
+    @Test
+    fun focusDoesNotChange() = testSpec.focusDoesNotChange()
+
     companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val instrumentation = InstrumentationRegistry.getInstrumentation()
-            val launcherPackageName = LauncherStrategyFactory.getInstance(instrumentation)
-                .launcherStrategy.supportedLauncherPackage
-            val testApp = SimpleAppHelper(instrumentation)
-
+        fun getParams(): Collection<FlickerTestParameter> {
             // b/161435597 causes the test not to work on 90 degrees
-            return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation,
-                supportedRotations = listOf(Surface.ROTATION_0)) { configuration ->
-                withTestName {
-                    buildTestTag("splitScreenToLauncher", configuration)
-                }
-                repeat { configuration.repetitions }
-                setup {
-                    test {
-                        device.wakeUpAndGoToHomeScreen()
-                        device.openQuickStepAndClearRecentAppsFromOverview()
-                    }
-                    eachRun {
-                        testApp.launchViaIntent(wmHelper)
-                        this.setRotation(configuration.endRotation)
-                        device.launchSplitScreen()
-                        device.waitForIdle()
-                    }
-                }
-                teardown {
-                    eachRun {
-                        testApp.exit()
-                    }
-                    test {
-                        if (device.isInSplitScreen()) {
-                            device.exitSplitScreen()
-                        }
-                    }
-                }
-                transitions {
-                    device.exitSplitScreen()
-                }
-                assertions {
-                    windowManagerTrace {
-                        navBarWindowIsAlwaysVisible()
-                        statusBarWindowIsAlwaysVisible()
-                        visibleWindowsShownMoreThanOneConsecutiveEntry()
-                    }
-
-                    layersTrace {
-                        navBarLayerIsAlwaysVisible()
-                        statusBarLayerIsAlwaysVisible()
-                        noUncoveredRegions(configuration.endRotation)
-                        navBarLayerRotatesAndScales(configuration.endRotation)
-                        statusBarLayerRotatesScales(configuration.endRotation)
-                        visibleLayersShownMoreThanOneConsecutiveEntry(
-                            listOf(launcherPackageName))
-
-                        // b/161435597 causes the test not to work on 90 degrees
-                        dockedStackDividerBecomesInvisible()
-
-                        layerBecomesInvisible(testApp.getPackage())
-                    }
-
-                    eventLog {
-                        focusDoesNotChange(bugId = 151179149)
-                    }
-                }
-            }
+            return FlickerTestParameterFactory.getInstance()
+                .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0))
         }
     }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenTransition.kt
index 328ff88..91ea871 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenTransition.kt
@@ -17,36 +17,35 @@
 package com.android.wm.shell.flicker.legacysplitscreen
 
 import android.app.Instrumentation
-import android.os.Bundle
 import android.support.test.launcherhelper.LauncherStrategyFactory
 import android.view.Surface
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.server.wm.flicker.FlickerBuilderProvider
+import com.android.server.wm.flicker.FlickerTestParameter
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isRotated
 import com.android.server.wm.flicker.helpers.openQuickStepAndClearRecentAppsFromOverview
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.repetitions
 import com.android.server.wm.flicker.startRotation
 import com.android.wm.shell.flicker.helpers.SplitScreenHelper
 
-abstract class LegacySplitScreenTransition(
-    protected val instrumentation: Instrumentation
-) {
-    internal val splitScreenApp = SplitScreenHelper.getPrimary(instrumentation)
-    internal val secondaryApp = SplitScreenHelper.getSecondary(instrumentation)
-    internal val nonResizeableApp = SplitScreenHelper.getNonResizeable(instrumentation)
-    internal val LAUNCHER_PACKAGE_NAME = LauncherStrategyFactory.getInstance(instrumentation)
+abstract class LegacySplitScreenTransition(protected val testSpec: FlickerTestParameter) {
+    protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    protected val isRotated = testSpec.config.startRotation.isRotated()
+    protected val splitScreenApp = SplitScreenHelper.getPrimary(instrumentation)
+    protected val secondaryApp = SplitScreenHelper.getSecondary(instrumentation)
+    protected val nonResizeableApp = SplitScreenHelper.getNonResizeable(instrumentation)
+    protected val LAUNCHER_PACKAGE_NAME = LauncherStrategyFactory.getInstance(instrumentation)
         .launcherStrategy.supportedLauncherPackage
-    internal val LIVE_WALLPAPER_PACKAGE_NAME =
-        "com.breel.wallpapers18.soundviz.wallpaper.variations.SoundVizWallpaperV2"
-    internal val LETTERBOX_NAME = "Letterbox"
-    internal val TOAST_NAME = "Toast"
-    internal val SPLASH_SCREEN_NAME = "Splash Screen"
 
-    internal open val defaultTransitionSetup: FlickerBuilder.(Bundle) -> Unit
+    protected open val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
         get() = { configuration ->
             setup {
                 eachRun {
                     device.wakeUpAndGoToHomeScreen()
-                    device.openQuickStepAndClearRecentAppsFromOverview()
+                    device.openQuickStepAndClearRecentAppsFromOverview(wmHelper)
                     secondaryApp.launchViaIntent(wmHelper)
                     splitScreenApp.launchViaIntent(wmHelper)
                     this.setRotation(configuration.startRotation)
@@ -54,46 +53,46 @@
             }
             teardown {
                 eachRun {
-                    splitScreenApp.exit()
-                    secondaryApp.exit()
+                    secondaryApp.exit(wmHelper)
+                    splitScreenApp.exit(wmHelper)
                     this.setRotation(Surface.ROTATION_0)
                 }
             }
         }
 
-    internal open val cleanSetup: FlickerBuilder.(Bundle) -> Unit
+    @FlickerBuilderProvider
+    fun buildFlicker(): FlickerBuilder {
+        return FlickerBuilder(instrumentation).apply {
+            withTestName { testSpec.name }
+            repeat { testSpec.config.repetitions }
+            transition(this, testSpec.config)
+        }
+    }
+
+    internal open val cleanSetup: FlickerBuilder.(Map<String, Any?>) -> Unit
         get() = { configuration ->
             setup {
                 eachRun {
                     device.wakeUpAndGoToHomeScreen()
-                    device.openQuickStepAndClearRecentAppsFromOverview()
+                    device.openQuickStepAndClearRecentAppsFromOverview(wmHelper)
                     this.setRotation(configuration.startRotation)
                 }
             }
             teardown {
                 eachRun {
-                    nonResizeableApp.exit()
+                    nonResizeableApp.exit(wmHelper)
+                    splitScreenApp.exit(wmHelper)
+                    device.pressHome()
                     this.setRotation(Surface.ROTATION_0)
                 }
             }
         }
 
-    internal open val customRotateSetup: FlickerBuilder.(Bundle) -> Unit
-        get() = { configuration ->
-            setup {
-                eachRun {
-                    device.wakeUpAndGoToHomeScreen()
-                    device.openQuickStepAndClearRecentAppsFromOverview()
-                    secondaryApp.launchViaIntent(wmHelper)
-                    splitScreenApp.launchViaIntent(wmHelper)
-                }
-            }
-            teardown {
-                eachRun {
-                    splitScreenApp.exit()
-                    secondaryApp.exit()
-                    this.setRotation(Surface.ROTATION_0)
-                }
-            }
-        }
+    companion object {
+        internal const val LIVE_WALLPAPER_PACKAGE_NAME =
+            "com.breel.wallpapers18.soundviz.wallpaper.variations.SoundVizWallpaperV2"
+        internal const val LETTERBOX_NAME = "Letterbox"
+        internal const val TOAST_NAME = "Toast"
+        internal const val SPLASH_SCREEN_NAME = "Splash Screen"
+    }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableDismissInLegacySplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableDismissInLegacySplitScreen.kt
index f2a7cda..caafa27 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableDismissInLegacySplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableDismissInLegacySplitScreen.kt
@@ -16,25 +16,26 @@
 
 package com.android.wm.shell.flicker.legacysplitscreen
 
-import android.os.Bundle
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.appWindowBecomesInVisible
 import com.android.server.wm.flicker.appWindowBecomesVisible
 import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.reopenAppFromOverview
 import com.android.server.wm.flicker.layerBecomesInvisible
 import com.android.server.wm.flicker.layerBecomesVisible
 import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.wm.shell.flicker.DOCKED_STACK_DIVIDER
 import com.android.wm.shell.flicker.helpers.SplitScreenHelper
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -44,58 +45,73 @@
  * (Non resizable activity launch via recent overview)
  * To run this test: `atest WMShellFlickerTests:NonResizableDismissInLegacySplitScreen`
  */
-@Presubmit
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class NonResizableDismissInLegacySplitScreen(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) {
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
-                withTestName {
-                    buildTestTag("testNonResizableDismissInLegacySplitScreen", configuration)
-                }
-                repeat { SplitScreenHelper.TEST_REPETITIONS }
-                transitions {
+    testSpec: FlickerTestParameter
+) : LegacySplitScreenTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = { configuration ->
+            cleanSetup(this, configuration)
+            setup {
+                eachRun {
                     nonResizeableApp.launchViaIntent(wmHelper)
                     splitScreenApp.launchViaIntent(wmHelper)
-                    device.launchSplitScreen()
-                    nonResizeableApp.reopenAppFromOverview()
-                    wmHelper.waitForAppTransitionIdle()
-                }
-                assertions {
-                    layersTrace {
-                        layerBecomesVisible(nonResizeableApp.defaultWindowName)
-                        layerBecomesInvisible(splitScreenApp.defaultWindowName)
-                        visibleLayersShownMoreThanOneConsecutiveEntry(
-                            listOf(DOCKED_STACK_DIVIDER, LAUNCHER_PACKAGE_NAME,
-                                LETTERBOX_NAME, TOAST_NAME,
-                                splitScreenApp.defaultWindowName,
-                                nonResizeableApp.defaultWindowName),
-                            bugId = 178447631
-                        )
-                    }
-                    windowManagerTrace {
-                        appWindowBecomesVisible(nonResizeableApp.defaultWindowName)
-                        appWindowBecomesInVisible(splitScreenApp.defaultWindowName)
-                        visibleWindowsShownMoreThanOneConsecutiveEntry(
-                            listOf(DOCKED_STACK_DIVIDER, LAUNCHER_PACKAGE_NAME,
-                                LETTERBOX_NAME, TOAST_NAME,
-                                splitScreenApp.defaultWindowName,
-                                nonResizeableApp.defaultWindowName),
-                            bugId = 178447631
-                        )
-                    }
+                    device.launchSplitScreen(wmHelper)
                 }
             }
-            return FlickerTestRunnerFactory.getInstance().buildTest(
-                instrumentation, cleanSetup, testSpec,
+            transitions {
+                device.reopenAppFromOverview(wmHelper)
+            }
+        }
+
+    @Presubmit
+    @Test
+    fun layerBecomesInvisible() = testSpec.layerBecomesInvisible(splitScreenApp.defaultWindowName)
+
+    @FlakyTest(bugId = 178447631)
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry(
+            listOf(DOCKED_STACK_DIVIDER, LAUNCHER_PACKAGE_NAME,
+                LETTERBOX_NAME, TOAST_NAME,
+                splitScreenApp.defaultWindowName,
+                nonResizeableApp.defaultWindowName)
+        )
+
+    @Presubmit
+    @Test
+    fun layerBecomesVisible() = testSpec.layerBecomesVisible(nonResizeableApp.defaultWindowName)
+
+    @Presubmit
+    @Test
+    fun appWindowBecomesVisible() =
+        testSpec.appWindowBecomesVisible(nonResizeableApp.defaultWindowName)
+
+    @Presubmit
+    @Test
+    fun appWindowBecomesInVisible() =
+        testSpec.appWindowBecomesInVisible(splitScreenApp.defaultWindowName)
+
+    @FlakyTest(bugId = 178447631)
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry(
+            listOf(DOCKED_STACK_DIVIDER, LAUNCHER_PACKAGE_NAME,
+                LETTERBOX_NAME, TOAST_NAME,
+                splitScreenApp.defaultWindowName,
+                nonResizeableApp.defaultWindowName)
+        )
+
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
                 repetitions = SplitScreenHelper.TEST_REPETITIONS,
-                supportedRotations = listOf(Surface.ROTATION_0 /* bugId = 178685668 */))
+                supportedRotations = listOf(Surface.ROTATION_0)) // b/178685668
         }
     }
-}
\ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableLaunchInLegacySplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableLaunchInLegacySplitScreen.kt
index 421ecff..543484a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableLaunchInLegacySplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableLaunchInLegacySplitScreen.kt
@@ -16,25 +16,25 @@
 
 package com.android.wm.shell.flicker.legacysplitscreen
 
-import android.os.Bundle
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.appWindowBecomesInVisible
 import com.android.server.wm.flicker.appWindowBecomesVisible
 import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.launchSplitScreen
 import com.android.server.wm.flicker.layerBecomesInvisible
 import com.android.server.wm.flicker.layerBecomesVisible
 import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.wm.shell.flicker.DOCKED_STACK_DIVIDER
 import com.android.wm.shell.flicker.helpers.SplitScreenHelper
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -47,56 +47,73 @@
 @Presubmit
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class NonResizableLaunchInLegacySplitScreen(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) {
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
-                withTestName {
-                    buildTestTag("testNonResizableLaunchInLegacySplitScreen", configuration)
-                }
-                repeat { SplitScreenHelper.TEST_REPETITIONS }
-                transitions {
+    testSpec: FlickerTestParameter
+) : LegacySplitScreenTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = { configuration ->
+            cleanSetup(this, configuration)
+            setup {
+                eachRun {
                     splitScreenApp.launchViaIntent(wmHelper)
-                    device.launchSplitScreen()
-                    nonResizeableApp.launchViaIntent(wmHelper)
-                    wmHelper.waitForAppTransitionIdle()
-                }
-                assertions {
-                    layersTrace {
-                        layerBecomesVisible(nonResizeableApp.defaultWindowName)
-                        layerBecomesInvisible(splitScreenApp.defaultWindowName)
-                        visibleLayersShownMoreThanOneConsecutiveEntry(
-                                listOf(DOCKED_STACK_DIVIDER,
-                                        LAUNCHER_PACKAGE_NAME,
-                                        LETTERBOX_NAME,
-                                        nonResizeableApp.defaultWindowName,
-                                        splitScreenApp.defaultWindowName),
-                            bugId = 178447631
-                        )
-                    }
-                    windowManagerTrace {
-                        appWindowBecomesVisible(nonResizeableApp.defaultWindowName)
-                        appWindowBecomesInVisible(splitScreenApp.defaultWindowName)
-                        visibleWindowsShownMoreThanOneConsecutiveEntry(
-                                listOf(DOCKED_STACK_DIVIDER,
-                                        LAUNCHER_PACKAGE_NAME,
-                                        LETTERBOX_NAME,
-                                        nonResizeableApp.defaultWindowName,
-                                        splitScreenApp.defaultWindowName),
-                            bugId = 178447631
-                        )
-                    }
+                    device.launchSplitScreen(wmHelper)
                 }
             }
-            return FlickerTestRunnerFactory.getInstance().buildTest(
-                instrumentation, cleanSetup, testSpec,
+            transitions {
+                nonResizeableApp.launchViaIntent(wmHelper)
+                wmHelper.waitForAppTransitionIdle()
+            }
+        }
+
+    @Presubmit
+    @Test
+    fun layerBecomesVisible() = testSpec.layerBecomesVisible(nonResizeableApp.defaultWindowName)
+
+    @Presubmit
+    @Test
+    fun layerBecomesInvisible() = testSpec.layerBecomesInvisible(splitScreenApp.defaultWindowName)
+
+    @FlakyTest(bugId = 178447631)
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry(
+            listOf(DOCKED_STACK_DIVIDER,
+                LAUNCHER_PACKAGE_NAME,
+                LETTERBOX_NAME,
+                nonResizeableApp.defaultWindowName,
+                splitScreenApp.defaultWindowName)
+        )
+
+    @Presubmit
+    @Test
+    fun appWindowBecomesVisible() =
+        testSpec.appWindowBecomesVisible(nonResizeableApp.defaultWindowName)
+
+    @Presubmit
+    @Test
+    fun appWindowBecomesInVisible() =
+        testSpec.appWindowBecomesInVisible(splitScreenApp.defaultWindowName)
+
+    @FlakyTest(bugId = 178447631)
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry(
+            listOf(DOCKED_STACK_DIVIDER,
+                LAUNCHER_PACKAGE_NAME,
+                LETTERBOX_NAME,
+                nonResizeableApp.defaultWindowName,
+                splitScreenApp.defaultWindowName)
+        )
+
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
                 repetitions = SplitScreenHelper.TEST_REPETITIONS,
-                supportedRotations = listOf(Surface.ROTATION_0 /* bugId = 178685668 */))
+                supportedRotations = listOf(Surface.ROTATION_0)) // b/178685668
         }
     }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreen.kt
index 7edef93..d228337 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreen.kt
@@ -16,17 +16,16 @@
 
 package com.android.wm.shell.flicker.legacysplitscreen
 
-import android.os.Bundle
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.appWindowBecomesVisible
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.focusChanges
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.launchSplitScreen
 import com.android.server.wm.flicker.layerBecomesVisible
 import com.android.server.wm.flicker.noUncoveredRegions
@@ -34,10 +33,10 @@
 import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 import com.android.wm.shell.flicker.appPairsDividerBecomesVisible
 import com.android.wm.shell.flicker.helpers.SplitScreenHelper
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -46,54 +45,66 @@
  * Test open app to split screen.
  * To run this test: `atest WMShellFlickerTests:OpenAppToLegacySplitScreen`
  */
-@Presubmit
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class OpenAppToLegacySplitScreen(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) {
+    testSpec: FlickerTestParameter
+) : LegacySplitScreenTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = { configuration ->
+            super.transition(this, configuration)
+            transitions {
+                device.launchSplitScreen(wmHelper)
+                wmHelper.waitForAppTransitionIdle()
+            }
+        }
+
+    @FlakyTest(bugId = 178447631)
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry(
+            listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName)
+        )
+
+    @Presubmit
+    @Test
+    fun appWindowBecomesVisible() = testSpec.appWindowBecomesVisible(splitScreenApp.getPackage())
+
+    @FlakyTest
+    @Test
+    fun noUncoveredRegions() = testSpec.noUncoveredRegions(testSpec.config.startRotation)
+
+    @Presubmit
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun appPairsDividerBecomesVisible() = testSpec.appPairsDividerBecomesVisible()
+
+    @Presubmit
+    @Test
+    fun layerBecomesVisible() = testSpec.layerBecomesVisible(splitScreenApp.getPackage())
+
+    @FlakyTest(bugId = 178447631)
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry(
+            listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName)
+        )
+
+    @FlakyTest(bugId = 151179149)
+    @Test
+    fun focusChanges() = testSpec.focusChanges(splitScreenApp.`package`,
+        "recents_animation_input_consumer", "NexusLauncherActivity")
+
+    companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val wmHelper = WindowManagerStateHelper()
-            val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
-                withTestName {
-                    buildTestTag("testOpenAppToLegacySplitScreen", configuration)
-                }
-                repeat { SplitScreenHelper.TEST_REPETITIONS }
-                transitions {
-                    device.launchSplitScreen()
-                    wmHelper.waitForAppTransitionIdle()
-                }
-                assertions {
-                    windowManagerTrace {
-                        visibleWindowsShownMoreThanOneConsecutiveEntry(
-                            listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName),
-                            bugId = 178447631)
-                        appWindowBecomesVisible(splitScreenApp.getPackage())
-                    }
-
-                    layersTrace {
-                        noUncoveredRegions(configuration.startRotation, enabled = false)
-                        statusBarLayerIsAlwaysVisible()
-                        appPairsDividerBecomesVisible()
-                        layerBecomesVisible(splitScreenApp.getPackage())
-                        visibleLayersShownMoreThanOneConsecutiveEntry(
-                            listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName),
-                            bugId = 178447631)
-                    }
-
-                    eventLog {
-                        focusChanges(splitScreenApp.`package`,
-                            "recents_animation_input_consumer", "NexusLauncherActivity",
-                            bugId = 151179149)
-                    }
-                }
-            }
-            return FlickerTestRunnerFactory.getInstance().buildTest(
-                instrumentation, defaultTransitionSetup, testSpec,
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
                 repetitions = SplitScreenHelper.TEST_REPETITIONS,
                 supportedRotations = listOf(Surface.ROTATION_0) // bugId = 179116910
             )
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt
index 54a37d7..f5174bc 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt
@@ -16,24 +16,19 @@
 
 package com.android.wm.shell.flicker.legacysplitscreen
 
-import android.platform.test.annotations.Presubmit
 import android.graphics.Region
 import android.util.Rational
 import android.view.Surface
 import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
 import androidx.test.uiautomator.By
-import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.endRotation
 import com.android.server.wm.flicker.helpers.ImeAppHelper
-import com.android.server.wm.flicker.focusDoesNotChange
 import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.helpers.buildTestTag
-import com.android.server.wm.flicker.helpers.exitSplitScreen
-import com.android.server.wm.flicker.helpers.isInSplitScreen
 import com.android.server.wm.flicker.helpers.launchSplitScreen
 import com.android.server.wm.flicker.helpers.resizeSplitScreen
 import com.android.server.wm.flicker.helpers.setRotation
@@ -42,7 +37,6 @@
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.noUncoveredRegions
-import com.android.server.wm.flicker.repetitions
 import com.android.server.wm.flicker.startRotation
 import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
@@ -50,8 +44,10 @@
 import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.traces.layers.getVisibleBounds
+import com.android.wm.shell.flicker.DOCKED_STACK_DIVIDER
 import com.android.wm.shell.flicker.helpers.SimpleAppHelper
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -62,14 +58,162 @@
  *
  * Currently it runs only in 0 degrees because of b/156100803
  */
-@Presubmit
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 @FlakyTest(bugId = 159096424)
 class ResizeLegacySplitScreen(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
+    testSpec: FlickerTestParameter
+) : LegacySplitScreenTransition(testSpec) {
+    private val testAppTop = SimpleAppHelper(instrumentation)
+    private val testAppBottom = ImeAppHelper(instrumentation)
+
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = { configuration ->
+            setup {
+                eachRun {
+                    device.wakeUpAndGoToHomeScreen()
+                    this.setRotation(configuration.startRotation)
+                    this.launcherStrategy.clearRecentAppsFromOverview()
+                    testAppBottom.launchViaIntent(wmHelper)
+                    device.pressHome()
+                    testAppTop.launchViaIntent(wmHelper)
+                    device.waitForIdle()
+                    device.launchSplitScreen(wmHelper)
+                    val snapshot =
+                        device.findObject(By.res(device.launcherPackageName, "snapshot"))
+                    snapshot.click()
+                    testAppBottom.openIME(device)
+                    device.pressBack()
+                    device.resizeSplitScreen(startRatio)
+                }
+            }
+            teardown {
+                eachRun {
+                    testAppTop.exit(wmHelper)
+                    testAppBottom.exit(wmHelper)
+                }
+            }
+            transitions {
+                device.resizeSplitScreen(stopRatio)
+            }
+        }
+
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry()
+
+    @FlakyTest(bugId = 156223549)
+    @Test
+    fun topAppWindowIsAlwaysVisible() {
+        testSpec.assertWm {
+            this.showsAppWindow(sSimpleActivity)
+        }
+    }
+
+    @FlakyTest(bugId = 156223549)
+    @Test
+    fun bottomAppWindowIsAlwaysVisible() {
+        testSpec.assertWm {
+            this.showsAppWindow(sImeActivity)
+        }
+    }
+
+    @Test
+    fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    @Test
+    fun noUncoveredRegions() = testSpec.noUncoveredRegions(testSpec.config.endRotation)
+
+    @Test
+    fun navBarLayerRotatesAndScales() =
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.endRotation)
+
+    @Test
+    fun statusBarLayerRotatesScales() =
+        testSpec.statusBarLayerRotatesScales(testSpec.config.endRotation)
+
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry()
+
+    @Test
+    fun topAppLayerIsAlwaysVisible() {
+        testSpec.assertLayers {
+            this.isVisible(sSimpleActivity)
+        }
+    }
+
+    @Test
+    fun bottomAppLayerIsAlwaysVisible() {
+        testSpec.assertLayers {
+            this.isVisible(sImeActivity)
+        }
+    }
+
+    @Test
+    fun dividerLayerIsAlwaysVisible() {
+        testSpec.assertLayers {
+            this.isVisible(DOCKED_STACK_DIVIDER)
+        }
+    }
+
+    @FlakyTest
+    @Test
+    fun appsStartingBounds() {
+        testSpec.assertLayersStart {
+            val displayBounds = WindowUtils.displayBounds
+            val dividerBounds =
+                entry.getVisibleBounds(DOCKED_STACK_DIVIDER).bounds
+
+            val topAppBounds = Region(0, 0, dividerBounds.right,
+                dividerBounds.top + WindowUtils.dockedStackDividerInset)
+            val bottomAppBounds = Region(0,
+                dividerBounds.bottom - WindowUtils.dockedStackDividerInset,
+                displayBounds.right,
+                displayBounds.bottom - WindowUtils.navigationBarHeight)
+            this.coversExactly(topAppBounds, "SimpleActivity")
+                .coversExactly(bottomAppBounds, "ImeActivity")
+        }
+    }
+
+    @FlakyTest
+    @Test
+    fun appsEndingBounds() {
+        testSpec.assertLayersStart {
+            val displayBounds = WindowUtils.displayBounds
+            val dividerBounds =
+                entry.getVisibleBounds(DOCKED_STACK_DIVIDER).bounds
+
+            val topAppBounds = Region(0, 0, dividerBounds.right,
+                dividerBounds.top + WindowUtils.dockedStackDividerInset)
+            val bottomAppBounds = Region(0,
+                dividerBounds.bottom - WindowUtils.dockedStackDividerInset,
+                displayBounds.right,
+                displayBounds.bottom - WindowUtils.navigationBarHeight)
+
+            this.coversExactly(topAppBounds, sSimpleActivity)
+                .coversExactly(bottomAppBounds, sImeActivity)
+        }
+    }
+
+    @Test
+    fun focusDoesNotChange() {
+        testSpec.assertEventLog {
+            focusDoesNotChange()
+        }
+    }
+
     companion object {
         private const val sSimpleActivity = "SimpleActivity"
         private const val sImeActivity = "ImeActivity"
@@ -78,126 +222,14 @@
 
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val instrumentation = InstrumentationRegistry.getInstrumentation()
-            val testAppTop = SimpleAppHelper(instrumentation)
-            val testAppBottom = ImeAppHelper(instrumentation)
-
-            return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation,
-                supportedRotations = listOf(Surface.ROTATION_0)) { configuration ->
-                    withTestName {
-                        val description = (startRatio.toString().replace("/", "-") + "_to_" +
-                            stopRatio.toString().replace("/", "-"))
-                        buildTestTag("resizeSplitScreen", configuration, description)
-                    }
-                    repeat { configuration.repetitions }
-                    setup {
-                        eachRun {
-                            device.wakeUpAndGoToHomeScreen()
-                            this.setRotation(configuration.startRotation)
-                            this.launcherStrategy.clearRecentAppsFromOverview()
-                            testAppBottom.launchViaIntent(wmHelper)
-                            device.pressHome()
-                            testAppTop.launchViaIntent(wmHelper)
-                            device.waitForIdle()
-                            device.launchSplitScreen()
-                            val snapshot =
-                                device.findObject(By.res(device.launcherPackageName, "snapshot"))
-                            snapshot.click()
-                            testAppBottom.openIME(device)
-                            device.pressBack()
-                            device.resizeSplitScreen(startRatio)
-                        }
-                    }
-                    teardown {
-                        eachRun {
-                            if (device.isInSplitScreen()) {
-                                device.exitSplitScreen()
-                            }
-                            device.pressHome()
-                            testAppTop.exit()
-                            testAppBottom.exit()
-                        }
-                        test {
-                            if (device.isInSplitScreen()) {
-                                device.exitSplitScreen()
-                            }
-                        }
-                    }
-                    transitions {
-                        device.resizeSplitScreen(stopRatio)
-                    }
-                    assertions {
-                        windowManagerTrace {
-                            navBarWindowIsAlwaysVisible()
-                            statusBarWindowIsAlwaysVisible()
-                            visibleWindowsShownMoreThanOneConsecutiveEntry()
-
-                            all("topAppWindowIsAlwaysVisible", bugId = 156223549) {
-                                this.showsAppWindow(sSimpleActivity)
-                            }
-
-                            all("bottomAppWindowIsAlwaysVisible", bugId = 156223549) {
-                                this.showsAppWindow(sImeActivity)
-                            }
-                        }
-
-                        layersTrace {
-                            navBarLayerIsAlwaysVisible()
-                            statusBarLayerIsAlwaysVisible()
-                            noUncoveredRegions(configuration.endRotation)
-                            navBarLayerRotatesAndScales(configuration.endRotation)
-                            statusBarLayerRotatesScales(configuration.endRotation)
-                            visibleLayersShownMoreThanOneConsecutiveEntry()
-
-                            all("topAppLayerIsAlwaysVisible") {
-                                this.showsLayer(sSimpleActivity)
-                            }
-
-                            all("bottomAppLayerIsAlwaysVisible") {
-                                this.showsLayer(sImeActivity)
-                            }
-
-                            all("dividerLayerIsAlwaysVisible") {
-                                this.showsLayer(DOCKED_STACK_DIVIDER)
-                            }
-
-                            start("appsStartingBounds", enabled = false) {
-                                val displayBounds = WindowUtils.displayBounds
-                                val dividerBounds =
-                                    entry.getVisibleBounds(DOCKED_STACK_DIVIDER).bounds
-
-                                val topAppBounds = Region(0, 0, dividerBounds.right,
-                                    dividerBounds.top + WindowUtils.dockedStackDividerInset)
-                                val bottomAppBounds = Region(0,
-                                    dividerBounds.bottom - WindowUtils.dockedStackDividerInset,
-                                    displayBounds.right,
-                                    displayBounds.bottom - WindowUtils.navigationBarHeight)
-                                this.hasVisibleRegion("SimpleActivity", topAppBounds)
-                                    .hasVisibleRegion("ImeActivity", bottomAppBounds)
-                            }
-
-                            end("appsEndingBounds", enabled = false) {
-                                val displayBounds = WindowUtils.displayBounds
-                                val dividerBounds =
-                                    entry.getVisibleBounds(DOCKED_STACK_DIVIDER).bounds
-
-                                val topAppBounds = Region(0, 0, dividerBounds.right,
-                                    dividerBounds.top + WindowUtils.dockedStackDividerInset)
-                                val bottomAppBounds = Region(0,
-                                    dividerBounds.bottom - WindowUtils.dockedStackDividerInset,
-                                    displayBounds.right,
-                                    displayBounds.bottom - WindowUtils.navigationBarHeight)
-
-                                this.hasVisibleRegion(sSimpleActivity, topAppBounds)
-                                    .hasVisibleRegion(sImeActivity, bottomAppBounds)
-                            }
-                        }
-
-                        eventLog {
-                            focusDoesNotChange()
-                        }
-                    }
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance()
+                .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0))
+                .map {
+                    val description = (startRatio.toString().replace("/", "-") + "_to_" +
+                        stopRatio.toString().replace("/", "-"))
+                    val newName = "${FlickerTestParameter.defaultName(it.config)}_$description"
+                    FlickerTestParameter(it.config, name = newName)
                 }
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt
index 214269e..c914ada 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt
@@ -16,17 +16,16 @@
 
 package com.android.wm.shell.flicker.legacysplitscreen
 
-import android.os.Bundle
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.appWindowBecomesVisible
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.endRotation
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.launchSplitScreen
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
@@ -38,6 +37,7 @@
 import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible
 import com.android.wm.shell.flicker.helpers.SplitScreenHelper
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -46,50 +46,64 @@
  * Test dock activity to primary split screen and rotate
  * To run this test: `atest WMShellFlickerTests:RotateOneLaunchedAppAndEnterSplitScreen`
  */
-@Presubmit
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class RotateOneLaunchedAppAndEnterSplitScreen(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) {
+    testSpec: FlickerTestParameter
+) : LegacySplitScreenRotateTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = { configuration ->
+            super.transition(this, configuration)
+            transitions {
+                device.launchSplitScreen(wmHelper)
+                this.setRotation(testSpec.config.startRotation)
+            }
+        }
+
+    @FlakyTest(bugId = 175687842)
+    @Test
+    fun dockedStackDividerIsVisible() = testSpec.dockedStackDividerIsVisible()
+
+    @FlakyTest(bugId = 175687842)
+    @Test
+    fun dockedStackPrimaryBoundsIsVisible() =
+        testSpec.dockedStackPrimaryBoundsIsVisible(testSpec.config.startRotation,
+            splitScreenApp.defaultWindowName)
+
+    @FlakyTest(bugId = 169271943)
+    @Test
+    fun navBarLayerRotatesAndScales() =
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation,
+            testSpec.config.endRotation)
+
+    @FlakyTest(bugId = 169271943)
+    @Test
+    fun statusBarLayerRotatesScales() =
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation,
+            testSpec.config.endRotation)
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun appWindowBecomesVisible() =
+        testSpec.appWindowBecomesVisible(splitScreenApp.defaultWindowName)
+
+    companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
-                withTestName {
-                    buildTestTag("testRotateOneLaunchedAppAndEnterSplitScreen", configuration)
-                }
-                repeat { SplitScreenHelper.TEST_REPETITIONS }
-                transitions {
-                    device.launchSplitScreen()
-                    this.setRotation(configuration.startRotation)
-                }
-                assertions {
-                    layersTrace {
-                        dockedStackDividerIsVisible(bugId = 175687842)
-                        dockedStackPrimaryBoundsIsVisible(
-                            configuration.startRotation,
-                            splitScreenApp.defaultWindowName, bugId = 175687842)
-                        navBarLayerRotatesAndScales(
-                            configuration.startRotation,
-                            configuration.endRotation, bugId = 169271943)
-                        statusBarLayerRotatesScales(
-                            configuration.startRotation,
-                            configuration.endRotation, bugId = 169271943)
-                    }
-                    windowManagerTrace {
-                        navBarWindowIsAlwaysVisible()
-                        statusBarWindowIsAlwaysVisible()
-                        appWindowBecomesVisible(splitScreenApp.defaultWindowName)
-                    }
-                }
-            }
-            return FlickerTestRunnerFactory.getInstance().buildTest(
-                instrumentation, customRotateSetup, testSpec,
-                repetitions = SplitScreenHelper.TEST_REPETITIONS,
-                supportedRotations = listOf(Surface.ROTATION_0 /* bugId = 178685668 */))
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance()
+                .getConfigNonRotationTests(repetitions = SplitScreenHelper.TEST_REPETITIONS,
+                    supportedRotations = listOf(Surface.ROTATION_0)) // b/178685668
         }
     }
-}
\ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt
index 4290c92..ffb20a4 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt
@@ -16,17 +16,16 @@
 
 package com.android.wm.shell.flicker.legacysplitscreen
 
-import android.os.Bundle
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.appWindowBecomesVisible
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.endRotation
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.launchSplitScreen
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
@@ -38,6 +37,7 @@
 import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible
 import com.android.wm.shell.flicker.helpers.SplitScreenHelper
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -46,50 +46,61 @@
  * Rotate
  * To run this test: `atest WMShellFlickerTests:RotateOneLaunchedAppInSplitScreenMode`
  */
-@Presubmit
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class RotateOneLaunchedAppInSplitScreenMode(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) {
+    testSpec: FlickerTestParameter
+) : LegacySplitScreenRotateTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = { configuration ->
+            super.transition(this, configuration)
+            transitions {
+                this.setRotation(testSpec.config.startRotation)
+                device.launchSplitScreen(wmHelper)
+            }
+        }
+
+    @FlakyTest(bugId = 175687842)
+    @Test
+    fun dockedStackDividerIsVisible() = testSpec.dockedStackDividerIsVisible()
+
+    @FlakyTest(bugId = 175687842)
+    @Test
+    fun dockedStackPrimaryBoundsIsVisible() = testSpec.dockedStackPrimaryBoundsIsVisible(
+        testSpec.config.startRotation, splitScreenApp.defaultWindowName)
+
+    @FlakyTest(bugId = 169271943)
+    @Test
+    fun navBarLayerRotatesAndScales() = testSpec.navBarLayerRotatesAndScales(
+        testSpec.config.startRotation, testSpec.config.endRotation)
+
+    @FlakyTest(bugId = 169271943)
+    @Test
+    fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales(
+        testSpec.config.startRotation, testSpec.config.endRotation)
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun appWindowBecomesVisible() =
+        testSpec.appWindowBecomesVisible(splitScreenApp.defaultWindowName)
+
+    companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
-                withTestName {
-                    buildTestTag("testRotateOneLaunchedAppInSplitScreenMode", configuration)
-                }
-                repeat { SplitScreenHelper.TEST_REPETITIONS }
-                transitions {
-                    this.setRotation(configuration.startRotation)
-                    device.launchSplitScreen()
-                }
-                assertions {
-                    layersTrace {
-                        dockedStackDividerIsVisible(bugId = 175687842)
-                        dockedStackPrimaryBoundsIsVisible(
-                            configuration.startRotation,
-                            splitScreenApp.defaultWindowName, bugId = 175687842)
-                        navBarLayerRotatesAndScales(
-                            configuration.startRotation,
-                            configuration.endRotation, bugId = 169271943)
-                        statusBarLayerRotatesScales(
-                            configuration.startRotation,
-                            configuration.endRotation, bugId = 169271943)
-                    }
-                    windowManagerTrace {
-                        navBarWindowIsAlwaysVisible()
-                        statusBarWindowIsAlwaysVisible()
-                        appWindowBecomesVisible(splitScreenApp.defaultWindowName)
-                    }
-                }
-            }
-            return FlickerTestRunnerFactory.getInstance().buildTest(
-                instrumentation, customRotateSetup, testSpec,
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
                 repetitions = SplitScreenHelper.TEST_REPETITIONS,
-                supportedRotations = listOf(Surface.ROTATION_0 /* bugId = 178685668 */))
+                supportedRotations = listOf(Surface.ROTATION_0)) // b/178685668
         }
     }
-}
\ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt
index 4095b9a..8cf1990 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt
@@ -16,18 +16,18 @@
 
 package com.android.wm.shell.flicker.legacysplitscreen
 
-import android.os.Bundle
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.appWindowBecomesVisible
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.endRotation
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.reopenAppFromOverview
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
@@ -39,6 +39,7 @@
 import com.android.wm.shell.flicker.dockedStackSecondaryBoundsIsVisible
 import com.android.wm.shell.flicker.helpers.SplitScreenHelper
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -47,54 +48,69 @@
  * Test open app to split screen.
  * To run this test: `atest WMShellFlickerTests:RotateTwoLaunchedAppAndEnterSplitScreen`
  */
-@Presubmit
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class RotateTwoLaunchedAppAndEnterSplitScreen(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) {
+    testSpec: FlickerTestParameter
+) : LegacySplitScreenRotateTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = { configuration ->
+            super.transition(this, configuration)
+            transitions {
+                this.setRotation(testSpec.config.startRotation)
+                device.launchSplitScreen(wmHelper)
+                device.reopenAppFromOverview(wmHelper)
+            }
+        }
+
+    @FlakyTest(bugId = 175687842)
+    @Test
+    fun dockedStackDividerIsVisible() = testSpec.dockedStackDividerIsVisible()
+
+    @FlakyTest(bugId = 175687842)
+    @Test
+    fun dockedStackPrimaryBoundsIsVisible() =
+        testSpec.dockedStackPrimaryBoundsIsVisible(testSpec.config.startRotation,
+            splitScreenApp.defaultWindowName)
+
+    @FlakyTest(bugId = 175687842)
+    @Test
+    fun dockedStackSecondaryBoundsIsVisible() =
+        testSpec.dockedStackSecondaryBoundsIsVisible(testSpec.config.startRotation,
+            secondaryApp.defaultWindowName)
+
+    @FlakyTest(bugId = 169271943)
+    @Test
+    fun navBarLayerRotatesAndScales() =
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation,
+            testSpec.config.endRotation)
+
+    @FlakyTest(bugId = 169271943)
+    @Test
+    fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales(
+        testSpec.config.startRotation, testSpec.config.endRotation)
+
+    @Presubmit
+    @Test
+    fun appWindowBecomesVisible() = testSpec.appWindowBecomesVisible(secondaryApp.defaultWindowName)
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
-                withTestName {
-                    buildTestTag("testRotateTwoLaunchedAppAndEnterSplitScreen", configuration)
-                }
-                repeat { SplitScreenHelper.TEST_REPETITIONS }
-                transitions {
-                    this.setRotation(configuration.startRotation)
-                    device.launchSplitScreen()
-                    secondaryApp.reopenAppFromOverview()
-                }
-                assertions {
-                    layersTrace {
-                        dockedStackDividerIsVisible(bugId = 175687842)
-                        dockedStackPrimaryBoundsIsVisible(
-                            configuration.startRotation,
-                            splitScreenApp.defaultWindowName, 175687842)
-                        dockedStackSecondaryBoundsIsVisible(
-                            configuration.startRotation,
-                            secondaryApp.defaultWindowName, bugId = 175687842)
-                        navBarLayerRotatesAndScales(
-                            configuration.startRotation,
-                            configuration.endRotation, bugId = 169271943)
-                        statusBarLayerRotatesScales(
-                            configuration.startRotation,
-                            configuration.endRotation, bugId = 169271943)
-                    }
-                    windowManagerTrace {
-                        appWindowBecomesVisible(secondaryApp.defaultWindowName)
-                        navBarWindowIsAlwaysVisible()
-                        statusBarWindowIsAlwaysVisible()
-                    }
-                }
-            }
-            return FlickerTestRunnerFactory.getInstance().buildTest(
-                instrumentation, customRotateSetup, testSpec,
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
                 repetitions = SplitScreenHelper.TEST_REPETITIONS,
-                supportedRotations = listOf(Surface.ROTATION_0 /* bugId = 178685668 */))
+                supportedRotations = listOf(Surface.ROTATION_0)) // b/178685668
         }
     }
-}
\ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt
index aebf606..9c798d8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt
@@ -16,18 +16,18 @@
 
 package com.android.wm.shell.flicker.legacysplitscreen
 
-import android.os.Bundle
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.appWindowBecomesVisible
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.endRotation
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.reopenAppFromOverview
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
@@ -39,6 +39,7 @@
 import com.android.wm.shell.flicker.dockedStackSecondaryBoundsIsVisible
 import com.android.wm.shell.flicker.helpers.SplitScreenHelper
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -47,59 +48,76 @@
  * Test open app to split screen.
  * To run this test: `atest WMShellFlickerTests:RotateTwoLaunchedAppInSplitScreenMode`
  */
-@Presubmit
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class RotateTwoLaunchedAppInSplitScreenMode(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) {
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
-                withTestName {
-                    buildTestTag("testRotateTwoLaunchedAppInSplitScreenMode", configuration)
-                }
-                repeat { SplitScreenHelper.TEST_REPETITIONS }
-                setup {
-                    eachRun {
-                        device.launchSplitScreen()
-                        splitScreenApp.reopenAppFromOverview()
-                        this.setRotation(configuration.startRotation)
-                    }
-                }
-                transitions {
-                    this.setRotation(configuration.startRotation)
-                }
-                assertions {
-                    layersTrace {
-                        dockedStackDividerIsVisible(bugId = 175687842)
-                        dockedStackPrimaryBoundsIsVisible(
-                            configuration.startRotation,
-                            splitScreenApp.defaultWindowName, bugId = 175687842)
-                        dockedStackSecondaryBoundsIsVisible(
-                            configuration.startRotation,
-                            secondaryApp.defaultWindowName, bugId = 175687842)
-                        navBarLayerRotatesAndScales(
-                            configuration.startRotation,
-                            configuration.endRotation, bugId = 169271943)
-                        statusBarLayerRotatesScales(
-                            configuration.startRotation,
-                            configuration.endRotation, bugId = 169271943)
-                    }
-                    windowManagerTrace {
-                        appWindowBecomesVisible(secondaryApp.defaultWindowName)
-                        navBarWindowIsAlwaysVisible()
-                        statusBarWindowIsAlwaysVisible()
-                    }
+    testSpec: FlickerTestParameter
+) : LegacySplitScreenRotateTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = { configuration ->
+            super.transition(this, configuration)
+            setup {
+                eachRun {
+                    device.launchSplitScreen(wmHelper)
+                    device.reopenAppFromOverview(wmHelper)
+                    this.setRotation(testSpec.config.startRotation)
                 }
             }
-            return FlickerTestRunnerFactory.getInstance().buildTest(
-                instrumentation, customRotateSetup, testSpec,
+            transitions {
+                this.setRotation(testSpec.config.startRotation)
+            }
+        }
+
+    @FlakyTest(bugId = 175687842)
+    @Test
+    fun dockedStackDividerIsVisible() = testSpec.dockedStackDividerIsVisible()
+
+    @FlakyTest(bugId = 175687842)
+    @Test
+    fun dockedStackPrimaryBoundsIsVisible() =
+        testSpec.dockedStackPrimaryBoundsIsVisible(testSpec.config.startRotation,
+            splitScreenApp.defaultWindowName)
+
+    @FlakyTest(bugId = 175687842)
+    @Test
+    fun dockedStackSecondaryBoundsIsVisible() =
+        testSpec.dockedStackSecondaryBoundsIsVisible(testSpec.config.startRotation,
+            secondaryApp.defaultWindowName)
+
+    @FlakyTest(bugId = 169271943)
+    @Test
+    fun navBarLayerRotatesAndScales() =
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation,
+            testSpec.config.endRotation)
+
+    @FlakyTest(bugId = 169271943)
+    @Test
+    fun statusBarLayerRotatesScales() =
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation,
+            testSpec.config.endRotation)
+
+    @Presubmit
+    @Test
+    fun appWindowBecomesVisible() =
+        testSpec.appWindowBecomesVisible(secondaryApp.defaultWindowName)
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
                 repetitions = SplitScreenHelper.TEST_REPETITIONS,
-                supportedRotations = listOf(Surface.ROTATION_0 /* bugId = 178685668 */))
+                supportedRotations = listOf(Surface.ROTATION_0)) // b/178685668
         }
     }
-}
\ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AppTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AppTestBase.kt
deleted file mode 100644
index bc42d5e..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AppTestBase.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.flicker.pip
-
-import android.os.SystemClock
-import com.android.wm.shell.flicker.NonRotationTestBase
-
-abstract class AppTestBase(
-    rotationName: String,
-    rotation: Int
-) : NonRotationTestBase(rotationName, rotation) {
-    companion object {
-        fun waitForAnimationComplete() {
-            // TODO: UiDevice doesn't have reliable way to wait for the completion of animation.
-            // Consider to introduce WindowManagerStateHelper to access Activity state.
-            SystemClock.sleep(1000)
-        }
-    }
-}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt
index d56ed02..75c33c6 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt
@@ -16,11 +16,13 @@
 
 package com.android.wm.shell.flicker.pip
 
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.WindowUtils
 import com.android.wm.shell.flicker.helpers.FixedAppHelper
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
@@ -29,6 +31,7 @@
 import com.android.server.wm.flicker.startRotation
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -39,64 +42,96 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class EnterExitPipTest(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : PipTransitionBase(InstrumentationRegistry.getInstrumentation()) {
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): List<Array<Any>> {
-            val testApp = FixedAppHelper(instrumentation)
-            val testSpec = getTransition(eachRun = true) { configuration ->
-                setup {
-                    eachRun {
-                        testApp.launchViaIntent(wmHelper)
-                    }
-                }
-                transitions {
-                    // This will bring PipApp to fullscreen
-                    pipApp.launchViaIntent(wmHelper)
-                }
-                assertions {
-                    val displayBounds = WindowUtils.getDisplayBounds(configuration.startRotation)
-                    presubmit {
-                        windowManagerTrace {
-                            all("pipApp must remain inside visible bounds") {
-                                coversAtMostRegion(pipApp.defaultWindowName, displayBounds)
-                            }
-                            all("Initially shows both app windows then pipApp hides testApp") {
-                                showsAppWindow(testApp.defaultWindowName)
-                                    .showsAppWindowOnTop(pipApp.defaultWindowName)
-                                    .then()
-                                    .hidesAppWindow(testApp.defaultWindowName)
-                            }
-                            navBarWindowIsAlwaysVisible()
-                            statusBarWindowIsAlwaysVisible()
-                        }
-                        layersTrace {
-                            all("Initially shows both app layers then pipApp hides testApp") {
-                                showsLayer(testApp.defaultWindowName)
-                                    .showsLayer(pipApp.defaultWindowName)
-                                    .then()
-                                    .hidesLayer(testApp.defaultWindowName)
-                            }
-                            start("testApp covers the fullscreen, pipApp remains inside display") {
-                                hasVisibleRegion(testApp.defaultWindowName, displayBounds)
-                                coversAtMostRegion(displayBounds, pipApp.defaultWindowName)
-                            }
-                            end("pipApp covers the fullscreen") {
-                                hasVisibleRegion(pipApp.defaultWindowName, displayBounds)
-                            }
-                            navBarLayerIsAlwaysVisible()
-                            statusBarLayerIsAlwaysVisible()
-                        }
-                    }
+    testSpec: FlickerTestParameter
+) : PipTransition(testSpec) {
+    private val testApp = FixedAppHelper(instrumentation)
+    private val displayBounds = WindowUtils.getDisplayBounds(testSpec.config.startRotation)
+
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = buildTransition(eachRun = true) {
+            setup {
+                eachRun {
+                    testApp.launchViaIntent(wmHelper)
                 }
             }
-            return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation,
-                testSpec, supportedRotations = listOf(Surface.ROTATION_0),
-                repetitions = 5)
+            transitions {
+                // This will bring PipApp to fullscreen
+                pipApp.launchViaIntent(wmHelper)
+            }
+        }
+
+    @Presubmit
+    @Test
+    fun pipAppRemainInsideVisibleBounds() {
+        testSpec.assertWm {
+            coversAtMost(displayBounds, pipApp.defaultWindowName)
         }
     }
-}
\ No newline at end of file
+
+    @Presubmit
+    @Test
+    fun showBothAppWindowsThenHidePip() {
+        testSpec.assertWm {
+            showsAppWindow(testApp.defaultWindowName)
+                .showsAppWindowOnTop(pipApp.defaultWindowName)
+                .then()
+                .hidesAppWindow(testApp.defaultWindowName)
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun showBothAppLayersThenHidePip() {
+        testSpec.assertLayers {
+            isVisible(testApp.defaultWindowName)
+                .isVisible(pipApp.defaultWindowName)
+                .then()
+                .isInvisible(testApp.defaultWindowName)
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun testAppCoversFullScreenWithPipOnDisplay() {
+        testSpec.assertLayersStart {
+            coversExactly(displayBounds, testApp.defaultWindowName)
+            coversAtMost(displayBounds, pipApp.defaultWindowName)
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun pipAppCoversFullScreen() {
+        testSpec.assertLayersEnd {
+            coversExactly(displayBounds, pipApp.defaultWindowName)
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): List<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
+                supportedRotations = listOf(Surface.ROTATION_0), repetitions = 5)
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
index ff31ba7..83dca53 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
@@ -16,11 +16,14 @@
 
 package com.android.wm.shell.flicker.pip
 
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
 import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
@@ -30,6 +33,7 @@
 import com.android.server.wm.flicker.noUncoveredRegions
 import com.android.server.wm.flicker.startRotation
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -40,58 +44,71 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class EnterPipTest(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : PipTransitionBase(InstrumentationRegistry.getInstrumentation()) {
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): List<Array<Any>> {
-            val testSpec = getTransition(eachRun = true,
-                stringExtras = emptyMap()) { configuration ->
-                transitions {
-                    pipApp.clickEnterPipButton()
-                    pipApp.expandPipWindow(wmHelper)
-                }
-                assertions {
-                    presubmit {
-                        windowManagerTrace {
-                            navBarWindowIsAlwaysVisible()
-                            statusBarWindowIsAlwaysVisible()
-
-                            all("pipWindowBecomesVisible") {
-                                this.showsAppWindow(pipApp.defaultWindowName)
-                            }
-                        }
-
-                        layersTrace {
-                            statusBarLayerIsAlwaysVisible()
-                            statusBarLayerRotatesScales(configuration.startRotation,
-                                Surface.ROTATION_0)
-                        }
-
-                        layersTrace {
-                            all("pipLayerBecomesVisible") {
-                                this.showsLayer(pipApp.launcherName)
-                            }
-                        }
-                    }
-
-                    flaky {
-                        layersTrace {
-                            navBarLayerIsAlwaysVisible(bugId = 140855415)
-                            noUncoveredRegions(configuration.startRotation, Surface.ROTATION_0)
-                            navBarLayerRotatesAndScales(configuration.startRotation,
-                                Surface.ROTATION_0, bugId = 140855415)
-                        }
-                    }
-                }
+class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = buildTransition(eachRun = true, stringExtras = emptyMap()) {
+            transitions {
+                pipApp.clickEnterPipButton()
+                pipApp.expandPipWindow(wmHelper)
             }
+        }
 
-            return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation,
-                testSpec, supportedRotations = listOf(Surface.ROTATION_0),
-                repetitions = 5)
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun pipWindowBecomesVisible() {
+        testSpec.assertWm {
+            this.showsAppWindow(pipApp.defaultWindowName)
         }
     }
-}
\ No newline at end of file
+
+    @Presubmit
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarLayerRotatesScales() =
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation, Surface.ROTATION_0)
+
+    @Presubmit
+    @Test
+    fun pipLayerBecomesVisible() {
+        testSpec.assertLayers {
+            this.isVisible(pipApp.launcherName)
+        }
+    }
+
+    @FlakyTest(bugId = 140855415)
+    @Test
+    fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @FlakyTest(bugId = 140855415)
+    @Test
+    fun navBarLayerRotatesAndScales() =
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation, Surface.ROTATION_0)
+
+    @FlakyTest(bugId = 140855415)
+    @Test
+    fun noUncoveredRegions() =
+        testSpec.noUncoveredRegions(testSpec.config.startRotation, Surface.ROTATION_0)
+
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): List<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance()
+                .getConfigRotationTests(supportedRotations = listOf(Surface.ROTATION_0),
+                    repetitions = 5)
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
index eaaa2f6..9011f1a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
@@ -16,22 +16,25 @@
 
 package com.android.wm.shell.flicker.pip
 
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.wm.shell.flicker.helpers.FixedAppHelper
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
-import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
-import com.android.wm.shell.flicker.pip.PipTransitionBase.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE
-import com.android.wm.shell.flicker.pip.PipTransitionBase.BroadcastActionTrigger.Companion.ORIENTATION_PORTRAIT
+import com.android.wm.shell.flicker.helpers.FixedAppHelper
+import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE
+import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_PORTRAIT
 import com.android.wm.shell.flicker.testapp.Components.PipActivity.ACTION_ENTER_PIP
 import com.android.wm.shell.flicker.testapp.Components.FixedActivity.EXTRA_FIXED_ORIENTATION
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -42,82 +45,108 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class EnterPipToOtherOrientationTest(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : PipTransitionBase(InstrumentationRegistry.getInstrumentation()) {
-        private val testApp = FixedAppHelper(instrumentation)
+    testSpec: FlickerTestParameter
+) : PipTransition(testSpec) {
+    private val testApp = FixedAppHelper(instrumentation)
+    private val startingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_90)
+    private val endingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_0)
 
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation,
-                supportedRotations = listOf(Surface.ROTATION_0),
-                repetitions = 5) { configuration ->
-                setupAndTeardown(this, configuration)
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = { configuration ->
+            setupAndTeardown(this, configuration)
 
-                setup {
-                    eachRun {
-                        // Launch a portrait only app on the fullscreen stack
-                        testApp.launchViaIntent(wmHelper, stringExtras = mapOf(
-                            EXTRA_FIXED_ORIENTATION to ORIENTATION_PORTRAIT.toString()))
-                        // Launch the PiP activity fixed as landscape
-                        pipApp.launchViaIntent(wmHelper, stringExtras = mapOf(
-                            EXTRA_FIXED_ORIENTATION to ORIENTATION_LANDSCAPE.toString()))
-                    }
-                }
-                teardown {
-                    eachRun {
-                        pipApp.exit()
-                        testApp.exit()
-                    }
-                }
-                transitions {
-                    // Enter PiP, and assert that the PiP is within bounds now that the device is back
-                    // in portrait
-                    broadcastActionTrigger.doAction(ACTION_ENTER_PIP)
-                    wmHelper.waitPipWindowShown()
-                    wmHelper.waitForAppTransitionIdle()
-                }
-                assertions {
-                    val startingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_90)
-                    val endingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_0)
-
-                    presubmit {
-                        windowManagerTrace {
-                            all("pipApp window is always on top") {
-                                showsAppWindowOnTop(pipApp.defaultWindowName)
-                            }
-                            start("pipApp window hides testApp") {
-                                isInvisible(testApp.defaultWindowName)
-                            }
-                            end("testApp windows is shown") {
-                                isVisible(testApp.defaultWindowName)
-                            }
-                            navBarWindowIsAlwaysVisible()
-                            statusBarWindowIsAlwaysVisible()
-                        }
-
-                        layersTrace {
-                            start("pipApp layer hides testApp") {
-                                hasVisibleRegion(pipApp.defaultWindowName, startingBounds)
-                                isInvisible(testApp.defaultWindowName)
-                            }
-                        }
-                    }
-
-                    flaky {
-                        layersTrace {
-                            end("testApp layer covers fullscreen") {
-                                hasVisibleRegion(testApp.defaultWindowName, endingBounds)
-                            }
-                            navBarLayerIsAlwaysVisible(bugId = 140855415)
-                            statusBarLayerIsAlwaysVisible(bugId = 140855415)
-                        }
-                    }
+            setup {
+                eachRun {
+                    // Launch a portrait only app on the fullscreen stack
+                    testApp.launchViaIntent(wmHelper, stringExtras = mapOf(
+                        EXTRA_FIXED_ORIENTATION to ORIENTATION_PORTRAIT.toString()))
+                    // Launch the PiP activity fixed as landscape
+                    pipApp.launchViaIntent(wmHelper, stringExtras = mapOf(
+                        EXTRA_FIXED_ORIENTATION to ORIENTATION_LANDSCAPE.toString()))
                 }
             }
+            teardown {
+                eachRun {
+                    pipApp.exit(wmHelper)
+                    testApp.exit(wmHelper)
+                }
+            }
+            transitions {
+                // Enter PiP, and assert that the PiP is within bounds now that the device is back
+                // in portrait
+                broadcastActionTrigger.doAction(ACTION_ENTER_PIP)
+                wmHelper.waitPipWindowShown()
+                wmHelper.waitForAppTransitionIdle()
+            }
+        }
+
+    @Presubmit
+    @Test
+    fun pipAppWindowIsAlwaysOnTop() {
+        testSpec.assertWm {
+            showsAppWindowOnTop(pipApp.defaultWindowName)
         }
     }
-}
\ No newline at end of file
+
+    @Presubmit
+    @Test
+    fun pipAppHidesTestApp() {
+        testSpec.assertWmStart {
+            isInvisible(testApp.defaultWindowName)
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun testAppWindowIsVisible() {
+        testSpec.assertWmEnd {
+            isVisible(testApp.defaultWindowName)
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun pipAppLayerHidesTestApp() {
+        testSpec.assertLayersStart {
+            coversExactly(startingBounds, pipApp.defaultWindowName)
+            isInvisible(testApp.defaultWindowName)
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun testAppLayerCoversFullScreen() {
+        testSpec.assertLayersEnd {
+            coversExactly(endingBounds, testApp.defaultWindowName)
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance()
+                .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0),
+                    repetitions = 5)
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/Extensions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/Extensions.kt
index 707d28d..96eb66c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/Extensions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/Extensions.kt
@@ -48,7 +48,7 @@
     activity: ComponentName
 ): WindowManagerStateSubject = apply {
     val windowName = activity.toWindowName()
-    hasWindow(windowName)
+    contains(windowName)
     val pinnedWindows = wmState.pinnedWindows
         .map { it.title }
     Truth.assertWithMessage("Window not in PIP mode")
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseTransition.kt
new file mode 100644
index 0000000..3e33176
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseTransition.kt
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip
+
+import android.platform.test.annotations.Presubmit
+import android.view.Surface
+import androidx.test.filters.FlakyTest
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.focusChanges
+import com.android.server.wm.flicker.helpers.setRotation
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.startRotation
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import org.junit.Test
+import org.junit.runners.Parameterized
+
+abstract class PipCloseTransition(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = buildTransition(eachRun = true) { configuration ->
+            setup {
+                eachRun {
+                    this.setRotation(configuration.startRotation)
+                }
+            }
+            teardown {
+                eachRun {
+                    this.setRotation(Surface.ROTATION_0)
+                }
+            }
+        }
+
+    @Presubmit
+    @Test
+    open fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    open fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    open fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    open fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    open fun pipWindowBecomesInvisible() {
+        testSpec.assertWm {
+            this.showsAppWindow(PIP_WINDOW_TITLE)
+                .then()
+                .hidesAppWindow(PIP_WINDOW_TITLE)
+        }
+    }
+
+    @Presubmit
+    @Test
+    open fun pipLayerBecomesInvisible() {
+        testSpec.assertLayers {
+            this.isVisible(PIP_WINDOW_TITLE)
+                .then()
+                .isInvisible(PIP_WINDOW_TITLE)
+        }
+    }
+
+    @Presubmit
+    @Test
+    open fun statusBarLayerRotatesScales() =
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation, Surface.ROTATION_0)
+
+    @Presubmit
+    @Test
+    open fun noUncoveredRegions() =
+        testSpec.noUncoveredRegions(testSpec.config.startRotation, Surface.ROTATION_0)
+
+    @Presubmit
+    @Test
+    open fun navBarLayerRotatesAndScales() =
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation, Surface.ROTATION_0)
+
+    @FlakyTest(bugId = 151179149)
+    @Test
+    open fun focusChanges() = testSpec.focusChanges(pipApp.launcherName, "NexusLauncherActivity")
+
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): List<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance()
+                .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0),
+                    repetitions = 5)
+        }
+    }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseWithDismissButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseWithDismissButtonTest.kt
new file mode 100644
index 0000000..0408421
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseWithDismissButtonTest.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip
+
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test Pip launch.
+ * To run this test: `atest WMShellFlickerTests:PipCloseWithDismissButton`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class PipCloseWithDismissButtonTest(testSpec: FlickerTestParameter) : PipCloseTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = {
+            super.transition(this, it)
+            transitions {
+                pipApp.closePipWindow(wmHelper)
+            }
+        }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseWithSwipeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseWithSwipeTest.kt
new file mode 100644
index 0000000..afaf33a
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseWithSwipeTest.kt
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip
+
+import android.platform.test.annotations.Postsubmit
+import android.view.Surface
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.startRotation
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test Pip launch.
+ * To run this test: `atest WMShellFlickerTests:PipCloseWithSwipe`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class PipCloseWithSwipeTest(testSpec: FlickerTestParameter) : PipCloseTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = {
+            super.transition(this, it)
+            transitions {
+                val pipRegion = wmHelper.getWindowRegion(pipApp.component).bounds
+                val pipCenterX = pipRegion.centerX()
+                val pipCenterY = pipRegion.centerY()
+                val displayCenterX = device.displayWidth / 2
+                device.swipe(pipCenterX, pipCenterY, displayCenterX, device.displayHeight, 5)
+            }
+        }
+
+    @Postsubmit
+    @Test
+    override fun navBarLayerIsAlwaysVisible() = super.navBarLayerIsAlwaysVisible()
+
+    @Postsubmit
+    @Test
+    override fun statusBarLayerIsAlwaysVisible() = super.statusBarLayerIsAlwaysVisible()
+
+    @Postsubmit
+    @Test
+    override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
+
+    @Postsubmit
+    @Test
+    override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
+
+    @Postsubmit
+    @Test
+    override fun pipWindowBecomesInvisible() = super.pipWindowBecomesInvisible()
+
+    @Postsubmit
+    @Test
+    override fun pipLayerBecomesInvisible() = super.pipLayerBecomesInvisible()
+
+    @Postsubmit
+    @Test
+    override fun statusBarLayerRotatesScales() =
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation, Surface.ROTATION_0)
+
+    @Postsubmit
+    @Test
+    override fun noUncoveredRegions() = super.noUncoveredRegions()
+
+    @Postsubmit
+    @Test
+    override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
index f054e64..4633960 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
@@ -16,17 +16,20 @@
 
 package com.android.wm.shell.flicker.pip
 
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.WindowUtils
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.startRotation
 import com.android.wm.shell.flicker.IME_WINDOW_NAME
 import com.android.wm.shell.flicker.helpers.ImeAppHelper
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -37,58 +40,67 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class PipKeyboardTest(testSpec: FlickerTestRunnerFactory.TestSpec) : FlickerTestRunner(testSpec) {
-    companion object : PipTransitionBase(InstrumentationRegistry.getInstrumentation()) {
+class PipKeyboardTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
+    private val imeApp = ImeAppHelper(instrumentation)
+
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = buildTransition(eachRun = false) { configuration ->
+            setup {
+                test {
+                    imeApp.launchViaIntent(wmHelper)
+                    setRotation(configuration.startRotation)
+                }
+            }
+            teardown {
+                test {
+                    imeApp.exit(wmHelper)
+                    setRotation(Surface.ROTATION_0)
+                }
+            }
+            transitions {
+                // open the soft keyboard
+                imeApp.openIME(wmHelper)
+                createTag(TAG_IME_VISIBLE)
+
+                // then close it again
+                imeApp.closeIME(wmHelper)
+            }
+        }
+
+    /**
+     * Ensure the pip window remains visible throughout any keyboard interactions
+     */
+    @Presubmit
+    @Test
+    fun pipInVisibleBounds() {
+        testSpec.assertWm {
+            val displayBounds = WindowUtils.getDisplayBounds(testSpec.config.startRotation)
+            coversAtMost(displayBounds, pipApp.defaultWindowName)
+        }
+    }
+
+    /**
+     * Ensure that the pip window does not obscure the keyboard
+     */
+    @Presubmit
+    @Test
+    fun pipIsAboveAppWindow() {
+        testSpec.assertWmTag(TAG_IME_VISIBLE) {
+            isAboveWindow(IME_WINDOW_NAME, pipApp.defaultWindowName)
+        }
+    }
+
+    companion object {
         private const val TAG_IME_VISIBLE = "imeIsVisible"
 
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val imeApp = ImeAppHelper(instrumentation)
-            val testSpec = getTransition(eachRun = false) { configuration ->
-                setup {
-                    test {
-                        imeApp.launchViaIntent(wmHelper)
-                        setRotation(configuration.startRotation)
-                    }
-                }
-                teardown {
-                    test {
-                        imeApp.exit()
-                        setRotation(Surface.ROTATION_0)
-                    }
-                }
-                transitions {
-                    // open the soft keyboard
-                    imeApp.openIME(wmHelper)
-                    createTag(TAG_IME_VISIBLE)
-
-                    // then close it again
-                    imeApp.closeIME(wmHelper)
-                }
-                assertions {
-                    presubmit {
-                        windowManagerTrace {
-                            // Ensure the pip window remains visible throughout
-                            // any keyboard interactions
-                            all("pipInVisibleBounds") {
-                                val displayBounds = WindowUtils.getDisplayBounds(
-                                    configuration.startRotation)
-                                coversAtMostRegion(pipApp.defaultWindowName, displayBounds)
-                            }
-                            // Ensure that the pip window does not obscure the keyboard
-                            tag(TAG_IME_VISIBLE) {
-                                isAboveWindow(IME_WINDOW_NAME, pipApp.defaultWindowName)
-                            }
-                        }
-                    }
-                }
-            }
-
-            return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation,
-                testSpec, supportedRotations = listOf(Surface.ROTATION_0),
-                repetitions = 5)
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance()
+                .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0),
+                    repetitions = 5)
         }
     }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
index f10bd7f..97afc65 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
@@ -16,21 +16,24 @@
 
 package com.android.wm.shell.flicker.pip
 
+import android.platform.test.annotations.Postsubmit
 import android.view.Surface
 import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.dsl.runFlicker
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.helpers.exitSplitScreen
-import com.android.server.wm.flicker.helpers.isInSplitScreen
 import com.android.server.wm.flicker.helpers.launchSplitScreen
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
 import com.android.wm.shell.flicker.helpers.ImeAppHelper
 import com.android.wm.shell.flicker.helpers.FixedAppHelper
-import com.android.wm.shell.flicker.helpers.PipAppHelper
-import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.repetitions
+import com.android.server.wm.flicker.startRotation
 import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
-import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
 import com.android.wm.shell.flicker.removeAllTasksButHome
 import com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_ENTER_PIP
@@ -46,83 +49,103 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 @FlakyTest(bugId = 161435597)
-class PipLegacySplitScreenTest(
-    rotationName: String,
-    rotation: Int
-) : AppTestBase(rotationName, rotation) {
-    private val pipApp = PipAppHelper(instrumentation)
+class PipLegacySplitScreenTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
     private val imeApp = ImeAppHelper(instrumentation)
     private val testApp = FixedAppHelper(instrumentation)
+    private val displayBounds = WindowUtils.getDisplayBounds(testSpec.config.startRotation)
 
-    @Test
-    fun testShowsPipLaunchingToSplitScreen() {
-        runFlicker(instrumentation) {
-            withTestName { "testShowsPipLaunchingToSplitScreen" }
-            repeat { TEST_REPETITIONS }
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = {
+            withTestName { testSpec.name }
+            repeat { testSpec.config.repetitions }
             setup {
                 test {
                     removeAllTasksButHome()
                     device.wakeUpAndGoToHomeScreen()
-                    pipApp.launchViaIntent(stringExtras = mapOf(EXTRA_ENTER_PIP to "true"))
-                    waitForAnimationComplete()
+                    pipApp.launchViaIntent(stringExtras = mapOf(EXTRA_ENTER_PIP to "true"),
+                        wmHelper = wmHelper)
                 }
             }
             transitions {
-                testApp.launchViaIntent()
-                device.launchSplitScreen()
-                imeApp.launchViaIntent()
-                waitForAnimationComplete()
+                testApp.launchViaIntent(wmHelper)
+                device.launchSplitScreen(wmHelper)
+                imeApp.launchViaIntent(wmHelper)
             }
             teardown {
                 eachRun {
-                    imeApp.exit()
-                    if (device.isInSplitScreen()) {
-                        device.exitSplitScreen()
-                    }
-                    testApp.exit()
+                    imeApp.exit(wmHelper)
+                    testApp.exit(wmHelper)
                 }
                 test {
                     removeAllTasksButHome()
                 }
             }
-            assertions {
-                val displayBounds = WindowUtils.getDisplayBounds(rotation)
-                windowManagerTrace {
-                    all("PIP window must remain inside visible bounds") {
-                        coversAtMostRegion(pipApp.defaultWindowName, displayBounds)
-                    }
-                    end("Both app windows should be visible") {
-                        isVisible(testApp.defaultWindowName)
-                        isVisible(imeApp.defaultWindowName)
-                        noWindowsOverlap(setOf(testApp.defaultWindowName, imeApp.defaultWindowName))
-                    }
-                    navBarWindowIsAlwaysVisible()
-                    statusBarWindowIsAlwaysVisible()
-                }
-                layersTrace {
-                    all("PIP layer must remain inside visible bounds") {
-                        coversAtMostRegion(displayBounds, pipApp.defaultWindowName)
-                    }
-                    end("Both app layers should be visible") {
-                        coversAtMostRegion(displayBounds, testApp.defaultWindowName)
-                        coversAtMostRegion(displayBounds, imeApp.defaultWindowName)
-                    }
-                    navBarLayerIsAlwaysVisible()
-                    statusBarLayerIsAlwaysVisible()
-                }
-            }
+        }
+
+    @Postsubmit
+    @Test
+    fun pipWindowInsideDisplayBounds() {
+        testSpec.assertWm {
+            coversAtMost(displayBounds, pipApp.defaultWindowName)
         }
     }
 
-    companion object {
-        const val TEST_REPETITIONS = 2
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val supportedRotations = intArrayOf(Surface.ROTATION_0)
-            return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
+    @Postsubmit
+    @Test
+    fun bothAppWindowsVisible() {
+        testSpec.assertWmEnd {
+            isVisible(testApp.defaultWindowName)
+            isVisible(imeApp.defaultWindowName)
+            noWindowsOverlap(testApp.defaultWindowName, imeApp.defaultWindowName)
         }
     }
-}
\ No newline at end of file
+
+    @Postsubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Postsubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Postsubmit
+    @Test
+    fun pipLayerInsideDisplayBounds() {
+        testSpec.assertLayers {
+            coversAtMost(displayBounds, pipApp.defaultWindowName)
+        }
+    }
+
+    @Postsubmit
+    @Test
+    fun bothAppLayersVisible() {
+        testSpec.assertLayersEnd {
+            coversAtMost(displayBounds, testApp.defaultWindowName)
+            coversAtMost(displayBounds, imeApp.defaultWindowName)
+        }
+    }
+
+    @Postsubmit
+    @Test
+    fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Postsubmit
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    companion object {
+        const val TEST_REPETITIONS = 2
+
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
+                supportedRotations = listOf(Surface.ROTATION_0),
+                repetitions = TEST_REPETITIONS
+            )
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipMovesInAllApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipMovesInAllApps.kt
new file mode 100644
index 0000000..4c95da2
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipMovesInAllApps.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip
+
+import android.platform.test.annotations.Postsubmit
+import android.view.Surface
+import androidx.test.filters.RequiresDevice
+import com.android.launcher3.tapl.LauncherInstrumentation
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.google.common.truth.Truth
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test Pip launch.
+ * To run this test: `atest WMShellFlickerTests:PipMovesInAllApps`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class PipMovesInAllApps(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
+    private val taplInstrumentation = LauncherInstrumentation()
+
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = buildTransition(eachRun = false) {
+            teardown {
+                eachRun {
+                    taplInstrumentation.pressHome()
+                }
+            }
+            transitions {
+                taplInstrumentation.pressHome().switchToAllApps()
+                wmHelper.waitForAppTransitionIdle()
+            }
+        }
+
+    @Postsubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Postsubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Postsubmit
+    @Test
+    fun pipAlwaysVisible() = testSpec.assertWm { this.showsAppWindow(pipApp.windowName) }
+
+    @Postsubmit
+    @Test
+    fun pipWindowMovesUp() = testSpec.assertWmEnd {
+        val initialState = this.trace?.first()?.wmState
+            ?: error("Trace should not be empty")
+        val startPos = initialState.pinnedWindows.first().frame
+        val currPos = this.wmState.pinnedWindows.first().frame
+        val subject = Truth.assertWithMessage("Pip should have moved up")
+        subject.that(currPos.top).isGreaterThan(startPos.top)
+        subject.that(currPos.bottom).isGreaterThan(startPos.bottom)
+        subject.that(currPos.left).isEqualTo(startPos.left)
+        subject.that(currPos.right).isEqualTo(startPos.right)
+    }
+
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): List<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
+                supportedRotations = listOf(Surface.ROTATION_0), repetitions = 5)
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
index ade65ac..df835d2 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
@@ -16,11 +16,14 @@
 
 package com.android.wm.shell.flicker.pip
 
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.endRotation
 import com.android.server.wm.flicker.helpers.WindowUtils
 import com.android.server.wm.flicker.helpers.setRotation
@@ -34,6 +37,7 @@
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -44,73 +48,91 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class PipRotationTest(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : PipTransitionBase(InstrumentationRegistry.getInstrumentation()) {
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val fixedApp = FixedAppHelper(instrumentation)
-            val testSpec = getTransition(eachRun = false) { configuration ->
-                setup {
-                    test {
-                        fixedApp.launchViaIntent(wmHelper)
-                    }
-                    eachRun {
-                        setRotation(configuration.startRotation)
-                    }
+class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
+    private val fixedApp = FixedAppHelper(instrumentation)
+    private val startingBounds = WindowUtils.getDisplayBounds(testSpec.config.startRotation)
+    private val endingBounds = WindowUtils.getDisplayBounds(testSpec.config.endRotation)
+
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = buildTransition(eachRun = false) { configuration ->
+            setup {
+                test {
+                    fixedApp.launchViaIntent(wmHelper)
                 }
-                transitions {
-                    setRotation(configuration.endRotation)
-                }
-                teardown {
-                    eachRun {
-                        setRotation(Surface.ROTATION_0)
-                    }
-                }
-                assertions {
-                    val startingBounds = WindowUtils.getDisplayBounds(configuration.startRotation)
-                    val endingBounds = WindowUtils.getDisplayBounds(configuration.endRotation)
-
-                    presubmit {
-                        windowManagerTrace {
-                            navBarWindowIsAlwaysVisible()
-                            statusBarWindowIsAlwaysVisible()
-                        }
-
-                        layersTrace {
-                            noUncoveredRegions(configuration.startRotation,
-                                configuration.endRotation, allStates = false)
-                        }
-                    }
-
-                    flaky {
-                        layersTrace {
-                            navBarLayerIsAlwaysVisible(bugId = 140855415)
-                            statusBarLayerIsAlwaysVisible(bugId = 140855415)
-                            navBarLayerRotatesAndScales(configuration.startRotation,
-                                configuration.endRotation, bugId = 140855415)
-                            statusBarLayerRotatesScales(configuration.startRotation,
-                                configuration.endRotation, bugId = 140855415)
-
-                            start("appLayerRotates_StartingBounds", bugId = 140855415) {
-                                hasVisibleRegion(fixedApp.defaultWindowName, startingBounds)
-                                coversAtMostRegion(startingBounds, pipApp.defaultWindowName)
-                            }
-                            end("appLayerRotates_EndingBounds", bugId = 140855415) {
-                                hasVisibleRegion(fixedApp.defaultWindowName, endingBounds)
-                                coversAtMostRegion(endingBounds, pipApp.defaultWindowName)
-                            }
-                        }
-                    }
+                eachRun {
+                    setRotation(configuration.startRotation)
                 }
             }
+            transitions {
+                setRotation(configuration.endRotation)
+            }
+            teardown {
+                eachRun {
+                    setRotation(Surface.ROTATION_0)
+                }
+            }
+        }
 
-            return FlickerTestRunnerFactory.getInstance().buildRotationTest(instrumentation,
-                testSpec, supportedRotations = listOf(Surface.ROTATION_0, Surface.ROTATION_90),
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun noUncoveredRegions() = testSpec.noUncoveredRegions(testSpec.config.startRotation,
+        testSpec.config.endRotation, allStates = false)
+
+    @Presubmit
+    @Test
+    fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    @FlakyTest(bugId = 140855415)
+    @Test
+    fun navBarLayerRotatesAndScales() =
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation,
+            testSpec.config.endRotation)
+
+    @FlakyTest(bugId = 140855415)
+    @Test
+    fun statusBarLayerRotatesScales() =
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation,
+            testSpec.config.endRotation)
+
+    @FlakyTest(bugId = 140855415)
+    @Test
+    fun appLayerRotates_StartingBounds() {
+        testSpec.assertLayersStart {
+            coversExactly(startingBounds, fixedApp.defaultWindowName)
+            coversAtMost(startingBounds, pipApp.defaultWindowName)
+        }
+    }
+
+    @FlakyTest(bugId = 140855415)
+    @Test
+    fun appLayerRotates_EndingBounds() {
+        testSpec.assertLayersEnd {
+            coversExactly(endingBounds, fixedApp.defaultWindowName)
+            coversAtMost(endingBounds, pipApp.defaultWindowName)
+        }
+    }
+
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigRotationTests(
+                supportedRotations = listOf(Surface.ROTATION_0, Surface.ROTATION_90),
                 repetitions = 5)
         }
     }
-}
\ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTestBase.kt
index 96b6c91..7ba085d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTestBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTestBase.kt
@@ -16,13 +16,14 @@
 
 package com.android.wm.shell.flicker.pip
 
+import com.android.wm.shell.flicker.FlickerTestBase
 import com.android.wm.shell.flicker.helpers.PipAppHelper
 import org.junit.Before
 
 abstract class PipTestBase(
     rotationName: String,
     rotation: Int
-) : AppTestBase(rotationName, rotation) {
+) : FlickerTestBase(rotationName, rotation) {
     protected val testApp = PipAppHelper(instrumentation)
 
     @Before
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt
index f2d5899..1bb1d28 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt
@@ -16,11 +16,14 @@
 
 package com.android.wm.shell.flicker.pip
 
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.focusChanges
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
@@ -32,6 +35,7 @@
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -42,73 +46,89 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class PipToAppTest(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : PipTransitionBase(InstrumentationRegistry.getInstrumentation()) {
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): List<Array<Any>> {
-            val testSpec = getTransition(eachRun = true) { configuration ->
-                setup {
-                    eachRun {
-                        this.setRotation(configuration.startRotation)
-                    }
-                }
-                teardown {
-                    eachRun {
-                        this.setRotation(Surface.ROTATION_0)
-                    }
-                }
-                transitions {
-                    pipApp.expandPipWindowToApp(wmHelper)
-                }
-                assertions {
-                    presubmit {
-                        windowManagerTrace {
-                            navBarWindowIsAlwaysVisible()
-                            statusBarWindowIsAlwaysVisible()
-
-                            all("appReplacesPipWindow") {
-                                this.showsAppWindow(PIP_WINDOW_TITLE)
-                                    .then()
-                                    .showsAppWindowOnTop(pipApp.launcherName)
-                            }
-                        }
-
-                        layersTrace {
-                            statusBarLayerIsAlwaysVisible()
-                            statusBarLayerRotatesScales(configuration.startRotation,
-                                Surface.ROTATION_0)
-
-                            all("appReplacesPipLayer") {
-                                this.showsLayer(PIP_WINDOW_TITLE)
-                                    .then()
-                                    .showsLayer(pipApp.launcherName)
-                            }
-                        }
-                    }
-
-                    flaky {
-                        layersTrace {
-                            navBarLayerIsAlwaysVisible(bugId = 140855415)
-                            noUncoveredRegions(configuration.startRotation, Surface.ROTATION_0)
-                            navBarLayerRotatesAndScales(configuration.startRotation,
-                                Surface.ROTATION_0, bugId = 140855415)
-                        }
-
-                        eventLog {
-                            focusChanges(
-                                "NexusLauncherActivity", pipApp.launcherName,
-                                "NexusLauncherActivity", bugId = 151179149)
-                        }
-                    }
+class PipToAppTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = buildTransition(eachRun = true) { configuration ->
+            setup {
+                eachRun {
+                    this.setRotation(configuration.startRotation)
                 }
             }
+            teardown {
+                eachRun {
+                    this.setRotation(Surface.ROTATION_0)
+                }
+            }
+            transitions {
+                pipApp.expandPipWindowToApp(wmHelper)
+            }
+        }
 
-            return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation,
-                testSpec, supportedRotations = listOf(Surface.ROTATION_0), repetitions = 5)
+    @Presubmit
+    @Test
+    fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun appReplacesPipWindow() {
+        testSpec.assertWm {
+            this.showsAppWindow(PIP_WINDOW_TITLE)
+                .then()
+                .showsAppWindowOnTop(pipApp.launcherName)
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun statusBarLayerRotatesScales() =
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation, Surface.ROTATION_0)
+
+    @Presubmit
+    @Test
+    fun appReplacesPipLayer() {
+        testSpec.assertLayers {
+            this.isVisible(PIP_WINDOW_TITLE)
+                .then()
+                .isVisible(pipApp.launcherName)
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun noUncoveredRegions() =
+        testSpec.noUncoveredRegions(testSpec.config.startRotation, Surface.ROTATION_0)
+
+    @Presubmit
+    @Test
+    fun navBarLayerRotatesAndScales() =
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation, Surface.ROTATION_0)
+
+    @FlakyTest(bugId = 151179149)
+    @Test
+    fun focusChanges() = testSpec.focusChanges("NexusLauncherActivity",
+        pipApp.launcherName, "NexusLauncherActivity")
+
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): List<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance()
+                .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0),
+                    repetitions = 5)
         }
     }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToHomeTest.kt
deleted file mode 100644
index 1b44377..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToHomeTest.kt
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.flicker.pip
-
-import android.view.Surface
-import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
-import com.android.server.wm.flicker.focusChanges
-import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
-import com.android.server.wm.flicker.navBarLayerRotatesAndScales
-import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
-import com.android.server.wm.flicker.noUncoveredRegions
-import com.android.server.wm.flicker.startRotation
-import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
-import com.android.server.wm.flicker.statusBarLayerRotatesScales
-import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test Pip launch.
- * To run this test: `atest WMShellFlickerTests:PipToHomeTest`
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class PipToHomeTest(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : PipTransitionBase(InstrumentationRegistry.getInstrumentation()) {
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): List<Array<Any>> {
-            val testSpec = getTransition(eachRun = true) { configuration ->
-                setup {
-                    eachRun {
-                        this.setRotation(configuration.startRotation)
-                    }
-                }
-                teardown {
-                    eachRun {
-                        this.setRotation(Surface.ROTATION_0)
-                    }
-                }
-                transitions {
-                    pipApp.closePipWindow(wmHelper)
-                }
-                assertions {
-                    presubmit {
-                        windowManagerTrace {
-                            navBarWindowIsAlwaysVisible()
-                            statusBarWindowIsAlwaysVisible()
-
-                            all("pipWindowBecomesInvisible") {
-                                this.showsAppWindow(PIP_WINDOW_TITLE)
-                                    .then()
-                                    .hidesAppWindow(PIP_WINDOW_TITLE)
-                            }
-                        }
-
-                        layersTrace {
-                            statusBarLayerIsAlwaysVisible()
-                            statusBarLayerRotatesScales(configuration.startRotation,
-                                Surface.ROTATION_0)
-
-                            all("pipLayerBecomesInvisible") {
-                                this.showsLayer(PIP_WINDOW_TITLE)
-                                    .then()
-                                    .hidesLayer(PIP_WINDOW_TITLE)
-                            }
-                        }
-                    }
-
-                    postsubmit {
-                        layersTrace {
-                            navBarLayerIsAlwaysVisible()
-                            noUncoveredRegions(configuration.startRotation, Surface.ROTATION_0)
-                            navBarLayerRotatesAndScales(configuration.startRotation,
-                                Surface.ROTATION_0)
-                        }
-                    }
-
-                    flaky {
-                        eventLog {
-                            focusChanges(pipApp.launcherName, "NexusLauncherActivity",
-                                bugId = 151179149)
-                        }
-                    }
-                }
-            }
-
-            return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation,
-                testSpec, supportedRotations = listOf(Surface.ROTATION_0), repetitions = 5)
-        }
-    }
-}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransitionBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
similarity index 77%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransitionBase.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
index b1e404e..b0a9afe 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransitionBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
@@ -18,18 +18,27 @@
 
 import android.app.Instrumentation
 import android.content.Intent
-import android.os.Bundle
 import android.view.Surface
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.server.wm.flicker.FlickerBuilderProvider
+import com.android.server.wm.flicker.FlickerTestParameter
 import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.buildTestTag
+import com.android.server.wm.flicker.helpers.isRotated
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
 import com.android.server.wm.flicker.repetitions
+import com.android.server.wm.flicker.startRotation
 import com.android.wm.shell.flicker.helpers.PipAppHelper
 import com.android.wm.shell.flicker.removeAllTasksButHome
 import com.android.wm.shell.flicker.testapp.Components
 
-abstract class PipTransitionBase(protected val instrumentation: Instrumentation) {
+abstract class PipTransition(protected val testSpec: FlickerTestParameter) {
+    protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    protected val isRotated = testSpec.config.startRotation.isRotated()
+    protected val pipApp = PipAppHelper(instrumentation)
+    protected val broadcastActionTrigger = BroadcastActionTrigger(instrumentation)
+    protected abstract val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+
     // Helper class to process test actions by broadcast.
     protected class BroadcastActionTrigger(private val instrumentation: Instrumentation) {
         private fun createIntentWithAction(broadcastAction: String): Intent {
@@ -59,16 +68,20 @@
         }
     }
 
-    protected val pipApp = PipAppHelper(instrumentation)
-    protected val broadcastActionTrigger = BroadcastActionTrigger(instrumentation)
+    @FlickerBuilderProvider
+    fun buildFlicker(): FlickerBuilder {
+        return FlickerBuilder(instrumentation).apply {
+            withTestName { testSpec.name }
+            repeat { testSpec.config.repetitions }
+            transition(this, testSpec.config)
+        }
+    }
 
     /**
      * Gets a configuration that handles basic setup and teardown of pip tests
      */
-    protected val setupAndTeardown: FlickerBuilder.(Bundle) -> Unit
-        get() = { configuration ->
-            withTestName { buildTestTag(configuration) }
-            repeat { configuration.repetitions }
+    protected val setupAndTeardown: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = {
             setup {
                 test {
                     removeAllTasksButHome()
@@ -81,7 +94,7 @@
                 }
                 test {
                     removeAllTasksButHome()
-                    pipApp.exit()
+                    pipApp.exit(wmHelper)
                 }
             }
         }
@@ -95,11 +108,11 @@
      * @param extraSpec Addicional segment of flicker specification
      */
     @JvmOverloads
-    open fun getTransition(
+    protected open fun buildTransition(
         eachRun: Boolean,
         stringExtras: Map<String, String> = mapOf(Components.PipActivity.EXTRA_ENTER_PIP to "true"),
-        extraSpec: FlickerBuilder.(Bundle) -> Unit = {}
-    ): FlickerBuilder.(Bundle) -> Unit {
+        extraSpec: FlickerBuilder.(Map<String, Any?>) -> Unit = {}
+    ): FlickerBuilder.(Map<String, Any?>) -> Unit {
         return { configuration ->
             setupAndTeardown(this, configuration)
 
@@ -121,12 +134,12 @@
             teardown {
                 eachRun {
                     if (eachRun) {
-                        pipApp.exit()
+                        pipApp.exit(wmHelper)
                     }
                 }
                 test {
                     if (!eachRun) {
-                        pipApp.exit()
+                        pipApp.exit(wmHelper)
                     }
                     removeAllTasksButHome()
                 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
index c01bc94..7916ce5 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
@@ -16,21 +16,25 @@
 
 package com.android.wm.shell.flicker.pip
 
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.WindowUtils
 import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
-import com.android.wm.shell.flicker.pip.PipTransitionBase.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE
+import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE
 import com.android.wm.shell.flicker.testapp.Components.FixedActivity.EXTRA_FIXED_ORIENTATION
 import com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_ENTER_PIP
 import org.junit.Assert.assertEquals
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -41,75 +45,99 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class SetRequestedOrientationWhilePinnedTest(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : PipTransitionBase(InstrumentationRegistry.getInstrumentation()) {
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation,
-                supportedRotations = listOf(Surface.ROTATION_0),
-                repetitions = 1) { configuration ->
-                setupAndTeardown(this, configuration)
+    testSpec: FlickerTestParameter
+) : PipTransition(testSpec) {
+    private val startingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_0)
+    private val endingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_90)
 
-                setup {
-                    eachRun {
-                        // Launch the PiP activity fixed as landscape
-                        pipApp.launchViaIntent(wmHelper, stringExtras = mapOf(
-                            EXTRA_FIXED_ORIENTATION to ORIENTATION_LANDSCAPE.toString(),
-                            EXTRA_ENTER_PIP to "true"))
-                    }
-                }
-                teardown {
-                    eachRun {
-                        pipApp.exit()
-                    }
-                }
-                transitions {
-                    // Request that the orientation is set to landscape
-                    broadcastActionTrigger.requestOrientationForPip(ORIENTATION_LANDSCAPE)
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = { configuration ->
+            setupAndTeardown(this, configuration)
 
-                    // Launch the activity back into fullscreen and
-                    // ensure that it is now in landscape
-                    pipApp.launchViaIntent(wmHelper)
-                    wmHelper.waitForFullScreenApp(pipApp.component)
-                    wmHelper.waitForRotation(Surface.ROTATION_90)
-                    assertEquals(Surface.ROTATION_90, device.displayRotation)
-                }
-                assertions {
-                    val startingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_0)
-                    val endingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_90)
-                    presubmit {
-                        windowManagerTrace {
-                            start("PIP window must remain inside display") {
-                                coversAtMostRegion(pipApp.defaultWindowName, startingBounds)
-                            }
-                            end("pipApp shows on top") {
-                                showsAppWindowOnTop(pipApp.defaultWindowName)
-                            }
-                            navBarWindowIsAlwaysVisible()
-                            statusBarWindowIsAlwaysVisible()
-                        }
-                        layersTrace {
-                            start("PIP layer must remain inside display") {
-                                coversAtMostRegion(startingBounds, pipApp.defaultWindowName)
-                            }
-                            end("pipApp layer covers fullscreen") {
-                                hasVisibleRegion(pipApp.defaultWindowName, endingBounds)
-                            }
-                        }
-                    }
-
-                    flaky {
-                        layersTrace {
-                            navBarLayerIsAlwaysVisible(bugId = 140855415)
-                            statusBarLayerIsAlwaysVisible(bugId = 140855415)
-                        }
-                    }
+            setup {
+                eachRun {
+                    // Launch the PiP activity fixed as landscape
+                    pipApp.launchViaIntent(wmHelper, stringExtras = mapOf(
+                        EXTRA_FIXED_ORIENTATION to ORIENTATION_LANDSCAPE.toString(),
+                        EXTRA_ENTER_PIP to "true"))
                 }
             }
+            teardown {
+                eachRun {
+                    pipApp.exit(wmHelper)
+                }
+            }
+            transitions {
+                // Request that the orientation is set to landscape
+                broadcastActionTrigger.requestOrientationForPip(ORIENTATION_LANDSCAPE)
+
+                // Launch the activity back into fullscreen and
+                // ensure that it is now in landscape
+                pipApp.launchViaIntent(wmHelper)
+                wmHelper.waitForFullScreenApp(pipApp.component)
+                wmHelper.waitForRotation(Surface.ROTATION_90)
+                assertEquals(Surface.ROTATION_90, device.displayRotation)
+            }
+        }
+
+    @Presubmit
+    @Test
+    fun pipWindowInsideDisplay() {
+        testSpec.assertWmStart {
+            coversAtMost(startingBounds, pipApp.defaultWindowName)
         }
     }
-}
\ No newline at end of file
+
+    @Presubmit
+    @Test
+    fun pipAppShowsOnTop() {
+        testSpec.assertWmEnd {
+            showsAppWindowOnTop(pipApp.defaultWindowName)
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun pipLayerInsideDisplay() {
+        testSpec.assertLayersStart {
+            coversAtMost(startingBounds, pipApp.defaultWindowName)
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun pipAppLayerCoversFullScreen() {
+        testSpec.assertLayersEnd {
+            coversExactly(endingBounds, pipApp.defaultWindowName)
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance()
+                .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0),
+                    repetitions = 1)
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/Android.bp b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/Android.bp
index 26627a4..ea606df 100644
--- a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/Android.bp
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "WMShellFlickerTestApp",
     srcs: ["**/*.java"],
@@ -23,4 +32,4 @@
     name: "wmshell-flicker-test-components",
     srcs: ["src/**/Components.java"],
     sdk_version: "test_current",
-}
\ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/Android.bp b/libs/WindowManager/Shell/tests/unittest/Android.bp
index c0ab20d..fb53e535 100644
--- a/libs/WindowManager/Shell/tests/unittest/Android.bp
+++ b/libs/WindowManager/Shell/tests/unittest/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "WMShellUnitTests",
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
index a0e9f43..06b492d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
@@ -53,7 +53,6 @@
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.common.TransactionPool;
 import com.android.wm.shell.sizecompatui.SizeCompatUIController;
-import com.android.wm.shell.startingsurface.StartingSurfaceDrawer;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -79,8 +78,6 @@
     private Context mContext;
     @Mock
     private SizeCompatUIController mSizeCompatUI;
-    @Mock
-    private StartingSurfaceDrawer mStartingSurfaceDrawer;
 
     ShellTaskOrganizer mOrganizer;
     private final SyncTransactionQueue mSyncTransactionQueue = mock(SyncTransactionQueue.class);
@@ -116,7 +113,7 @@
                     .when(mTaskOrganizerController).registerTaskOrganizer(any());
         } catch (RemoteException e) {}
         mOrganizer = spy(new ShellTaskOrganizer(mTaskOrganizerController, mTestExecutor, mContext,
-                mSizeCompatUI, mStartingSurfaceDrawer));
+                mSizeCompatUI));
     }
 
     @Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestAppPairsController.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestAppPairsController.java
index e094158..27c6261 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestAppPairsController.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestAppPairsController.java
@@ -20,17 +20,17 @@
 
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayImeController;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
 
-import org.mockito.Mock;
-
 public class TestAppPairsController extends AppPairsController {
     private TestAppPairsPool mPool;
 
     public TestAppPairsController(ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue,
             DisplayController displayController) {
-        super(organizer, syncQueue, displayController, mock(ShellExecutor.class));
+        super(organizer, syncQueue, displayController, mock(ShellExecutor.class),
+                mock(DisplayImeController.class));
         mPool = new TestAppPairsPool(this);
         setPairsPool(mPool);
     }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubblePersistentRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubblePersistentRepositoryTest.kt
index 4160280..bdf75fc 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubblePersistentRepositoryTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubblePersistentRepositoryTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.bubbles.storage
 
+import android.app.ActivityTaskManager.INVALID_TASK_ID
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
 import com.android.wm.shell.ShellTestCase
@@ -31,9 +32,10 @@
 class BubblePersistentRepositoryTest : ShellTestCase() {
 
     private val bubbles = listOf(
-            BubbleEntity(0, "com.example.messenger", "shortcut-1", "key-1", 120, 0),
-            BubbleEntity(10, "com.example.chat", "alice and bob", "key-2", 0, 16537428, "title"),
-            BubbleEntity(0, "com.example.messenger", "shortcut-2", "key-3", 120, 0)
+            BubbleEntity(0, "com.example.messenger", "shortcut-1", "key-1", 120, 0, null, 1),
+            BubbleEntity(10, "com.example.chat", "alice and bob", "key-2", 0, 16537428, "title", 2),
+            BubbleEntity(0, "com.example.messenger", "shortcut-2", "key-3", 120, 0, null,
+                    INVALID_TASK_ID)
     )
     private lateinit var repository: BubblePersistentRepository
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleVolatileRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleVolatileRepositoryTest.kt
index dd1a6a5..05795fd 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleVolatileRepositoryTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleVolatileRepositoryTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.bubbles.storage
 
+import android.app.ActivityTaskManager.INVALID_TASK_ID
 import android.content.pm.LauncherApps
 import android.os.UserHandle
 import android.testing.AndroidTestingRunner
@@ -37,10 +38,12 @@
     private val user0 = UserHandle.of(0)
     private val user10 = UserHandle.of(10)
 
-    private val bubble1 = BubbleEntity(0, "com.example.messenger", "shortcut-1", "key-1", 120, 0)
+    private val bubble1 = BubbleEntity(0, "com.example.messenger", "shortcut-1", "key-1", 120, 0,
+            null, 1)
     private val bubble2 = BubbleEntity(10, "com.example.chat", "alice and bob",
-            "key-2", 0, 16537428, "title")
-    private val bubble3 = BubbleEntity(0, "com.example.messenger", "shortcut-2", "key-3", 120, 0)
+            "key-2", 0, 16537428, "title", 2)
+    private val bubble3 = BubbleEntity(0, "com.example.messenger", "shortcut-2", "key-3", 120, 0,
+            null, INVALID_TASK_ID)
 
     private val bubbles = listOf(bubble1, bubble2, bubble3)
 
@@ -105,13 +108,13 @@
 
     @Test
     fun testAddBubbleMatchesByKey() {
-        val bubble = BubbleEntity(0, "com.example.pkg", "shortcut-id", "key", 120, 0, "title")
+        val bubble = BubbleEntity(0, "com.example.pkg", "shortcut-id", "key", 120, 0, "title", 1)
         repository.addBubbles(listOf(bubble))
         assertEquals(bubble, repository.bubbles.get(0))
 
         // Same key as first bubble but different entry
         val bubbleModified = BubbleEntity(0, "com.example.pkg", "shortcut-id", "key", 120, 0,
-                "different title")
+                "different title", 2)
         repository.addBubbles(listOf(bubbleModified))
         assertEquals(bubbleModified, repository.bubbles.get(0))
     }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelperTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelperTest.kt
index e0891a9..839b873 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelperTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelperTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.bubbles.storage
 
+import android.app.ActivityTaskManager.INVALID_TASK_ID
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
 import com.android.wm.shell.ShellTestCase
@@ -31,17 +32,18 @@
 class BubbleXmlHelperTest : ShellTestCase() {
 
     private val bubbles = listOf(
-            BubbleEntity(0, "com.example.messenger", "shortcut-1", "k1", 120, 0),
-            BubbleEntity(10, "com.example.chat", "alice and bob", "k2", 0, 16537428, "title"),
-            BubbleEntity(0, "com.example.messenger", "shortcut-2", "k3", 120, 0)
+            BubbleEntity(0, "com.example.messenger", "shortcut-1", "k1", 120, 0, null, 1),
+            BubbleEntity(10, "com.example.chat", "alice and bob", "k2", 0, 16537428, "title", 2),
+            BubbleEntity(0, "com.example.messenger", "shortcut-2", "k3", 120, 0, null,
+                    INVALID_TASK_ID)
     )
 
     @Test
     fun testWriteXml() {
         val expectedEntries = """
-<bb uid="0" pkg="com.example.messenger" sid="shortcut-1" key="k1" h="120" hid="0" />
-<bb uid="10" pkg="com.example.chat" sid="alice and bob" key="k2" h="0" hid="16537428" t="title" />
-<bb uid="0" pkg="com.example.messenger" sid="shortcut-2" key="k3" h="120" hid="0" />
+<bb uid="0" pkg="com.example.messenger" sid="shortcut-1" key="k1" h="120" hid="0" tid="1" />
+<bb uid="10" pkg="com.example.chat" sid="alice and bob" key="k2" h="0" hid="16537428" t="title" tid="2" />
+<bb uid="0" pkg="com.example.messenger" sid="shortcut-2" key="k3" h="120" hid="0" tid="-1" />
         """.trimIndent()
         ByteArrayOutputStream().use {
             writeXml(it, bubbles)
@@ -56,9 +58,9 @@
         val src = """
 <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
 <bs v="1">
-<bb uid="0" pkg="com.example.messenger" sid="shortcut-1" key="k1" h="120" hid="0" />
-<bb uid="10" pkg="com.example.chat" sid="alice and bob" key="k2" h="0" hid="16537428" t="title" />
-<bb uid="0" pkg="com.example.messenger" sid="shortcut-2" key="k3" h="120" hid="0" />
+<bb uid="0" pkg="com.example.messenger" sid="shortcut-1" key="k1" h="120" hid="0" tid="1" />
+<bb uid="10" pkg="com.example.chat" sid="alice and bob" key="k2" h="0" hid="16537428" t="title" tid="2" />
+<bb uid="0" pkg="com.example.messenger" sid="shortcut-2" key="k3" h="120" hid="0" tid="-1" />
 </bs>
         """.trimIndent()
         val actual = readXml(ByteArrayInputStream(src.toByteArray(Charsets.UTF_8)))
@@ -79,4 +81,32 @@
         val actual = readXml(ByteArrayInputStream(src.toByteArray(Charsets.UTF_8)))
         assertEquals("failed parsing bubbles from xml\n$src", emptyList<BubbleEntity>(), actual)
     }
+
+    /**
+     * In S we changed the XML to include a taskId, version didn't increase because we can set a
+     * reasonable default for taskId (INVALID_TASK_ID) if it wasn't in the XML previously, this
+     * tests that that works.
+     */
+    @Test
+    fun testReadXMLWithoutTaskId() {
+        val expectedBubbles = listOf(
+                BubbleEntity(0, "com.example.messenger", "shortcut-1", "k1", 120, 0, null,
+                        INVALID_TASK_ID),
+                BubbleEntity(10, "com.example.chat", "alice and bob", "k2", 0, 16537428, "title",
+                        INVALID_TASK_ID),
+                BubbleEntity(0, "com.example.messenger", "shortcut-2", "k3", 120, 0, null,
+                        INVALID_TASK_ID)
+        )
+
+        val src = """
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<bs v="1">
+<bb uid="0" pkg="com.example.messenger" sid="shortcut-1" key="k1" h="120" hid="0" />
+<bb uid="10" pkg="com.example.chat" sid="alice and bob" key="k2" h="0" hid="16537428" t="title" />
+<bb uid="0" pkg="com.example.messenger" sid="shortcut-2" key="k3" h="120" hid="0" />
+</bs>
+        """.trimIndent()
+        val actual = readXml(ByteArrayInputStream(src.toByteArray(Charsets.UTF_8)))
+        assertEquals("failed parsing bubbles from xml\n$src", expectedBubbles, actual)
+    }
 }
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java
index 2b5b77e..88e754c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java
@@ -38,6 +38,12 @@
 
 import org.junit.Test;
 
+/**
+ * Tests for {@link DisplayLayout}.
+ *
+ * Build/Install/Run:
+ *  atest WMShellUnitTests:DisplayLayoutTest
+ */
 @SmallTest
 public class DisplayLayoutTest {
 
@@ -70,18 +76,6 @@
     @Test
     public void testRotate() {
         // Basic rotate utility
-        Rect testParent = new Rect(0, 0, 1000, 600);
-        Rect testInner = new Rect(40, 20, 120, 80);
-        Rect testResult = new Rect(testInner);
-        DisplayLayout.rotateBounds(testResult, testParent, 1);
-        assertEquals(new Rect(20, 880, 80, 960), testResult);
-        testResult.set(testInner);
-        DisplayLayout.rotateBounds(testResult, testParent, 2);
-        assertEquals(new Rect(880, 20, 960, 80), testResult);
-        testResult.set(testInner);
-        DisplayLayout.rotateBounds(testResult, testParent, 3);
-        assertEquals(new Rect(520, 40, 580, 120), testResult);
-
         Resources res = createResources(40, 50, false, 30, 40);
         DisplayInfo info = createDisplayInfo(1000, 1500, 60, ROTATION_0);
         DisplayLayout dl = new DisplayLayout(info, res, true, true);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TaskStackListenerImplTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TaskStackListenerImplTest.java
index 21bc32c..d8aebc2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TaskStackListenerImplTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TaskStackListenerImplTest.java
@@ -198,7 +198,7 @@
 
     @Test
     public void testOnActivityDismissingDockedStack() {
-        mImpl.onActivityDismissingDockedStack();
+        mImpl.onActivityDismissingDockedTask();
         verify(mCallback).onActivityDismissingDockedStack();
         verify(mOtherCallback).onActivityDismissingDockedStack();
     }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
index 5821eed..7b0e6b9 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
@@ -36,6 +36,7 @@
 
 import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.wm.shell.ShellTestCase;
+import com.android.wm.shell.common.DisplayImeController;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -49,6 +50,7 @@
 public class SplitLayoutTests extends ShellTestCase {
     @Mock SplitLayout.LayoutChangeListener mLayoutChangeListener;
     @Mock SurfaceControl mRootLeash;
+    @Mock DisplayImeController mDisplayImeController;
     private SplitLayout mSplitLayout;
 
     @Before
@@ -59,7 +61,8 @@
                 mContext,
                 getConfiguration(false),
                 mLayoutChangeListener,
-                b -> b.setParent(mRootLeash));
+                b -> b.setParent(mRootLeash),
+                mDisplayImeController);
     }
 
     @Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
index 698315a..86d0d82 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
@@ -29,6 +29,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.wm.shell.ShellTestCase;
+import com.android.wm.shell.common.DisplayImeController;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -42,6 +43,7 @@
 public class SplitWindowManagerTests extends ShellTestCase {
     @Mock SurfaceControl mSurfaceControl;
     @Mock SplitLayout mSplitLayout;
+    @Mock DisplayImeController mDisplayImeController;
     private SplitWindowManager mSplitWindowManager;
 
     @Before
@@ -50,7 +52,7 @@
         final Configuration configuration = new Configuration();
         configuration.setToDefaults();
         mSplitWindowManager = new SplitWindowManager("TestSplitDivider", mContext, configuration,
-                b -> b.setParent(mSurfaceControl));
+                b -> b.setParent(mSurfaceControl), mDisplayImeController);
         when(mSplitLayout.getDividerBounds()).thenReturn(
                 new Rect(0, 0, configuration.windowConfiguration.getBounds().width(),
                         configuration.windowConfiguration.getBounds().height()));
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedAnimationControllerTest.java
index 8d5139b..a8feb04 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedAnimationControllerTest.java
@@ -47,7 +47,6 @@
     private static final int TEST_BOUNDS_HEIGHT = 1000;
 
     OneHandedAnimationController mOneHandedAnimationController;
-    OneHandedTutorialHandler mTutorialHandler;
 
     @Mock
     private SurfaceControl mMockLeash;
@@ -60,8 +59,6 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-
-        mTutorialHandler = new OneHandedTutorialHandler(mContext, mMainExecutor);
         mOneHandedAnimationController = new OneHandedAnimationController(mContext);
     }
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizerTest.java
index e9c4af1..b0f52cf 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizerTest.java
@@ -59,7 +59,7 @@
     DisplayController mMockDisplayController;
 
     @Before
-    public void setUp() throws Exception {
+    public void setUp() {
         MockitoAnnotations.initMocks(this);
         mTestableLooper = TestableLooper.get(this);
         mToken = new WindowContainerToken(mMockRealToken);
@@ -82,15 +82,6 @@
     }
 
     @Test
-    public void testUnregisterOrganizer() {
-        mBackgroundPanelOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash);
-        mTestableLooper.processAllMessages();
-        mBackgroundPanelOrganizer.unregisterOrganizer();
-
-        assertThat(mBackgroundPanelOrganizer.getBackgroundSurface()).isNull();
-    }
-
-    @Test
     public void testShowBackgroundLayer() {
         mBackgroundPanelOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash);
         mBackgroundPanelOrganizer.showBackgroundPanelLayer();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
index f141167..1ad8fd3 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
@@ -16,19 +16,24 @@
 
 package com.android.wm.shell.onehanded;
 
+import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED;
+
 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.atLeastOnce;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.content.om.IOverlayManager;
 import android.os.Handler;
-import android.provider.Settings;
 import android.testing.AndroidTestingRunner;
+import android.util.ArrayMap;
 import android.view.Display;
+import android.view.SurfaceControl;
 
 import androidx.test.filters.SmallTest;
 
@@ -37,19 +42,17 @@
 import com.android.wm.shell.common.TaskStackListenerImpl;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 public class OneHandedControllerTest extends OneHandedTestCase {
     Display mDisplay;
-    OneHandedController mOneHandedController;
-    OneHandedTimeoutHandler mTimeoutHandler;
+    OneHandedController mSpiedOneHandedController;
+    OneHandedTimeoutHandler mSpiedTimeoutHandler;
 
     @Mock
     DisplayController mMockDisplayController;
@@ -64,8 +67,6 @@
     @Mock
     OneHandedGestureHandler mMockGestureHandler;
     @Mock
-    OneHandedTimeoutHandler mMockTimeoutHandler;
-    @Mock
     OneHandedUiEventLogger mMockUiEventLogger;
     @Mock
     IOverlayManager mMockOverlayManager;
@@ -74,14 +75,30 @@
     @Mock
     ShellExecutor mMockShellMainExecutor;
     @Mock
+    SurfaceControl mMockLeash;
+    @Mock
     Handler mMockShellMainHandler;
 
+    final boolean mDefaultEnabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
+            getTestContext().getContentResolver());
+    final boolean mDefaultSwipeToNotificationEnabled =
+            OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
+                    getTestContext().getContentResolver());
+    final boolean mDefaultTapAppToExitEnabled = OneHandedSettingsUtil.getSettingsTapsAppToExit(
+            getTestContext().getContentResolver());
+
     @Before
-    public void setUp() throws Exception {
+    public void setUp() {
         MockitoAnnotations.initMocks(this);
         mDisplay = mContext.getDisplay();
-        mTimeoutHandler = Mockito.spy(new OneHandedTimeoutHandler(mMockShellMainExecutor));
-        OneHandedController oneHandedController = new OneHandedController(
+        mSpiedTimeoutHandler = spy(new OneHandedTimeoutHandler(mMockShellMainExecutor));
+
+        when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay);
+        when(mMockDisplayAreaOrganizer.isInOneHanded()).thenReturn(false);
+        when(mMockDisplayAreaOrganizer.getDisplayAreaTokenMap()).thenReturn(new ArrayMap<>());
+        when(mMockBackgroundOrganizer.getBackgroundSurface()).thenReturn(mMockLeash);
+
+        mSpiedOneHandedController = spy(new OneHandedController(
                 mContext,
                 mMockDisplayController,
                 mMockBackgroundOrganizer,
@@ -89,16 +106,13 @@
                 mMockTouchHandler,
                 mMockTutorialHandler,
                 mMockGestureHandler,
-                mTimeoutHandler,
+                mSpiedTimeoutHandler,
                 mMockUiEventLogger,
                 mMockOverlayManager,
                 mMockTaskStackListener,
                 mMockShellMainExecutor,
-                mMockShellMainHandler);
-        mOneHandedController = Mockito.spy(oneHandedController);
-
-        when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay);
-        when(mMockDisplayAreaOrganizer.isInOneHanded()).thenReturn(false);
+                mMockShellMainHandler)
+        );
     }
 
     @Test
@@ -113,21 +127,36 @@
     }
 
     @Test
-    public void testRegisterOrganizer() {
-        verify(mMockDisplayAreaOrganizer, atLeastOnce()).registerOrganizer(anyInt());
+    public void testNoRegisterAndUnregisterInSameCall() {
+        if (mDefaultEnabled) {
+            verify(mMockDisplayAreaOrganizer, never()).unregisterOrganizer();
+        } else {
+            verify(mMockDisplayAreaOrganizer, never()).registerOrganizer(FEATURE_ONE_HANDED);
+        }
     }
 
     @Test
-    public void testStartOneHanded() {
-        mOneHandedController.startOneHanded();
+    public void testStartOneHandedShouldTriggerScheduleOffset() {
+        when(mMockDisplayAreaOrganizer.isInOneHanded()).thenReturn(false);
+        mSpiedOneHandedController.setOneHandedEnabled(true);
+        mSpiedOneHandedController.startOneHanded();
 
         verify(mMockDisplayAreaOrganizer).scheduleOffset(anyInt(), anyInt());
     }
 
     @Test
+    public void testStartOneHandedShouldNotTriggerScheduleOffset() {
+        mSpiedOneHandedController.setOneHandedEnabled(true);
+        when(mMockDisplayAreaOrganizer.isInOneHanded()).thenReturn(true);
+        mSpiedOneHandedController.startOneHanded();
+
+        verify(mMockDisplayAreaOrganizer, never()).scheduleOffset(anyInt(), anyInt());
+    }
+
+    @Test
     public void testStopOneHanded() {
         when(mMockDisplayAreaOrganizer.isInOneHanded()).thenReturn(false);
-        mOneHandedController.stopOneHanded();
+        mSpiedOneHandedController.stopOneHanded();
 
         verify(mMockDisplayAreaOrganizer, never()).scheduleOffset(anyInt(), anyInt());
     }
@@ -141,71 +170,121 @@
 
     @Test
     public void testRegisterTransitionCallback() {
-        OneHandedTransitionCallback callback = new OneHandedTransitionCallback() {};
-        mOneHandedController.registerTransitionCallback(callback);
+        OneHandedTransitionCallback callback = new OneHandedTransitionCallback() {
+        };
+        mSpiedOneHandedController.registerTransitionCallback(callback);
 
         verify(mMockDisplayAreaOrganizer).registerTransitionCallback(callback);
     }
 
-
     @Test
-    public void testStopOneHanded_shouldRemoveTimer() {
-        mOneHandedController.stopOneHanded();
+    public void testStopOneHandedShouldRemoveTimer() {
+        when(mMockDisplayAreaOrganizer.isInOneHanded()).thenReturn(true);
+        mSpiedOneHandedController.stopOneHanded();
 
-        verify(mTimeoutHandler).removeTimer();
+        verify(mSpiedTimeoutHandler, atLeastOnce()).removeTimer();
     }
 
     @Test
-    public void testUpdateIsEnabled() {
-        final boolean enabled = true;
-        mOneHandedController.setOneHandedEnabled(enabled);
+    public void testUpdateEnabled() {
+        mSpiedOneHandedController.setOneHandedEnabled(true);
 
-        verify(mMockTouchHandler, atLeastOnce()).onOneHandedEnabled(enabled);
+        verify(mMockTouchHandler, atLeastOnce()).onOneHandedEnabled(mDefaultEnabled);
+        verify(mMockGestureHandler, atLeastOnce()).onOneHandedEnabled(
+                mDefaultEnabled || mDefaultSwipeToNotificationEnabled);
     }
 
     @Test
-    public void testUpdateSwipeToNotificationIsEnabled() {
-        final boolean enabled = true;
-        mOneHandedController.setSwipeToNotificationEnabled(enabled);
+    public void testUpdateSwipeToNotification() {
+        mSpiedOneHandedController.setSwipeToNotificationEnabled(mDefaultSwipeToNotificationEnabled);
 
-        verify(mMockTouchHandler, atLeastOnce()).onOneHandedEnabled(enabled);
+        verify(mMockTouchHandler, atLeastOnce()).onOneHandedEnabled(mDefaultEnabled);
+        verify(mMockGestureHandler, atLeastOnce()).onOneHandedEnabled(
+                mDefaultEnabled || mDefaultSwipeToNotificationEnabled);
     }
 
-    @Ignore("b/167943723, refactor it and fix it")
     @Test
-    public void tesSettingsObserver_updateTapAppToExit() {
-        Settings.Secure.putInt(mContext.getContentResolver(),
-                Settings.Secure.TAPS_APP_TO_EXIT, 1);
-
-        verify(mOneHandedController).setTaskChangeToExit(true);
+    public void testSettingsObserverUpdateTapAppToExit() {
+        mSpiedOneHandedController.onTaskChangeExitSettingChanged();
+        if (mDefaultTapAppToExitEnabled) {
+            verify(mMockTaskStackListener, atLeastOnce()).addListener(any());
+        } else {
+            verify(mMockTaskStackListener, atLeastOnce()).removeListener(any());
+        }
     }
 
-    @Ignore("b/167943723, refactor it and fix it")
     @Test
-    public void tesSettingsObserver_updateEnabled() {
-        Settings.Secure.putInt(mContext.getContentResolver(),
-                Settings.Secure.ONE_HANDED_MODE_ENABLED, 1);
+    public void testSettingsObserverUpdateEnabled() {
+        mSpiedOneHandedController.onEnabledSettingChanged();
 
-        verify(mOneHandedController).setOneHandedEnabled(true);
+        verify(mSpiedOneHandedController).setOneHandedEnabled(mDefaultEnabled);
     }
 
-    @Ignore("b/167943723, refactor it and fix it")
     @Test
-    public void tesSettingsObserver_updateTimeout() {
-        Settings.Secure.putInt(mContext.getContentResolver(),
-                Settings.Secure.ONE_HANDED_MODE_TIMEOUT,
-                OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS);
+    public void testSettingsObserverUpdateTimeout() {
+        mSpiedOneHandedController.onTimeoutSettingChanged();
 
-        verify(mMockTimeoutHandler).setTimeout(
-                OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS);
+        verify(mSpiedTimeoutHandler, atLeastOnce()).setTimeout(anyInt());
     }
 
-    @Ignore("b/167943723, refactor it and fix it")
     @Test
-    public void tesSettingsObserver_updateSwipeToNotification() {
-        Settings.Secure.putInt(mContext.getContentResolver(),
-                Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 1);
+    public void testSettingsObserverUpdateSwipeToNotification() {
+        mSpiedOneHandedController.onSwipeToNotificationEnabledSettingChanged();
 
-        verify(mOneHandedController).setSwipeToNotificationEnabled(true);
+        // Swipe to notification function is opposite with one handed mode function
+        if (mDefaultSwipeToNotificationEnabled) {
+            verify(mSpiedOneHandedController).setSwipeToNotificationEnabled(
+                    mDefaultSwipeToNotificationEnabled);
+        } else {
+            verify(mSpiedOneHandedController, never()).setSwipeToNotificationEnabled(
+                    mDefaultSwipeToNotificationEnabled);
+        }
+    }
+
+    @Test
+    public void testLockedOneHandedDisabled() {
+        // Default mLockDisabled is false
+        assertThat(mSpiedOneHandedController.isLockedDisabled()).isFalse();
+
+        mSpiedOneHandedController.setOneHandedEnabled(true);
+        mSpiedOneHandedController.setLockedDisabled(false /* locked */, true /* enabled */);
+
+        // If mOneHandedEnabled == enabled, then keep unlocked
+        assertThat(mSpiedOneHandedController.isLockedDisabled()).isFalse();
+
+        // If prefer locked enabled state and 'mOneHandedEnabled == enabled', then unlocked
+        mSpiedOneHandedController.setLockedDisabled(true /* locked */, true /* enabled */);
+
+        assertThat(mSpiedOneHandedController.isLockedDisabled()).isFalse();
+
+        // If prefer locked disabled state and 'mOneHandedEnabled != enabled', then locked disabled
+        mSpiedOneHandedController.setLockedDisabled(true /* locked */, false /* enabled */);
+
+        assertThat(mSpiedOneHandedController.isLockedDisabled()).isTrue();
+
+        // If prefer unlock disabled state and 'mOneHandedEnabled != enabled', then unlocked
+        mSpiedOneHandedController.setLockedDisabled(false /* locked */, false /* enabled */);
+
+        assertThat(mSpiedOneHandedController.isLockedDisabled()).isFalse();
+    }
+
+    @Test
+    public void testKeyguardShowingLockOneHandedDisabled() {
+        when(mMockDisplayAreaOrganizer.isInOneHanded()).thenReturn(false);
+        mSpiedOneHandedController.setOneHandedEnabled(true);
+        mSpiedOneHandedController.setLockedDisabled(true /* locked */, false /* enabled */);
+        mSpiedOneHandedController.startOneHanded();
+
+        verify(mMockDisplayAreaOrganizer, never()).scheduleOffset(anyInt(), anyInt());
+    }
+
+    @Test
+    public void testResetKeyguardShowingLockOneHandedDisabled() {
+        when(mMockDisplayAreaOrganizer.isInOneHanded()).thenReturn(false);
+        mSpiedOneHandedController.setOneHandedEnabled(true);
+        mSpiedOneHandedController.setLockedDisabled(false /* locked */, false /* enabled */);
+        mSpiedOneHandedController.startOneHanded();
+
+        verify(mMockDisplayAreaOrganizer).scheduleOffset(anyInt(), anyInt());
     }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java
index 01162b5c..7a826c1 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java
@@ -27,6 +27,7 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -37,6 +38,7 @@
 import android.view.Display;
 import android.view.Surface;
 import android.view.SurfaceControl;
+import android.window.DisplayAreaAppearedInfo;
 import android.window.DisplayAreaInfo;
 import android.window.IWindowContainerToken;
 import android.window.WindowContainerToken;
@@ -53,15 +55,19 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
+    static final int DISPLAYAREA_INFO_COUNT = 3;
     static final int DISPLAY_WIDTH = 1000;
     static final int DISPLAY_HEIGHT = 1000;
 
     DisplayAreaInfo mDisplayAreaInfo;
     Display mDisplay;
-    OneHandedDisplayAreaOrganizer mDisplayAreaOrganizer;
+    OneHandedDisplayAreaOrganizer mSpiedDisplayAreaOrganizer;
     OneHandedTutorialHandler mTutorialHandler;
     OneHandedAnimationController.OneHandedTransitionAnimator mFakeAnimator;
     WindowContainerToken mToken;
@@ -86,6 +92,8 @@
     @Mock
     ShellExecutor mMockShellMainExecutor;
 
+    List<DisplayAreaAppearedInfo> mDisplayAreaAppearedInfoList = new ArrayList<>();
+
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
@@ -112,170 +120,195 @@
         when(mMockLeash.getWidth()).thenReturn(DISPLAY_WIDTH);
         when(mMockLeash.getHeight()).thenReturn(DISPLAY_HEIGHT);
 
-        mDisplayAreaOrganizer = spy(new OneHandedDisplayAreaOrganizer(mContext,
+        mSpiedDisplayAreaOrganizer = spy(new OneHandedDisplayAreaOrganizer(mContext,
                 mMockDisplayController,
                 mMockAnimationController,
                 mTutorialHandler,
                 mMockBackgroundOrganizer,
                 mMockShellMainExecutor));
+
+        for (int i = 0; i < DISPLAYAREA_INFO_COUNT; i++) {
+            mDisplayAreaAppearedInfoList.add(getDummyDisplayAreaInfo());
+        }
+        doReturn(mDisplayAreaAppearedInfoList).when(mSpiedDisplayAreaOrganizer).registerOrganizer(
+                FEATURE_ONE_HANDED);
+    }
+
+    private DisplayAreaAppearedInfo getDummyDisplayAreaInfo() {
+        return new DisplayAreaAppearedInfo(mDisplayAreaInfo, mMockLeash);
+    }
+
+    @Test
+    public void testRegisterDisplayAreaOrganizer() {
+        assertThat(mSpiedDisplayAreaOrganizer.registerOrganizer(FEATURE_ONE_HANDED)).isNotNull();
     }
 
     @Test
     public void testOnDisplayAreaAppeared() {
-        mDisplayAreaOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash);
+        mDisplayAreaAppearedInfoList.forEach(
+                (info) -> mSpiedDisplayAreaOrganizer.onDisplayAreaAppeared(
+                        info.getDisplayAreaInfo(),
+                        info.getLeash()));
 
         verify(mMockAnimationController, never()).getAnimator(any(), any(), any(), any());
     }
 
     @Test
     public void testOnDisplayAreaVanished() {
-        mDisplayAreaOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash);
-        mDisplayAreaOrganizer.onDisplayAreaVanished(mDisplayAreaInfo);
+        mDisplayAreaAppearedInfoList.forEach(
+                (info) -> mSpiedDisplayAreaOrganizer.onDisplayAreaAppeared(
+                        info.getDisplayAreaInfo(),
+                        info.getLeash()));
 
-        assertThat(mDisplayAreaOrganizer.mDisplayAreaTokenMap).isEmpty();
+        mDisplayAreaAppearedInfoList.forEach(
+                (info) -> mSpiedDisplayAreaOrganizer.onDisplayAreaVanished(
+                        info.getDisplayAreaInfo()));
+
+        verify(mSpiedDisplayAreaOrganizer, times(DISPLAYAREA_INFO_COUNT)).onDisplayAreaVanished(
+                any());
     }
 
     @Test
     public void testRotation_portrait_0_to_landscape_90() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 0 -> 90
-        mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_90,
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_90,
                 mMockWindowContainerTransaction);
-        verify(mDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
+        verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
     }
 
     @Test
     public void testRotation_portrait_0_to_seascape_270() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 0 -> 270
-        mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_270,
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_270,
                 mMockWindowContainerTransaction);
-        verify(mDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
+        verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
     }
 
     @Test
     public void testRotation_portrait_180_to_landscape_90() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 180 -> 90
-        mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_90,
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_90,
                 mMockWindowContainerTransaction);
-        verify(mDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
+        verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
     }
 
     @Test
     public void testRotation_portrait_180_to_seascape_270() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 180 -> 270
-        mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_270,
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_270,
                 mMockWindowContainerTransaction);
-        verify(mDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
+        verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
     }
 
     @Test
     public void testRotation_landscape_90_to_portrait_0() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 90 -> 0
-        mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_0,
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_0,
                 mMockWindowContainerTransaction);
-        verify(mDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
+        verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
     }
 
     @Test
     public void testRotation_landscape_90_to_portrait_180() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 90 -> 180
-        mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_180,
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_180,
                 mMockWindowContainerTransaction);
-        verify(mDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
+        verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
     }
 
     @Test
     public void testRotation_Seascape_270_to_portrait_0() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 270 -> 0
-        mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_0,
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_0,
                 mMockWindowContainerTransaction);
-        verify(mDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
+        verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
     }
 
     @Test
     public void testRotation_seascape_90_to_portrait_180() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 270 -> 180
-        mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_180,
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_180,
                 mMockWindowContainerTransaction);
-        verify(mDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
+        verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
     }
 
     @Test
     public void testRotation_portrait_0_to_portrait_0() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 0 -> 0
-        mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_0,
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_0,
                 mMockWindowContainerTransaction);
-        verify(mDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
+        verify(mSpiedDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
     }
 
     @Test
     public void testRotation_portrait_0_to_portrait_180() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 0 -> 180
-        mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_180,
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_180,
                 mMockWindowContainerTransaction);
-        verify(mDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
+        verify(mSpiedDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
     }
 
     @Test
     public void testRotation_portrait_180_to_portrait_180() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 180 -> 180
-        mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_180,
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_180,
                 mMockWindowContainerTransaction);
-        verify(mDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
+        verify(mSpiedDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
     }
 
     @Test
     public void testRotation_portrait_180_to_portrait_0() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 180 -> 0
-        mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_0,
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_0,
                 mMockWindowContainerTransaction);
-        verify(mDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
+        verify(mSpiedDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
     }
 
     @Test
     public void testRotation_landscape_90_to_landscape_90() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 90 -> 90
-        mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_90,
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_90,
                 mMockWindowContainerTransaction);
-        verify(mDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
+        verify(mSpiedDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
     }
 
     @Test
     public void testRotation_landscape_90_to_seascape_270() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 90 -> 270
-        mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_270,
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_270,
                 mMockWindowContainerTransaction);
-        verify(mDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
+        verify(mSpiedDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
     }
 
     @Test
     public void testRotation_seascape_270_to_seascape_270() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 270 -> 270
-        mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_270,
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_270,
                 mMockWindowContainerTransaction);
-        verify(mDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
+        verify(mSpiedDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
     }
 
     @Test
     public void testRotation_seascape_90_to_landscape_90() {
         when(mMockLeash.isValid()).thenReturn(false);
         // Rotate 270 -> 90
-        mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_90,
+        mSpiedDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_90,
                 mMockWindowContainerTransaction);
-        verify(mDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
+        verify(mSpiedDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
     }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedGestureHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedGestureHandlerTest.java
index e5f2ff7..b275b70 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedGestureHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedGestureHandlerTest.java
@@ -18,10 +18,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.any;
-
 import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
+import android.view.ViewConfiguration;
 
 import androidx.test.filters.SmallTest;
 
@@ -29,7 +27,6 @@
 import com.android.wm.shell.common.ShellExecutor;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -38,7 +35,6 @@
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 public class OneHandedGestureHandlerTest extends OneHandedTestCase {
-    OneHandedTutorialHandler mTutorialHandler;
     OneHandedGestureHandler mGestureHandler;
     @Mock
     DisplayController mMockDisplayController;
@@ -46,11 +42,10 @@
     ShellExecutor mMockShellMainExecutor;
 
     @Before
-    public void setUp() throws Exception {
+    public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mTutorialHandler = new OneHandedTutorialHandler(mContext, mMockShellMainExecutor);
         mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController,
-                mMockShellMainExecutor);
+                ViewConfiguration.get(mTestContext), mMockShellMainExecutor);
     }
 
     @Test
@@ -68,16 +63,6 @@
         assertThat(mGestureHandler.mGestureEventCallback).isEqualTo(callback);
     }
 
-    @Ignore("b/167943723, refactor it and fix it")
-    @Test
-    public void testReceiveNewConfig_whenThreeButtonModeEnabled() {
-        mGestureHandler.onOneHandedEnabled(true);
-        mGestureHandler.onThreeButtonModeEnabled(true);
-
-        assertThat(mGestureHandler.mInputMonitor).isNotNull();
-        assertThat(mGestureHandler.mInputEventReceiver).isNotNull();
-    }
-
     @Test
     public void testOneHandedDisabled_shouldDisposeInputChannel() {
         mGestureHandler.onOneHandedEnabled(false);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedSettingsUtilTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedSettingsUtilTest.java
index f8c9d53..61643d8 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedSettingsUtilTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedSettingsUtilTest.java
@@ -28,7 +28,6 @@
 import android.net.Uri;
 import android.provider.Settings;
 import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
 
 import androidx.test.filters.SmallTest;
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTestCase.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTestCase.java
index 73a9534..32a188d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTestCase.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTestCase.java
@@ -19,88 +19,47 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import static com.android.wm.shell.onehanded.OneHandedController.SUPPORT_ONE_HANDED_MODE;
-import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
 
 import static org.junit.Assume.assumeTrue;
 
 import android.content.Context;
 import android.hardware.display.DisplayManager;
 import android.os.SystemProperties;
-import android.provider.Settings;
+import android.testing.TestableContext;
 
 import androidx.test.platform.app.InstrumentationRegistry;
 
-import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
+import org.mockito.Answers;
+import org.mockito.Mock;
 
 /**
  * Base class that does One Handed specific setup.
  */
 public abstract class OneHandedTestCase {
-    static boolean sOrigEnabled;
-    static boolean sOrigTapsAppToExitEnabled;
-    static int sOrigTimeout;
-    static boolean sOrigSwipeToNotification;
-
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     protected Context mContext;
 
+    @Rule
+    public TestableContext mTestContext = new TestableContext(
+            InstrumentationRegistry.getInstrumentation().getTargetContext(), null);
+
     @Before
-    public void setupSettings() {
+    public void setUpContext() {
         assumeTrue(SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false));
 
-        final Context testContext =
-                InstrumentationRegistry.getInstrumentation().getTargetContext();
-        final DisplayManager dm = testContext.getSystemService(DisplayManager.class);
-        mContext = testContext.createDisplayContext(dm.getDisplay(DEFAULT_DISPLAY));
-
-        InstrumentationRegistry
-                .getInstrumentation()
-                .getUiAutomation()
-                .adoptShellPermissionIdentity();
-
-        sOrigEnabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
-                getContext().getContentResolver());
-        sOrigTimeout = OneHandedSettingsUtil.getSettingsOneHandedModeTimeout(
-                getContext().getContentResolver());
-        sOrigTapsAppToExitEnabled = OneHandedSettingsUtil.getSettingsTapsAppToExit(
-                getContext().getContentResolver());
-        sOrigSwipeToNotification = OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
-                getContext().getContentResolver());
-        Settings.Secure.putInt(getContext().getContentResolver(),
-                Settings.Secure.ONE_HANDED_MODE_ENABLED, 1);
-        Settings.Secure.putInt(getContext().getContentResolver(),
-                Settings.Secure.ONE_HANDED_MODE_TIMEOUT, ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS);
-        Settings.Secure.putInt(getContext().getContentResolver(),
-                Settings.Secure.TAPS_APP_TO_EXIT, 1);
-        Settings.Secure.putInt(getContext().getContentResolver(),
-                Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 1);
+        final DisplayManager dm = getTestContext().getSystemService(DisplayManager.class);
+        mContext = getTestContext().createDisplayContext(dm.getDisplay(DEFAULT_DISPLAY));
     }
 
-    @After
-    public void restoreSettings() {
-        if (mContext == null) {
-            // Return early if one-handed mode is not supported
-            return;
-        }
-
-        Settings.Secure.putInt(getContext().getContentResolver(),
-                Settings.Secure.ONE_HANDED_MODE_ENABLED, sOrigEnabled ? 1 : 0);
-        Settings.Secure.putInt(mContext.getContentResolver(),
-                Settings.Secure.ONE_HANDED_MODE_TIMEOUT, sOrigTimeout);
-        Settings.Secure.putInt(mContext.getContentResolver(),
-                Settings.Secure.TAPS_APP_TO_EXIT, sOrigTapsAppToExitEnabled ? 1 : 0);
-        Settings.Secure.putInt(mContext.getContentResolver(),
-                Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED,
-                sOrigSwipeToNotification ? 1 : 0);
-
-        InstrumentationRegistry
-                .getInstrumentation()
-                .getUiAutomation()
-                .dropShellPermissionIdentity();
+    /** return testable context */
+    protected TestableContext getTestContext() {
+        return mTestContext;
     }
 
+    /** return display context */
     protected Context getContext() {
         return mContext;
     }
 }
-
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTimeoutHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTimeoutHandlerTest.java
index bbe8891..98f240a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTimeoutHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTimeoutHandlerTest.java
@@ -27,24 +27,18 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.verify;
 
-import android.os.Looper;
 import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
 
 import androidx.test.filters.SmallTest;
 
 import com.android.wm.shell.TestShellExecutor;
-import com.android.wm.shell.common.ShellExecutor;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
-import java.util.ArrayList;
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 public class OneHandedTimeoutHandlerTest extends OneHandedTestCase {
@@ -52,7 +46,7 @@
     private TestShellExecutor mMainExecutor;
 
     @Before
-    public void setUp() throws Exception {
+    public void setUp() {
         MockitoAnnotations.initMocks(this);
         mMainExecutor = new TestShellExecutor();
         mTimeoutHandler = Mockito.spy(new OneHandedTimeoutHandler(mMainExecutor));
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTouchHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTouchHandlerTest.java
index d3b02ca..8660e0e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTouchHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTouchHandlerTest.java
@@ -18,8 +18,9 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.spy;
+
 import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
 
 import androidx.test.filters.SmallTest;
 
@@ -35,18 +36,20 @@
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 public class OneHandedTouchHandlerTest extends OneHandedTestCase {
+    boolean mIsEventCallback = false;
+
     private OneHandedTouchHandler mTouchHandler;
-
+    private OneHandedTimeoutHandler mSpiedTimeoutHandler;
+    private OneHandedTouchHandler.OneHandedTouchEventCallback mTouchEventCallback =
+            () -> mIsEventCallback = true;
     @Mock
-    private OneHandedTimeoutHandler mTimeoutHandler;
-
-    @Mock
-    private ShellExecutor mMainExecutor;
+    private ShellExecutor mMockShellMainExecutor;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mTouchHandler = new OneHandedTouchHandler(mTimeoutHandler, mMainExecutor);
+        mSpiedTimeoutHandler = spy(new OneHandedTimeoutHandler(mMockShellMainExecutor));
+        mTouchHandler = new OneHandedTouchHandler(mSpiedTimeoutHandler, mMockShellMainExecutor);
     }
 
     @Test
@@ -55,7 +58,7 @@
         };
         mTouchHandler.registerTouchEventListener(callback);
 
-        assertThat(mTouchHandler.mTouchEventCallback).isEqualTo(callback);
+        assertThat(mIsEventCallback).isFalse();
     }
 
     @Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java
index c3e6bf3..024cf7f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java
@@ -17,10 +17,12 @@
 package com.android.wm.shell.onehanded;
 
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.content.om.IOverlayManager;
 import android.os.Handler;
 import android.testing.AndroidTestingRunner;
+import android.util.ArrayMap;
 
 import androidx.test.filters.SmallTest;
 
@@ -37,12 +39,15 @@
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
-    @Mock
-    OneHandedTouchHandler mTouchHandler;
-    OneHandedTutorialHandler mTutorialHandler;
-    OneHandedGestureHandler mGestureHandler;
     OneHandedTimeoutHandler mTimeoutHandler;
     OneHandedController mOneHandedController;
+
+    @Mock
+    OneHandedGestureHandler mMockGestureHandler;
+    @Mock
+    OneHandedTouchHandler mMockTouchHandler;
+    @Mock
+    OneHandedTutorialHandler mMockTutorialHandler;
     @Mock
     DisplayController mMockDisplayController;
     @Mock
@@ -64,18 +69,17 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mTutorialHandler = new OneHandedTutorialHandler(mContext, mMockShellMainExecutor);
         mTimeoutHandler = new OneHandedTimeoutHandler(mMockShellMainExecutor);
-        mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController,
-                mMockShellMainExecutor);
+
+        when(mMockDisplayAreaOrganizer.getDisplayAreaTokenMap()).thenReturn(new ArrayMap<>());
         mOneHandedController = new OneHandedController(
                 getContext(),
                 mMockDisplayController,
                 mMockBackgroundOrganizer,
                 mMockDisplayAreaOrganizer,
-                mTouchHandler,
-                mTutorialHandler,
-                mGestureHandler,
+                mMockTouchHandler,
+                mMockTutorialHandler,
+                mMockGestureHandler,
                 mTimeoutHandler,
                 mMockUiEventLogger,
                 mMockOverlayManager,
@@ -86,6 +90,6 @@
 
     @Test
     public void testRegisterForDisplayAreaOrganizer() {
-        verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mTutorialHandler);
+        verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mMockTutorialHandler);
     }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
index 3147dab..63b9413 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.pip;
 
+import static android.util.RotationUtils.rotateBounds;
 import static android.view.Surface.ROTATION_0;
 import static android.view.Surface.ROTATION_90;
 
@@ -37,7 +38,6 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.wm.shell.ShellTestCase;
-import com.android.wm.shell.common.DisplayLayout;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -141,7 +141,7 @@
         // Apply fraction 1 to compute the end value.
         animator.applySurfaceControlTransaction(mLeash, new DummySurfaceControlTx(), 1);
         final Rect rotatedEndBounds = new Rect(endBounds);
-        DisplayLayout.rotateBounds(rotatedEndBounds, endBounds, ROTATION_90);
+        rotateBounds(rotatedEndBounds, endBounds, ROTATION_90);
 
         assertEquals("Expect 90 degree rotated bounds", rotatedEndBounds, animator.mCurrentValue);
     }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
index cfe8463..f2b4e97 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
@@ -124,7 +124,7 @@
         final ComponentName component1 = new ComponentName(mContext, "component1");
         when(mMockPipBoundsState.getLastPipComponentName()).thenReturn(component1);
 
-        mPipController.mPinnedStackListener.onActivityHidden(component1);
+        mPipController.mPinnedTaskListener.onActivityHidden(component1);
 
         verify(mMockPipBoundsState).setLastPipComponentName(null);
     }
@@ -135,7 +135,7 @@
         final ComponentName component2 = new ComponentName(mContext, "component2");
         when(mMockPipBoundsState.getLastPipComponentName()).thenReturn(component1);
 
-        mPipController.mPinnedStackListener.onActivityHidden(component2);
+        mPipController.mPinnedTaskListener.onActivityHidden(component2);
 
         verify(mMockPipBoundsState, never()).setLastPipComponentName(null);
     }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatHintPopupTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatHintPopupTest.java
new file mode 100644
index 0000000..9845d46
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatHintPopupTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.sizecompatui;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.verify;
+
+import android.content.res.Configuration;
+import android.os.IBinder;
+import android.testing.AndroidTestingRunner;
+import android.view.LayoutInflater;
+import android.widget.Button;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.R;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.ShellTestCase;
+import com.android.wm.shell.common.DisplayLayout;
+import com.android.wm.shell.common.SyncTransactionQueue;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for {@link SizeCompatHintPopup}.
+ *
+ * Build/Install/Run:
+ *  atest WMShellUnitTests:SizeCompatHintPopupTest
+ */
+@RunWith(AndroidTestingRunner.class)
+@SmallTest
+public class SizeCompatHintPopupTest extends ShellTestCase {
+
+    @Mock private SyncTransactionQueue mSyncTransactionQueue;
+    @Mock private IBinder mActivityToken;
+    @Mock private ShellTaskOrganizer.TaskListener mTaskListener;
+    @Mock private DisplayLayout mDisplayLayout;
+
+    private SizeCompatUILayout mLayout;
+    private SizeCompatHintPopup mHint;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        final int taskId = 1;
+        mLayout = new SizeCompatUILayout(mSyncTransactionQueue, mContext, new Configuration(),
+                taskId, mActivityToken, mTaskListener, mDisplayLayout, false /* hasShownHint*/);
+        mHint = (SizeCompatHintPopup)
+                LayoutInflater.from(mContext).inflate(R.layout.size_compat_mode_hint, null);
+        mHint.inject(mLayout);
+
+        spyOn(mLayout);
+    }
+
+    @Test
+    public void testOnClick() {
+        doNothing().when(mLayout).dismissHint();
+
+        final Button button = mHint.findViewById(R.id.got_it);
+        button.performClick();
+
+        verify(mLayout).dismissHint();
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButtonTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButtonTest.java
index d9086a6..5a43925 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButtonTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButtonTest.java
@@ -19,13 +19,13 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 
 import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
 import android.content.res.Configuration;
 import android.os.IBinder;
 import android.testing.AndroidTestingRunner;
 import android.view.LayoutInflater;
+import android.widget.ImageButton;
 
 import androidx.test.filters.SmallTest;
 
@@ -71,45 +71,25 @@
         mButton.inject(mLayout);
 
         spyOn(mLayout);
-        spyOn(mButton);
-        doNothing().when(mButton).showHint();
     }
 
     @Test
     public void testOnClick() {
         doNothing().when(mLayout).onRestartButtonClicked();
 
-        mButton.onClick(mButton);
+        final ImageButton button = mButton.findViewById(R.id.size_compat_restart_button);
+        button.performClick();
 
         verify(mLayout).onRestartButtonClicked();
     }
 
     @Test
     public void testOnLongClick() {
-        verify(mButton, never()).showHint();
+        doNothing().when(mLayout).onRestartButtonLongClicked();
 
-        mButton.onLongClick(mButton);
+        final ImageButton button = mButton.findViewById(R.id.size_compat_restart_button);
+        button.performLongClick();
 
-        verify(mButton).showHint();
-    }
-
-    @Test
-    public void testOnAttachedToWindow_showHint() {
-        mLayout.mShouldShowHint = false;
-        mButton.onAttachedToWindow();
-
-        verify(mButton, never()).showHint();
-
-        mLayout.mShouldShowHint = true;
-        mButton.onAttachedToWindow();
-
-        verify(mButton).showHint();
-    }
-
-    @Test
-    public void testRemove() {
-        mButton.remove();
-
-        verify(mButton).dismissHint();
+        verify(mLayout).onRestartButtonLongClicked();
     }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUILayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUILayoutTest.java
index 236db44..f33cfe8 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUILayoutTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUILayoutTest.java
@@ -18,6 +18,7 @@
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.mockito.ArgumentMatchers.any;
@@ -27,6 +28,7 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
 import android.app.ActivityClient;
@@ -68,6 +70,7 @@
     @Mock private ShellTaskOrganizer.TaskListener mTaskListener;
     @Mock private DisplayLayout mDisplayLayout;
     @Mock private SizeCompatRestartButton mButton;
+    @Mock private SizeCompatHintPopup mHint;
     private Configuration mTaskConfig;
 
     private SizeCompatUILayout mLayout;
@@ -81,8 +84,13 @@
                 TASK_ID, mActivityToken, mTaskListener, mDisplayLayout, false /* hasShownHint*/);
 
         spyOn(mLayout);
-        spyOn(mLayout.mWindowManager);
-        doReturn(mButton).when(mLayout.mWindowManager).createSizeCompatUI();
+        spyOn(mLayout.mButtonWindowManager);
+        doReturn(mButton).when(mLayout.mButtonWindowManager).createSizeCompatButton();
+
+        final SizeCompatUIWindowManager hintWindowManager = mLayout.createHintWindowManager();
+        spyOn(hintWindowManager);
+        doReturn(mHint).when(hintWindowManager).createSizeCompatHint();
+        doReturn(hintWindowManager).when(mLayout).createHintWindowManager();
     }
 
     @Test
@@ -90,24 +98,45 @@
         // Not create button if IME is showing.
         mLayout.createSizeCompatButton(true /* isImeShowing */);
 
-        verify(mLayout.mWindowManager, never()).createSizeCompatUI();
+        verify(mLayout.mButtonWindowManager, never()).createSizeCompatButton();
         assertNull(mLayout.mButton);
+        assertNull(mLayout.mHintWindowManager);
+        assertNull(mLayout.mHint);
 
+        // Not create hint popup.
+        mLayout.mShouldShowHint = false;
         mLayout.createSizeCompatButton(false /* isImeShowing */);
 
-        verify(mLayout.mWindowManager).createSizeCompatUI();
+        verify(mLayout.mButtonWindowManager).createSizeCompatButton();
         assertNotNull(mLayout.mButton);
+        assertNull(mLayout.mHintWindowManager);
+        assertNull(mLayout.mHint);
+
+        // Create hint popup.
+        mLayout.release();
+        mLayout.mShouldShowHint = true;
+        mLayout.createSizeCompatButton(false /* isImeShowing */);
+
+        verify(mLayout.mButtonWindowManager, times(2)).createSizeCompatButton();
+        assertNotNull(mLayout.mButton);
+        assertNotNull(mLayout.mHintWindowManager);
+        verify(mLayout.mHintWindowManager).createSizeCompatHint();
+        assertNotNull(mLayout.mHint);
+        assertFalse(mLayout.mShouldShowHint);
     }
 
     @Test
     public void testRelease() {
         mLayout.createSizeCompatButton(false /* isImeShowing */);
+        final SizeCompatUIWindowManager hintWindowManager = mLayout.mHintWindowManager;
 
         mLayout.release();
 
         assertNull(mLayout.mButton);
-        verify(mButton).remove();
-        verify(mLayout.mWindowManager).release();
+        assertNull(mLayout.mHint);
+        verify(hintWindowManager).release();
+        assertNull(mLayout.mHintWindowManager);
+        verify(mLayout.mButtonWindowManager).release();
     }
 
     @Test
@@ -119,7 +148,7 @@
         mLayout.updateSizeCompatInfo(mTaskConfig, mActivityToken, mTaskListener,
                 false /* isImeShowing */);
 
-        verify(mLayout, never()).updateSurfacePosition();
+        verify(mLayout, never()).updateButtonSurfacePosition();
         verify(mLayout, never()).release();
         verify(mLayout, never()).createSizeCompatButton(anyBoolean());
 
@@ -140,7 +169,8 @@
         mLayout.updateSizeCompatInfo(newTaskConfiguration, mActivityToken, newTaskListener,
                 false /* isImeShowing */);
 
-        verify(mLayout).updateSurfacePosition();
+        verify(mLayout).updateButtonSurfacePosition();
+        verify(mLayout).updateHintSurfacePosition();
     }
 
     @Test
@@ -152,14 +182,16 @@
                 mContext.getResources(), false, false);
 
         mLayout.updateDisplayLayout(displayLayout1);
-        verify(mLayout).updateSurfacePosition();
+        verify(mLayout).updateButtonSurfacePosition();
+        verify(mLayout).updateHintSurfacePosition();
 
         // No update if the display bounds is the same.
         clearInvocations(mLayout);
         final DisplayLayout displayLayout2 = new DisplayLayout(displayInfo,
                 mContext.getResources(), false, false);
         mLayout.updateDisplayLayout(displayLayout2);
-        verify(mLayout, never()).updateSurfacePosition();
+        verify(mLayout, never()).updateButtonSurfacePosition();
+        verify(mLayout, never()).updateHintSurfacePosition();
     }
 
     @Test
@@ -203,4 +235,29 @@
 
         verify(ActivityClient.getInstance()).restartActivityProcessIfVisible(mActivityToken);
     }
+
+    @Test
+    public void testOnRestartButtonLongClicked_showHint() {
+        mLayout.dismissHint();
+
+        assertNull(mLayout.mHint);
+
+        mLayout.onRestartButtonLongClicked();
+
+        assertNotNull(mLayout.mHint);
+    }
+
+    @Test
+    public void testDismissHint() {
+        mLayout.onRestartButtonLongClicked();
+        final SizeCompatUIWindowManager hintWindowManager = mLayout.mHintWindowManager;
+        assertNotNull(mLayout.mHint);
+        assertNotNull(hintWindowManager);
+
+        mLayout.dismissHint();
+
+        assertNull(mLayout.mHint);
+        assertNull(mLayout.mHintWindowManager);
+        verify(hintWindowManager).release();
+    }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index d2d1812..74753aa 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -41,6 +41,7 @@
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.ShellTestCase;
 import com.android.wm.shell.TestRunningTaskInfoBuilder;
+import com.android.wm.shell.common.DisplayImeController;
 import com.android.wm.shell.common.SyncTransactionQueue;
 
 import org.junit.Before;
@@ -58,13 +59,14 @@
     @Mock private RootTaskDisplayAreaOrganizer mRootTDAOrganizer;
     @Mock private MainStage mMainStage;
     @Mock private SideStage mSideStage;
+    @Mock private DisplayImeController mDisplayImeController;
     private StageCoordinator mStageCoordinator;
 
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
         mStageCoordinator = new TestStageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue,
-                mRootTDAOrganizer, mTaskOrganizer, mMainStage, mSideStage);
+                mRootTDAOrganizer, mTaskOrganizer, mMainStage, mSideStage, mDisplayImeController);
     }
 
     @Test
@@ -94,9 +96,9 @@
 
         TestStageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
                 RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer,
-                MainStage mainStage, SideStage sideStage) {
+                MainStage mainStage, SideStage sideStage, DisplayImeController imeController) {
             super(context, displayId, syncQueue, rootTDAOrganizer, taskOrganizer, mainStage,
-                    sideStage);
+                    sideStage, imeController);
 
             // Prepare default TaskDisplayArea for testing.
             mDisplayAreaInfo = new DisplayAreaInfo(
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
index de7d6c7..b9af9ce 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
@@ -125,7 +125,7 @@
         final Handler mainLoop = new Handler(Looper.getMainLooper());
         final StartingWindowInfo windowInfo =
                 createWindowInfo(taskId, android.R.style.Theme);
-        mStartingSurfaceDrawer.addStartingWindow(windowInfo, mBinder);
+        mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder);
         waitHandlerIdle(mainLoop);
         verify(mStartingSurfaceDrawer).postAddWindow(
                 eq(taskId), eq(mBinder), any(), any(), any(), any());
@@ -143,7 +143,7 @@
         final Handler mainLoop = new Handler(Looper.getMainLooper());
         final StartingWindowInfo windowInfo =
                 createWindowInfo(taskId, 0);
-        mStartingSurfaceDrawer.addStartingWindow(windowInfo, mBinder);
+        mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder);
         waitHandlerIdle(mainLoop);
         verify(mStartingSurfaceDrawer).postAddWindow(
                 eq(taskId), eq(mBinder), any(), any(), any(), any());
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
index 5eca3e7..926108c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
@@ -41,6 +41,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.app.ActivityManager.RunningTaskInfo;
+import android.content.Context;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -58,6 +59,7 @@
 import androidx.annotation.Nullable;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.wm.shell.TestShellExecutor;
 import com.android.wm.shell.common.ShellExecutor;
@@ -78,6 +80,8 @@
 
     private final WindowOrganizer mOrganizer = mock(WindowOrganizer.class);
     private final TransactionPool mTransactionPool = mock(TransactionPool.class);
+    private final Context mContext =
+            InstrumentationRegistry.getInstrumentation().getTargetContext();
     private final TestShellExecutor mMainExecutor = new TestShellExecutor();
     private final ShellExecutor mAnimExecutor = new TestShellExecutor();
     private final TestTransitionHandler mDefaultHandler = new TestTransitionHandler();
@@ -90,8 +94,8 @@
 
     @Test
     public void testBasicTransitionFlow() {
-        Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mMainExecutor,
-                mAnimExecutor);
+        Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
+                mMainExecutor, mAnimExecutor);
         transitions.replaceDefaultHandlerForTest(mDefaultHandler);
 
         IBinder transitToken = new Binder();
@@ -109,8 +113,8 @@
 
     @Test
     public void testNonDefaultHandler() {
-        Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mMainExecutor,
-                mAnimExecutor);
+        Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
+                mMainExecutor, mAnimExecutor);
         transitions.replaceDefaultHandlerForTest(mDefaultHandler);
 
         final WindowContainerTransaction handlerWCT = new WindowContainerTransaction();
@@ -188,8 +192,8 @@
 
     @Test
     public void testRequestRemoteTransition() {
-        Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mMainExecutor,
-                mAnimExecutor);
+        Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
+                mMainExecutor, mAnimExecutor);
         transitions.replaceDefaultHandlerForTest(mDefaultHandler);
 
         final boolean[] remoteCalled = new boolean[]{false};
@@ -255,8 +259,8 @@
 
     @Test
     public void testRegisteredRemoteTransition() {
-        Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mMainExecutor,
-                mAnimExecutor);
+        Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
+                mMainExecutor, mAnimExecutor);
         transitions.replaceDefaultHandlerForTest(mDefaultHandler);
 
         final boolean[] remoteCalled = new boolean[]{false};
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index 4b4284a..aba0f1b 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -14,6 +14,23 @@
 
 // libandroidfw is partially built for the host (used by obbtool, aapt, and others)
 
+package {
+    default_applicable_licenses: ["frameworks_base_libs_androidfw_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_libs_androidfw_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_defaults {
     name: "libandroidfw_defaults",
     cflags: [
diff --git a/libs/androidfw/TEST_MAPPING b/libs/androidfw/TEST_MAPPING
index 777aa0b..766714c 100644
--- a/libs/androidfw/TEST_MAPPING
+++ b/libs/androidfw/TEST_MAPPING
@@ -1,10 +1,6 @@
 {
   "presubmit": [
     {
-      "name": "libandroidfw_tests",
-      "host": true
-    },
-    {
       "name": "CtsResourcesLoaderTests"
     }
   ]
diff --git a/libs/androidfw/fuzz/cursorwindow_fuzzer/Android.bp b/libs/androidfw/fuzz/cursorwindow_fuzzer/Android.bp
index b36ff09..3035a79 100644
--- a/libs/androidfw/fuzz/cursorwindow_fuzzer/Android.bp
+++ b/libs/androidfw/fuzz/cursorwindow_fuzzer/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_libs_androidfw_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_libs_androidfw_license"],
+}
+
 cc_fuzz {
     name: "cursorwindow_fuzzer",
     srcs: [
diff --git a/libs/androidfw/fuzz/resourcefile_fuzzer/Android.bp b/libs/androidfw/fuzz/resourcefile_fuzzer/Android.bp
index 77ef8df..b511244 100644
--- a/libs/androidfw/fuzz/resourcefile_fuzzer/Android.bp
+++ b/libs/androidfw/fuzz/resourcefile_fuzzer/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_libs_androidfw_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_libs_androidfw_license"],
+}
+
 cc_fuzz {
     name: "resourcefile_fuzzer",
     srcs: [
diff --git a/libs/hostgraphics/Android.bp b/libs/hostgraphics/Android.bp
index 3a99d41..f166fde 100644
--- a/libs/hostgraphics/Android.bp
+++ b/libs/hostgraphics/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_library_host_static {
     name: "libhostgraphics",
 
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 678b0ad..77ceda9 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -1,3 +1,33 @@
+package {
+    default_applicable_licenses: ["frameworks_base_libs_hwui_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_libs_hwui_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+        "SPDX-license-identifier-BSD",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_defaults {
     name: "hwui_defaults",
     defaults: [
diff --git a/libs/hwui/DamageAccumulator.cpp b/libs/hwui/DamageAccumulator.cpp
index b39f4f2..0bf9480 100644
--- a/libs/hwui/DamageAccumulator.cpp
+++ b/libs/hwui/DamageAccumulator.cpp
@@ -249,5 +249,20 @@
     mHead->pendingDirty.setEmpty();
 }
 
+const StretchEffect* DamageAccumulator::findNearestStretchEffect() const {
+    DirtyStack* frame = mHead;
+    while (frame->prev != frame) {
+        frame = frame->prev;
+        if (frame->type == TransformRenderNode) {
+            const auto& effect =
+                    frame->renderNode->properties().layerProperties().getStretchEffect();
+            if (!effect.isEmpty()) {
+                return &effect;
+            }
+        }
+    }
+    return nullptr;
+}
+
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/DamageAccumulator.h b/libs/hwui/DamageAccumulator.h
index 2faa9d0..89ee0e3 100644
--- a/libs/hwui/DamageAccumulator.h
+++ b/libs/hwui/DamageAccumulator.h
@@ -35,6 +35,7 @@
 struct DirtyStack;
 class RenderNode;
 class Matrix4;
+class StretchEffect;
 
 class DamageAccumulator {
     PREVENT_COPY_AND_ASSIGN(DamageAccumulator);
@@ -62,6 +63,8 @@
 
     void finish(SkRect* totalDirty);
 
+    const StretchEffect* findNearestStretchEffect() const;
+
 private:
     void pushCommon();
     void applyMatrix4Transform(DirtyStack* frame);
diff --git a/libs/hwui/FrameInfo.cpp b/libs/hwui/FrameInfo.cpp
index ce9b288..2448cc9 100644
--- a/libs/hwui/FrameInfo.cpp
+++ b/libs/hwui/FrameInfo.cpp
@@ -20,13 +20,12 @@
 namespace android {
 namespace uirenderer {
 
-const std::array<std::string, static_cast<int>(FrameInfoIndex::NumIndexes)> FrameInfoNames = {
+const std::array FrameInfoNames{
         "Flags",
         "FrameTimelineVsyncId",
         "IntendedVsync",
         "Vsync",
-        "OldestInputEvent",
-        "NewestInputEvent",
+        "InputEventId",
         "HandleInputStart",
         "AnimationStart",
         "PerformTraversalsStart",
@@ -40,6 +39,8 @@
         "DequeueBufferDuration",
         "QueueBufferDuration",
         "GpuCompleted",
+        "SwapBuffersCompleted",
+        "DisplayPresentTime",
 };
 
 static_assert(static_cast<int>(FrameInfoIndex::NumIndexes) == 20,
diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h
index 45a367f..912d04c5 100644
--- a/libs/hwui/FrameInfo.h
+++ b/libs/hwui/FrameInfo.h
@@ -28,15 +28,14 @@
 namespace android {
 namespace uirenderer {
 
-#define UI_THREAD_FRAME_INFO_SIZE 11
+static constexpr size_t UI_THREAD_FRAME_INFO_SIZE = 10;
 
 enum class FrameInfoIndex {
     Flags = 0,
     FrameTimelineVsyncId,
     IntendedVsync,
     Vsync,
-    OldestInputEvent,
-    NewestInputEvent,
+    InputEventId,
     HandleInputStart,
     AnimationStart,
     PerformTraversalsStart,
@@ -56,13 +55,14 @@
 
     GpuCompleted,
     SwapBuffersCompleted,
+    DisplayPresentTime,
 
     // Must be the last value!
     // Also must be kept in sync with FrameMetrics.java#FRAME_STATS_COUNT
     NumIndexes
 };
 
-extern const std::array<std::string, static_cast<int>(FrameInfoIndex::NumIndexes)> FrameInfoNames;
+extern const std::array<const char*, static_cast<int>(FrameInfoIndex::NumIndexes)> FrameInfoNames;
 
 namespace FrameInfoFlags {
 enum {
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index 4a2e30d..4eefe92 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -112,7 +112,7 @@
     std::lock_guard lock(mDataMutex);
 
     // Fast-path for jank-free frames
-    int64_t totalDuration = frame.duration(sFrameStart, FrameInfoIndex::FrameCompleted);
+    int64_t totalDuration = frame.duration(sFrameStart, FrameInfoIndex::SwapBuffersCompleted);
     if (mDequeueTimeForgiveness && frame[FrameInfoIndex::DequeueBufferDuration] > 500_us) {
         nsecs_t expectedDequeueDuration = mDequeueTimeForgiveness + frame[FrameInfoIndex::Vsync] -
                                           frame[FrameInfoIndex::IssueDrawCommandsStart];
@@ -219,7 +219,7 @@
 void JankTracker::dumpFrames(int fd) {
     dprintf(fd, "\n\n---PROFILEDATA---\n");
     for (size_t i = 0; i < static_cast<size_t>(FrameInfoIndex::NumIndexes); i++) {
-        dprintf(fd, "%s", FrameInfoNames[i].c_str());
+        dprintf(fd, "%s", FrameInfoNames[i]);
         dprintf(fd, ",");
     }
     for (size_t i = 0; i < mFrames.size(); i++) {
@@ -236,7 +236,6 @@
 }
 
 void JankTracker::reset() {
-    std::lock_guard lock(mDataMutex);
     mFrames.clear();
     mData->reset();
     (*mGlobalData)->reset();
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 64b8b71..170f731 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -384,10 +384,11 @@
 struct DrawTextBlob final : Op {
     static const auto kType = Type::DrawTextBlob;
     DrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint)
-            : blob(sk_ref_sp(blob)), x(x), y(y), paint(paint) {}
+        : blob(sk_ref_sp(blob)), x(x), y(y), paint(paint), drawTextBlobMode(gDrawTextBlobMode) {}
     sk_sp<const SkTextBlob> blob;
     SkScalar x, y;
     SkPaint paint;
+    DrawTextBlobMode drawTextBlobMode;
     void draw(SkCanvas* c, const SkMatrix&) const { c->drawTextBlob(blob.get(), x, y, paint); }
 };
 
@@ -832,6 +833,24 @@
     }
 }
 
+template<>
+constexpr color_transform_fn colorTransformForOp<DrawTextBlob>() {
+    return [](const void *opRaw, ColorTransform transform) {
+        const DrawTextBlob *op = reinterpret_cast<const DrawTextBlob*>(opRaw);
+        switch (op->drawTextBlobMode) {
+        case DrawTextBlobMode::HctOutline:
+            const_cast<SkPaint&>(op->paint).setColor(SK_ColorBLACK);
+            break;
+        case DrawTextBlobMode::HctInner:
+            const_cast<SkPaint&>(op->paint).setColor(SK_ColorWHITE);
+            break;
+        default:
+            transformPaint(transform, const_cast<SkPaint*>(&(op->paint)));
+            break;
+        }
+    };
+}
+
 #define X(T) colorTransformForOp<T>(),
 static const color_transform_fn color_transform_fns[] = {
 #include "DisplayListOps.in"
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 44f54ee..f5b2675 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -226,6 +226,9 @@
     if (!mProperties.getAllowForceDark()) {
         info.disableForceDark++;
     }
+    if (!mProperties.layerProperties().getStretchEffect().isEmpty()) {
+        info.stretchEffectCount++;
+    }
 
     uint32_t animatorDirtyMask = 0;
     if (CC_LIKELY(info.runAnimations)) {
@@ -267,6 +270,9 @@
     if (!mProperties.getAllowForceDark()) {
         info.disableForceDark--;
     }
+    if (!mProperties.layerProperties().getStretchEffect().isEmpty()) {
+        info.stretchEffectCount--;
+    }
     info.damageAccumulator->popTransform();
 }
 
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index 8fba9cf..0589f13 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -70,6 +70,7 @@
     setXferMode(other.xferMode());
     setColorFilter(other.getColorFilter());
     setImageFilter(other.getImageFilter());
+    mStretchEffect = other.mStretchEffect;
     return *this;
 }
 
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 1fddac4..28d2b4c 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -188,7 +188,7 @@
     }
 
     if (mCanvas->getSaveCount() == restoreCount + 1) {
-        SkCanvasPriv::DrawBehind(mCanvas, *filterPaint(paint));
+        SkCanvasPriv::DrawBehind(mCanvas, filterPaint(paint));
         this->restore();
     }
 }
@@ -431,15 +431,14 @@
     mCanvas->drawColor(color, mode);
 }
 
-SkiaCanvas::PaintCoW&& SkiaCanvas::filterPaint(PaintCoW&& paint) const {
+void SkiaCanvas::onFilterPaint(SkPaint& paint) {
     if (mPaintFilter) {
-        mPaintFilter->filter(&paint.writeable());
+        mPaintFilter->filter(&paint);
     }
-    return std::move(paint);
 }
 
 void SkiaCanvas::drawPaint(const SkPaint& paint) {
-    mCanvas->drawPaint(*filterPaint(paint));
+    mCanvas->drawPaint(filterPaint(paint));
 }
 
 // ----------------------------------------------------------------------------
@@ -457,13 +456,11 @@
         points += 2;
     }
 
-    apply_looper(&paint, [&](const SkPaint& p) {
-        mCanvas->drawPoints(mode, count, pts.get(), p);
-    });
+    applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawPoints(mode, count, pts.get(), p); });
 }
 
 void SkiaCanvas::drawPoint(float x, float y, const Paint& paint) {
-    apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawPoint(x, y, p); });
+    applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawPoint(x, y, p); });
 }
 
 void SkiaCanvas::drawPoints(const float* points, int count, const Paint& paint) {
@@ -472,9 +469,8 @@
 
 void SkiaCanvas::drawLine(float startX, float startY, float stopX, float stopY,
                           const Paint& paint) {
-    apply_looper(&paint, [&](const SkPaint& p) {
-        mCanvas->drawLine(startX, startY, stopX, stopY, p);
-    });
+    applyLooper(&paint,
+                [&](const SkPaint& p) { mCanvas->drawLine(startX, startY, stopX, stopY, p); });
 }
 
 void SkiaCanvas::drawLines(const float* points, int count, const Paint& paint) {
@@ -484,46 +480,44 @@
 
 void SkiaCanvas::drawRect(float left, float top, float right, float bottom, const Paint& paint) {
     if (CC_UNLIKELY(paint.nothingToDraw())) return;
-    apply_looper(&paint, [&](const SkPaint& p) {
+    applyLooper(&paint, [&](const SkPaint& p) {
         mCanvas->drawRect({left, top, right, bottom}, p);
     });
 }
 
 void SkiaCanvas::drawRegion(const SkRegion& region, const Paint& paint) {
     if (CC_UNLIKELY(paint.nothingToDraw())) return;
-    apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawRegion(region, p); });
+    applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawRegion(region, p); });
 }
 
 void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
                                const Paint& paint) {
     if (CC_UNLIKELY(paint.nothingToDraw())) return;
     SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
-    apply_looper(&paint, [&](const SkPaint& p) {
-        mCanvas->drawRoundRect(rect, rx, ry, p);
-    });
+    applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawRoundRect(rect, rx, ry, p); });
 }
 
 void SkiaCanvas::drawDoubleRoundRect(const SkRRect& outer, const SkRRect& inner,
                                 const Paint& paint) {
-    apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawDRRect(outer, inner, p); });
+    applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawDRRect(outer, inner, p); });
 }
 
 void SkiaCanvas::drawCircle(float x, float y, float radius, const Paint& paint) {
     if (CC_UNLIKELY(radius <= 0 || paint.nothingToDraw())) return;
-    apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawCircle(x, y, radius, p); });
+    applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawCircle(x, y, radius, p); });
 }
 
 void SkiaCanvas::drawOval(float left, float top, float right, float bottom, const Paint& paint) {
     if (CC_UNLIKELY(paint.nothingToDraw())) return;
     SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
-    apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawOval(oval, p); });
+    applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawOval(oval, p); });
 }
 
 void SkiaCanvas::drawArc(float left, float top, float right, float bottom, float startAngle,
                          float sweepAngle, bool useCenter, const Paint& paint) {
     if (CC_UNLIKELY(paint.nothingToDraw())) return;
     SkRect arc = SkRect::MakeLTRB(left, top, right, bottom);
-    apply_looper(&paint, [&](const SkPaint& p) {
+    applyLooper(&paint, [&](const SkPaint& p) {
         if (fabs(sweepAngle) >= 360.0f) {
             mCanvas->drawOval(arc, p);
         } else {
@@ -537,13 +531,11 @@
     if (CC_UNLIKELY(path.isEmpty() && (!path.isInverseFillType()))) {
         return;
     }
-    apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawPath(path, p); });
+    applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawPath(path, p); });
 }
 
 void SkiaCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const Paint& paint) {
-    apply_looper(&paint, [&](const SkPaint& p) {
-        mCanvas->drawVertices(vertices, mode, p);
-    });
+    applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawVertices(vertices, mode, p); });
 }
 
 // ----------------------------------------------------------------------------
@@ -552,7 +544,7 @@
 
 void SkiaCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) {
     auto image = bitmap.makeImage();
-    apply_looper(paint, [&](const SkPaint& p) {
+    applyLooper(paint, [&](const SkPaint& p) {
         auto sampling = SkSamplingOptions(p.getFilterQuality());
         mCanvas->drawImage(image, left, top, sampling, &p);
     });
@@ -562,7 +554,7 @@
     auto image = bitmap.makeImage();
     SkAutoCanvasRestore acr(mCanvas, true);
     mCanvas->concat(matrix);
-    apply_looper(paint, [&](const SkPaint& p) {
+    applyLooper(paint, [&](const SkPaint& p) {
         auto sampling = SkSamplingOptions(p.getFilterQuality());
         mCanvas->drawImage(image, 0, 0, sampling, &p);
     });
@@ -575,7 +567,7 @@
     SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
     SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
 
-    apply_looper(paint, [&](const SkPaint& p) {
+    applyLooper(paint, [&](const SkPaint& p) {
         auto sampling = SkSamplingOptions(p.getFilterQuality());
         mCanvas->drawImageRect(image, srcRect, dstRect, sampling, &p,
                                SkCanvas::kFast_SrcRectConstraint);
@@ -672,11 +664,11 @@
     pnt.setShader(image->makeShader(sampling));
 
     auto v = builder.detach();
-    apply_looper(&pnt, [&](const SkPaint& p) {
+    applyLooper(&pnt, [&](const SkPaint& p) {
         SkPaint copy(p);
         auto s = SkSamplingOptions(p.getFilterQuality());
         if (s != sampling) {
-            // apply_looper changed the quality?
+            // applyLooper changed the quality?
             copy.setShader(image->makeShader(s));
         }
         mCanvas->drawVertices(v, SkBlendMode::kModulate, copy);
@@ -707,7 +699,7 @@
     lattice.fBounds = nullptr;
     SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
     auto image = bitmap.makeImage();
-    apply_looper(paint, [&](const SkPaint& p) {
+    applyLooper(paint, [&](const SkPaint& p) {
         auto filter = SkSamplingOptions(p.getFilterQuality()).filter;
         mCanvas->drawImageLattice(image.get(), lattice, dst, filter, &p);
     });
@@ -746,9 +738,7 @@
 
     sk_sp<SkTextBlob> textBlob(builder.make());
 
-    apply_looper(&paintCopy, [&](const SkPaint& p) {
-        mCanvas->drawTextBlob(textBlob, 0, 0, p);
-    });
+    applyLooper(&paintCopy, [&](const SkPaint& p) { mCanvas->drawTextBlob(textBlob, 0, 0, p); });
     drawTextDecorations(x, y, totalAdvance, paintCopy);
 }
 
@@ -788,9 +778,7 @@
 
     sk_sp<SkTextBlob> textBlob(builder.make());
 
-    apply_looper(&paintCopy, [&](const SkPaint& p) {
-        mCanvas->drawTextBlob(textBlob, 0, 0, p);
-    });
+    applyLooper(&paintCopy, [&](const SkPaint& p) { mCanvas->drawTextBlob(textBlob, 0, 0, p); });
 }
 
 // ----------------------------------------------------------------------------
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index eac3f22..9ab2b10 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -169,53 +169,24 @@
                                   const Paint& paint, const SkPath& path, size_t start,
                                   size_t end) override;
 
-    /** This class acts as a copy on write SkPaint.
-     *
-     *  Initially this will be the SkPaint passed to the contructor.
-     *  The first time writable() is called this will become a copy of the
-     *  initial SkPaint (or a default SkPaint if nullptr).
-     */
-    struct PaintCoW {
-        PaintCoW(const SkPaint& that) : mPtr(&that) {}
-        PaintCoW(const SkPaint* ptr) : mPtr(ptr) {}
-        PaintCoW(const PaintCoW&) = delete;
-        PaintCoW(PaintCoW&&) = delete;
-        PaintCoW& operator=(const PaintCoW&) = delete;
-        PaintCoW& operator=(PaintCoW&&) = delete;
-        SkPaint& writeable() {
-            if (!mStorage) {
-                if (!mPtr) {
-                    mStorage.emplace();
-                } else {
-                    mStorage.emplace(*mPtr);
-                }
-                mPtr = &*mStorage;
-            }
-            return *mStorage;
-        }
-        operator const SkPaint*() const { return mPtr; }
-        const SkPaint* operator->() const { assert(mPtr); return mPtr; }
-        explicit operator bool() { return mPtr != nullptr; }
-    private:
-        const SkPaint* mPtr;
-        std::optional<SkPaint> mStorage;
-    };
+    void onFilterPaint(SkPaint& paint);
 
-    /** Filters the paint using the current paint filter.
-     *
-     *  @param paint the paint to filter. Will be initialized with the default
-     *      SkPaint before filtering if filtering is required.
-     */
-    PaintCoW&& filterPaint(PaintCoW&& paint) const;
+    SkPaint filterPaint(const SkPaint& src) {
+        SkPaint dst(src);
+        this->onFilterPaint(dst);
+        return dst;
+    }
 
     // proc(const SkPaint& modifiedPaint)
-    template <typename Proc> void apply_looper(const Paint* paint, Proc proc) {
-        SkPaint skp;
-        BlurDrawLooper* looper = nullptr;
-        if (paint) {
-            skp = *filterPaint(paint);
-            looper = paint->getLooper();
+    template <typename Proc>
+    void applyLooper(const Paint* paint, Proc proc, void (*preFilter)(SkPaint&) = nullptr) {
+        BlurDrawLooper* looper = paint ? paint->getLooper() : nullptr;
+        const SkPaint* skpPtr = paint;
+        SkPaint skp = skpPtr ? *skpPtr : SkPaint();
+        if (preFilter) {
+            preFilter(skp);
         }
+        this->onFilterPaint(skp);
         if (looper) {
             looper->apply(skp, [&](SkPoint offset, const SkPaint& modifiedPaint) {
                 mCanvas->save();
@@ -228,7 +199,6 @@
         }
     }
 
-
 private:
     struct SaveRec {
         int saveCount;
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index f2481f8..cc9094c 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -98,6 +98,8 @@
 
     const SkISize screenSize;
 
+    int stretchEffectCount = 0;
+
     struct Out {
         bool hasFunctors = false;
         // This is only updated if evaluateAnimations is true
diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp
index 146bf28..b046f45 100644
--- a/libs/hwui/hwui/Canvas.cpp
+++ b/libs/hwui/hwui/Canvas.cpp
@@ -110,16 +110,19 @@
             bool darken = channelSum < (128 * 3);
 
             // outline
+            gDrawTextBlobMode = DrawTextBlobMode::HctOutline;
             Paint outlinePaint(paint);
             simplifyPaint(darken ? SK_ColorWHITE : SK_ColorBLACK, &outlinePaint);
             outlinePaint.setStyle(SkPaint::kStrokeAndFill_Style);
             canvas->drawGlyphs(glyphFunc, glyphCount, outlinePaint, x, y, totalAdvance);
 
             // inner
+            gDrawTextBlobMode = DrawTextBlobMode::HctInner;
             Paint innerPaint(paint);
             simplifyPaint(darken ? SK_ColorBLACK : SK_ColorWHITE, &innerPaint);
             innerPaint.setStyle(SkPaint::kFill_Style);
             canvas->drawGlyphs(glyphFunc, glyphCount, innerPaint, x, y, totalAdvance);
+            gDrawTextBlobMode = DrawTextBlobMode::Normal;
         } else {
             // standard draw path
             canvas->drawGlyphs(glyphFunc, glyphCount, paint, x, y, totalAdvance);
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index fdfa288..d1bdb71 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -61,6 +61,14 @@
 class Paint;
 struct Typeface;
 
+enum class DrawTextBlobMode {
+    Normal,
+    HctOutline,
+    HctInner,
+};
+
+inline DrawTextBlobMode gDrawTextBlobMode = DrawTextBlobMode::Normal;
+
 class ANDROID_API Canvas {
 public:
     virtual ~Canvas(){};
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index df66981..f24ba5c 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -240,8 +240,8 @@
 static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
     LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
-            "Mismatched size expectations, given %d expected %d",
-            frameInfoSize, UI_THREAD_FRAME_INFO_SIZE);
+                        "Mismatched size expectations, given %d expected %zu", frameInfoSize,
+                        UI_THREAD_FRAME_INFO_SIZE);
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
     env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
     return proxy->syncAndDrawFrame();
diff --git a/libs/hwui/jni/android_graphics_RenderNode.cpp b/libs/hwui/jni/android_graphics_RenderNode.cpp
index 8023968..5f60437 100644
--- a/libs/hwui/jni/android_graphics_RenderNode.cpp
+++ b/libs/hwui/jni/android_graphics_RenderNode.cpp
@@ -25,6 +25,7 @@
 #include <renderthread/CanvasContext.h>
 #endif
 #include <TreeInfo.h>
+#include <effects/StretchEffect.h>
 #include <hwui/Paint.h>
 #include <utils/TraceUtils.h>
 
@@ -549,6 +550,7 @@
 // ----------------------------------------------------------------------------
 
 jmethodID gPositionListener_PositionChangedMethod;
+jmethodID gPositionListener_ApplyStretchMethod;
 jmethodID gPositionListener_PositionLostMethod;
 
 static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
@@ -571,6 +573,11 @@
             Matrix4 transform;
             info.damageAccumulator->computeCurrentTransform(&transform);
             const RenderProperties& props = node.properties();
+
+            if (info.stretchEffectCount) {
+                handleStretchEffect(info, transform);
+            }
+
             uirenderer::Rect bounds(props.getWidth(), props.getHeight());
             transform.mapRect(bounds);
 
@@ -613,7 +620,7 @@
             JNIEnv* env = jnienv();
             jobject localref = env->NewLocalRef(mWeakRef);
             if (CC_UNLIKELY(!localref)) {
-                jnienv()->DeleteWeakGlobalRef(mWeakRef);
+                env->DeleteWeakGlobalRef(mWeakRef);
                 mWeakRef = nullptr;
                 return;
             }
@@ -634,6 +641,32 @@
             return env;
         }
 
+        void handleStretchEffect(const TreeInfo& info, const Matrix4& transform) {
+            // Search up to find the nearest stretcheffect parent
+            const StretchEffect* effect = info.damageAccumulator->findNearestStretchEffect();
+            if (!effect) {
+                return;
+            }
+
+            uirenderer::Rect area = effect->stretchArea;
+            transform.mapRect(area);
+            JNIEnv* env = jnienv();
+
+            jobject localref = env->NewLocalRef(mWeakRef);
+            if (CC_UNLIKELY(!localref)) {
+                env->DeleteWeakGlobalRef(mWeakRef);
+                mWeakRef = nullptr;
+                return;
+            }
+#ifdef __ANDROID__  // Layoutlib does not support CanvasContext
+            env->CallVoidMethod(localref, gPositionListener_ApplyStretchMethod,
+                                info.canvasContext.getFrameNumber(), area.left, area.top,
+                                area.right, area.bottom, effect->stretchDirection.fX,
+                                effect->stretchDirection.fY, effect->maxStretchAmount);
+#endif
+            env->DeleteLocalRef(localref);
+        }
+
         void doUpdatePositionAsync(jlong frameNumber, jint left, jint top,
                 jint right, jint bottom) {
             ATRACE_NAME("Update SurfaceView position");
@@ -775,6 +808,8 @@
     jclass clazz = FindClassOrDie(env, "android/graphics/RenderNode$PositionUpdateListener");
     gPositionListener_PositionChangedMethod = GetMethodIDOrDie(env, clazz,
             "positionChanged", "(JIIII)V");
+    gPositionListener_ApplyStretchMethod =
+            GetMethodIDOrDie(env, clazz, "applyStretch", "(JFFFFFFF)V");
     gPositionListener_PositionLostMethod = GetMethodIDOrDie(env, clazz,
             "positionLost", "(J)V");
     return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 389fe7e..50eea31 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -105,7 +105,6 @@
     LightingInfo::updateLighting(lightGeometry, lightInfo);
     renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
                 SkMatrix::I());
-    layerUpdateQueue->clear();
 
     // Draw visual debugging features
     if (CC_UNLIKELY(Properties::showDirtyRegions ||
@@ -113,9 +112,14 @@
         SkCanvas* profileCanvas = surface->getCanvas();
         SkiaProfileRenderer profileRenderer(profileCanvas);
         profiler->draw(profileRenderer);
-        profileCanvas->flush();
     }
 
+    {
+        ATRACE_NAME("flush commands");
+        surface->flushAndSubmit();
+    }
+    layerUpdateQueue->clear();
+
     // Log memory statistics
     if (CC_UNLIKELY(Properties::debugLevel != kDebugDisabled)) {
         dumpResourceCacheUsage();
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 6456e36..1f73ac9 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -454,9 +454,6 @@
         renderOverdraw(clip, nodes, contentDrawBounds, surface, preTransform);
     }
 
-    ATRACE_NAME("flush commands");
-    surface->flushAndSubmit();
-
     Properties::skpCaptureEnabled = previousSkpEnabled;
 }
 
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index b288402..af7271e 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -170,55 +170,23 @@
 // Recording Canvas draw operations: Bitmaps
 // ----------------------------------------------------------------------------
 
-SkiaCanvas::PaintCoW&& SkiaRecordingCanvas::filterBitmap(PaintCoW&& paint) {
-    bool fixBlending = false;
-    bool fixAA = false;
-    if (paint) {
-        // kClear blend mode is drawn as kDstOut on HW for compatibility with Android O and
-        // older.
-        fixBlending = sApiLevel <= 27 && paint->getBlendMode() == SkBlendMode::kClear;
-        fixAA = paint->isAntiAlias();
+void SkiaRecordingCanvas::FilterForImage(SkPaint& paint) {
+    // kClear blend mode is drawn as kDstOut on HW for compatibility with Android O and
+    // older.
+    if (sApiLevel <= 27 && paint.getBlendMode() == SkBlendMode::kClear) {
+        paint.setBlendMode(SkBlendMode::kDstOut);
     }
 
-    if (fixBlending || fixAA) {
-        SkPaint& tmpPaint = paint.writeable();
-
-        if (fixBlending) {
-            tmpPaint.setBlendMode(SkBlendMode::kDstOut);
-        }
-
-        // disabling AA on bitmap draws matches legacy HWUI behavior
-        tmpPaint.setAntiAlias(false);
-    }
-
-    return filterPaint(std::move(paint));
+    // disabling AA on bitmap draws matches legacy HWUI behavior
+    paint.setAntiAlias(false);
 }
 
-static BlurDrawLooper* get_looper(const Paint* paint) {
-    return paint ? paint->getLooper() : nullptr;
+static SkFilterMode Paint_to_filter(const SkPaint& paint) {
+    return paint.getFilterQuality() != kNone_SkFilterQuality ? SkFilterMode::kLinear
+                                                             : SkFilterMode::kNearest;
 }
 
-template <typename Proc>
-void applyLooper(BlurDrawLooper* looper, const SkPaint* paint, Proc proc) {
-    if (looper) {
-        SkPaint p;
-        if (paint) {
-            p = *paint;
-        }
-        looper->apply(p, [&](SkPoint offset, const SkPaint& modifiedPaint) {
-            proc(offset.fX, offset.fY, &modifiedPaint);
-        });
-    } else {
-        proc(0, 0, paint);
-    }
-}
-
-static SkFilterMode Paint_to_filter(const SkPaint* paint) {
-    return paint && paint->getFilterQuality() != kNone_SkFilterQuality ? SkFilterMode::kLinear
-                                                                       : SkFilterMode::kNearest;
-}
-
-static SkSamplingOptions Paint_to_sampling(const SkPaint* paint) {
+static SkSamplingOptions Paint_to_sampling(const SkPaint& paint) {
     // Android only has 1-bit for "filter", so we don't try to cons-up mipmaps or cubics
     return SkSamplingOptions(Paint_to_filter(paint), SkMipmapMode::kNone);
 }
@@ -226,10 +194,12 @@
 void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) {
     sk_sp<SkImage> image = bitmap.makeImage();
 
-    applyLooper(get_looper(paint), filterBitmap(paint), [&](SkScalar x, SkScalar y,
-                const SkPaint* p) {
-        mRecorder.drawImage(image, left + x, top + y, Paint_to_sampling(p), p, bitmap.palette());
-    });
+    applyLooper(
+            paint,
+            [&](const SkPaint& p) {
+                mRecorder.drawImage(image, left, top, Paint_to_sampling(p), &p, bitmap.palette());
+            },
+            FilterForImage);
 
     // if image->unique() is true, then mRecorder.drawImage failed for some reason. It also means
     // it is not safe to store a raw SkImage pointer, because the image object will be destroyed
@@ -245,10 +215,12 @@
 
     sk_sp<SkImage> image = bitmap.makeImage();
 
-    applyLooper(get_looper(paint), filterBitmap(paint), [&](SkScalar x, SkScalar y,
-                const SkPaint* p) {
-        mRecorder.drawImage(image, x, y, Paint_to_sampling(p), p, bitmap.palette());
-    });
+    applyLooper(
+            paint,
+            [&](const SkPaint& p) {
+                mRecorder.drawImage(image, 0, 0, Paint_to_sampling(p), &p, bitmap.palette());
+            },
+            FilterForImage);
 
     if (!bitmap.isImmutable() && image.get() && !image->unique()) {
         mDisplayList->mMutableImages.push_back(image.get());
@@ -263,11 +235,13 @@
 
     sk_sp<SkImage> image = bitmap.makeImage();
 
-    applyLooper(get_looper(paint), filterBitmap(paint), [&](SkScalar x, SkScalar y,
-                const SkPaint* p) {
-        mRecorder.drawImageRect(image, srcRect, dstRect.makeOffset(x, y), Paint_to_sampling(p),
-                                p, SkCanvas::kFast_SrcRectConstraint, bitmap.palette());
-    });
+    applyLooper(
+            paint,
+            [&](const SkPaint& p) {
+                mRecorder.drawImageRect(image, srcRect, dstRect, Paint_to_sampling(p), &p,
+                                        SkCanvas::kFast_SrcRectConstraint, bitmap.palette());
+            },
+            FilterForImage);
 
     if (!bitmap.isImmutable() && image.get() && !image->unique() && !srcRect.isEmpty() &&
         !dstRect.isEmpty()) {
@@ -303,11 +277,12 @@
     // HWUI always draws 9-patches with linear filtering, regardless of the Paint.
     const SkFilterMode filter = SkFilterMode::kLinear;
 
-    applyLooper(get_looper(paint), filterBitmap(paint), [&](SkScalar x, SkScalar y,
-                const SkPaint* p) {
-        mRecorder.drawImageLattice(image, lattice, dst.makeOffset(x, y), filter, p,
-                                   bitmap.palette());
-    });
+    applyLooper(
+            paint,
+            [&](const SkPaint& p) {
+                mRecorder.drawImageLattice(image, lattice, dst, filter, &p, bitmap.palette());
+            },
+            FilterForImage);
 
     if (!bitmap.isImmutable() && image.get() && !image->unique() && !dst.isEmpty()) {
         mDisplayList->mMutableImages.push_back(image.get());
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
index 8d7a21a..ff03e0c 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
@@ -87,6 +87,8 @@
     std::unique_ptr<SkiaDisplayList> mDisplayList;
     StartReorderBarrierDrawable* mCurrentBarrier;
 
+    static void FilterForImage(SkPaint&);
+
     /**
      *  A new SkiaDisplayList is created or recycled if available.
      *
@@ -96,7 +98,7 @@
      */
     void initDisplayList(uirenderer::RenderNode* renderNode, int width, int height);
 
-    PaintCoW&& filterBitmap(PaintCoW&& paint);
+    using INHERITED = SkiaCanvas;
 };
 
 }  // namespace skiapipeline
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index ad6363b..1bd943f 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -17,14 +17,15 @@
 #include "SkiaVulkanPipeline.h"
 
 #include "DeferredLayerUpdater.h"
+#include "LightingInfo.h"
 #include "Readback.h"
 #include "ShaderCache.h"
-#include "LightingInfo.h"
 #include "SkiaPipeline.h"
 #include "SkiaProfileRenderer.h"
 #include "VkInteropFunctorDrawable.h"
 #include "renderstate/RenderState.h"
 #include "renderthread/Frame.h"
+#include "utils/TraceUtils.h"
 
 #include <SkSurface.h>
 #include <SkTypes.h>
@@ -73,8 +74,6 @@
     LightingInfo::updateLighting(lightGeometry, lightInfo);
     renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, backBuffer,
                 mVkSurface->getCurrentPreTransform());
-    ShaderCache::get().onVkFrameFlushed(mRenderThread.getGrContext());
-    layerUpdateQueue->clear();
 
     // Draw visual debugging features
     if (CC_UNLIKELY(Properties::showDirtyRegions ||
@@ -82,9 +81,14 @@
         SkCanvas* profileCanvas = backBuffer->getCanvas();
         SkiaProfileRenderer profileRenderer(profileCanvas);
         profiler->draw(profileRenderer);
-        profileCanvas->flush();
     }
 
+    {
+        ATRACE_NAME("flush commands");
+        mVkManager.finishFrame(backBuffer.get());
+    }
+    layerUpdateQueue->clear();
+
     // Log memory statistics
     if (CC_UNLIKELY(Properties::debugLevel != kDebugDisabled)) {
         dumpResourceCacheUsage();
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index b760db2..f69ddac 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -484,7 +484,8 @@
         // TODO(b/165985262): measure performance impact
         const auto vsyncId = mCurrentFrameInfo->get(FrameInfoIndex::FrameTimelineVsyncId);
         if (vsyncId != UiFrameInfoBuilder::INVALID_VSYNC_ID) {
-            const auto inputEventId = mCurrentFrameInfo->get(FrameInfoIndex::NewestInputEvent);
+            const auto inputEventId =
+                    static_cast<int32_t>(mCurrentFrameInfo->get(FrameInfoIndex::InputEventId));
             native_window_set_frame_timeline_info(mNativeSurface->getNativeWindow(), vsyncId,
                                                   inputEventId);
         }
@@ -591,7 +592,6 @@
 }
 
 void CanvasContext::finishFrame(FrameInfo* frameInfo) {
-
     // TODO (b/169858044): Consolidate this into a single call.
     mJankTracker.finishFrame(*frameInfo);
     mJankTracker.finishGpuDraw(*frameInfo);
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index b9568fc..423cc08 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -230,7 +230,10 @@
 }
 
 void RenderProxy::resetProfileInfo() {
-    mRenderThread.queue().runSync([=]() { mContext->resetFrameStats(); });
+    mRenderThread.queue().runSync([=]() {
+        std::lock_guard lock(mRenderThread.getJankDataMutex());
+        mContext->resetFrameStats();
+    });
 }
 
 uint32_t RenderProxy::frameTimePercentile(int percentile) {
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 3e7ce36..e93824d 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -31,6 +31,7 @@
 
 #include "Properties.h"
 #include "RenderThread.h"
+#include "pipeline/skia/ShaderCache.h"
 #include "renderstate/RenderState.h"
 #include "utils/TraceUtils.h"
 
@@ -476,17 +477,10 @@
     }
 }
 
-void VulkanManager::swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect) {
-    if (CC_UNLIKELY(Properties::waitForGpuCompletion)) {
-        ATRACE_NAME("Finishing GPU work");
-        mDeviceWaitIdle(mDevice);
-    }
-
-    VulkanSurface::NativeBufferInfo* bufferInfo = surface->getCurrentBufferInfo();
-    if (!bufferInfo) {
-        // If VulkanSurface::dequeueNativeBuffer failed earlier, then swapBuffers is a no-op.
-        return;
-    }
+void VulkanManager::finishFrame(SkSurface* surface) {
+    ATRACE_NAME("Vulkan finish frame");
+    ALOGE_IF(mSwapSemaphore != VK_NULL_HANDLE || mDestroySemaphoreContext != nullptr,
+             "finishFrame already has an outstanding semaphore");
 
     VkExportSemaphoreCreateInfo exportInfo;
     exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
@@ -499,32 +493,52 @@
     semaphoreInfo.flags = 0;
     VkSemaphore semaphore;
     VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
-    ALOGE_IF(VK_SUCCESS != err, "VulkanManager::swapBuffers(): Failed to create semaphore");
+    ALOGE_IF(VK_SUCCESS != err, "VulkanManager::makeSwapSemaphore(): Failed to create semaphore");
 
     GrBackendSemaphore backendSemaphore;
     backendSemaphore.initVulkan(semaphore);
 
-    int fenceFd = -1;
-    DestroySemaphoreInfo* destroyInfo =
-            new DestroySemaphoreInfo(mDestroySemaphore, mDevice, semaphore);
     GrFlushInfo flushInfo;
-    flushInfo.fNumSemaphores = 1;
-    flushInfo.fSignalSemaphores = &backendSemaphore;
-    flushInfo.fFinishedProc = destroy_semaphore;
-    flushInfo.fFinishedContext = destroyInfo;
-    GrSemaphoresSubmitted submitted = bufferInfo->skSurface->flush(
-            SkSurface::BackendSurfaceAccess::kPresent, flushInfo);
-    GrDirectContext* context = GrAsDirectContext(bufferInfo->skSurface->recordingContext());
+    if (err == VK_SUCCESS) {
+        mDestroySemaphoreContext = new DestroySemaphoreInfo(mDestroySemaphore, mDevice, semaphore);
+        flushInfo.fNumSemaphores = 1;
+        flushInfo.fSignalSemaphores = &backendSemaphore;
+        flushInfo.fFinishedProc = destroy_semaphore;
+        flushInfo.fFinishedContext = mDestroySemaphoreContext;
+    } else {
+        semaphore = VK_NULL_HANDLE;
+    }
+    GrSemaphoresSubmitted submitted =
+            surface->flush(SkSurface::BackendSurfaceAccess::kPresent, flushInfo);
+    GrDirectContext* context = GrAsDirectContext(surface->recordingContext());
     ALOGE_IF(!context, "Surface is not backed by gpu");
     context->submit();
-    if (submitted == GrSemaphoresSubmitted::kYes) {
+    if (semaphore != VK_NULL_HANDLE) {
+        if (submitted == GrSemaphoresSubmitted::kYes) {
+            mSwapSemaphore = semaphore;
+        } else {
+            destroy_semaphore(mDestroySemaphoreContext);
+            mDestroySemaphoreContext = nullptr;
+        }
+    }
+    skiapipeline::ShaderCache::get().onVkFrameFlushed(context);
+}
+
+void VulkanManager::swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect) {
+    if (CC_UNLIKELY(Properties::waitForGpuCompletion)) {
+        ATRACE_NAME("Finishing GPU work");
+        mDeviceWaitIdle(mDevice);
+    }
+
+    int fenceFd = -1;
+    if (mSwapSemaphore != VK_NULL_HANDLE) {
         VkSemaphoreGetFdInfoKHR getFdInfo;
         getFdInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
         getFdInfo.pNext = nullptr;
-        getFdInfo.semaphore = semaphore;
+        getFdInfo.semaphore = mSwapSemaphore;
         getFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
 
-        err = mGetSemaphoreFdKHR(mDevice, &getFdInfo, &fenceFd);
+        VkResult err = mGetSemaphoreFdKHR(mDevice, &getFdInfo, &fenceFd);
         ALOGE_IF(VK_SUCCESS != err, "VulkanManager::swapBuffers(): Failed to get semaphore Fd");
     } else {
         ALOGE("VulkanManager::swapBuffers(): Semaphore submission failed");
@@ -532,9 +546,11 @@
         std::lock_guard<std::mutex> lock(mGraphicsQueueMutex);
         mQueueWaitIdle(mGraphicsQueue);
     }
-    destroy_semaphore(destroyInfo);
+    destroy_semaphore(mDestroySemaphoreContext);
 
     surface->presentCurrentBuffer(dirtyRect, fenceFd);
+    mSwapSemaphore = VK_NULL_HANDLE;
+    mDestroySemaphoreContext = nullptr;
 }
 
 void VulkanManager::destroySurface(VulkanSurface* surface) {
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 121afc9..0912369 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -69,6 +69,7 @@
     void destroySurface(VulkanSurface* surface);
 
     Frame dequeueNextBuffer(VulkanSurface* surface);
+    void finishFrame(SkSurface* surface);
     void swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect);
 
     // Inserts a wait on fence command into the Vulkan command buffer.
@@ -200,6 +201,9 @@
     SwapBehavior mSwapBehavior = SwapBehavior::Discard;
     GrVkExtensions mExtensions;
     uint32_t mDriverVersion = 0;
+
+    VkSemaphore mSwapSemaphore = VK_NULL_HANDLE;
+    void* mDestroySemaphoreContext = nullptr;
 };
 
 } /* namespace renderthread */
diff --git a/libs/hwui/tests/common/TestContext.cpp b/libs/hwui/tests/common/TestContext.cpp
index 6a9a98d..898c64b 100644
--- a/libs/hwui/tests/common/TestContext.cpp
+++ b/libs/hwui/tests/common/TestContext.cpp
@@ -22,16 +22,16 @@
 namespace uirenderer {
 namespace test {
 
-const DisplayInfo& getDisplayInfo() {
-    static DisplayInfo info = [] {
-        DisplayInfo info;
+const ui::StaticDisplayInfo& getDisplayInfo() {
+    static ui::StaticDisplayInfo info = [] {
+        ui::StaticDisplayInfo info;
 #if HWUI_NULL_GPU
         info.density = 2.f;
 #else
         const sp<IBinder> token = SurfaceComposerClient::getInternalDisplayToken();
         LOG_ALWAYS_FATAL_IF(!token, "%s: No internal display", __FUNCTION__);
 
-        const status_t status = SurfaceComposerClient::getDisplayInfo(token, &info);
+        const status_t status = SurfaceComposerClient::getStaticDisplayInfo(token, &info);
         LOG_ALWAYS_FATAL_IF(status, "%s: Failed to get display info", __FUNCTION__);
 #endif
         return info;
diff --git a/libs/hwui/tests/common/TestContext.h b/libs/hwui/tests/common/TestContext.h
index 7d2f6d8..9d00366d 100644
--- a/libs/hwui/tests/common/TestContext.h
+++ b/libs/hwui/tests/common/TestContext.h
@@ -23,8 +23,8 @@
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
 #include <gui/SurfaceControl.h>
-#include <ui/DisplayInfo.h>
 #include <ui/DisplayMode.h>
+#include <ui/StaticDisplayInfo.h>
 #include <utils/Looper.h>
 
 #include <atomic>
@@ -36,7 +36,7 @@
 namespace uirenderer {
 namespace test {
 
-const DisplayInfo& getDisplayInfo();
+const ui::StaticDisplayInfo& getDisplayInfo();
 const ui::DisplayMode& getActiveDisplayMode();
 
 inline const ui::Size& getActiveDisplayResolution() {
diff --git a/libs/hwui/tests/unit/TypefaceTests.cpp b/libs/hwui/tests/unit/TypefaceTests.cpp
index ab23448..1a3dbe7 100644
--- a/libs/hwui/tests/unit/TypefaceTests.cpp
+++ b/libs/hwui/tests/unit/TypefaceTests.cpp
@@ -33,7 +33,7 @@
 
 constexpr char kRobotoVariable[] = "/system/fonts/Roboto-Regular.ttf";
 
-constexpr char kRegularFont[] = "/system/fonts/NotoSerif-Regular.ttf";
+constexpr char kRegularFont[] = "/system/fonts/NotoSerif.ttf";
 constexpr char kBoldFont[] = "/system/fonts/NotoSerif-Bold.ttf";
 constexpr char kItalicFont[] = "/system/fonts/NotoSerif-Italic.ttf";
 constexpr char kBoldItalicFont[] = "/system/fonts/NotoSerif-BoldItalic.ttf";
diff --git a/libs/incident/Android.bp b/libs/incident/Android.bp
index 438a92e..f322bff 100644
--- a/libs/incident/Android.bp
+++ b/libs/incident/Android.bp
@@ -13,6 +13,15 @@
 // limitations under the License.
 
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_defaults {
     name: "libincidentpriv_defaults",
 
@@ -125,6 +134,3 @@
         "libgmock",
     ],
 }
-
-
-
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index dca3501..55f932d 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_library_shared {
     name: "libinputservice",
     srcs: [
diff --git a/libs/input/MouseCursorController.h b/libs/input/MouseCursorController.h
index e6dfc4c..c0ab58b 100644
--- a/libs/input/MouseCursorController.h
+++ b/libs/input/MouseCursorController.h
@@ -20,7 +20,6 @@
 #include <gui/DisplayEventReceiver.h>
 #include <input/DisplayViewport.h>
 #include <input/Input.h>
-#include <ui/DisplayInfo.h>
 #include <utils/BitSet.h>
 #include <utils/Looper.h>
 #include <utils/RefBase.h>
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index 827fcf1..97567ba 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -21,7 +21,6 @@
 #include <gui/DisplayEventReceiver.h>
 #include <input/DisplayViewport.h>
 #include <input/Input.h>
-#include <ui/DisplayInfo.h>
 #include <utils/BitSet.h>
 #include <utils/Looper.h>
 #include <utils/RefBase.h>
diff --git a/libs/input/PointerControllerContext.h b/libs/input/PointerControllerContext.h
index 98073fe..26a65a4 100644
--- a/libs/input/PointerControllerContext.h
+++ b/libs/input/PointerControllerContext.h
@@ -21,7 +21,6 @@
 #include <gui/DisplayEventReceiver.h>
 #include <input/DisplayViewport.h>
 #include <input/Input.h>
-#include <ui/DisplayInfo.h>
 #include <utils/BitSet.h>
 #include <utils/Looper.h>
 #include <utils/RefBase.h>
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index 213b3ad..4eabfb2 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_test {
     name: "libinputservice_test",
     srcs: [
diff --git a/libs/protoutil/Android.bp b/libs/protoutil/Android.bp
index d2b7d5c..132d71e 100644
--- a/libs/protoutil/Android.bp
+++ b/libs/protoutil/Android.bp
@@ -12,6 +12,15 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_defaults {
     name: "libprotoutil_defaults",
 
diff --git a/libs/services/Android.bp b/libs/services/Android.bp
index 1e62107..bf2e764 100644
--- a/libs/services/Android.bp
+++ b/libs/services/Android.bp
@@ -14,6 +14,15 @@
 
 // Provides C++ wrappers for system services.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_library_shared {
     name: "libservices",
     srcs: [
diff --git a/libs/storage/Android.bp b/libs/storage/Android.bp
index c19933e..e8c6c07 100644
--- a/libs/storage/Android.bp
+++ b/libs/storage/Android.bp
@@ -1,3 +1,20 @@
+package {
+    default_applicable_licenses: ["frameworks_base_libs_storage_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_libs_storage_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_library_static {
     name: "libstorage",
 
diff --git a/libs/tracingproxy/Android.bp b/libs/tracingproxy/Android.bp
index 67f407f..7126bfa 100644
--- a/libs/tracingproxy/Android.bp
+++ b/libs/tracingproxy/Android.bp
@@ -14,6 +14,17 @@
 
 // Provides C++ wrappers for system services.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_library_shared {
     name: "libtracingproxy",
 
diff --git a/libs/usb/Android.bp b/libs/usb/Android.bp
index e752b55..edc8474 100644
--- a/libs/usb/Android.bp
+++ b/libs/usb/Android.bp
@@ -14,6 +14,16 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-GPL-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_sdk_library {
     name: "com.android.future.usb.accessory",
     srcs: ["src/**/*.java"],
diff --git a/libs/usb/tests/AccessoryChat/Android.bp b/libs/usb/tests/AccessoryChat/Android.bp
index 19ed3d3..72090fb 100644
--- a/libs/usb/tests/AccessoryChat/Android.bp
+++ b/libs/usb/tests/AccessoryChat/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "AccessoryChat",
 
diff --git a/libs/usb/tests/AccessoryChat/accessorychat/Android.bp b/libs/usb/tests/AccessoryChat/accessorychat/Android.bp
index 5613745..108649a 100644
--- a/libs/usb/tests/AccessoryChat/accessorychat/Android.bp
+++ b/libs/usb/tests/AccessoryChat/accessorychat/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_binary {
     name: "accessorychat",
     host_supported: true,
diff --git a/libs/usb/tests/accessorytest/Android.bp b/libs/usb/tests/accessorytest/Android.bp
index c6340e3..69761ae 100644
--- a/libs/usb/tests/accessorytest/Android.bp
+++ b/libs/usb/tests/accessorytest/Android.bp
@@ -1,3 +1,13 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-GPL-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_binary_host {
     name: "accessorytest",
 
diff --git a/location/java/android/location/GnssAntennaInfo.java b/location/java/android/location/GnssAntennaInfo.java
index f1eb8fc..6633d24 100644
--- a/location/java/android/location/GnssAntennaInfo.java
+++ b/location/java/android/location/GnssAntennaInfo.java
@@ -39,11 +39,7 @@
 
     /**
      * Used for receiving GNSS antenna info from the GNSS engine.
-     *
-     * @deprecated Prefer to use a broadcast receiver for
-     * {@link LocationManager#ACTION_GNSS_ANTENNA_INFOS_CHANGED}.
      */
-    @Deprecated
     public interface Listener {
         /**
          * Invoked on a change to GNSS antenna info.
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index 3dcaffb..242d9a3 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -1096,13 +1096,7 @@
      * Gets the carrier frequency of the tracked signal.
      *
      * <p>For example it can be the GPS central frequency for L1 = 1575.45 MHz, or L2 = 1227.60 MHz,
-     * L5 = 1176.45 MHz, varying GLO channels, etc. If the field is not set, it is the primary
-     * common use central frequency, e.g. L1 = 1575.45 MHz for GPS.
-     *
-     * <p> For an L1, L5 receiver tracking a satellite on L1 and L5 at the same time, two raw
-     * measurement objects will be reported for this same satellite, in one of the measurement
-     * objects, all the values related to L1 will be filled, and in the other all of the values
-     * related to L5 will be filled.
+     * L5 = 1176.45 MHz, varying GLO channels, etc.
      *
      * <p>The value is only available if {@link #hasCarrierFrequencyHz()} is {@code true}.
      *
@@ -1382,7 +1376,8 @@
      * <p> AGC acts as a variable gain amplifier adjusting the power of the incoming signal. The AGC
      * level may be used to indicate potential interference. Higher gain (and/or lower input power)
      * shall be output as a positive number. Hence in cases of strong jamming, in the band of this
-     * signal, this value will go more negative.
+     * signal, this value will go more negative. This value must be consistent given the same level
+     * of the incoming signal power.
      *
      * <p> Note: Different hardware designs (e.g. antenna, pre-amplification, or other RF HW
      * components) may also affect the typical output of of this value on any given hardware design
diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java
index b46e8ce..23390fc 100644
--- a/location/java/android/location/GnssStatus.java
+++ b/location/java/android/location/GnssStatus.java
@@ -284,12 +284,7 @@
      * Gets the carrier frequency of the signal tracked.
      *
      * <p>For example it can be the GPS central frequency for L1 = 1575.45 MHz, or L2 = 1227.60
-     * MHz, L5 = 1176.45 MHz, varying GLO channels, etc. If the field is not set, it is the primary
-     * common use central frequency, e.g. L1 = 1575.45 MHz for GPS.
-     *
-     * For an L1, L5 receiver tracking a satellite on L1 and L5 at the same time, two measurements
-     * will be reported for this same satellite, in one all the values related to L1 will be
-     * filled, and in the other all of the values related to L5 will be filled.
+     * MHz, L5 = 1176.45 MHz, varying GLO channels, etc.
      *
      * <p>The value is only available if {@link #hasCarrierFrequencyHz(int satelliteIndex)} is
      * {@code true}.
diff --git a/core/java/android/service/screenshot/ScreenshotHash.aidl b/location/java/android/location/IGnssAntennaInfoListener.aidl
similarity index 61%
copy from core/java/android/service/screenshot/ScreenshotHash.aidl
copy to location/java/android/location/IGnssAntennaInfoListener.aidl
index a7c50db..3cceea3 100644
--- a/core/java/android/service/screenshot/ScreenshotHash.aidl
+++ b/location/java/android/location/IGnssAntennaInfoListener.aidl
@@ -1,11 +1,11 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2020, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,6 +14,13 @@
  * limitations under the License.
  */
 
-package android.service.screenshot;
+package android.location;
 
-parcelable ScreenshotHash;
+import android.location.GnssAntennaInfo;
+
+/**
+ * {@hide}
+ */
+oneway interface IGnssAntennaInfoListener {
+    void onGnssAntennaInfoChanged(in List<GnssAntennaInfo> antennaInfos);
+}
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index adf58da..6fa6536 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -26,6 +26,7 @@
 import android.location.GnssMeasurementCorrections;
 import android.location.GnssMeasurementRequest;
 import android.location.IGeocodeListener;
+import android.location.IGnssAntennaInfoListener;
 import android.location.IGnssMeasurementsListener;
 import android.location.IGnssStatusListener;
 import android.location.IGnssNavigationMessageListener;
@@ -48,13 +49,13 @@
  */
 interface ILocationManager
 {
-    @nullable Location getLastLocation(String provider, in LastLocationRequest request, String packageName, String attributionTag);
-    @nullable ICancellationSignal getCurrentLocation(String provider, in LocationRequest request, in ILocationCallback callback, String packageName, String attributionTag, String listenerId);
+    @nullable Location getLastLocation(String provider, in LastLocationRequest request, String packageName, @nullable String attributionTag);
+    @nullable ICancellationSignal getCurrentLocation(String provider, in LocationRequest request, in ILocationCallback callback, String packageName, @nullable String attributionTag, String listenerId);
 
-    void registerLocationListener(String provider, in LocationRequest request, in ILocationListener listener, String packageName, String attributionTag, String listenerId);
+    void registerLocationListener(String provider, in LocationRequest request, in ILocationListener listener, String packageName, @nullable String attributionTag, String listenerId);
     void unregisterLocationListener(in ILocationListener listener);
 
-    void registerLocationPendingIntent(String provider, in LocationRequest request, in PendingIntent pendingIntent, String packageName, String attributionTag);
+    void registerLocationPendingIntent(String provider, in LocationRequest request, in PendingIntent pendingIntent, String packageName, @nullable String attributionTag);
     void unregisterLocationPendingIntent(in PendingIntent pendingIntent);
 
     void injectLocation(in Location location);
@@ -79,24 +80,27 @@
 
     @nullable List<GnssAntennaInfo> getGnssAntennaInfos();
 
-    void registerGnssStatusCallback(in IGnssStatusListener callback, String packageName, @nullable String attributionTag);
+    void registerGnssStatusCallback(in IGnssStatusListener callback, String packageName, @nullable String attributionTag, String listenerId);
     void unregisterGnssStatusCallback(in IGnssStatusListener callback);
 
-    void registerGnssNmeaCallback(in IGnssNmeaListener callback, String packageName, @nullable String attributionTag);
+    void registerGnssNmeaCallback(in IGnssNmeaListener callback, String packageName, @nullable String attributionTag, String listenerId);
     void unregisterGnssNmeaCallback(in IGnssNmeaListener callback);
 
-    void addGnssMeasurementsListener(in GnssMeasurementRequest request, in IGnssMeasurementsListener listener, String packageName, @nullable String attributionTag);
+    void addGnssMeasurementsListener(in GnssMeasurementRequest request, in IGnssMeasurementsListener listener, String packageName, @nullable String attributionTag, String listenerId);
     void removeGnssMeasurementsListener(in IGnssMeasurementsListener listener);
     void injectGnssMeasurementCorrections(in GnssMeasurementCorrections corrections);
 
-    void addGnssNavigationMessageListener(in IGnssNavigationMessageListener listener, String packageName, @nullable String attributionTag);
+    void addGnssNavigationMessageListener(in IGnssNavigationMessageListener listener, String packageName, @nullable String attributionTag, String listenerId);
     void removeGnssNavigationMessageListener(in IGnssNavigationMessageListener listener);
 
+    void addGnssAntennaInfoListener(in IGnssAntennaInfoListener listener, String packageName, @nullable String attributionTag, String listenerId);
+    void removeGnssAntennaInfoListener(in IGnssAntennaInfoListener listener);
+
     void addProviderRequestListener(in IProviderRequestListener listener);
     void removeProviderRequestListener(in IProviderRequestListener listener);
 
     int getGnssBatchSize();
-    void startGnssBatch(long periodNanos, in ILocationListener listener, String packageName, @nullable String attributionTag, @nullable String listenerId);
+    void startGnssBatch(long periodNanos, in ILocationListener listener, String packageName, @nullable String attributionTag, String listenerId);
     void flushGnssBatch();
     void stopGnssBatch();
 
@@ -117,7 +121,8 @@
     boolean isLocationEnabledForUser(int userId);
     void setLocationEnabledForUser(boolean enabled, int userId);
 
-    void addTestProvider(String name, in ProviderProperties properties, String packageName, @nullable String attributionTag);
+    void addTestProvider(String name, in ProviderProperties properties,
+        in List<String> locationTags, String packageName, @nullable String attributionTag);
     void removeTestProvider(String provider, String packageName, @nullable String attributionTag);
     void setTestProviderLocation(String provider, in Location location, String packageName, @nullable String attributionTag);
     void setTestProviderEnabled(String provider, boolean enabled, String packageName, @nullable String attributionTag);
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 088b789..e73e915 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -20,7 +20,6 @@
 import static android.Manifest.permission.ACCESS_FINE_LOCATION;
 import static android.Manifest.permission.LOCATION_HARDWARE;
 import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
-import static android.location.GpsStatus.GPS_EVENT_STARTED;
 import static android.location.LocationRequest.createFromDeprecatedCriteria;
 import static android.location.LocationRequest.createFromDeprecatedProvider;
 
@@ -44,15 +43,13 @@
 import android.compat.Compatibility;
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledAfter;
-import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.location.provider.IProviderRequestListener;
 import android.location.provider.ProviderProperties;
 import android.location.provider.ProviderRequest;
-import android.location.provider.ProviderRequest.Listener;
+import android.location.provider.ProviderRequest.ChangedListener;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.CancellationSignal;
@@ -77,6 +74,7 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 import java.util.WeakHashMap;
 import java.util.concurrent.Executor;
 import java.util.function.Consumer;
@@ -349,28 +347,6 @@
     public static final String EXTRA_GNSS_CAPABILITIES = "android.location.extra.GNSS_CAPABILITIES";
 
     /**
-     * Broadcast intent action when GNSS antenna infos change. Includes an intent extra,
-     * {@link #EXTRA_GNSS_ANTENNA_INFOS}, with an ArrayList of the new {@link GnssAntennaInfo}. This
-     * may be read via {@link android.content.Intent#getParcelableArrayListExtra(String)}.
-     *
-     * @see #EXTRA_GNSS_ANTENNA_INFOS
-     * @see #getGnssAntennaInfos()
-     */
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_GNSS_ANTENNA_INFOS_CHANGED =
-            "android.location.action.GNSS_ANTENNA_INFOS_CHANGED";
-
-    /**
-     * Intent extra included with {@link #ACTION_GNSS_ANTENNA_INFOS_CHANGED} broadcasts, containing
-     * the new ArrayList of {@link GnssAntennaInfo}. This may be read via
-     * {@link android.content.Intent#getParcelableArrayListExtra(String)}.
-     *
-     * @see #ACTION_GNSS_ANTENNA_INFOS_CHANGED
-     */
-    public static final String EXTRA_GNSS_ANTENNA_INFOS =
-            "android.location.extra.GNSS_ANTENNA_INFOS";
-
-    /**
      * Broadcast intent action for Settings app to inject a footer at the bottom of location
      * settings. This is for use only by apps that are included in the system image.
      *
@@ -412,7 +388,7 @@
     private static final String CACHE_KEY_LOCATION_ENABLED_PROPERTY =
             "cache_key.location_enabled";
 
-    private static ILocationManager getService() throws RemoteException {
+    static ILocationManager getService() throws RemoteException {
         try {
             return ILocationManager.Stub.asInterface(
                     ServiceManager.getServiceOrThrow(Context.LOCATION_SERVICE));
@@ -439,11 +415,13 @@
                 new GnssNavigationTransportManager();
     }
 
-    private static final ProviderRequestTransportManager sProviderRequestListeners =
-            new ProviderRequestTransportManager();
+    private static class ProviderRequestLazyLoader {
+        static final ProviderRequestTransportManager sProviderRequestListeners =
+                new ProviderRequestTransportManager();
+    }
 
-    private final Context mContext;
-    private final ILocationManager mService;
+    final Context mContext;
+    final ILocationManager mService;
 
     private volatile PropertyInvalidatedCache<Integer, Boolean> mLocationEnabledCache =
             new PropertyInvalidatedCache<Integer, Boolean>(
@@ -1956,12 +1934,33 @@
      * allowed} for your app.
      */
     public void addTestProvider(@NonNull String provider, @NonNull ProviderProperties properties) {
+        addTestProvider(provider, properties, Collections.emptySet());
+    }
+
+    /**
+     * 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 provider the provider name
+     * @param properties the provider properties
+     * @param extraAttributionTags additional attribution tags associated with this provider
+     *
+     * @throws IllegalArgumentException if provider is null
+     * @throws IllegalArgumentException if properties 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.
+     */
+    public void addTestProvider(@NonNull String provider, @NonNull ProviderProperties properties,
+            @NonNull Set<String> extraAttributionTags) {
         Preconditions.checkArgument(provider != null, "invalid null provider");
         Preconditions.checkArgument(properties != null, "invalid null properties");
+        Preconditions.checkArgument(extraAttributionTags != null,
+                "invalid null extra attribution tags");
 
         try {
-            mService.addTestProvider(provider, properties, mContext.getOpPackageName(),
-                    mContext.getFeatureId());
+            mService.addTestProvider(provider, properties, new ArrayList<>(extraAttributionTags),
+                    mContext.getOpPackageName(), mContext.getFeatureId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -2637,10 +2636,11 @@
     }
 
     /**
-     * Registers a GNSS antenna info listener. GNSS antenna info updates will only be received while
-     * the {@link #GPS_PROVIDER} is enabled, and while the client app is in the foreground.
+     * Registers a GNSS antenna info listener that will receive all changes to antenna info. Use
+     * {@link #getGnssAntennaInfos()} to get current antenna info.
      *
-     * <p>Not all GNSS chipsets support antenna info updates, see {@link #getGnssCapabilities()}.
+     * <p>Not all GNSS chipsets support antenna info updates, see {@link #getGnssCapabilities()}. If
+     * unsupported, the listener will never be invoked.
      *
      * <p>Prior to Android S, this requires the {@link Manifest.permission#ACCESS_FINE_LOCATION}
      * permission.
@@ -2651,10 +2651,7 @@
      *
      * @throws IllegalArgumentException if executor is null
      * @throws IllegalArgumentException if listener is null
-     *
-     * @deprecated Prefer to use a receiver for {@link #ACTION_GNSS_ANTENNA_INFOS_CHANGED}.
      */
-    @Deprecated
     public boolean registerAntennaInfoListener(
             @NonNull @CallbackExecutor Executor executor,
             @NonNull GnssAntennaInfo.Listener listener) {
@@ -2664,13 +2661,10 @@
     }
 
     /**
-     * Unregisters a GNSS Antenna Info listener.
+     * Unregisters a GNSS antenna info listener.
      *
      * @param listener a {@link GnssAntennaInfo.Listener} object to remove
-     *
-     * @deprecated Prefer to use a receiver for {@link #ACTION_GNSS_ANTENNA_INFOS_CHANGED}.
      */
-    @Deprecated
     public void unregisterAntennaInfoListener(@NonNull GnssAntennaInfo.Listener listener) {
         GnssLazyLoader.sGnssAntennaInfoListeners.removeListener(listener);
     }
@@ -2778,34 +2772,33 @@
     }
 
     /**
-     * Registers a {@link ProviderRequest.Listener} to all providers.
+     * Adds a {@link ProviderRequest.ChangedListener} for listening to all providers'
+     * {@link ProviderRequest} changed events.
      *
      * @param executor the executor that the callback runs on
      * @param listener the listener to register
-     * @return {@code true} always
      * @hide
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
-    public boolean registerProviderRequestListener(
+    public void addProviderRequestChangedListener(
             @NonNull @CallbackExecutor Executor executor,
-            @NonNull Listener listener) {
-        sProviderRequestListeners.addListener(listener,
+            @NonNull ChangedListener listener) {
+        ProviderRequestLazyLoader.sProviderRequestListeners.addListener(listener,
                 new ProviderRequestTransport(executor, listener));
-        return true;
     }
 
     /**
-     * Unregisters a {@link ProviderRequest.Listener}.
+     * Removes a {@link ProviderRequest.ChangedListener} that has been added.
      *
      * @param listener the listener to remove.
      * @hide
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
-    public void unregisterProviderRequestListener(
-            @NonNull Listener listener) {
-        sProviderRequestListeners.removeListener(listener);
+    public void removeProviderRequestChangedListener(
+            @NonNull ProviderRequest.ChangedListener listener) {
+        ProviderRequestLazyLoader.sProviderRequestListeners.removeListener(listener);
     }
 
     /**
@@ -2917,11 +2910,16 @@
     private static class GnssStatusTransportManager extends
             ListenerTransportManager<GnssStatusTransport> {
 
+        GnssStatusTransportManager() {
+            super(false);
+        }
+
         @Override
         protected void registerTransport(GnssStatusTransport transport)
                             throws RemoteException {
             getService().registerGnssStatusCallback(transport, transport.getPackage(),
-                    transport.getAttributionTag());
+                    transport.getAttributionTag(),
+                    AppOpsManager.toReceiverId(transport.getListener()));
         }
 
         @Override
@@ -2934,11 +2932,16 @@
     private static class GnssNmeaTransportManager extends
             ListenerTransportManager<GnssNmeaTransport> {
 
+        GnssNmeaTransportManager() {
+            super(false);
+        }
+
         @Override
         protected void registerTransport(GnssNmeaTransport transport)
                             throws RemoteException {
             getService().registerGnssNmeaCallback(transport, transport.getPackage(),
-                    transport.getAttributionTag());
+                    transport.getAttributionTag(),
+                    AppOpsManager.toReceiverId(transport.getListener()));
         }
 
         @Override
@@ -2951,11 +2954,16 @@
     private static class GnssMeasurementsTransportManager extends
             ListenerTransportManager<GnssMeasurementsTransport> {
 
+        GnssMeasurementsTransportManager() {
+            super(false);
+        }
+
         @Override
         protected void registerTransport(GnssMeasurementsTransport transport)
                             throws RemoteException {
             getService().addGnssMeasurementsListener(transport.getRequest(), transport,
-                    transport.getPackage(), transport.getAttributionTag());
+                    transport.getPackage(), transport.getAttributionTag(),
+                    AppOpsManager.toReceiverId(transport.getListener()));
         }
 
         @Override
@@ -2968,26 +2976,38 @@
     private static class GnssAntennaTransportManager extends
             ListenerTransportManager<GnssAntennaInfoTransport> {
 
-        @Override
-        protected void registerTransport(GnssAntennaInfoTransport transport) {
-            transport.getContext().registerReceiver(transport,
-                    new IntentFilter(ACTION_GNSS_ANTENNA_INFOS_CHANGED));
+        GnssAntennaTransportManager() {
+            super(false);
         }
 
         @Override
-        protected void unregisterTransport(GnssAntennaInfoTransport transport) {
-            transport.getContext().unregisterReceiver(transport);
+        protected void registerTransport(GnssAntennaInfoTransport transport)
+                throws RemoteException {
+            getService().addGnssAntennaInfoListener(transport, transport.getPackage(),
+                    transport.getAttributionTag(),
+                    AppOpsManager.toReceiverId(transport.getListener()));
+        }
+
+        @Override
+        protected void unregisterTransport(GnssAntennaInfoTransport transport)
+                throws RemoteException {
+            getService().removeGnssAntennaInfoListener(transport);
         }
     }
 
     private static class GnssNavigationTransportManager extends
             ListenerTransportManager<GnssNavigationTransport> {
 
+        GnssNavigationTransportManager() {
+            super(false);
+        }
+
         @Override
         protected void registerTransport(GnssNavigationTransport transport)
                             throws RemoteException {
             getService().addGnssNavigationMessageListener(transport,
-                    transport.getPackage(), transport.getAttributionTag());
+                    transport.getPackage(), transport.getAttributionTag(),
+                    AppOpsManager.toReceiverId(transport.getListener()));
         }
 
         @Override
@@ -3000,6 +3020,10 @@
     private static class ProviderRequestTransportManager extends
             ListenerTransportManager<ProviderRequestTransport> {
 
+        ProviderRequestTransportManager() {
+            super(false);
+        }
+
         @Override
         protected void registerTransport(ProviderRequestTransport transport)
                 throws RemoteException {
@@ -3117,6 +3141,8 @@
         }
     }
 
+    /** @deprecated */
+    @Deprecated
     private static class GpsAdapter extends GnssStatus.Callback {
 
         private final GpsStatus.Listener mGpsListener;
@@ -3127,7 +3153,7 @@
 
         @Override
         public void onStarted() {
-            mGpsListener.onGpsStatusChanged(GPS_EVENT_STARTED);
+            mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_STARTED);
         }
 
         @Override
@@ -3204,6 +3230,8 @@
         }
     }
 
+    /** @deprecated */
+    @Deprecated
     private static class GpsStatusTransport extends GnssStatusTransport {
 
         static volatile int sTtff;
@@ -3323,11 +3351,12 @@
         }
     }
 
-    private static class GnssAntennaInfoTransport extends BroadcastReceiver implements
+    private static class GnssAntennaInfoTransport extends IGnssAntennaInfoListener.Stub implements
             ListenerTransport<GnssAntennaInfo.Listener> {
 
         private final Executor mExecutor;
-        private final Context mContext;
+        private final String mPackageName;
+        private final String mAttributionTag;
 
         private volatile @Nullable GnssAntennaInfo.Listener mListener;
 
@@ -3336,12 +3365,17 @@
             Preconditions.checkArgument(executor != null, "invalid null executor");
             Preconditions.checkArgument(listener != null, "invalid null listener");
             mExecutor = executor;
-            mContext = context;
+            mPackageName = context.getPackageName();
+            mAttributionTag = context.getAttributionTag();
             mListener = listener;
         }
 
-        public Context getContext() {
-            return mContext;
+        public String getPackage() {
+            return mPackageName;
+        }
+
+        public String getAttributionTag() {
+            return mAttributionTag;
         }
 
         @Override
@@ -3355,12 +3389,8 @@
         }
 
         @Override
-        public void onReceive(Context context, Intent intent) {
-            ArrayList<GnssAntennaInfo> infos = intent.getParcelableArrayListExtra(
-                    EXTRA_GNSS_ANTENNA_INFOS);
-            if (infos != null) {
-                execute(mExecutor, callback -> callback.onGnssAntennaInfoReceived(infos));
-            }
+        public void onGnssAntennaInfoChanged(List<GnssAntennaInfo> antennaInfos) {
+            execute(mExecutor, callback -> callback.onGnssAntennaInfoReceived(antennaInfos));
         }
     }
 
@@ -3413,13 +3443,13 @@
     }
 
     private static class ProviderRequestTransport extends IProviderRequestListener.Stub
-            implements ListenerTransport<ProviderRequest.Listener> {
+            implements ListenerTransport<ChangedListener> {
 
         private final Executor mExecutor;
 
-        private volatile @Nullable ProviderRequest.Listener mListener;
+        private volatile @Nullable ProviderRequest.ChangedListener mListener;
 
-        ProviderRequestTransport(Executor executor, ProviderRequest.Listener listener) {
+        ProviderRequestTransport(Executor executor, ChangedListener listener) {
             Preconditions.checkArgument(executor != null, "invalid null executor");
             Preconditions.checkArgument(listener != null, "invalid null callback");
             mExecutor = executor;
@@ -3432,7 +3462,7 @@
         }
 
         @Override
-        public @Nullable ProviderRequest.Listener getListener() {
+        public @Nullable ProviderRequest.ChangedListener getListener() {
             return mListener;
         }
 
@@ -3442,6 +3472,8 @@
         }
     }
 
+    /** @deprecated */
+    @Deprecated
     private static class BatchedLocationCallbackWrapper implements LocationListener {
 
         private final BatchedLocationCallback mCallback;
@@ -3461,6 +3493,8 @@
         }
     }
 
+    /** @deprecated */
+    @Deprecated
     private static class BatchedLocationCallbackTransport extends LocationListenerTransport {
 
         BatchedLocationCallbackTransport(BatchedLocationCallback callback, Handler handler) {
diff --git a/location/java/android/location/LocationManagerInternal.java b/location/java/android/location/LocationManagerInternal.java
index a6a0e7a..763835c 100644
--- a/location/java/android/location/LocationManagerInternal.java
+++ b/location/java/android/location/LocationManagerInternal.java
@@ -21,6 +21,10 @@
 import android.annotation.Nullable;
 import android.location.util.identity.CallerIdentity;
 
+import com.android.internal.annotations.Immutable;
+
+import java.util.Set;
+
 /**
  * Location manager local system service interface.
  *
@@ -39,6 +43,21 @@
     }
 
     /**
+     * Interface for getting callbacks when a location provider's location tags change.
+     *
+     * @see LocationTagInfo
+     */
+    public interface OnProviderLocationTagsChangeListener {
+
+        /**
+         * Called when the location tags for a provider change.
+         *
+         * @param providerLocationTagInfo The tag info for a provider.
+         */
+        void onLocationTagsChanged(@NonNull LocationTagInfo providerLocationTagInfo);
+    }
+
+    /**
      * Returns true if the given provider is enabled for the given user.
      *
      * @param provider A location provider as listed by {@link LocationManager#getAllProviders()}
@@ -88,4 +107,60 @@
      * provider, and the elapsed nanos since boot the current time was computed at.
      */
     public abstract @Nullable LocationTime getGnssTimeMillis();
+
+    /**
+     * Sets a listener for changes in the location providers' tags. Passing
+     * {@code null} clears the current listener.
+     *
+     * @param listener The listener.
+     */
+    public abstract void setOnProviderLocationTagsChangeListener(
+            @Nullable OnProviderLocationTagsChangeListener listener);
+
+    /**
+     * This class represents the location permission tags used by the location provider
+     * packages in a given UID. These tags are strictly used for accessing state guarded
+     * by the location permission(s) by a location provider which are required for the
+     * provider to fulfill its function as being a location provider.
+     */
+    @Immutable
+    public static class LocationTagInfo {
+        private final int mUid;
+
+        @NonNull
+        private final String mPackageName;
+
+        @Nullable
+        private final Set<String> mLocationTags;
+
+        public LocationTagInfo(int uid, @NonNull String packageName,
+                @Nullable Set<String> locationTags) {
+            mUid = uid;
+            mPackageName = packageName;
+            mLocationTags = locationTags;
+        }
+
+        /**
+         * @return The UID for which tags are related.
+         */
+        public int getUid() {
+            return mUid;
+        }
+
+        /**
+         * @return The package for which tags are related.
+         */
+        @NonNull
+        public String getPackageName() {
+            return mPackageName;
+        }
+
+        /**
+         * @return The tags for the package used for location related accesses.
+         */
+        @Nullable
+        public Set<String> getTags() {
+            return mLocationTags;
+        }
+    }
 }
diff --git a/location/java/android/location/provider/ProviderRequest.java b/location/java/android/location/provider/ProviderRequest.java
index b6ec323..b72d365 100644
--- a/location/java/android/location/provider/ProviderRequest.java
+++ b/location/java/android/location/provider/ProviderRequest.java
@@ -56,10 +56,13 @@
     /**
      * Listener to be invoked when a new request is set to the provider.
      */
-    public interface Listener {
+    public interface ChangedListener {
 
         /**
          * Invoked when a new request is set.
+         *
+         * @param provider the location provider associated with the request
+         * @param request the new {@link ProviderRequest}
          */
         void onProviderRequestChanged(@NonNull String provider, @NonNull ProviderRequest request);
     }
diff --git a/location/java/android/location/util/identity/CallerIdentity.java b/location/java/android/location/util/identity/CallerIdentity.java
index 0bb7dbb..85a083e 100644
--- a/location/java/android/location/util/identity/CallerIdentity.java
+++ b/location/java/android/location/util/identity/CallerIdentity.java
@@ -42,7 +42,16 @@
     @VisibleForTesting
     public static CallerIdentity forTest(int uid, int pid, String packageName,
             @Nullable String attributionTag) {
-        return new CallerIdentity(uid, pid, packageName, attributionTag, null);
+        return forTest(uid, pid, packageName, attributionTag, null);
+    }
+
+    /**
+     * Construct a CallerIdentity for test purposes.
+     */
+    @VisibleForTesting
+    public static CallerIdentity forTest(int uid, int pid, String packageName,
+            @Nullable String attributionTag, @Nullable String listenerId) {
+        return new CallerIdentity(uid, pid, packageName, attributionTag, listenerId);
     }
 
     /**
@@ -145,7 +154,10 @@
         return mAttributionTag;
     }
 
-    /** The calling listener id. */
+    /**
+     * The calling listener id. A null listener id will match any other listener id for the purposes
+     * of {@link #equals(Object)}.
+     */
     public String getListenerId() {
         return mListenerId;
     }
@@ -168,6 +180,17 @@
         }
     }
 
+    /**
+     * Returns a CallerIdentity corrosponding to this CallerIdentity but with a null listener id.
+     */
+    public CallerIdentity stripListenerId() {
+        if (mListenerId == null) {
+            return this;
+        } else {
+            return new CallerIdentity(mUid, mPid, mPackageName, mAttributionTag, null);
+        }
+    }
+
     @Override
     public String toString() {
         int length = 10 + mPackageName.length();
@@ -201,15 +224,12 @@
             return false;
         }
         CallerIdentity that = (CallerIdentity) o;
-        return equalsIgnoringListenerId(that) && Objects.equals(mListenerId, that.mListenerId);
-    }
-
-    public boolean equalsIgnoringListenerId(CallerIdentity that) {
-        return that != null
-                && mUid == that.mUid
+        return mUid == that.mUid
                 && mPid == that.mPid
                 && mPackageName.equals(that.mPackageName)
-                && Objects.equals(mAttributionTag, that.mAttributionTag);
+                && Objects.equals(mAttributionTag, that.mAttributionTag)
+                && (mListenerId == null || that.mListenerId == null || mListenerId.equals(
+                that.mListenerId));
     }
 
     @Override
diff --git a/location/lib/Android.bp b/location/lib/Android.bp
index c0188c0..696125c 100644
--- a/location/lib/Android.bp
+++ b/location/lib/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_sdk_library {
     name: "com.android.location.provider",
     srcs: ["java/**/*.java"],
diff --git a/lowpan/tests/Android.bp b/lowpan/tests/Android.bp
index ad2bc27..5908929 100644
--- a/lowpan/tests/Android.bp
+++ b/lowpan/tests/Android.bp
@@ -14,6 +14,15 @@
 
 // Make test APK
 // ============================================================
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworksLowpanApiTests",
     srcs: ["**/*.java"],
diff --git a/media/Android.bp b/media/Android.bp
index 8b06bb2..9268b22 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 aidl_interface {
     name: "audio_common-aidl",
     unstable: true,
diff --git a/media/java/Android.bp b/media/java/Android.bp
index 0810699..aea63a0 100644
--- a/media/java/Android.bp
+++ b/media/java/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "IMidiDeviceServer.aidl",
     srcs: ["android/media/midi/IMidiDeviceServer.aidl"],
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index bb1dbd4..7e729d8 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -1264,6 +1264,8 @@
      *
      * @param usage one of the {@link AudioAttributes} usage constants
      * @return string representing the {@link AudioAttributes} usage constant passed as a parameter
+     *
+     * @hide
      */
     @NonNull
     public static String usageToString(@AttributeSdkUsage int usage) {
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index 205c1f4..383c93d 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -16,8 +16,10 @@
 
 package android.media;
 
+import android.Manifest;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
 import android.util.SparseIntArray;
 
 import java.lang.annotation.Retention;
@@ -161,6 +163,14 @@
      */
     public static final int TYPE_BLE_SPEAKER   = 27;
 
+    /**
+     * A device type describing an Echo Canceller loopback Reference.
+     * This device is only used when capturing with MediaRecorder.AudioSource.ECHO_REFERENCE,
+     * which requires privileged permission
+     * {@link android.Manifest.permission#CAPTURE_AUDIO_OUTPUT}.
+     * @hide */
+    @RequiresPermission(Manifest.permission.CAPTURE_AUDIO_OUTPUT)
+    public static final int TYPE_ECHO_REFERENCE   = 28;
 
     /** @hide */
     @IntDef(flag = false, prefix = "TYPE", value = {
@@ -188,7 +198,8 @@
             TYPE_FM_TUNER,
             TYPE_TV_TUNER,
             TYPE_BLE_HEADSET,
-            TYPE_BLE_SPEAKER}
+            TYPE_BLE_SPEAKER,
+            TYPE_ECHO_REFERENCE}
     )
     @Retention(RetentionPolicy.SOURCE)
     public @interface AudioDeviceType {}
@@ -211,7 +222,8 @@
             TYPE_LINE_DIGITAL,
             TYPE_IP,
             TYPE_BUS,
-            TYPE_BLE_HEADSET}
+            TYPE_BLE_HEADSET,
+            TYPE_ECHO_REFERENCE}
     )
     @Retention(RetentionPolicy.SOURCE)
     public @interface AudioDeviceTypeIn {}
@@ -297,6 +309,7 @@
             case TYPE_BUS:
             case TYPE_REMOTE_SUBMIX:
             case TYPE_BLE_HEADSET:
+            case TYPE_ECHO_REFERENCE:
                 return true;
             default:
                 return false;
@@ -621,6 +634,8 @@
         INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUS, TYPE_BUS);
         INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_REMOTE_SUBMIX, TYPE_REMOTE_SUBMIX);
         INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLE_HEADSET, TYPE_BLE_HEADSET);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_ECHO_REFERENCE, TYPE_ECHO_REFERENCE);
+
 
         // privileges mapping to output device
         EXT_TO_INT_DEVICE_MAPPING = new SparseIntArray();
@@ -678,6 +693,9 @@
         EXT_TO_INT_INPUT_DEVICE_MAPPING.put(
                 TYPE_REMOTE_SUBMIX, AudioSystem.DEVICE_IN_REMOTE_SUBMIX);
         EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_BLE_HEADSET, AudioSystem.DEVICE_IN_BLE_HEADSET);
+        EXT_TO_INT_INPUT_DEVICE_MAPPING.put(
+                TYPE_ECHO_REFERENCE, AudioSystem.DEVICE_IN_ECHO_REFERENCE);
+
     }
 }
 
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index d896c1f..b2de49d 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -568,7 +568,7 @@
     public static final int FLAG_FROM_KEY = 1 << 12;
 
     /** @hide */
-    @IntDef(flag = false, prefix = "FLAG", value = {
+    @IntDef(flag = true, prefix = "FLAG", value = {
             FLAG_SHOW_UI,
             FLAG_ALLOW_RINGER_MODES,
             FLAG_PLAY_SOUND,
@@ -3123,52 +3123,57 @@
 
     /**
      * @hide Home sound
-     * Played by the framework when the home app becomes active if config_enableHomeSound is set to
-     * true. This is currently only used on TV devices.
+     * <p>
+     * To be played by the framework when the home app becomes active if config_enableHomeSound is
+     * set to true. This is currently only used on TV devices.
      * Note that this sound is only available if a sound file is specified in audio_assets.xml.
      * @see #playSoundEffect(int)
      */
     public static final int FX_HOME = 11;
 
     /**
-     * @hide Fast scroll sound 1
-     * To be by the framework when a fast-scrolling is performed and
-     * {@link #areFastScrollSoundEffectsEnabled()} is true.
+     * @hide Navigation repeat sound 1
+     * <p>
+     * To be played by the framework when a focus navigation is repeatedly triggered
+     * (e.g. due to long-pressing) and {@link #areNavigationRepeatSoundEffectsEnabled()} is true.
      * This is currently only used on TV devices.
      * Note that this sound is only available if a sound file is specified in audio_assets.xml
      * @see #playSoundEffect(int)
      */
-    public static final int FX_FAST_SCROLL_1 = 12;
+    public static final int FX_FOCUS_NAVIGATION_REPEAT_1 = 12;
 
     /**
-     * @hide Fast scroll sound 2
-     * To be by the framework when a fast-scrolling is performed and
-     * {@link #areFastScrollSoundEffectsEnabled()} is true.
+     * @hide Navigation repeat sound 2
+     * <p>
+     * To be played by the framework when a focus navigation is repeatedly triggered
+     * (e.g. due to long-pressing) and {@link #areNavigationRepeatSoundEffectsEnabled()} is true.
      * This is currently only used on TV devices.
      * Note that this sound is only available if a sound file is specified in audio_assets.xml
      * @see #playSoundEffect(int)
      */
-    public static final int FX_FAST_SCROLL_2 = 13;
+    public static final int FX_FOCUS_NAVIGATION_REPEAT_2 = 13;
 
     /**
-     * @hide Fast scroll sound 3
-     * To be by the framework when a fast-scrolling is performed and
-     * {@link #areFastScrollSoundEffectsEnabled()} is true.
+     * @hide Navigation repeat sound 3
+     * <p>
+     * To be played by the framework when a focus navigation is repeatedly triggered
+     * (e.g. due to long-pressing) and {@link #areNavigationRepeatSoundEffectsEnabled()} is true.
      * This is currently only used on TV devices.
      * Note that this sound is only available if a sound file is specified in audio_assets.xml
      * @see #playSoundEffect(int)
      */
-    public static final int FX_FAST_SCROLL_3 = 14;
+    public static final int FX_FOCUS_NAVIGATION_REPEAT_3 = 14;
 
     /**
-     * @hide Fast scroll sound 4
-     * To be by the framework when a fast-scrolling is performed and
-     * {@link #areFastScrollSoundEffectsEnabled()} is true.
+     * @hide Navigation repeat sound 4
+     * <p>
+     * To be played by the framework when a focus navigation is repeatedly triggered
+     * (e.g. due to long-pressing) and {@link #areNavigationRepeatSoundEffectsEnabled()} is true.
      * This is currently only used on TV devices.
      * Note that this sound is only available if a sound file is specified in audio_assets.xml
      * @see #playSoundEffect(int)
      */
-    public static final int FX_FAST_SCROLL_4 = 15;
+    public static final int FX_FOCUS_NAVIGATION_REPEAT_4 = 15;
 
     /**
      * @hide Number of sound effects
@@ -3177,27 +3182,27 @@
     public static final int NUM_SOUND_EFFECTS = 16;
 
     /**
-     * @hide Number of fast scroll sound effects
+     * @hide Number of FX_FOCUS_NAVIGATION_REPEAT_* sound effects
      */
-    public static final int NUM_FAST_SCROLL_SOUND_EFFECTS = 4;
+    public static final int NUM_NAVIGATION_REPEAT_SOUND_EFFECTS = 4;
 
     /**
      * @hide
-     * @param n a value in [0, {@link #NUM_FAST_SCROLL_SOUND_EFFECTS}[
-     * @return The id of a fast scroll sound effect or -1 if out of bounds
+     * @param n a value in [0, {@link #NUM_NAVIGATION_REPEAT_SOUND_EFFECTS}[
+     * @return The id of a navigation repeat sound effect or -1 if out of bounds
      */
-    public static int getNthFastScrollSoundEffectId(int n) {
+    public static int getNthNavigationRepeatSoundEffect(int n) {
         switch (n) {
             case 0:
-                return FX_FAST_SCROLL_1;
+                return FX_FOCUS_NAVIGATION_REPEAT_1;
             case 1:
-                return FX_FAST_SCROLL_2;
+                return FX_FOCUS_NAVIGATION_REPEAT_2;
             case 2:
-                return FX_FAST_SCROLL_3;
+                return FX_FOCUS_NAVIGATION_REPEAT_3;
             case 3:
-                return FX_FAST_SCROLL_4;
+                return FX_FOCUS_NAVIGATION_REPEAT_4;
             default:
-                Log.w(TAG, "Invalid fast-scroll sound effect id: " + n);
+                Log.w(TAG, "Invalid navigation repeat sound effect id: " + n);
                 return -1;
         }
     }
@@ -3205,9 +3210,9 @@
     /**
      * @hide
      */
-    public void setFastScrollSoundEffectsEnabled(boolean enabled) {
+    public void setNavigationRepeatSoundEffectsEnabled(boolean enabled) {
         try {
-            getService().setFastScrollSoundEffectsEnabled(enabled);
+            getService().setNavigationRepeatSoundEffectsEnabled(enabled);
         } catch (RemoteException e) {
 
         }
@@ -3215,11 +3220,11 @@
 
     /**
      * @hide
-     * @return true if the fast scroll sound effects are enabled
+     * @return true if the navigation repeat sound effects are enabled
      */
-    public boolean areFastScrollSoundEffectsEnabled() {
+    public boolean areNavigationRepeatSoundEffectsEnabled() {
         try {
-            return getService().areFastScrollSoundEffectsEnabled();
+            return getService().areNavigationRepeatSoundEffectsEnabled();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index b196437..bf04b66 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -275,6 +275,12 @@
     private AudioAttributes mAudioAttributes;
     private boolean mIsSubmixFullVolume = false;
 
+    /**
+     * The log session id used for metrics.
+     * A null or empty string here means it is not set.
+     */
+    private String mLogSessionId;
+
     //---------------------------------------------------------
     // Constructor, Finalize
     //--------------------
@@ -1913,6 +1919,25 @@
         return native_set_preferred_microphone_field_dimension(zoom) == AudioSystem.SUCCESS;
     }
 
+    /**
+     * Sets a string handle to this AudioRecord for metrics collection.
+     *
+     * @param logSessionId a string which is used to identify this object
+     *        to the metrics service.  Proper generated Ids must be obtained
+     *        from the Java metrics service and should be considered opaque.
+     *        Use null to remove the logSessionId association.
+     * @throws IllegalStateException if AudioRecord not initialized.
+     *
+     * @hide
+     */
+    public void setLogSessionId(@Nullable String logSessionId) {
+        if (mState == STATE_UNINITIALIZED) {
+            throw new IllegalStateException("AudioRecord not initialized");
+        }
+        native_setLogSessionId(logSessionId);
+        mLogSessionId = logSessionId;
+    }
+
     //---------------------------------------------------------
     // Interface definitions
     //--------------------
@@ -2072,6 +2097,8 @@
     private native int native_set_preferred_microphone_direction(int direction);
     private native int native_set_preferred_microphone_field_dimension(float zoom);
 
+    private native void native_setLogSessionId(@Nullable String logSessionId);
+
     //---------------------------------------------------------
     // Utility methods
     //------------------
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 7fb83f1..88731d2 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -565,6 +565,12 @@
      */
     private int mOffloadPaddingFrames = 0;
 
+    /**
+     * The log session id used for metrics.
+     * A null or empty string here means it is not set.
+     */
+    private String mLogSessionId;
+
     //--------------------------------
     // Used exclusively by native code
     //--------------------
@@ -837,6 +843,7 @@
         }
 
         baseRegisterPlayer(mSessionId);
+        native_setPlayerIId(mPlayerIId); // mPlayerIId now ready to send to native AudioTrack.
     }
 
     /**
@@ -922,12 +929,21 @@
         private final int mSyncId;
 
         /**
+         * A special content id for {@link #TunerConfiguration(int, int)}
+         * indicating audio is delivered
+         * from an {@code AudioTrack} write, not tunneled from the tuner stack.
+         */
+        public static final int CONTENT_ID_NONE = 0;
+
+        /**
          * Constructs a TunerConfiguration instance for use in {@link AudioTrack.Builder}
          *
          * @param contentId selects the audio stream to use.
          *     The contentId may be obtained from
-         *     {@link android.media.tv.tuner.filter.Filter#getId()}.
-         *     This is always a positive number.
+         *     {@link android.media.tv.tuner.filter.Filter#getId()},
+         *     such obtained id is always a positive number.
+         *     If audio is to be delivered through an {@code AudioTrack} write
+         *     then {@code CONTENT_ID_NONE} may be used.
          * @param syncId selects the clock to use for synchronization
          *     of audio with other streams such as video.
          *     The syncId may be obtained from
@@ -936,10 +952,10 @@
          */
         @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
         public TunerConfiguration(
-                @IntRange(from = 1) int contentId, @IntRange(from = 1)int syncId) {
-            if (contentId < 1) {
+                @IntRange(from = 0) int contentId, @IntRange(from = 1)int syncId) {
+            if (contentId < 0) {
                 throw new IllegalArgumentException(
-                        "contentId " + contentId + " must be positive");
+                        "contentId " + contentId + " must be positive or CONTENT_ID_NONE");
             }
             if (syncId < 1) {
                 throw new IllegalArgumentException("syncId " + syncId + " must be positive");
@@ -3520,8 +3536,9 @@
                 native_enableDeviceCallback();
                 return true;
             } catch (IllegalStateException e) {
-                // Fail silently as track state could have changed in between start
-                // and enabling routing callback, return false to indicate not enabled
+                if (Log.isLoggable(TAG, Log.DEBUG)) {
+                    Log.d(TAG, "testEnableNativeRoutingCallbacks failed", e);
+                }
             }
         }
         return false;
@@ -3571,7 +3588,7 @@
             Handler handler) {
         synchronized (mRoutingChangeListeners) {
             if (listener != null && !mRoutingChangeListeners.containsKey(listener)) {
-                testEnableNativeRoutingCallbacksLocked();
+                mEnableSelfRoutingMonitor = testEnableNativeRoutingCallbacksLocked();
                 mRoutingChangeListeners.put(
                         listener, new NativeRoutingEventHandlerDelegate(this, listener,
                                 handler != null ? handler : new Handler(mInitializationLooper)));
@@ -3967,6 +3984,25 @@
         }
     }
 
+    /**
+     * Sets a string handle to this AudioTrack for metrics collection.
+     *
+     * @param logSessionId a string which is used to identify this object
+     *        to the metrics service.  Proper generated Ids must be obtained
+     *        from the Java metrics service and should be considered opaque.
+     *        Use null to remove the logSessionId association.
+     * @throws IllegalStateException if AudioTrack not initialized.
+     *
+     * @hide
+     */
+    public void setLogSessionId(@Nullable String logSessionId) {
+        if (mState == STATE_UNINITIALIZED) {
+            throw new IllegalStateException("track not initialized");
+        }
+        native_setLogSessionId(logSessionId);
+        mLogSessionId = logSessionId;
+    }
+
     //---------------------------------------------------------
     // Inner classes
     //--------------------
@@ -4202,6 +4238,21 @@
     private native int native_get_audio_description_mix_level_db(float[] level);
     private native int native_set_dual_mono_mode(int dualMonoMode);
     private native int native_get_dual_mono_mode(int[] dualMonoMode);
+    private native void native_setLogSessionId(@Nullable String logSessionId);
+
+    /**
+     * Sets the audio service Player Interface Id.
+     *
+     * The playerIId does not change over the lifetime of the client
+     * Java AudioTrack and is set automatically on creation.
+     *
+     * This call informs the native AudioTrack for metrics logging purposes.
+     *
+     * @param id the value reported by AudioManager when registering the track.
+     *           A value of -1 indicates invalid - the playerIId was never set.
+     * @throws IllegalStateException if AudioTrack not initialized.
+     */
+    private native void native_setPlayerIId(int playerIId);
 
     //---------------------------------------------------------
     // Utility methods
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 71ee57e..0073b5c 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -351,9 +351,9 @@
     oneway void unregisterCommunicationDeviceDispatcher(
             ICommunicationDeviceDispatcher dispatcher);
 
-    boolean areFastScrollSoundEffectsEnabled();
+    boolean areNavigationRepeatSoundEffectsEnabled();
 
-    oneway void setFastScrollSoundEffectsEnabled(boolean enabled);
+    oneway void setNavigationRepeatSoundEffectsEnabled(boolean enabled);
 
     boolean isHomeSoundEffectEnabled();
 
diff --git a/media/java/android/media/ImageWriter.java b/media/java/android/media/ImageWriter.java
index 44f8385..9ab4aac 100644
--- a/media/java/android/media/ImageWriter.java
+++ b/media/java/android/media/ImageWriter.java
@@ -131,7 +131,59 @@
      */
     public static @NonNull ImageWriter newInstance(@NonNull Surface surface,
             @IntRange(from = 1) int maxImages) {
-        return new ImageWriter(surface, maxImages, ImageFormat.UNKNOWN);
+        return new ImageWriter(surface, maxImages, ImageFormat.UNKNOWN, -1 /*width*/,
+                -1 /*height*/);
+    }
+
+    /**
+     * <p>
+     * Create a new ImageWriter with given number of max Images, format and producer dimension.
+     * </p>
+     * <p>
+     * The {@code maxImages} parameter determines the maximum number of
+     * {@link Image} objects that can be be dequeued from the
+     * {@code ImageWriter} simultaneously. Requesting more buffers will use up
+     * more memory, so it is important to use only the minimum number necessary.
+     * </p>
+     * <p>
+     * The format specifies the image format of this ImageWriter. The format
+     * from the {@code surface} will be overridden with this format. For example,
+     * if the surface is obtained from a {@link android.graphics.SurfaceTexture}, the default
+     * format may be {@link PixelFormat#RGBA_8888}. If the application creates an ImageWriter
+     * with this surface and {@link ImageFormat#PRIVATE}, this ImageWriter will be able to operate
+     * with {@link ImageFormat#PRIVATE} Images.
+     * </p>
+     * <p>
+     * Note that the consumer end-point may or may not be able to support Images with different
+     * format, for such case, the application should only use this method if the consumer is able
+     * to consume such images.
+     * </p>
+     * <p> The input Image size can also be set by the client. </p>
+     *
+     * @param surface The destination Surface this writer produces Image data
+     *            into.
+     * @param maxImages The maximum number of Images the user will want to
+     *            access simultaneously for producing Image data. This should be
+     *            as small as possible to limit memory use. Once maxImages
+     *            Images are dequeued by the user, one of them has to be queued
+     *            back before a new Image can be dequeued for access via
+     *            {@link #dequeueInputImage()}.
+     * @param format The format of this ImageWriter. It can be any valid format specified by
+     *            {@link ImageFormat} or {@link PixelFormat}.
+     *
+     * @param width Input size width.
+     * @param height Input size height.
+     *
+     * @return a new ImageWriter instance.
+     *
+     * @hide
+     */
+    public static @NonNull ImageWriter newInstance(@NonNull Surface surface,
+            @IntRange(from = 1) int maxImages, @Format int format, int width, int height) {
+        if (!ImageFormat.isPublicFormat(format) && !PixelFormat.isPublicFormat(format)) {
+            throw new IllegalArgumentException("Invalid format is specified: " + format);
+        }
+        return new ImageWriter(surface, maxImages, format, width, height);
     }
 
     /**
@@ -180,13 +232,13 @@
         if (!ImageFormat.isPublicFormat(format) && !PixelFormat.isPublicFormat(format)) {
             throw new IllegalArgumentException("Invalid format is specified: " + format);
         }
-        return new ImageWriter(surface, maxImages, format);
+        return new ImageWriter(surface, maxImages, format, -1 /*width*/, -1 /*height*/);
     }
 
     /**
      * @hide
      */
-    protected ImageWriter(Surface surface, int maxImages, int format) {
+    protected ImageWriter(Surface surface, int maxImages, int format, int width, int height) {
         if (surface == null || maxImages < 1) {
             throw new IllegalArgumentException("Illegal input argument: surface " + surface
                     + ", maxImages: " + maxImages);
@@ -196,7 +248,8 @@
 
         // Note that the underlying BufferQueue is working in synchronous mode
         // to avoid dropping any buffers.
-        mNativeContext = nativeInit(new WeakReference<>(this), surface, maxImages, format);
+        mNativeContext = nativeInit(new WeakReference<>(this), surface, maxImages, format, width,
+                height);
 
         // nativeInit internally overrides UNKNOWN format. So does surface format query after
         // nativeInit and before getEstimatedNativeAllocBytes().
@@ -919,7 +972,7 @@
 
     // Native implemented ImageWriter methods.
     private synchronized native long nativeInit(Object weakSelf, Surface surface, int maxImgs,
-            int format);
+            int format, int width, int height);
 
     private synchronized native void nativeClose(long nativeCtx);
 
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 607c8f1..cf31e41 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -2414,37 +2414,44 @@
          * This indicates that the requested key was not found when trying to
          * perform a decrypt operation.  The operation can be retried after adding
          * the correct decryption key.
+         * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_NO_KEY}.
          */
-        public static final int ERROR_NO_KEY = 1;
+        public static final int ERROR_NO_KEY = MediaDrm.ErrorCodes.ERROR_NO_KEY;
 
         /**
          * This indicates that the key used for decryption is no longer
          * valid due to license term expiration.  The operation can be retried
          * after updating the expired keys.
+         * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_KEY_EXPIRED}.
          */
-        public static final int ERROR_KEY_EXPIRED = 2;
+        public static final int ERROR_KEY_EXPIRED = MediaDrm.ErrorCodes.ERROR_KEY_EXPIRED;
 
         /**
          * This indicates that a required crypto resource was not able to be
          * allocated while attempting the requested operation.  The operation
          * can be retried if the app is able to release resources.
+         * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_RESOURCE_BUSY}
          */
-        public static final int ERROR_RESOURCE_BUSY = 3;
+        public static final int ERROR_RESOURCE_BUSY = MediaDrm.ErrorCodes.ERROR_RESOURCE_BUSY;
 
         /**
          * This indicates that the output protection levels supported by the
          * device are not sufficient to meet the requirements set by the
          * content owner in the license policy.
+         * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_INSUFFICIENT_OUTPUT_PROTECTION}
          */
-        public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4;
+        public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION =
+                MediaDrm.ErrorCodes.ERROR_INSUFFICIENT_OUTPUT_PROTECTION;
 
         /**
          * This indicates that decryption was attempted on a session that is
          * not opened, which could be due to a failure to open the session,
          * closing the session prematurely, or the session being reclaimed
          * by the resource manager.
+         * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_SESSION_NOT_OPENED}
          */
-        public static final int ERROR_SESSION_NOT_OPENED = 5;
+        public static final int ERROR_SESSION_NOT_OPENED =
+                MediaDrm.ErrorCodes.ERROR_SESSION_NOT_OPENED;
 
         /**
          * This indicates that an operation was attempted that could not be
@@ -2453,23 +2460,28 @@
          * device security features that aren't supported by the device,
          * or due to an internal error in the crypto system that prevents
          * the specified security policy from being met.
+         * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_UNSUPPORTED_OPERATION}
          */
-        public static final int ERROR_UNSUPPORTED_OPERATION = 6;
+        public static final int ERROR_UNSUPPORTED_OPERATION =
+                MediaDrm.ErrorCodes.ERROR_UNSUPPORTED_OPERATION;
 
         /**
          * This indicates that the security level of the device is not
          * sufficient to meet the requirements set by the content owner
          * in the license policy.
+         * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_INSUFFICIENT_SECURITY}
          */
-        public static final int ERROR_INSUFFICIENT_SECURITY = 7;
+        public static final int ERROR_INSUFFICIENT_SECURITY =
+                MediaDrm.ErrorCodes.ERROR_INSUFFICIENT_SECURITY;
 
         /**
          * This indicates that the video frame being decrypted exceeds
          * the size of the device's protected output buffers. When
          * encountering this error the app should try playing content
          * of a lower resolution.
+         * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_FRAME_TOO_LARGE}
          */
-        public static final int ERROR_FRAME_TOO_LARGE = 8;
+        public static final int ERROR_FRAME_TOO_LARGE = MediaDrm.ErrorCodes.ERROR_FRAME_TOO_LARGE;
 
         /**
          * This error indicates that session state has been
@@ -2477,26 +2489,37 @@
          * of retaining crypto session state across device
          * suspend/resume. The session must be closed and a new
          * session opened to resume operation.
+         * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_LOST_STATE}
          */
-        public static final int ERROR_LOST_STATE = 9;
+        public static final int ERROR_LOST_STATE = MediaDrm.ErrorCodes.ERROR_LOST_STATE;
 
         /** @hide */
         @IntDef({
-            ERROR_NO_KEY,
-            ERROR_KEY_EXPIRED,
-            ERROR_RESOURCE_BUSY,
-            ERROR_INSUFFICIENT_OUTPUT_PROTECTION,
-            ERROR_SESSION_NOT_OPENED,
-            ERROR_UNSUPPORTED_OPERATION,
-            ERROR_INSUFFICIENT_SECURITY,
-            ERROR_FRAME_TOO_LARGE,
-            ERROR_LOST_STATE
+            MediaDrm.ErrorCodes.ERROR_NO_KEY,
+            MediaDrm.ErrorCodes.ERROR_KEY_EXPIRED,
+            MediaDrm.ErrorCodes.ERROR_RESOURCE_BUSY,
+            MediaDrm.ErrorCodes.ERROR_INSUFFICIENT_OUTPUT_PROTECTION,
+            MediaDrm.ErrorCodes.ERROR_SESSION_NOT_OPENED,
+            MediaDrm.ErrorCodes.ERROR_UNSUPPORTED_OPERATION,
+            MediaDrm.ErrorCodes.ERROR_INSUFFICIENT_SECURITY,
+            MediaDrm.ErrorCodes.ERROR_FRAME_TOO_LARGE,
+            MediaDrm.ErrorCodes.ERROR_LOST_STATE,
+            MediaDrm.ErrorCodes.ERROR_GENERIC_OEM,
+            MediaDrm.ErrorCodes.ERROR_GENERIC_PLUGIN,
+            MediaDrm.ErrorCodes.ERROR_LICENSE_PARSE,
+            MediaDrm.ErrorCodes.ERROR_MEDIA_FRAMEWORK,
+            MediaDrm.ErrorCodes.ERROR_ZERO_SUBSAMPLES
         })
         @Retention(RetentionPolicy.SOURCE)
         public @interface CryptoErrorCode {}
 
         /**
-         * Retrieve the error code associated with a CryptoException
+         * Returns error code associated with this {@link CryptoException}.
+         * <p>
+         * Please refer to {@link MediaDrm.ErrorCodes} for the general error
+         * handling strategy and details about each possible return value.
+         *
+         * @return an error code defined in {@link MediaDrm.ErrorCodes}.
          */
         @CryptoErrorCode
         public int getErrorCode() {
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 4d7ed11..06d0eb0 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -19,6 +19,7 @@
 import static android.media.Utils.intersectSortedDistinctRanges;
 import static android.media.Utils.sortDistinctRanges;
 
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SuppressLint;
@@ -1133,6 +1134,7 @@
          * in the ranges returned by {@link #getInputChannelCountRanges}
          *
          */
+        @IntRange(from = 1, to = 255)
         public int getMaxInputChannelCount() {
             int overall_max = 0;
             for (int i = mInputChannelRanges.length - 1; i >= 0; i--) {
@@ -1151,6 +1153,7 @@
          * This returns the lowest channel count in the ranges returned by
          * {@link #getInputChannelCountRanges}.
          */
+        @IntRange(from = 1, to = 255)
         public int getMinInputChannelCount() {
             int overall_min = MAX_INPUT_CHANNEL_COUNT;
             for (int i = mInputChannelRanges.length - 1; i >= 0; i--) {
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index adb8a54c..f7467a6 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -23,7 +23,11 @@
 import android.annotation.StringDef;
 import android.annotation.TestApi;
 import android.app.ActivityThread;
+import android.app.Application;
 import android.compat.annotation.UnsupportedAppUsage;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.Signature;
 import android.media.metrics.PlaybackComponent;
 import android.os.Handler;
 import android.os.HandlerExecutor;
@@ -39,7 +43,10 @@
 import java.lang.ref.WeakReference;
 import java.nio.ByteBuffer;
 import java.time.Instant;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
+import java.util.Base64;
 import java.util.HashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
@@ -144,6 +151,7 @@
     private static final String PERMISSION = android.Manifest.permission.ACCESS_DRM_CERTIFICATES;
 
     private long mNativeContext;
+    private final String mAppPackageName;
 
     /**
      * Specify no certificate type
@@ -281,16 +289,371 @@
         /* Native setup requires a weak reference to our object.
          * It's easier to create it here than in C++.
          */
+        mAppPackageName = ActivityThread.currentOpPackageName();
         native_setup(new WeakReference<MediaDrm>(this),
-                getByteArrayFromUUID(uuid),  ActivityThread.currentOpPackageName());
+                getByteArrayFromUUID(uuid), mAppPackageName);
 
         mCloseGuard.open("release");
     }
 
     /**
-     * Thrown when an unrecoverable failure occurs during a MediaDrm operation.
-     * Extends java.lang.IllegalStateException with the addition of an error
+     * Error codes that may be returned from {@link
+     * MediaDrmStateException#getErrorCode()} and {@link
+     * MediaCodec.CryptoException#getErrorCode()}
+     * <p>
+     * The description of each error code includes steps that may be taken to
+     * resolve the error condition. For some errors however, a recovery action
+     * cannot be predetermined. The description of those codes refers to a
+     * general strategy for handling the error condition programmatically, which
+     * is to try the following in listed order until successful:
+     * <ol>
+     * <li> retry the operation </li>
+     * <li> if the operation is related to a session, {@link
+     * #closeSession(byte[]) close} the session, {@link #openSession() open} a
+     * new session, and retry the operation </li>
+     * <li> {@link #close() close} the {@link MediaDrm} instance and any other
+     * related components such as the {@link MediaCodec codec} and retry
+     * playback, or </li>
+     * <li> try using a different configuration of the {@link MediaDrm} plugin,
+     * such as a different {@link #openSession(int) security level}. </li>
+     * </ol>
+     * <p>
+     * If the problem still persists after all the aforementioned steps, please
+     * report the failure to the {@link MediaDrm} plugin vendor along with the
+     * {@link LogMessage log messages} returned by {@link
+     * MediaDrm#getLogMessages()}, and a bugreport if possible.
+     */
+    public final static class ErrorCodes {
+        private ErrorCodes() {}
+
+        /**
+         * ERROR_UNKNOWN is used where no other defined error code is applicable
+         * to the current failure.
+         * <p>
+         * Please see the general error handling strategy for unexpected errors
+         * described in {@link ErrorCodes}.
+         */
+        public static final int ERROR_UNKNOWN = 0;
+
+        /**
+         * The requested key was not found when trying to perform a decrypt
+         * operation.
+         * <p>
+         * The operation can be retried after adding the correct decryption key.
+         */
+        public static final int ERROR_NO_KEY = 1;
+
+        /**
+         * The key used for decryption is no longer valid due to license term
+         * expiration.
+         * <p>
+         * The operation can be retried after updating the expired keys.
+         */
+        public static final int ERROR_KEY_EXPIRED = 2;
+
+        /**
+         * A required crypto resource was not able to be allocated while
+         * attempting the requested operation.
+         * <p>
+         * The operation can be retried if the app is able to release resources.
+         */
+        public static final int ERROR_RESOURCE_BUSY = 3;
+
+        /**
+         * The output protection levels supported by the device are not
+         * sufficient to meet the requirements set by the content owner in the
+         * license policy.
+         */
+        public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4;
+
+        /**
+         * Decryption was attempted on a session that is not opened, which could
+         * be due to a failure to open the session, closing the session
+         * prematurely, the session being reclaimed by the resource manager, or
+         * a non-existent session id.
+         */
+        public static final int ERROR_SESSION_NOT_OPENED = 5;
+
+        /**
+         * An operation was attempted that could not be supported by the crypto
+         * system of the device in its current configuration.
+         * <p>
+         * This may occur when the license policy requires device security
+         * features that aren't supported by the device, or due to an internal
+         * error in the crypto system that prevents the specified security
+         * policy from being met.
+         */
+        public static final int ERROR_UNSUPPORTED_OPERATION = 6;
+
+        /**
+         * The security level of the device is not sufficient to meet the
+         * requirements set by the content owner in the license policy.
+         */
+        public static final int ERROR_INSUFFICIENT_SECURITY = 7;
+
+        /**
+         * The video frame being decrypted exceeds the size of the device's
+         * protected output buffers.
+         * <p>
+         * When encountering this error the app should try playing content
+         * of a lower resolution or skipping the problematic frame.
+         */
+        public static final int ERROR_FRAME_TOO_LARGE = 8;
+
+        /**
+         * The session state has been invalidated. This can occur on devices
+         * that are not capable of retaining crypto session state across device
+         * suspend/resume.
+         * <p>
+         * The session must be closed and a new session opened to resume
+         * operation.
+         */
+        public static final int ERROR_LOST_STATE = 9;
+
+        /**
+         * Certificate is malformed or is of the wrong type.
+         * <p>
+         * Ensure the certificate provided by the app or returned from the
+         * license server is valid. Check with the {@link MediaDrm} plugin
+         * vendor for the expected certificate format.
+         */
+        public static final int ERROR_CERTIFICATE_MALFORMED = 10;
+
+        /**
+         * Certificate has not been set.
+         * <p>
+         * Ensure the certificate has been provided by the app. Check with the
+         * {@link MediaDrm} plugin vendor for the expected method to provide
+         * {@link MediaDrm} a certificate.
+         */
+        public static final int ERROR_CERTIFICATE_MISSING = 11;
+
+        /**
+         * An error happened within the crypto library used by the drm plugin.
+         */
+        public static final int ERROR_CRYPTO_LIBRARY = 12;
+
+        /**
+         * Unexpected error reported by the device OEM subsystem.
+         * <p>
+         * Please see the general error handling strategy for unexpected errors
+         * described in {@link ErrorCodes}.
+         */
+        public static final int ERROR_GENERIC_OEM = 13;
+
+        /**
+         * Unexpected internal failure in {@link MediaDrm}/{@link MediaCrypto}.
+         * <p>
+         * Please see the general error handling strategy for unexpected errors
+         * described in {@link ErrorCodes}.
+         */
+        public static final int ERROR_GENERIC_PLUGIN = 14;
+
+        /**
+         * The init data parameter passed to {@link MediaDrm#getKeyRequest} is
+         * empty or invalid.
+         * <p>
+         * Init data is typically obtained from {@link
+         * MediaExtractor#getPsshInfo()} or {@link
+         * MediaExtractor#getDrmInitData()}. Check with the {@link MediaDrm}
+         * plugin vendor for the expected init data format.
+         */
+        public static final int ERROR_INIT_DATA = 15;
+
+        /**
+         * Either the key was not loaded from the license before attempting the
+         * operation, or the key ID parameter provided by the app is incorrect.
+         * <p>
+         * Ensure the proper keys are in the license, and check the key ID
+         * parameter provided by the app is correct. Check with the {@link
+         * MediaDrm} plugin vendor for the expected license format.
+         */
+        public static final int ERROR_KEY_NOT_LOADED = 16;
+
+        /**
+         * The license response was empty, fields are missing or otherwise
+         * unable to be parsed or decrypted.
+         * <p>
+         * Check for mistakes such as empty or overwritten buffers. Otherwise,
+         * check with the {@link MediaDrm} plugin vendor for the expected
+         * license format.
+         */
+        public static final int ERROR_LICENSE_PARSE = 17;
+
+        /**
+         * The operation (e.g. to renew or persist a license) is prohibited by
+         * the license policy.
+         * <p>
+         * Check the license policy configuration on the license server.
+         */
+        public static final int ERROR_LICENSE_POLICY = 18;
+
+        /**
+         * Failed to generate a release request because a field in the offline
+         * license is empty or malformed.
+         * <p>
+         * The license can't be released on the server, but the app may remove
+         * the offline license explicitly using {@link
+         * MediaDrm#removeOfflineLicense}.
+         */
+        public static final int ERROR_LICENSE_RELEASE = 19;
+
+        /**
+         * The license server detected an error in the license request.
+         * <p>
+         * Check for errors on the license server.
+         */
+        public static final int ERROR_LICENSE_REQUEST_REJECTED = 20;
+
+        /**
+         * Failed to restore an offline license because a field in the offline
+         * license is empty or malformed.
+         * <p>
+         * Try requesting the license again if the device is online.
+         */
+        public static final int ERROR_LICENSE_RESTORE = 21;
+
+        /**
+         * Offline license is in an invalid state for the attempted operation.
+         * <p>
+         * Check the sequence of API calls made that can affect offline license
+         * state. For example, this could happen when the app attempts to
+         * restore a license after it has been released.
+         */
+        public static final int ERROR_LICENSE_STATE = 22;
+
+        /**
+         * Failure in the media framework.
+         * <p>
+         * Try releasing media resources (e.g. {@link MediaCodec}, {@link
+         * MediaDrm}), and restarting playback.
+         */
+        public static final int ERROR_MEDIA_FRAMEWORK = 23;
+
+        /**
+         * Error loading the provisioned certificate.
+         * <p>
+         * Re-provisioning may resolve the problem; check with the {@link
+         * MediaDrm} plugin vendor for re-provisioning instructions. Otherwise,
+         * using a different security level may resolve the issue.
+         */
+        public static final int ERROR_PROVISIONING_CERTIFICATE = 24;
+
+        /**
+         * Required steps were not performed before provisioning was attempted.
+         * <p>
+         * Ask the {@link MediaDrm} plugin vendor for situations where this
+         * error may occur.
+         */
+        public static final int ERROR_PROVISIONING_CONFIG = 25;
+
+        /**
+         * The provisioning response was empty, fields are missing or otherwise
+         * unable to be parsed.
+         * <p>
+         * Check for mistakes such as empty or overwritten buffers. Otherwise,
+         * check with the {@link MediaDrm} plugin vendor for the expected
+         * provisioning response format.
+         */
+        public static final int ERROR_PROVISIONING_PARSE = 26;
+
+        /**
+         * Provisioning failed in a way that is likely to succeed on a
+         * subsequent attempt.
+         * <p>
+         * The app should retry the operation.
+         */
+        public static final int ERROR_PROVISIONING_RETRY = 27;
+
+        /**
+         * This indicates that apps using MediaDrm sessions are
+         * temporarily exceeding the capacity of available crypto
+         * resources.
+         * <p>
+         * The app should retry the operation later.
+         */
+        public static final int ERROR_RESOURCE_CONTENTION = 28;
+
+        /**
+         * Failed to generate a secure stop request because a field in the
+         * stored license is empty or malformed.
+         * <p>
+         * The secure stop can't be released on the server, but the app may
+         * remove it explicitly using {@link MediaDrm#removeSecureStop}.
+         */
+        public static final int ERROR_SECURE_STOP_RELEASE = 29;
+
+        /**
+         * The plugin was unable to read data from the filesystem.
+         * <p>
+         * Please see the general error handling strategy for unexpected errors
+         * described in {@link ErrorCodes}.
+         */
+        public static final int ERROR_STORAGE_READ = 30;
+
+        /**
+         * The plugin was unable to write data to the filesystem.
+         * <p>
+         * Please see the general error handling strategy for unexpected errors
+         * described in {@link ErrorCodes}.
+         */
+        public static final int ERROR_STORAGE_WRITE = 31;
+
+        /**
+         * {@link MediaCodec#queueSecureInputBuffer} called with 0 subsamples.
+         * <p>
+         * Check the {@link MediaCodec.CryptoInfo} object passed to {@link
+         * MediaCodec#queueSecureInputBuffer}.
+         */
+        public static final int ERROR_ZERO_SUBSAMPLES = 32;
+
+    }
+
+    /** @hide */
+    @IntDef({
+        ErrorCodes.ERROR_NO_KEY,
+        ErrorCodes.ERROR_KEY_EXPIRED,
+        ErrorCodes.ERROR_RESOURCE_BUSY,
+        ErrorCodes.ERROR_INSUFFICIENT_OUTPUT_PROTECTION,
+        ErrorCodes.ERROR_SESSION_NOT_OPENED,
+        ErrorCodes.ERROR_UNSUPPORTED_OPERATION,
+        ErrorCodes.ERROR_INSUFFICIENT_SECURITY,
+        ErrorCodes.ERROR_FRAME_TOO_LARGE,
+        ErrorCodes.ERROR_LOST_STATE,
+        ErrorCodes.ERROR_CERTIFICATE_MALFORMED,
+        ErrorCodes.ERROR_CERTIFICATE_MISSING,
+        ErrorCodes.ERROR_CRYPTO_LIBRARY,
+        ErrorCodes.ERROR_GENERIC_OEM,
+        ErrorCodes.ERROR_GENERIC_PLUGIN,
+        ErrorCodes.ERROR_INIT_DATA,
+        ErrorCodes.ERROR_KEY_NOT_LOADED,
+        ErrorCodes.ERROR_LICENSE_PARSE,
+        ErrorCodes.ERROR_LICENSE_POLICY,
+        ErrorCodes.ERROR_LICENSE_RELEASE,
+        ErrorCodes.ERROR_LICENSE_REQUEST_REJECTED,
+        ErrorCodes.ERROR_LICENSE_RESTORE,
+        ErrorCodes.ERROR_LICENSE_STATE,
+        ErrorCodes.ERROR_MEDIA_FRAMEWORK,
+        ErrorCodes.ERROR_PROVISIONING_CERTIFICATE,
+        ErrorCodes.ERROR_PROVISIONING_CONFIG,
+        ErrorCodes.ERROR_PROVISIONING_PARSE,
+        ErrorCodes.ERROR_PROVISIONING_RETRY,
+        ErrorCodes.ERROR_SECURE_STOP_RELEASE,
+        ErrorCodes.ERROR_STORAGE_READ,
+        ErrorCodes.ERROR_STORAGE_WRITE,
+        ErrorCodes.ERROR_ZERO_SUBSAMPLES
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface MediaDrmErrorCode {}
+
+    /**
+     * Thrown when a general failure occurs during a MediaDrm operation.
+     * Extends {@link IllegalStateException} with the addition of an error
      * code that may be useful in diagnosing the failure.
+     * <p>
+     * Please refer to {@link ErrorCodes} for the general error handling
+     * strategy and details about each possible return value from {@link
+     * MediaDrmStateException#getErrorCode()}.
      */
     public static final class MediaDrmStateException extends java.lang.IllegalStateException {
         private final int mErrorCode;
@@ -311,15 +674,30 @@
         }
 
         /**
-         * Retrieve the associated error code
+         * Returns error code associated with this {@link
+         * MediaDrmStateException}.
+         * <p>
+         * Please refer to {@link ErrorCodes} for the general error handling
+         * strategy and details about each possible return value.
          *
-         * @hide
+         * @return an error code defined in {@link MediaDrm.ErrorCodes}.
          */
+        @MediaDrmErrorCode
         public int getErrorCode() {
             return mErrorCode;
         }
 
         /**
+         * Returns true if the {@link MediaDrmStateException} is a transient
+         * issue, perhaps due to resource constraints, and that the operation
+         * (e.g. provisioning) may succeed on a subsequent attempt.
+         */
+        public boolean isTransient() {
+            return mErrorCode == ErrorCodes.ERROR_PROVISIONING_RETRY
+                    || mErrorCode == ErrorCodes.ERROR_RESOURCE_CONTENTION;
+        }
+
+        /**
          * Retrieve a developer-readable diagnostic information string
          * associated with the exception. Do not show this to end-users,
          * since this string will not be localized or generally comprehensible
@@ -332,7 +710,13 @@
     }
 
     /**
-     * Thrown when an error occurs in any method that has a session context.
+     * {@link SessionException} is a misnomer because it may occur in methods
+     * <b>without</b> a session context.
+     * <p>
+     * A {@link SessionException} is most likely to be thrown when an operation
+     * failed in a way that is likely to succeed on a subsequent attempt; call
+     * {@link #isTransient()} to determine whether the app should retry the
+     * failing operation.
      */
     public static final class SessionException extends RuntimeException {
         public SessionException(int errorCode, @Nullable String detailMessage) {
@@ -342,6 +726,7 @@
 
         /**
          * The SessionException has an unknown error code.
+         * @deprecated Unused.
          */
         public static final int ERROR_UNKNOWN = 0;
 
@@ -349,6 +734,10 @@
          * This indicates that apps using MediaDrm sessions are
          * temporarily exceeding the capacity of available crypto
          * resources. The app should retry the operation later.
+         *
+         * @deprecated Please use {@link #isTransient()} instead of comparing
+         * the return value of {@link #getErrorCode()} against
+         * {@link SessionException#ERROR_RESOURCE_CONTENTION}.
          */
         public static final int ERROR_RESOURCE_CONTENTION = 1;
 
@@ -361,12 +750,26 @@
 
         /**
          * Retrieve the error code associated with the SessionException
+         *
+         * @deprecated Please use {@link #isTransient()} instead of comparing
+         * the return value of {@link #getErrorCode()} against
+         * {@link SessionException#ERROR_RESOURCE_CONTENTION}.
          */
         @SessionErrorCode
         public int getErrorCode() {
             return mErrorCode;
         }
 
+        /**
+         * Returns true if the {@link SessionException} is a transient
+         * issue, perhaps due to resource constraints, and that the operation
+         * (e.g. provisioning, generating requests) may succeed on a subsequent
+         * attempt.
+         */
+        public boolean isTransient() {
+            return mErrorCode == ERROR_RESOURCE_CONTENTION;
+        }
+
         private final int mErrorCode;
     }
 
@@ -1144,13 +1547,79 @@
      * problem with the certifcate
      */
     @NonNull
-    public native KeyRequest getKeyRequest(
+    public KeyRequest getKeyRequest(
+            @NonNull byte[] scope, @Nullable byte[] init,
+            @Nullable String mimeType, @KeyType int keyType,
+            @Nullable HashMap<String, String> optionalParameters)
+            throws NotProvisionedException {
+        HashMap<String, String> internalParams;
+        if (optionalParameters == null) {
+            internalParams = new HashMap<>();
+        } else {
+            internalParams = new HashMap<>(optionalParameters);
+        }
+        byte[] rawBytes = getNewestAvailablePackageCertificateRawBytes();
+        byte[] hashBytes = null;
+        if (rawBytes != null) {
+            hashBytes = getDigestBytes(rawBytes, "SHA-256");
+        }
+        if (hashBytes != null) {
+            Base64.Encoder encoderB64 = Base64.getEncoder();
+            String hashBytesB64 = encoderB64.encodeToString(hashBytes);
+            internalParams.put("package_certificate_hash_bytes", hashBytesB64);
+        }
+        return getKeyRequestNative(scope, init, mimeType, keyType, internalParams);
+    }
+
+    @Nullable
+    private byte[] getNewestAvailablePackageCertificateRawBytes() {
+        Application application = ActivityThread.currentApplication();
+        if (application == null) {
+            Log.w(TAG, "pkg cert: Application is null");
+            return null;
+        }
+        PackageManager pm = application.getPackageManager();
+        if (pm == null) {
+            Log.w(TAG, "pkg cert: PackageManager is null");
+            return null;
+        }
+        PackageInfo packageInfo = null;
+        try {
+            packageInfo = pm.getPackageInfo(mAppPackageName,
+                    PackageManager.GET_SIGNING_CERTIFICATES);
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.w(TAG, mAppPackageName, e);
+        }
+        if (packageInfo == null || packageInfo.signingInfo == null) {
+            Log.w(TAG, "pkg cert: PackageInfo or SigningInfo is null");
+            return null;
+        }
+        Signature[] signers = packageInfo.signingInfo.getApkContentsSigners();
+        if (signers != null && signers.length == 1) {
+            return signers[0].toByteArray();
+        }
+        Log.w(TAG, "pkg cert: " + signers.length + " signers");
+        return null;
+    }
+
+    @Nullable
+    private static byte[] getDigestBytes(@NonNull byte[] rawBytes, @NonNull String algorithm) {
+        try {
+            MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
+            return messageDigest.digest(rawBytes);
+        } catch (NoSuchAlgorithmException e) {
+            Log.w(TAG, algorithm, e);
+        }
+        return null;
+    }
+
+    @NonNull
+    private native KeyRequest getKeyRequestNative(
             @NonNull byte[] scope, @Nullable byte[] init,
             @Nullable String mimeType, @KeyType int keyType,
             @Nullable HashMap<String, String> optionalParameters)
             throws NotProvisionedException;
 
-
     /**
      * A key response is received from the license server by the app, then it is
      * provided to the MediaDrm instance using provideKeyResponse.  When the
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 67f1660..f8a642a 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -980,6 +980,74 @@
     public static final String KEY_BITRATE_MODE = "bitrate-mode";
 
     /**
+     * A key describing the maximum Quantization Parameter allowed for encoding video.
+     * This key applies to all three video frame types (I, P, and B). This value fills
+     * in for any of the frame-specific #KEY_VIDEO_QP_I_MAX, #KEY_VIDEO_QP_P_MAX, or
+     * #KEY_VIDEO_QP_B_MAX keys that are not specified
+     *
+     * The associated value is an integer.
+     */
+    public static final String KEY_VIDEO_QP_MAX = "video-qp-max";
+
+    /**
+     * A key describing the maximum Quantization Parameter allowed for encoding video.
+     * This key applies to all three video frame types (I, P, and B). This value fills
+     * in for any of the frame-specific #KEY_VIDEO_QP_I_MIN, #KEY_VIDEO_QP_P_MIN, or
+     * #KEY_VIDEO_QP_B_MIN keys that are not specified
+     *
+     * The associated value is an integer.
+     */
+    public static final String KEY_VIDEO_QP_MIN = "video-qp-min";
+
+    /**
+     * A key describing the maximum Quantization Parameter allowed for encoding video.
+     * This value applies to video I-frames.
+     *
+     * The associated value is an integer.
+     */
+    public static final String KEY_VIDEO_QP_I_MAX = "video-qp-i-max";
+
+    /**
+     * A key describing the minimum Quantization Parameter allowed for encoding video.
+     * This value applies to video I-frames.
+     *
+     * The associated value is an integer.
+     */
+    public static final String KEY_VIDEO_QP_I_MIN = "video-qp-i-min";
+
+    /**
+     * A key describing the maximum Quantization Parameter allowed for encoding video.
+     * This value applies to video P-frames.
+     *
+     * The associated value is an integer.
+     */
+    public static final String KEY_VIDEO_QP_P_MAX = "video-qp-p-max";
+
+    /**
+     * A key describing the minimum Quantization Parameter allowed for encoding video.
+     * This value applies to video P-frames.
+     *
+     * The associated value is an integer.
+     */
+    public static final String KEY_VIDEO_QP_P_MIN = "video-qp-p-min";
+
+    /**
+     * A key describing the maximum Quantization Parameter allowed for encoding video.
+     * This value applies to video B-frames.
+     *
+     * The associated value is an integer.
+     */
+    public static final String KEY_VIDEO_QP_B_MAX = "video-qp-b-max";
+
+    /**
+     * A key describing the minimum Quantization Parameter allowed for encoding video.
+     * This value applies to video B-frames.
+     *
+     * The associated value is an integer.
+     */
+    public static final String KEY_VIDEO_QP_B_MIN = "video-qp-b-min";
+
+    /**
      * A key describing the audio session ID of the AudioTrack associated
      * to a tunneled video codec.
      * The associated value is an integer.
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index c51c9dd..9176dae 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -19,6 +19,7 @@
 import static android.Manifest.permission.BIND_IMS_SERVICE;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
+import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -91,6 +92,7 @@
 import java.util.Set;
 import java.util.UUID;
 import java.util.Vector;
+import java.util.concurrent.Executor;
 
 
 /**
@@ -1358,6 +1360,7 @@
     private void startImpl() {
         baseStart(0); // unknown device at this point
         stayAwake(true);
+        tryToEnableNativeRoutingCallback();
         _start();
     }
 
@@ -1383,6 +1386,7 @@
         stayAwake(false);
         _stop();
         baseStop();
+        tryToDisableNativeRoutingCallback();
     }
 
     private native void _stop() throws IllegalStateException;
@@ -1524,8 +1528,9 @@
                 native_enableDeviceCallback(true);
                 return true;
             } catch (IllegalStateException e) {
-                // Fail silently as media player state could have changed in between start
-                // and enabling routing callback, return false to indicate not enabled
+                if (Log.isLoggable(TAG, Log.DEBUG)) {
+                    Log.d(TAG, "testEnableNativeRoutingCallbacks failed", e);
+                }
             }
         }
         return false;
@@ -1588,7 +1593,7 @@
             Handler handler) {
         synchronized (mRoutingChangeListeners) {
             if (listener != null && !mRoutingChangeListeners.containsKey(listener)) {
-                testEnableNativeRoutingCallbacksLocked();
+                mEnableSelfRoutingMonitor = testEnableNativeRoutingCallbacksLocked();
                 mRoutingChangeListeners.put(
                         listener, new NativeRoutingEventHandlerDelegate(this, listener,
                                 handler != null ? handler : mEventHandler));
@@ -2172,7 +2177,7 @@
         mOnVideoSizeChangedListener = null;
         mOnTimedTextListener = null;
         mOnRtpRxNoticeListener = null;
-        mOnRtpRxNoticeHandler = null;
+        mOnRtpRxNoticeExecutor = null;
         synchronized (mTimeProviderLock) {
             if (mTimeProvider != null) {
                 mTimeProvider.close();
@@ -3481,9 +3486,6 @@
 
             case MEDIA_STOPPED:
                 {
-                    tryToDisableNativeRoutingCallback();
-                    // FIXME see b/179218630
-                    //baseStop();
                     TimeProvider timeProvider = mTimeProvider;
                     if (timeProvider != null) {
                         timeProvider.onStopped();
@@ -3492,18 +3494,9 @@
                 break;
 
             case MEDIA_STARTED:
-                {
-                    // FIXME see b/179218630
-                    //baseStart(native_getRoutedDeviceId());
-                    tryToEnableNativeRoutingCallback();
-                }
                 // fall through
             case MEDIA_PAUSED:
                 {
-                    // FIXME see b/179218630
-                    //if (msg.what == MEDIA_PAUSED) {
-                    //    basePause();
-                    //}
                     TimeProvider timeProvider = mTimeProvider;
                     if (timeProvider != null) {
                         timeProvider.onPaused(msg.what == MEDIA_PAUSED);
@@ -3711,7 +3704,6 @@
 
             case MEDIA_RTP_RX_NOTICE:
                 final OnRtpRxNoticeListener rtpRxNoticeListener = mOnRtpRxNoticeListener;
-                final Handler rtpRxNoticeHandler = mOnRtpRxNoticeHandler;
                 if (rtpRxNoticeListener == null) {
                     return;
                 }
@@ -3730,14 +3722,9 @@
                     } finally {
                         parcel.recycle();
                     }
-                    if (rtpRxNoticeHandler == null) {
-                        rtpRxNoticeListener.onRtpRxNotice(mMediaPlayer, noticeType, data);
-                    } else {
-                        rtpRxNoticeHandler.post(
-                                () ->
-                                        rtpRxNoticeListener
-                                                .onRtpRxNotice(mMediaPlayer, noticeType, data));
-                    }
+                    mOnRtpRxNoticeExecutor.execute(() ->
+                            rtpRxNoticeListener
+                                    .onRtpRxNotice(mMediaPlayer, noticeType, data));
                 }
                 return;
 
@@ -4305,28 +4292,26 @@
      *
      * @see OnRtpRxNoticeListener
      *
-     * @param listener the listener called after a notice from RTP Rx
-     * @param handler the {@link Handler} that receives RTP Tx events. If null is passed,
-     *                notifications will be posted on the thread that created this MediaPlayer
-     *                instance. If the creating thread does not have a {@link Looper}, then
-     *                notifications will be posted on the main thread.
+     * @param listener the listener called after a notice from RTP Rx.
+     * @param executor the {@link Executor} on which to post RTP Tx events.
      * @hide
      */
     @SystemApi
     @RequiresPermission(BIND_IMS_SERVICE)
     public void setOnRtpRxNoticeListener(
             @NonNull Context context,
-            @NonNull OnRtpRxNoticeListener listener, @Nullable Handler handler) {
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull OnRtpRxNoticeListener listener) {
         Objects.requireNonNull(context);
         Preconditions.checkArgument(
                 context.checkSelfPermission(BIND_IMS_SERVICE) == PERMISSION_GRANTED,
                 BIND_IMS_SERVICE + " permission not granted.");
         mOnRtpRxNoticeListener = Objects.requireNonNull(listener);
-        mOnRtpRxNoticeHandler = handler;
+        mOnRtpRxNoticeExecutor = Objects.requireNonNull(executor);
     }
 
     private OnRtpRxNoticeListener mOnRtpRxNoticeListener;
-    private Handler mOnRtpRxNoticeHandler;
+    private Executor mOnRtpRxNoticeExecutor;
 
     /**
      * Register a callback to be invoked when a selected track has timed metadata available.
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 6cf99e2..dc43ad3 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -384,7 +384,12 @@
         }
 
         public Display[] getAllPresentationDisplays() {
-            return mDisplayService.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
+            try {
+                return mDisplayService.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
+            } catch (RuntimeException ex) {
+                Log.e(TAG, "Unable to get displays.", ex);
+                return null;
+            }
         }
 
         private void updatePresentationDisplays(int changedDisplayId) {
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index 4407efa..5d0f0aa 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -78,7 +78,7 @@
 
     private final int mImplType;
     // uniquely identifies the Player Interface throughout the system (P I Id)
-    private int mPlayerIId = AudioPlaybackConfiguration.PLAYER_PIID_INVALID;
+    protected int mPlayerIId = AudioPlaybackConfiguration.PLAYER_PIID_INVALID;
 
     @GuardedBy("mLock")
     private int mState;
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index 66d5794..96bffee117 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -38,9 +38,7 @@
 interface ISessionManager {
     ISession createSession(String packageName, in ISessionCallback sessionCb, String tag,
             in Bundle sessionInfo, int userId);
-    void notifySession2Created(in Session2Token sessionToken);
     List<MediaSession.Token> getSessions(in ComponentName compName, int userId);
-    ParceledListSlice getSession2Tokens(int userId);
     void dispatchMediaKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent,
             boolean needWakeLock);
     boolean dispatchMediaKeyEventToSessionAsSystemService(String packageName,
@@ -73,8 +71,10 @@
     void setOnMediaKeyListener(in IOnMediaKeyListener listener);
 
     boolean isTrusted(String controllerPackageName, int controllerPid, int controllerUid);
-    void setCustomMediaKeyDispatcherForTesting(String name);
-    void setCustomSessionPolicyProviderForTesting(String name);
+    void setCustomMediaKeyDispatcher(String name);
+    void setCustomMediaSessionPolicyProvider(String name);
+    boolean hasCustomMediaKeyDispatcher(String componentName);
+    boolean hasCustomMediaSessionPolicyProvider(String componentName);
     int getSessionPolicies(in MediaSession.Token token);
     void setSessionPolicies(in MediaSession.Token token, int policies);
 }
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 13a3436..98a13cf 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -25,15 +25,16 @@
 import android.annotation.SystemService;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.pm.ParceledListSlice;
 import android.media.AudioManager;
 import android.media.IRemoteSessionCallback;
+import android.media.MediaCommunicationManager;
 import android.media.MediaFrameworkPlatformInitializer;
 import android.media.MediaSession2;
 import android.media.Session2Token;
 import android.media.VolumeProvider;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.UserHandle;
@@ -83,6 +84,7 @@
     public static final int RESULT_MEDIA_KEY_HANDLED = 1;
 
     private final ISessionManager mService;
+    private final MediaCommunicationManager mCommunicationManager;
     private final OnMediaKeyEventDispatchedListenerStub mOnMediaKeyEventDispatchedListenerStub =
             new OnMediaKeyEventDispatchedListenerStub();
     private final OnMediaKeyEventSessionChangedListenerStub
@@ -127,6 +129,8 @@
                 .getMediaServiceManager()
                 .getMediaSessionServiceRegisterer()
                 .get());
+        mCommunicationManager = (MediaCommunicationManager) context
+                .getSystemService(Context.MEDIA_COMMUNICATION_SERVICE);
     }
 
     /**
@@ -163,17 +167,11 @@
      * {@link MediaSession2.Builder} instead.
      *
      * @param token newly created session2 token
+     * @deprecated Don't use this method. A new media session is notified automatically.
      */
+    @Deprecated
     public void notifySession2Created(@NonNull Session2Token token) {
-        Objects.requireNonNull(token, "token shouldn't be null");
-        if (token.getType() != Session2Token.TYPE_SESSION) {
-            throw new IllegalArgumentException("token's type should be TYPE_SESSION");
-        }
-        try {
-            mService.notifySession2Created(token);
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
+        // Does nothing
     }
 
     /**
@@ -254,37 +252,7 @@
      */
     @NonNull
     public List<Session2Token> getSession2Tokens() {
-        return getSession2Tokens(UserHandle.myUserId());
-    }
-
-    /**
-     * Gets a list of {@link Session2Token} with type {@link Session2Token#TYPE_SESSION} for the
-     * given user.
-     * <p>
-     * The calling application needs to hold the
-     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission in order to
-     * retrieve session tokens for user ids that do not belong to current process.
-     *
-     * @param userHandle The user handle to fetch sessions for.
-     * @return A list of {@link Session2Token}
-     * @hide
-     */
-    @NonNull
-    @SuppressLint("UserHandle")
-    public List<Session2Token> getSession2Tokens(@NonNull UserHandle userHandle) {
-        Objects.requireNonNull(userHandle, "userHandle shouldn't be null");
-        return getSession2Tokens(userHandle.getIdentifier());
-
-    }
-
-    private List<Session2Token> getSession2Tokens(int userId) {
-        try {
-            ParceledListSlice slice = mService.getSession2Tokens(userId);
-            return slice == null ? new ArrayList<>() : slice.getList();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to get session tokens", e);
-        }
-        return new ArrayList<>();
+        return mCommunicationManager.getSession2Tokens();
     }
 
     /**
@@ -321,7 +289,7 @@
             @NonNull OnActiveSessionsChangedListener sessionListener,
             @Nullable ComponentName notificationListener, @Nullable Handler handler) {
         addOnActiveSessionsChangedListener(sessionListener, notificationListener,
-                UserHandle.myUserId(), handler);
+                UserHandle.myUserId(), handler == null ? null : new HandlerExecutor(handler));
     }
 
     /**
@@ -337,38 +305,40 @@
      * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission in order to
      * add listeners for user ids that do not belong to current process.
      *
-     * @param sessionListener The listener to add.
      * @param notificationListener The enabled notification listener component. May be null.
      * @param userHandle The user handle to listen for changes on.
-     * @param handler The handler to post updates on.
+     * @param executor The executor on which the listener should be invoked
+     * @param sessionListener The listener to add.
      * @hide
      */
-    @SuppressLint({"ExecutorRegistration", "SamShouldBeLast", "UserHandle"})
+    @SuppressLint("UserHandle")
     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
     public void addOnActiveSessionsChangedListener(
-            @NonNull OnActiveSessionsChangedListener sessionListener,
-            @Nullable ComponentName notificationListener, @NonNull UserHandle userHandle,
-            @Nullable Handler handler) {
+            @Nullable ComponentName notificationListener,
+            @NonNull UserHandle userHandle, @NonNull Executor executor,
+            @NonNull OnActiveSessionsChangedListener sessionListener) {
         Objects.requireNonNull(userHandle, "userHandle shouldn't be null");
+        Objects.requireNonNull(executor, "executor shouldn't be null");
         addOnActiveSessionsChangedListener(sessionListener, notificationListener,
-                userHandle.getIdentifier(), handler);
+                userHandle.getIdentifier(), executor);
     }
 
     private void addOnActiveSessionsChangedListener(
             @NonNull OnActiveSessionsChangedListener sessionListener,
             @Nullable ComponentName notificationListener, int userId,
-            @Nullable Handler handler) {
+            @Nullable Executor executor) {
         Objects.requireNonNull(sessionListener, "sessionListener shouldn't be null");
-        if (handler == null) {
-            handler = new Handler();
+        if (executor == null) {
+            executor = new HandlerExecutor(new Handler());
         }
+
         synchronized (mLock) {
             if (mListeners.get(sessionListener) != null) {
                 Log.w(TAG, "Attempted to add session listener twice, ignoring.");
                 return;
             }
             SessionsChangedWrapper wrapper = new SessionsChangedWrapper(mContext, sessionListener,
-                    handler);
+                    executor);
             try {
                 mService.addSessionsListener(wrapper.mStub, notificationListener, userId);
                 mListeners.put(sessionListener, wrapper);
@@ -412,7 +382,8 @@
      */
     public void addOnSession2TokensChangedListener(
             @NonNull OnSession2TokensChangedListener listener) {
-        addOnSession2TokensChangedListener(UserHandle.myUserId(), listener, new Handler());
+        addOnSession2TokensChangedListener(UserHandle.myUserId(), listener,
+                new HandlerExecutor(new Handler()));
     }
 
     /**
@@ -428,7 +399,9 @@
      */
     public void addOnSession2TokensChangedListener(
             @NonNull OnSession2TokensChangedListener listener, @NonNull Handler handler) {
-        addOnSession2TokensChangedListener(UserHandle.myUserId(), listener, handler);
+        Objects.requireNonNull(handler, "handler shouldn't be null");
+        addOnSession2TokensChangedListener(UserHandle.myUserId(), listener,
+                new HandlerExecutor(handler));
     }
 
     /**
@@ -445,20 +418,19 @@
      *
      * @param userHandle The userHandle to listen for changes on
      * @param listener The listener to add
-     * @param handler The handler to call listener on. If {@code null}, calling thread's looper will
-     *                be used.
+     * @param executor The executor on which the listener should be invoked
      * @hide
      */
     @SuppressLint("UserHandle")
     public void addOnSession2TokensChangedListener(@NonNull UserHandle userHandle,
-            @NonNull OnSession2TokensChangedListener listener, @NonNull Handler handler) {
+            @NonNull OnSession2TokensChangedListener listener, @NonNull Executor executor) {
         Objects.requireNonNull(userHandle, "userHandle shouldn't be null");
-        addOnSession2TokensChangedListener(userHandle.getIdentifier(), listener, handler);
+        Objects.requireNonNull(executor, "executor shouldn't be null");
+        addOnSession2TokensChangedListener(userHandle.getIdentifier(), listener, executor);
     }
 
     private void addOnSession2TokensChangedListener(int userId,
-            OnSession2TokensChangedListener listener, Handler handler) {
-        Objects.requireNonNull(handler, "handler shouldn't be null");
+            OnSession2TokensChangedListener listener, Executor executor) {
         Objects.requireNonNull(listener, "listener shouldn't be null");
         synchronized (mLock) {
             if (mSession2TokensListeners.get(listener) != null) {
@@ -466,7 +438,7 @@
                 return;
             }
             Session2TokensChangedWrapper wrapper =
-                    new Session2TokensChangedWrapper(listener, handler);
+                    new Session2TokensChangedWrapper(listener, executor);
             try {
                 mService.addSession2TokensListener(wrapper.getStub(), userId);
                 mSession2TokensListeners.put(listener, wrapper);
@@ -529,8 +501,7 @@
         }
         if (shouldRegisterCallback) {
             try {
-                mService.registerRemoteSessionCallback(
-                        mRemoteSessionCallbackStub);
+                mService.registerRemoteSessionCallback(mRemoteSessionCallbackStub);
             } catch (RemoteException e) {
                 Log.e(TAG, "Failed to register remote volume controller callback", e);
             }
@@ -847,7 +818,7 @@
     /**
      * Add a {@link OnMediaKeyEventDispatchedListener}.
      *
-     * @param executor The executor on which the callback should be invoked
+     * @param executor The executor on which the listener should be invoked
      * @param listener A {@link OnMediaKeyEventDispatchedListener}.
      * @hide
      */
@@ -898,7 +869,7 @@
     /**
      * Add a {@link OnMediaKeyEventDispatchedListener}.
      *
-     * @param executor The executor on which the callback should be invoked
+     * @param executor The executor on which the listener should be invoked
      * @param listener A {@link OnMediaKeyEventSessionChangedListener}.
      * @hide
      */
@@ -958,9 +929,9 @@
      * @hide
      */
     @VisibleForTesting
-    public void setCustomMediaKeyDispatcherForTesting(@Nullable String name) {
+    public void setCustomMediaKeyDispatcher(@Nullable String name) {
         try {
-            mService.setCustomMediaKeyDispatcherForTesting(name);
+            mService.setCustomMediaKeyDispatcher(name);
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to set custom media key dispatcher name", e);
         }
@@ -968,22 +939,58 @@
 
     /**
      * Set the component name for the custom
-     * {@link com.android.server.media.SessionPolicyProvider} class. Set to null to restore to the
-     * custom {@link com.android.server.media.SessionPolicyProvider} class name retrieved from the
-     * config value.
+     * {@link com.android.server.media.MediaSessionPolicyProvider} class. Set to null to restore to
+     * the custom {@link com.android.server.media.MediaSessionPolicyProvider} class name retrieved
+     * from the config value.
      *
      * @hide
      */
     @VisibleForTesting
-    public void setCustomSessionPolicyProviderForTesting(@Nullable String name) {
+    public void setCustomMediaSessionPolicyProvider(@Nullable String name) {
         try {
-            mService.setCustomSessionPolicyProviderForTesting(name);
+            mService.setCustomMediaSessionPolicyProvider(name);
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to set custom session policy provider name", e);
         }
     }
 
     /**
+     * Get the component name for the custom {@link com.android.server.media.MediaKeyDispatcher}
+     * class.
+     *
+     * @hide
+     */
+    @VisibleForTesting
+    public boolean hasCustomMediaKeyDispatcher(@NonNull String componentName) {
+        Objects.requireNonNull(componentName, "componentName shouldn't be null");
+        try {
+            return mService.hasCustomMediaKeyDispatcher(componentName);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to check if custom media key dispatcher with given component"
+                    + " name exists", e);
+        }
+        return false;
+    }
+
+    /**
+     * Get the component name for the custom
+     * {@link com.android.server.media.MediaSessionPolicyProvider} class.
+     *
+     * @hide
+     */
+    @VisibleForTesting
+    public boolean hasCustomMediaSessionPolicyProvider(@NonNull String componentName) {
+        Objects.requireNonNull(componentName, "componentName shouldn't be null");
+        try {
+            return mService.hasCustomMediaSessionPolicyProvider(componentName);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to check if custom media session policy provider with given"
+                    + " component name exists", e);
+        }
+        return false;
+    }
+
+    /**
      * Get session policies of the specified {@link MediaSession.Token}.
      *
      * @hide
@@ -1221,62 +1228,61 @@
     private static final class SessionsChangedWrapper {
         private Context mContext;
         private OnActiveSessionsChangedListener mListener;
-        private Handler mHandler;
+        private Executor mExecutor;
 
         public SessionsChangedWrapper(Context context, OnActiveSessionsChangedListener listener,
-                Handler handler) {
+                Executor executor) {
             mContext = context;
             mListener = listener;
-            mHandler = handler;
+            mExecutor = executor;
         }
 
         private final IActiveSessionsListener.Stub mStub = new IActiveSessionsListener.Stub() {
             @Override
             public void onActiveSessionsChanged(final List<MediaSession.Token> tokens) {
-                final Handler handler = mHandler;
-                if (handler != null) {
-                    handler.post(new Runnable() {
-                        @Override
-                        public void run() {
-                            final Context context = mContext;
-                            if (context != null) {
-                                ArrayList<MediaController> controllers = new ArrayList<>();
-                                int size = tokens.size();
-                                for (int i = 0; i < size; i++) {
-                                    controllers.add(new MediaController(context, tokens.get(i)));
-                                }
-                                final OnActiveSessionsChangedListener listener = mListener;
-                                if (listener != null) {
-                                    listener.onActiveSessionsChanged(controllers);
-                                }
-                            }
-                        }
-                    });
+                if (mExecutor != null) {
+                    final Executor executor = mExecutor;
+                    executor.execute(() -> callOnActiveSessionsChangedListener(tokens));
                 }
             }
         };
 
+        private void callOnActiveSessionsChangedListener(final List<MediaSession.Token> tokens) {
+            final Context context = mContext;
+            if (context != null) {
+                ArrayList<MediaController> controllers = new ArrayList<>();
+                int size = tokens.size();
+                for (int i = 0; i < size; i++) {
+                    controllers.add(new MediaController(context, tokens.get(i)));
+                }
+                final OnActiveSessionsChangedListener listener = mListener;
+                if (listener != null) {
+                    listener.onActiveSessionsChanged(controllers);
+                }
+            }
+        }
+
         private void release() {
             mListener = null;
             mContext = null;
-            mHandler = null;
+            mExecutor = null;
         }
     }
 
     private static final class Session2TokensChangedWrapper {
         private final OnSession2TokensChangedListener mListener;
-        private final Handler mHandler;
+        private final Executor mExecutor;
         private final ISession2TokensListener.Stub mStub =
                 new ISession2TokensListener.Stub() {
                     @Override
                     public void onSession2TokensChanged(final List<Session2Token> tokens) {
-                        mHandler.post(() -> mListener.onSession2TokensChanged(tokens));
+                        mExecutor.execute(() -> mListener.onSession2TokensChanged(tokens));
                     }
                 };
 
-        Session2TokensChangedWrapper(OnSession2TokensChangedListener listener, Handler handler) {
+        Session2TokensChangedWrapper(OnSession2TokensChangedListener listener, Executor executor) {
             mListener = listener;
-            mHandler = (handler == null) ? new Handler() : new Handler(handler.getLooper());
+            mExecutor = executor;
         }
 
         public ISession2TokensListener.Stub getStub() {
diff --git a/media/java/android/media/soundtrigger/OWNERS b/media/java/android/media/soundtrigger/OWNERS
index 6a351d3..e5d0370 100644
--- a/media/java/android/media/soundtrigger/OWNERS
+++ b/media/java/android/media/soundtrigger/OWNERS
@@ -1 +1,2 @@
+ytai@google.com
 elaurent@google.com
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 740bc2d..c0185dc 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -2525,7 +2525,9 @@
         /**
          * Pauses TV program recording in the current recording session.
          *
-         * @param params A set of extra parameters which might be handled with this event.
+         * @param params Domain-specific data for this request. Keys <em>must</em> be a scoped
+         *            name, i.e. prefixed with a package name you own, so that different developers
+         *            will not create conflicting keys.
          *        {@link TvRecordingClient#pauseRecording(Bundle)}.
          */
         void pauseRecording(@NonNull Bundle params) {
@@ -2543,7 +2545,9 @@
         /**
          * Resumes TV program recording in the current recording session.
          *
-         * @param params A set of extra parameters which might be handled with this event.
+         * @param params Domain-specific data for this request. Keys <em>must</em> be a scoped
+         *            name, i.e. prefixed with a package name you own, so that different developers
+         *            will not create conflicting keys.
          *        {@link TvRecordingClient#resumeRecording(Bundle)}.
          */
         void resumeRecording(@NonNull Bundle params) {
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index ee0be01..952bbf5 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -149,7 +149,7 @@
     /**
      * Invalid 64-bit filter ID.
      */
-    public static final long INVALID_FILTER_ID_64BIT =
+    public static final long INVALID_FILTER_ID_LONG =
             android.hardware.tv.tuner.V1_1.Constants.Constant64Bit.INVALID_FILTER_ID_64BIT;
     /**
      * Invalid frequency that is used as the default frontend frequency setting.
@@ -932,8 +932,8 @@
     public int connectFrontendToCiCam(int ciCamId) {
         if (TunerVersionChecker.checkHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1,
                 "linkFrontendToCiCam")) {
-            if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND)
-                    && checkCiCamResource(ciCamId)) {
+            if (checkCiCamResource(ciCamId)
+                    && checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND)) {
                 return nativeLinkCiCam(ciCamId);
             }
         }
@@ -978,7 +978,8 @@
     public int disconnectFrontendToCiCam(int ciCamId) {
         if (TunerVersionChecker.checkHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1,
                 "unlinkFrontendToCiCam")) {
-            if (mFrontendCiCamHandle != null && mFrontendCiCamId == ciCamId) {
+            if (mFrontendCiCamHandle != null && mFrontendCiCamId != null
+                    && mFrontendCiCamId == ciCamId) {
                 int result = nativeUnlinkCiCam(ciCamId);
                 if (result == RESULT_SUCCESS) {
                     mTunerResourceManager.releaseCiCam(mFrontendCiCamHandle, mClientId);
@@ -1409,6 +1410,7 @@
         boolean granted = mTunerResourceManager.requestCiCam(request, ciCamHandle);
         if (granted) {
             mFrontendCiCamHandle = ciCamHandle[0];
+            mFrontendCiCamId = ciCamId;
         }
         return granted;
     }
diff --git a/media/java/android/media/tv/tuner/filter/DownloadEvent.java b/media/java/android/media/tv/tuner/filter/DownloadEvent.java
index 9f97b61..394211be 100644
--- a/media/java/android/media/tv/tuner/filter/DownloadEvent.java
+++ b/media/java/android/media/tv/tuner/filter/DownloadEvent.java
@@ -16,6 +16,7 @@
 
 package android.media.tv.tuner.filter;
 
+import android.annotation.IntRange;
 import android.annotation.SystemApi;
 
 /**
@@ -51,6 +52,7 @@
     /**
      * Gets MPU sequence number of filtered data.
      */
+    @IntRange(from = 0)
     public int getMpuSequenceNumber() {
         return mMpuSequenceNumber;
     }
diff --git a/media/java/android/media/tv/tuner/filter/Filter.java b/media/java/android/media/tv/tuner/filter/Filter.java
index 51b685a..2f3e2d8 100644
--- a/media/java/android/media/tv/tuner/filter/Filter.java
+++ b/media/java/android/media/tv/tuner/filter/Filter.java
@@ -309,7 +309,8 @@
     }
 
     /**
-     * Gets the filter Id.
+     * Gets the filter Id in 32-bit. For any Tuner SoC that supports 64-bit filter architecture,
+     * use {@link #getIdLong()}.
      */
     public int getId() {
         synchronized (mLock) {
@@ -319,9 +320,10 @@
     }
 
     /**
-     * Gets the 64-bit filter Id.
+     * Gets the 64-bit filter Id. For any Tuner SoC that supports 32-bit filter architecture,
+     * use {@link #getId()}.
      */
-    public long getId64Bit() {
+    public long getIdLong() {
         synchronized (mLock) {
             TunerUtils.checkResourceState(TAG, mIsClosed);
             return nativeGetId64Bit();
diff --git a/media/java/android/media/tv/tuner/filter/MediaEvent.java b/media/java/android/media/tv/tuner/filter/MediaEvent.java
index 91be5c3..dbd85e9 100644
--- a/media/java/android/media/tv/tuner/filter/MediaEvent.java
+++ b/media/java/android/media/tv/tuner/filter/MediaEvent.java
@@ -17,6 +17,7 @@
 package android.media.tv.tuner.filter;
 
 import android.annotation.BytesLong;
+import android.annotation.IntRange;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.media.MediaCodec.LinearBlock;
@@ -154,6 +155,7 @@
     /**
      * Gets MPU sequence number of filtered data.
      */
+    @IntRange(from = 0)
     public int getMpuSequenceNumber() {
         return mMpuSequenceNumber;
     }
diff --git a/media/java/android/media/tv/tuner/filter/MmtpRecordEvent.java b/media/java/android/media/tv/tuner/filter/MmtpRecordEvent.java
index 6a41c74..58a81d9 100644
--- a/media/java/android/media/tv/tuner/filter/MmtpRecordEvent.java
+++ b/media/java/android/media/tv/tuner/filter/MmtpRecordEvent.java
@@ -17,6 +17,7 @@
 package android.media.tv.tuner.filter;
 
 import android.annotation.BytesLong;
+import android.annotation.IntRange;
 import android.annotation.SystemApi;
 import android.media.tv.tuner.filter.RecordSettings.ScHevcIndex;
 
@@ -69,6 +70,7 @@
      * {@link android.media.tv.tuner.TunerVersionChecker#getTunerVersion()} to get the version
      * information.
      */
+    @IntRange(from = 0)
     public int getMpuSequenceNumber() {
         return mMpuSequenceNumber;
     }
diff --git a/media/java/android/media/tv/tuner/filter/PesEvent.java b/media/java/android/media/tv/tuner/filter/PesEvent.java
index 695e596..bfb7460 100644
--- a/media/java/android/media/tv/tuner/filter/PesEvent.java
+++ b/media/java/android/media/tv/tuner/filter/PesEvent.java
@@ -16,6 +16,7 @@
 
 package android.media.tv.tuner.filter;
 
+import android.annotation.IntRange;
 import android.annotation.SystemApi;
 
 /**
@@ -53,6 +54,7 @@
     /**
      * Gets MPU sequence number of filtered data.
      */
+    @IntRange(from = 0)
     public int getMpuSequenceNumber() {
         return mMpuSequenceNumber;
     }
diff --git a/media/java/android/media/tv/tunerresourcemanager/Android.bp b/media/java/android/media/tv/tunerresourcemanager/Android.bp
index c38d919..c904ca2 100644
--- a/media/java/android/media/tv/tunerresourcemanager/Android.bp
+++ b/media/java/android/media/tv/tunerresourcemanager/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "framework-media-tv-tunerresourcemanager-sources-aidl",
     srcs: [
diff --git a/media/java/android/mtp/MtpServer.java b/media/java/android/mtp/MtpServer.java
index 042d02f..1d2657a 100644
--- a/media/java/android/mtp/MtpServer.java
+++ b/media/java/android/mtp/MtpServer.java
@@ -144,11 +144,6 @@
         native_remove_storage(storage.getStorageId());
     }
 
-    public static void configure(boolean usePtp) {
-        native_configure(usePtp);
-    }
-
-    public static native final void native_configure(boolean usePtp);
     private native final void native_setup(
             MtpDatabase database,
             FileDescriptor controlFd,
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 6160b81..ce45504 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -1,3 +1,20 @@
+package {
+    default_applicable_licenses: ["frameworks_base_media_jni_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_media_jni_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_library_shared {
     name: "libmedia_jni",
 
diff --git a/media/jni/android_media_ImageWriter.cpp b/media/jni/android_media_ImageWriter.cpp
index 5d959a3..b291ac95b 100644
--- a/media/jni/android_media_ImageWriter.cpp
+++ b/media/jni/android_media_ImageWriter.cpp
@@ -364,7 +364,7 @@
 }
 
 static jlong ImageWriter_init(JNIEnv* env, jobject thiz, jobject weakThiz, jobject jsurface,
-        jint maxImages, jint userFormat) {
+        jint maxImages, jint userFormat, jint userWidth, jint userHeight) {
     status_t res;
 
     ALOGV("%s: maxImages:%d", __FUNCTION__, maxImages);
@@ -405,20 +405,38 @@
     // Get the dimension and format of the producer.
     sp<ANativeWindow> anw = producer;
     int32_t width, height, surfaceFormat;
-    if ((res = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, &width)) != OK) {
-        ALOGE("%s: Query Surface width failed: %s (%d)", __FUNCTION__, strerror(-res), res);
-        jniThrowRuntimeException(env, "Failed to query Surface width");
-        return 0;
+    if (userWidth < 0) {
+        if ((res = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, &width)) != OK) {
+            ALOGE("%s: Query Surface width failed: %s (%d)", __FUNCTION__, strerror(-res), res);
+            jniThrowRuntimeException(env, "Failed to query Surface width");
+            return 0;
+        }
+    } else {
+        width = userWidth;
     }
+
     ctx->setBufferWidth(width);
 
-    if ((res = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, &height)) != OK) {
-        ALOGE("%s: Query Surface height failed: %s (%d)", __FUNCTION__, strerror(-res), res);
-        jniThrowRuntimeException(env, "Failed to query Surface height");
-        return 0;
+    if (userHeight < 0) {
+        if ((res = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, &height)) != OK) {
+            ALOGE("%s: Query Surface height failed: %s (%d)", __FUNCTION__, strerror(-res), res);
+            jniThrowRuntimeException(env, "Failed to query Surface height");
+            return 0;
+        }
+    } else {
+        height = userHeight;
     }
     ctx->setBufferHeight(height);
 
+    if ((userWidth > 0) && (userHeight > 0)) {
+        res = native_window_set_buffers_user_dimensions(anw.get(), userWidth, userHeight);
+        if (res != OK) {
+            ALOGE("%s: Set buffer dimensions failed: %s (%d)", __FUNCTION__, strerror(-res), res);
+            jniThrowRuntimeException(env, "Set buffer dimensions failed");
+            return 0;
+        }
+    }
+
     // Query surface format if no valid user format is specified, otherwise, override surface format
     // with user format.
     if (userFormat == IMAGE_FORMAT_UNKNOWN) {
@@ -1045,7 +1063,7 @@
 
 static JNINativeMethod gImageWriterMethods[] = {
     {"nativeClassInit",         "()V",                        (void*)ImageWriter_classInit },
-    {"nativeInit",              "(Ljava/lang/Object;Landroid/view/Surface;II)J",
+    {"nativeInit",              "(Ljava/lang/Object;Landroid/view/Surface;IIII)J",
                                                               (void*)ImageWriter_init },
     {"nativeClose",              "(J)V",                      (void*)ImageWriter_close },
     {"nativeAttachAndQueueImage", "(JJIJIIIIII)I",          (void*)ImageWriter_attachAndQueueImage },
diff --git a/media/jni/android_media_JetPlayer.cpp b/media/jni/android_media_JetPlayer.cpp
index 481f80b..10a5b58 100644
--- a/media/jni/android_media_JetPlayer.cpp
+++ b/media/jni/android_media_JetPlayer.cpp
@@ -43,12 +43,34 @@
     jfieldID  nativePlayerInJavaObj; // stores in Java the native JetPlayer object
 };
 
-static fields_t javaJetPlayerFields;
+static fields_t javaJetPlayerFields {};
 
+#define JAVA_NATIVEJETPLAYERINJAVAOBJ_FIELD_NAME "mNativePlayerInJavaObj"
+#define JAVA_NATIVEJETPOSTEVENT_CALLBACK_NAME "postEventFromNative"
+
+static void initializeJavaIDs(JNIEnv* env) {
+    static std::once_flag sJniInitialized;
+
+    std::call_once(sJniInitialized, [](JNIEnv* env) {
+        // Get the JetPlayer java class
+        jclass jetPlayerClass = FindClassOrDie(env, kClassPathName);
+        javaJetPlayerFields.jetClass = MakeGlobalRefOrDie(env, jetPlayerClass);
+
+        // Get the mNativePlayerInJavaObj variable field
+        javaJetPlayerFields.nativePlayerInJavaObj =
+                GetFieldIDOrDie(env, jetPlayerClass, JAVA_NATIVEJETPLAYERINJAVAOBJ_FIELD_NAME, "J");
+
+        // Get the callback to post events from this native code to Java
+        javaJetPlayerFields.postNativeEventInJava = GetStaticMethodIDOrDie(env,
+                javaJetPlayerFields.jetClass, JAVA_NATIVEJETPOSTEVENT_CALLBACK_NAME,
+                "(Ljava/lang/Object;III)V");
+    }, env);
+}
 
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 
+
 /*
  * This function is called from JetPlayer instance's render thread
  */
@@ -79,6 +101,8 @@
 android_media_JetPlayer_setup(JNIEnv *env, jobject thiz, jobject weak_this,
     jint maxTracks, jint trackBufferSize)
 {
+    initializeJavaIDs(env);
+
     //ALOGV("android_media_JetPlayer_setup(): entering.");
     JetPlayer* lpJet = new JetPlayer(env->NewGlobalRef(weak_this), maxTracks, trackBufferSize);
 
@@ -511,28 +535,9 @@
     {"native_clearQueue",  "()Z",                   (void *)android_media_JetPlayer_clearQueue},
 };
 
-#define JAVA_NATIVEJETPLAYERINJAVAOBJ_FIELD_NAME "mNativePlayerInJavaObj"
-#define JAVA_NATIVEJETPOSTEVENT_CALLBACK_NAME "postEventFromNative"
 
 
 int register_android_media_JetPlayer(JNIEnv *env)
 {
-    javaJetPlayerFields.jetClass = NULL;
-    javaJetPlayerFields.postNativeEventInJava = NULL;
-    javaJetPlayerFields.nativePlayerInJavaObj = NULL;
-
-    // Get the JetPlayer java class
-    jclass jetPlayerClass = FindClassOrDie(env, kClassPathName);
-    javaJetPlayerFields.jetClass = MakeGlobalRefOrDie(env, jetPlayerClass);
-
-    // Get the mNativePlayerInJavaObj variable field
-    javaJetPlayerFields.nativePlayerInJavaObj = GetFieldIDOrDie(env,
-            jetPlayerClass, JAVA_NATIVEJETPLAYERINJAVAOBJ_FIELD_NAME, "J");
-
-    // Get the callback to post events from this native code to Java
-    javaJetPlayerFields.postNativeEventInJava = GetStaticMethodIDOrDie(env,
-            javaJetPlayerFields.jetClass, JAVA_NATIVEJETPOSTEVENT_CALLBACK_NAME,
-            "(Ljava/lang/Object;III)V");
-
     return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
 }
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 71c86cc..1870a93 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -61,6 +61,7 @@
 #include <media/stagefright/foundation/AString.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/PersistentSurface.h>
+#include <mediadrm/DrmUtils.h>
 #include <mediadrm/ICrypto.h>
 
 #include <private/android/AHardwareBufferHelpers.h>
@@ -312,6 +313,7 @@
     mGraphicOutput = (mime.startsWithIgnoreCase("video/") || mime.startsWithIgnoreCase("image/"))
             && !(flags & CONFIGURE_FLAG_ENCODE);
     mHasCryptoOrDescrambler = (crypto != nullptr) || (descrambler != nullptr);
+    mCrypto = crypto;
 
     return mCodec->configure(
             format, mSurfaceTextureClient, crypto, descrambler, flags);
@@ -1103,6 +1105,8 @@
     }
 }
 
+jint MediaErrorToJavaError(status_t err);
+
 }  // namespace android
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1150,7 +1154,8 @@
     env->Throw(exception);
 }
 
-static void throwCryptoException(JNIEnv *env, status_t err, const char *msg) {
+static void throwCryptoException(JNIEnv *env, status_t err, const char *msg,
+        const sp<ICrypto> &crypto) {
     ScopedLocalRef<jclass> clazz(
             env, env->FindClass("android/media/MediaCodec$CryptoException"));
     CHECK(clazz.get() != NULL);
@@ -1159,7 +1164,7 @@
         env->GetMethodID(clazz.get(), "<init>", "(ILjava/lang/String;)V");
     CHECK(constructID != NULL);
 
-    const char *defaultMsg = "Unknown Error";
+    std::string defaultMsg = "Unknown Error";
 
     /* translate OS errors to Java API CryptoException errorCodes (which are positive) */
     switch (err) {
@@ -1199,11 +1204,17 @@
             err = gCryptoErrorCodes.cryptoErrorLostState;
             defaultMsg = "Session state was lost, open a new session and retry";
             break;
-        default:  /* Other negative DRM error codes go out as is. */
+        default:  /* Other negative DRM error codes go out best-effort. */
+            err = MediaErrorToJavaError(err);
+            defaultMsg = StrCryptoError(err);
             break;
     }
 
-    jstring msgObj = env->NewStringUTF(msg != NULL ? msg : defaultMsg);
+    std::string msgStr(msg != NULL ? msg : defaultMsg.c_str());
+    if (crypto != NULL) {
+        msgStr = DrmUtils::GetExceptionMessage(err, msgStr.c_str(), crypto);
+    }
+    jstring msgObj = env->NewStringUTF(msgStr.c_str());
 
     jthrowable exception =
         (jthrowable)env->NewObject(clazz.get(), constructID, err, msgObj);
@@ -1213,7 +1224,7 @@
 
 static jint throwExceptionAsNecessary(
         JNIEnv *env, status_t err, int32_t actionCode = ACTION_CODE_FATAL,
-        const char *msg = NULL) {
+        const char *msg = NULL, const sp<ICrypto>& crypto = NULL) {
     switch (err) {
         case OK:
             return 0;
@@ -1237,7 +1248,7 @@
 
         default:
             if (isCryptoError(err)) {
-                throwCryptoException(env, err, msg);
+                throwCryptoException(env, err, msg, crypto);
                 return 0;
             }
             throwCodecException(env, err, actionCode, msg);
@@ -1899,7 +1910,8 @@
     subSamples = NULL;
 
     throwExceptionAsNecessary(
-            env, err, ACTION_CODE_FATAL, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
+            env, err, ACTION_CODE_FATAL, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str(),
+            codec->getCrypto());
 }
 
 static jobject android_media_MediaCodec_mapHardwareBuffer(JNIEnv *env, jclass, jobject bufferObj) {
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index a58f9a7..f16bcf3 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -164,6 +164,8 @@
 
     bool hasCryptoOrDescrambler() { return mHasCryptoOrDescrambler; }
 
+    const sp<ICrypto> &getCrypto() { return mCrypto; }
+
 protected:
     virtual ~JMediaCodec();
 
@@ -193,6 +195,8 @@
 
     status_t mInitStatus;
 
+    sp<ICrypto> mCrypto;
+
     template <typename T>
     status_t createByteBufferFromABuffer(
             JNIEnv *env, bool readOnly, bool clearBuffer, const sp<T> &buffer,
diff --git a/media/jni/android_media_MediaCrypto.cpp b/media/jni/android_media_MediaCrypto.cpp
index 517672e..f491be8 100644
--- a/media/jni/android_media_MediaCrypto.cpp
+++ b/media/jni/android_media_MediaCrypto.cpp
@@ -202,10 +202,11 @@
     uuid = NULL;
 
     if (err != OK) {
-        jniThrowException(
+        std::string strerr(StrCryptoError(err));
+        jniThrowExceptionFmt(
                 env,
                 "android/media/MediaCryptoException",
-                "Failed to instantiate crypto object.");
+                "Failed to instantiate crypto object: %s", strerr.c_str());
         return;
     }
 
@@ -295,7 +296,8 @@
         } else if (err == NO_INIT) {
             msg += ": crypto plugin not initialized";
         } else {
-            msg.appendFormat(": general failure (%d)", err);
+            std::string strerr(StrCryptoError(err));
+            msg.appendFormat(": general failure (%s)", strerr.c_str());
         }
         jniThrowException(env, "android/media/MediaCryptoException", msg.string());
     }
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 22c3572..56f6c45 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -343,11 +343,56 @@
     }
 }
 
+jint MediaErrorToJavaError(status_t err) {
+#define STATUS_CASE(status) \
+    case status: \
+        return J##status
+
+    switch (err) {
+        STATUS_CASE(ERROR_DRM_UNKNOWN);
+        STATUS_CASE(ERROR_DRM_NO_LICENSE);
+        STATUS_CASE(ERROR_DRM_LICENSE_EXPIRED);
+        STATUS_CASE(ERROR_DRM_RESOURCE_BUSY);
+        STATUS_CASE(ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION);
+        STATUS_CASE(ERROR_DRM_SESSION_NOT_OPENED);
+        STATUS_CASE(ERROR_DRM_CANNOT_HANDLE);
+        STATUS_CASE(ERROR_DRM_INSUFFICIENT_SECURITY);
+        STATUS_CASE(ERROR_DRM_FRAME_TOO_LARGE);
+        STATUS_CASE(ERROR_DRM_SESSION_LOST_STATE);
+        STATUS_CASE(ERROR_DRM_CERTIFICATE_MALFORMED);
+        STATUS_CASE(ERROR_DRM_CERTIFICATE_MISSING);
+        STATUS_CASE(ERROR_DRM_CRYPTO_LIBRARY);
+        STATUS_CASE(ERROR_DRM_GENERIC_OEM);
+        STATUS_CASE(ERROR_DRM_GENERIC_PLUGIN);
+        STATUS_CASE(ERROR_DRM_INIT_DATA);
+        STATUS_CASE(ERROR_DRM_KEY_NOT_LOADED);
+        STATUS_CASE(ERROR_DRM_LICENSE_PARSE);
+        STATUS_CASE(ERROR_DRM_LICENSE_POLICY);
+        STATUS_CASE(ERROR_DRM_LICENSE_RELEASE);
+        STATUS_CASE(ERROR_DRM_LICENSE_REQUEST_REJECTED);
+        STATUS_CASE(ERROR_DRM_LICENSE_RESTORE);
+        STATUS_CASE(ERROR_DRM_LICENSE_STATE);
+        STATUS_CASE(ERROR_DRM_MEDIA_FRAMEWORK);
+        STATUS_CASE(ERROR_DRM_PROVISIONING_CERTIFICATE);
+        STATUS_CASE(ERROR_DRM_PROVISIONING_CONFIG);
+        STATUS_CASE(ERROR_DRM_PROVISIONING_PARSE);
+        STATUS_CASE(ERROR_DRM_PROVISIONING_RETRY);
+        STATUS_CASE(ERROR_DRM_RESOURCE_CONTENTION);
+        STATUS_CASE(ERROR_DRM_SECURE_STOP_RELEASE);
+        STATUS_CASE(ERROR_DRM_STORAGE_READ);
+        STATUS_CASE(ERROR_DRM_STORAGE_WRITE);
+        STATUS_CASE(ERROR_DRM_ZERO_SUBSAMPLES);
+#undef STATUS_CASE
+    }
+    return static_cast<jint>(err);
+}
+
 static void throwStateException(JNIEnv *env, const char *msg, status_t err) {
     ALOGE("Illegal state exception: %s (%d)", msg, err);
 
+    jint jerr = MediaErrorToJavaError(err);
     jobject exception = env->NewObject(gFields.stateException.classId,
-            gFields.stateException.init, static_cast<int>(err),
+            gFields.stateException.init, static_cast<int>(jerr),
             env->NewStringUTF(msg));
     env->Throw(static_cast<jthrowable>(exception));
 }
@@ -377,43 +422,11 @@
 }
 
 static bool throwExceptionAsNecessary(
-        JNIEnv *env, status_t err, const char *msg = NULL) {
-
-    const char *drmMessage = NULL;
-
-    switch (err) {
-    case ERROR_DRM_UNKNOWN:
-        drmMessage = "General DRM error";
-        break;
-    case ERROR_DRM_NO_LICENSE:
-        drmMessage = "No license";
-        break;
-    case ERROR_DRM_LICENSE_EXPIRED:
-        drmMessage = "License expired";
-        break;
-    case ERROR_DRM_SESSION_NOT_OPENED:
-        drmMessage = "Session not opened";
-        break;
-    case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED:
-        drmMessage = "Not initialized";
-        break;
-    case ERROR_DRM_DECRYPT:
-        drmMessage = "Decrypt error";
-        break;
-    case ERROR_DRM_CANNOT_HANDLE:
-        drmMessage = "Invalid parameter or data format";
-        break;
-    case ERROR_DRM_INVALID_STATE:
-        drmMessage = "Invalid state";
-        break;
-    default:
-        break;
-    }
-
-    String8 vendorMessage;
-    if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
-        vendorMessage = String8::format("DRM vendor-defined error: %d", err);
-        drmMessage = vendorMessage.string();
+        JNIEnv *env, const sp<IDrm> &drm, status_t err, const char *msg = NULL) {
+    std::string msgStr;
+    if (drm != NULL && err != OK) {
+        msgStr = DrmUtils::GetExceptionMessage(err, msg, drm);
+        msg = msgStr.c_str();
     }
 
     if (err == BAD_VALUE || err == ERROR_DRM_CANNOT_HANDLE) {
@@ -439,15 +452,6 @@
         throwSessionException(env, msg, err);
         return true;
     } else if (err != OK) {
-        String8 errbuf;
-        if (drmMessage != NULL) {
-            if (msg == NULL) {
-                msg = drmMessage;
-            } else {
-                errbuf = String8::format("%s: %s", msg, drmMessage);
-                msg = errbuf.string();
-            }
-        }
         throwStateException(env, msg, err);
         return true;
     }
@@ -1045,7 +1049,7 @@
     status_t err = JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType,
             securityLevel, &isSupported);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to query crypto scheme support")) {
+    if (throwExceptionAsNecessary(env, NULL, err, "Failed to query crypto scheme support")) {
         return false;
     }
     return isSupported;
@@ -1068,7 +1072,7 @@
 
     status_t err = drm->openSession(level, sessionId);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to open session")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to open session")) {
         return NULL;
     }
 
@@ -1087,7 +1091,7 @@
 
     status_t err = drm->closeSession(sessionId);
 
-    throwExceptionAsNecessary(env, err, "Failed to close session");
+    throwExceptionAsNecessary(env, drm, err, "Failed to close session");
 }
 
 static jobject android_media_MediaDrm_getKeyRequest(
@@ -1140,7 +1144,7 @@
     status_t err = drm->getKeyRequest(sessionId, initData, mimeType,
             keyType, optParams, request, defaultUrl, &keyRequestType);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get key request")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get key request")) {
         return NULL;
     }
 
@@ -1210,7 +1214,7 @@
 
     status_t err = drm->provideKeyResponse(sessionId, response, keySetId);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to handle key response")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to handle key response")) {
         return NULL;
     }
     return VectorToJByteArray(env, keySetId);
@@ -1234,7 +1238,7 @@
 
     status_t err = drm->removeKeys(keySetId);
 
-    throwExceptionAsNecessary(env, err, "Failed to remove keys");
+    throwExceptionAsNecessary(env, drm, err, "Failed to remove keys");
 }
 
 static void android_media_MediaDrm_restoreKeys(
@@ -1257,7 +1261,7 @@
 
     status_t err = drm->restoreKeys(sessionId, keySetId);
 
-    throwExceptionAsNecessary(env, err, "Failed to restore keys");
+    throwExceptionAsNecessary(env, drm, err, "Failed to restore keys");
 }
 
 static jobject android_media_MediaDrm_queryKeyStatus(
@@ -1273,7 +1277,7 @@
 
     status_t err = drm->queryKeyStatus(sessionId, infoMap);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to query key status")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to query key status")) {
         return NULL;
     }
 
@@ -1303,7 +1307,7 @@
     String8 certAuthority = JStringToString8(env, jcertAuthority);
     status_t err = drm->getProvisionRequest(certType, certAuthority, request, defaultUrl);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get provision request")) {
         return NULL;
     }
 
@@ -1358,7 +1362,7 @@
         env->SetObjectField(certificateObj, gFields.certificate.wrappedPrivateKey, jwrappedKey);
     }
 
-    throwExceptionAsNecessary(env, err, "Failed to handle provision response");
+    throwExceptionAsNecessary(env, drm, err, "Failed to handle provision response");
     return certificateObj;
 }
 
@@ -1374,7 +1378,7 @@
 
     status_t err = drm->getSecureStops(secureStops);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get secure stops")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get secure stops")) {
         return NULL;
     }
 
@@ -1393,7 +1397,7 @@
 
     status_t err = drm->getSecureStopIds(secureStopIds);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get secure stop Ids")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get secure stop Ids")) {
         return NULL;
     }
 
@@ -1412,7 +1416,7 @@
 
     status_t err = drm->getSecureStop(JByteArrayToVector(env, ssid), secureStop);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get secure stop")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get secure stop")) {
         return NULL;
     }
 
@@ -1431,7 +1435,7 @@
 
     status_t err = drm->releaseSecureStops(ssRelease);
 
-    throwExceptionAsNecessary(env, err, "Failed to release secure stops");
+    throwExceptionAsNecessary(env, drm, err, "Failed to release secure stops");
 }
 
 static void android_media_MediaDrm_removeSecureStop(
@@ -1444,7 +1448,7 @@
 
     status_t err = drm->removeSecureStop(JByteArrayToVector(env, ssid));
 
-    throwExceptionAsNecessary(env, err, "Failed to remove secure stop");
+    throwExceptionAsNecessary(env, drm, err, "Failed to remove secure stop");
 }
 
 static void android_media_MediaDrm_removeAllSecureStops(
@@ -1457,7 +1461,7 @@
 
     status_t err = drm->removeAllSecureStops();
 
-    throwExceptionAsNecessary(env, err, "Failed to remove all secure stops");
+    throwExceptionAsNecessary(env, drm, err, "Failed to remove all secure stops");
 }
 
 
@@ -1496,7 +1500,7 @@
 
     status_t err = drm->getHdcpLevels(&connected, &max);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get HDCP levels")) {
         return gHdcpLevels.kHdcpLevelUnknown;
     }
     return HdcpLevelTojint(connected);
@@ -1515,7 +1519,7 @@
 
     status_t err = drm->getHdcpLevels(&connected, &max);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get HDCP levels")) {
         return gHdcpLevels.kHdcpLevelUnknown;
     }
     return HdcpLevelTojint(max);
@@ -1532,7 +1536,7 @@
     uint32_t open = 0, max = 0;
     status_t err = drm->getNumberOfSessions(&open, &max);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get number of sessions")) {
         return 0;
     }
     return open;
@@ -1549,7 +1553,7 @@
     uint32_t open = 0, max = 0;
     status_t err = drm->getNumberOfSessions(&open, &max);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get number of sessions")) {
         return 0;
     }
     return max;
@@ -1569,7 +1573,7 @@
 
     status_t err = drm->getSecurityLevel(sessionId, &level);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get security level")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get security level")) {
         return gSecurityLevels.kSecurityLevelUnknown;
     }
 
@@ -1601,7 +1605,7 @@
 
     status_t err = drm->getOfflineLicenseKeySetIds(keySetIds);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get offline key set Ids")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get offline key set Ids")) {
         return NULL;
     }
 
@@ -1618,7 +1622,7 @@
 
     status_t err = drm->removeOfflineLicense(JByteArrayToVector(env, keySetId));
 
-    throwExceptionAsNecessary(env, err, "Failed to remove offline license");
+    throwExceptionAsNecessary(env, drm, err, "Failed to remove offline license");
 }
 
 static jint android_media_MediaDrm_getOfflineLicenseState(JNIEnv *env,
@@ -1635,7 +1639,7 @@
 
     status_t err = drm->getOfflineLicenseState(keySetId, &state);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get offline license state")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get offline license state")) {
         return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
     }
 
@@ -1668,7 +1672,7 @@
 
     status_t err = drm->getPropertyString(name, value);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get property")) {
         return NULL;
     }
 
@@ -1694,7 +1698,7 @@
 
     status_t err = drm->getPropertyByteArray(name, value);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get property")) {
         return NULL;
     }
 
@@ -1726,7 +1730,7 @@
 
     status_t err = drm->setPropertyString(name, value);
 
-    throwExceptionAsNecessary(env, err, "Failed to set property");
+    throwExceptionAsNecessary(env, drm, err, "Failed to set property");
 }
 
 static void android_media_MediaDrm_setPropertyByteArray(
@@ -1754,7 +1758,7 @@
 
     status_t err = drm->setPropertyByteArray(name, value);
 
-    throwExceptionAsNecessary(env, err, "Failed to set property");
+    throwExceptionAsNecessary(env, drm, err, "Failed to set property");
 }
 
 static void android_media_MediaDrm_setCipherAlgorithmNative(
@@ -1778,7 +1782,7 @@
 
     status_t err = drm->setCipherAlgorithm(sessionId, algorithm);
 
-    throwExceptionAsNecessary(env, err, "Failed to set cipher algorithm");
+    throwExceptionAsNecessary(env, drm, err, "Failed to set cipher algorithm");
 }
 
 static void android_media_MediaDrm_setMacAlgorithmNative(
@@ -1802,7 +1806,7 @@
 
     status_t err = drm->setMacAlgorithm(sessionId, algorithm);
 
-    throwExceptionAsNecessary(env, err, "Failed to set mac algorithm");
+    throwExceptionAsNecessary(env, drm, err, "Failed to set mac algorithm");
 }
 
 
@@ -1830,7 +1834,7 @@
 
     status_t err = drm->encrypt(sessionId, keyId, input, iv, output);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to encrypt")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to encrypt")) {
         return NULL;
     }
 
@@ -1860,7 +1864,7 @@
     Vector<uint8_t> output;
 
     status_t err = drm->decrypt(sessionId, keyId, input, iv, output);
-    if (throwExceptionAsNecessary(env, err, "Failed to decrypt")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to decrypt")) {
         return NULL;
     }
 
@@ -1890,7 +1894,7 @@
 
     status_t err = drm->sign(sessionId, keyId, message, signature);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to sign")) {
         return NULL;
     }
 
@@ -1921,7 +1925,7 @@
 
     status_t err = drm->verify(sessionId, keyId, message, signature, match);
 
-    throwExceptionAsNecessary(env, err, "Failed to verify");
+    throwExceptionAsNecessary(env, drm, err, "Failed to verify");
     return match;
 }
 
@@ -1970,7 +1974,7 @@
 
     status_t err = drm->signRSA(sessionId, algorithm, message, wrappedKey, signature);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to sign")) {
         return NULL;
     }
 
@@ -2017,7 +2021,7 @@
         playbackId = JStringToString8(env, jplaybackId);
     }
     status_t err = drm->setPlaybackId(sessionId, playbackId.c_str());
-    throwExceptionAsNecessary(env, err, "Failed to set playbackId");
+    throwExceptionAsNecessary(env, drm, err, "Failed to set playbackId");
 }
 
 static jobject android_media_MediaDrm_getLogMessages(
@@ -2030,7 +2034,7 @@
     Vector<drm::V1_4::LogMessage> logs;
     status_t err = drm->getLogMessages(logs);
     ALOGI("drm->getLogMessages %zu logs", logs.size());
-    if (throwExceptionAsNecessary(env, err, "Failed to get log messages")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get log messages")) {
         return NULL;
     }
     return hidlLogMessagesToJavaList(env, logs);
@@ -2056,7 +2060,7 @@
     { "closeSessionNative", "([B)V",
       (void *)android_media_MediaDrm_closeSession },
 
-    { "getKeyRequest", "([B[BLjava/lang/String;ILjava/util/HashMap;)"
+    { "getKeyRequestNative", "([B[BLjava/lang/String;ILjava/util/HashMap;)"
       "Landroid/media/MediaDrm$KeyRequest;",
       (void *)android_media_MediaDrm_getKeyRequest },
 
diff --git a/media/jni/android_media_MediaDrm.h b/media/jni/android_media_MediaDrm.h
index b1f544c..dc0793a 100644
--- a/media/jni/android_media_MediaDrm.h
+++ b/media/jni/android_media_MediaDrm.h
@@ -28,6 +28,44 @@
 
 namespace {
 
+enum {
+    // TODO(b/180483929): use reverse jni e.g. android_media_MediaDrm_native_init
+    // KEEP IN SYNC with MediaDrm$ErrorCodes in MediaDrm.java!
+    JERROR_DRM_UNKNOWN = 0,
+    JERROR_DRM_NO_LICENSE = 1,
+    JERROR_DRM_LICENSE_EXPIRED = 2,
+    JERROR_DRM_RESOURCE_BUSY = 3,
+    JERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION = 4,
+    JERROR_DRM_SESSION_NOT_OPENED = 5,
+    JERROR_DRM_CANNOT_HANDLE = 6,
+    JERROR_DRM_INSUFFICIENT_SECURITY = 7,
+    JERROR_DRM_FRAME_TOO_LARGE = 8,
+    JERROR_DRM_SESSION_LOST_STATE = 9,
+    JERROR_DRM_CERTIFICATE_MALFORMED = 10,
+    JERROR_DRM_CERTIFICATE_MISSING = 11,
+    JERROR_DRM_CRYPTO_LIBRARY = 12,
+    JERROR_DRM_GENERIC_OEM = 13,
+    JERROR_DRM_GENERIC_PLUGIN = 14,
+    JERROR_DRM_INIT_DATA = 15,
+    JERROR_DRM_KEY_NOT_LOADED = 16,
+    JERROR_DRM_LICENSE_PARSE = 17,
+    JERROR_DRM_LICENSE_POLICY = 18,
+    JERROR_DRM_LICENSE_RELEASE = 19,
+    JERROR_DRM_LICENSE_REQUEST_REJECTED = 20,
+    JERROR_DRM_LICENSE_RESTORE = 21,
+    JERROR_DRM_LICENSE_STATE = 22,
+    JERROR_DRM_MEDIA_FRAMEWORK = 23,
+    JERROR_DRM_PROVISIONING_CERTIFICATE = 24,
+    JERROR_DRM_PROVISIONING_CONFIG = 25,
+    JERROR_DRM_PROVISIONING_PARSE = 26,
+    JERROR_DRM_PROVISIONING_RETRY = 27,
+    JERROR_DRM_RESOURCE_CONTENTION = 28,
+    JERROR_DRM_SECURE_STOP_RELEASE = 29,
+    JERROR_DRM_STORAGE_READ = 30,
+    JERROR_DRM_STORAGE_WRITE = 31,
+    JERROR_DRM_ZERO_SUBSAMPLES = 32,
+};
+
 struct ListenerArgs {
     jbyteArray jSessionId;
     jbyteArray jData;
@@ -98,6 +136,8 @@
     DISALLOW_EVIL_CONSTRUCTORS(JDrm);
 };
 
+jint MediaErrorToJavaError(status_t err);
+
 }  // namespace android
 
 #endif  // _ANDROID_MEDIA_DRM_H_
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index eee9f1e..7562d39 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -217,23 +217,34 @@
 void LnbClientCallbackImpl::onEvent(const LnbEventType lnbEventType) {
     ALOGD("LnbClientCallbackImpl::onEvent, type=%d", lnbEventType);
     JNIEnv *env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(
-            mLnbObj,
-            gFields.onLnbEventID,
-            (jint)lnbEventType);
+    jobject lnb(env->NewLocalRef(mLnbObj));
+    if (!env->IsSameObject(lnb, nullptr)) {
+        env->CallVoidMethod(
+                lnb,
+                gFields.onLnbEventID,
+                (jint)lnbEventType);
+    } else {
+        ALOGE("LnbClientCallbackImpl::onEvent:"
+                "Lnb object has been freed. Ignoring callback.");
+    }
 }
 
 void LnbClientCallbackImpl::onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) {
     ALOGD("LnbClientCallbackImpl::onDiseqcMessage");
     JNIEnv *env = AndroidRuntime::getJNIEnv();
-    jbyteArray array = env->NewByteArray(diseqcMessage.size());
-    env->SetByteArrayRegion(
-            array, 0, diseqcMessage.size(), reinterpret_cast<jbyte*>(diseqcMessage[0]));
-
-    env->CallVoidMethod(
-            mLnbObj,
-            gFields.onLnbDiseqcMessageID,
-            array);
+    jobject lnb(env->NewLocalRef(mLnbObj));
+    if (!env->IsSameObject(lnb, nullptr)) {
+        jbyteArray array = env->NewByteArray(diseqcMessage.size());
+        env->SetByteArrayRegion(
+                array, 0, diseqcMessage.size(), reinterpret_cast<jbyte*>(diseqcMessage[0]));
+        env->CallVoidMethod(
+                lnb,
+                gFields.onLnbDiseqcMessageID,
+                array);
+    } else {
+        ALOGE("LnbClientCallbackImpl::onDiseqcMessage:"
+                "Lnb object has been freed. Ignoring callback.");
+    }
 }
 
 void LnbClientCallbackImpl::setLnb(jweak lnbObj) {
@@ -254,19 +265,31 @@
 void DvrClientCallbackImpl::onRecordStatus(RecordStatus status) {
     ALOGD("DvrClientCallbackImpl::onRecordStatus");
     JNIEnv *env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(
-            mDvrObj,
-            gFields.onDvrRecordStatusID,
-            (jint) status);
+    jobject dvr(env->NewLocalRef(mDvrObj));
+    if (!env->IsSameObject(dvr, nullptr)) {
+        env->CallVoidMethod(
+                dvr,
+                gFields.onDvrRecordStatusID,
+                (jint) status);
+    } else {
+        ALOGE("DvrClientCallbackImpl::onRecordStatus:"
+                "Dvr object has been freed. Ignoring callback.");
+    }
 }
 
 void DvrClientCallbackImpl::onPlaybackStatus(PlaybackStatus status) {
     ALOGD("DvrClientCallbackImpl::onPlaybackStatus");
     JNIEnv *env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(
-            mDvrObj,
-            gFields.onDvrPlaybackStatusID,
-            (jint) status);
+    jobject dvr(env->NewLocalRef(mDvrObj));
+    if (!env->IsSameObject(dvr, nullptr)) {
+        env->CallVoidMethod(
+                dvr,
+                gFields.onDvrPlaybackStatusID,
+                (jint) status);
+    } else {
+        ALOGE("DvrClientCallbackImpl::onPlaybackStatus:"
+                "Dvr object has been freed. Ignoring callback.");
+    }
 }
 
 void DvrClientCallbackImpl::setDvr(jweak dvrObj) {
@@ -538,7 +561,7 @@
                 const std::vector<DemuxFilterEventExt::Event>& eventsExt) {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/TsRecordEvent");
-    jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IIIJJ)V");
+    jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IIIJJI)V");
 
     for (int i = 0; i < events.size(); i++) {
         auto event = events[i];
@@ -591,7 +614,7 @@
                 const std::vector<DemuxFilterEventExt::Event>& eventsExt) {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/MmtpRecordEvent");
-    jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IJIJ)V");
+    jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IJIJII)V");
 
     for (int i = 0; i < events.size(); i++) {
         auto event = events[i];
@@ -810,10 +833,16 @@
             }
         }
     }
-    env->CallVoidMethod(
-            mFilterObj,
-            gFields.onFilterEventID,
-            array);
+    jobject filter(env->NewLocalRef(mFilterObj));
+    if (!env->IsSameObject(filter, nullptr)) {
+        env->CallVoidMethod(
+                filter,
+                gFields.onFilterEventID,
+                array);
+    } else {
+        ALOGE("FilterClientCallbackImpl::onFilterEvent_1_1:"
+                "Filter object has been freed. Ignoring callback.");
+    }
 }
 
 void FilterClientCallbackImpl::onFilterEvent(const DemuxFilterEvent& filterEvent) {
@@ -828,10 +857,16 @@
 void FilterClientCallbackImpl::onFilterStatus(const DemuxFilterStatus status) {
     ALOGD("FilterClientCallbackImpl::onFilterStatus");
     JNIEnv *env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(
-            mFilterObj,
-            gFields.onFilterStatusID,
-            (jint)status);
+    jobject filter(env->NewLocalRef(mFilterObj));
+    if (!env->IsSameObject(filter, nullptr)) {
+        env->CallVoidMethod(
+                filter,
+                gFields.onFilterStatusID,
+                (jint)status);
+    } else {
+        ALOGE("FilterClientCallbackImpl::onFilterStatus:"
+                "Filter object has been freed. Ignoring callback.");
+    }
 }
 
 void FilterClientCallbackImpl::setFilter(jweak filterObj, sp<FilterClient> filterClient) {
@@ -841,6 +876,15 @@
     mFilterClient = filterClient;
 }
 
+FilterClientCallbackImpl::~FilterClientCallbackImpl() {
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    if (mFilterObj != NULL) {
+        env->DeleteWeakGlobalRef(mFilterObj);
+        mFilterObj = NULL;
+    }
+    mFilterClient = NULL;
+}
+
 /////////////// FrontendClientCallbackImpl ///////////////////////
 
 FrontendClientCallbackImpl::FrontendClientCallbackImpl(jweak tunerObj) : mObject(tunerObj) {}
@@ -848,10 +892,16 @@
 void FrontendClientCallbackImpl::onEvent(FrontendEventType frontendEventType) {
     ALOGD("FrontendClientCallbackImpl::onEvent, type=%d", frontendEventType);
     JNIEnv *env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(
-            mObject,
-            gFields.onFrontendEventID,
-            (jint)frontendEventType);
+    jobject frontend(env->NewLocalRef(mObject));
+    if (!env->IsSameObject(frontend, nullptr)) {
+        env->CallVoidMethod(
+                frontend,
+                gFields.onFrontendEventID,
+                (jint)frontendEventType);
+    } else {
+        ALOGE("FrontendClientCallbackImpl::onEvent:"
+                "Frontend object has been freed. Ignoring callback.");
+    }
 }
 
 void FrontendClientCallbackImpl::onScanMessage(
@@ -859,11 +909,17 @@
     ALOGD("FrontendClientCallbackImpl::onScanMessage, type=%d", type);
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
+    jobject frontend(env->NewLocalRef(mObject));
+    if (env->IsSameObject(frontend, nullptr)) {
+        ALOGE("FrontendClientCallbackImpl::onScanMessage:"
+                "Frontend object has been freed. Ignoring callback.");
+        return;
+    }
     switch(type) {
         case FrontendScanMessageType::LOCKED: {
             if (message.isLocked()) {
                 env->CallVoidMethod(
-                        mObject,
+                        frontend,
                         env->GetMethodID(clazz, "onLocked", "()V"));
             }
             break;
@@ -871,14 +927,14 @@
         case FrontendScanMessageType::END: {
             if (message.isEnd()) {
                 env->CallVoidMethod(
-                        mObject,
+                        frontend,
                         env->GetMethodID(clazz, "onScanStopped", "()V"));
             }
             break;
         }
         case FrontendScanMessageType::PROGRESS_PERCENT: {
             env->CallVoidMethod(
-                    mObject,
+                    frontend,
                     env->GetMethodID(clazz, "onProgress", "(I)V"),
                     (jint) message.progressPercent());
             break;
@@ -889,7 +945,7 @@
             env->SetIntArrayRegion(freqs, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
 
             env->CallVoidMethod(
-                    mObject,
+                    frontend,
                     env->GetMethodID(clazz, "onFrequenciesReport", "([I)V"),
                     freqs);
             break;
@@ -900,21 +956,21 @@
             env->SetIntArrayRegion(symbolRates, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
 
             env->CallVoidMethod(
-                    mObject,
+                    frontend,
                     env->GetMethodID(clazz, "onSymbolRates", "([I)V"),
                     symbolRates);
             break;
         }
         case FrontendScanMessageType::HIERARCHY: {
             env->CallVoidMethod(
-                    mObject,
+                    frontend,
                     env->GetMethodID(clazz, "onHierarchy", "(I)V"),
                     (jint) message.hierarchy());
             break;
         }
         case FrontendScanMessageType::ANALOG_TYPE: {
             env->CallVoidMethod(
-                    mObject,
+                    frontend,
                     env->GetMethodID(clazz, "onSignalType", "(I)V"),
                     (jint) message.analogType());
             break;
@@ -926,7 +982,7 @@
             env->SetIntArrayRegion(plpIds, 0, jintV.size(), &jintV[0]);
 
             env->CallVoidMethod(
-                    mObject,
+                    frontend,
                     env->GetMethodID(clazz, "onPlpIds", "([I)V"),
                     plpIds);
             break;
@@ -938,7 +994,7 @@
             env->SetIntArrayRegion(groupIds, 0, jintV.size(), &jintV[0]);
 
             env->CallVoidMethod(
-                    mObject,
+                    frontend,
                     env->GetMethodID(clazz, "onGroupIds", "([I)V"),
                     groupIds);
             break;
@@ -950,7 +1006,7 @@
             env->SetIntArrayRegion(streamIds, 0, jintV.size(), &jintV[0]);
 
             env->CallVoidMethod(
-                    mObject,
+                    frontend,
                     env->GetMethodID(clazz, "onInputStreamIds", "([I)V"),
                     streamIds);
             break;
@@ -961,21 +1017,21 @@
             if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::sStd) {
                 standard = (jint) std.sStd();
                 env->CallVoidMethod(
-                        mObject,
+                        frontend,
                         env->GetMethodID(clazz, "onDvbsStandard", "(I)V"),
                         standard);
             } else if (std.getDiscriminator() ==
                     FrontendScanMessage::Standard::hidl_discriminator::tStd) {
                 standard = (jint) std.tStd();
                 env->CallVoidMethod(
-                        mObject,
+                        frontend,
                         env->GetMethodID(clazz, "onDvbtStandard", "(I)V"),
                         standard);
             } else if (std.getDiscriminator() ==
                     FrontendScanMessage::Standard::hidl_discriminator::sifStd) {
                 standard = (jint) std.sifStd();
                 env->CallVoidMethod(
-                        mObject,
+                        frontend,
                         env->GetMethodID(clazz, "onAnalogSifStandard", "(I)V"),
                         standard);
             }
@@ -996,7 +1052,7 @@
                 env->SetObjectArrayElement(array, i, obj);
             }
             env->CallVoidMethod(
-                    mObject,
+                    frontend,
                     env->GetMethodID(clazz, "onAtsc3PlpInfos",
                             "([Landroid/media/tv/tuner/frontend/Atsc3PlpInfo;)V"),
                     array);
@@ -1010,6 +1066,12 @@
     ALOGD("FrontendClientCallbackImpl::onScanMessageExt1_1, type=%d", type);
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
+    jobject frontend(env->NewLocalRef(mObject));
+    if (env->IsSameObject(frontend, nullptr)) {
+        ALOGE("FrontendClientCallbackImpl::onScanMessageExt1_1:"
+                "Frontend object has been freed. Ignoring callback.");
+        return;
+    }
     switch(type) {
         case FrontendScanMessageTypeExt1_1::MODULATION: {
             jint modulation = -1;
@@ -1056,7 +1118,7 @@
             }
             if (modulation > 0) {
                 env->CallVoidMethod(
-                        mObject,
+                        frontend,
                         env->GetMethodID(clazz, "onModulationReported", "(I)V"),
                         modulation);
             }
@@ -1065,15 +1127,15 @@
         case FrontendScanMessageTypeExt1_1::HIGH_PRIORITY: {
             bool isHighPriority = message.isHighPriority();
             env->CallVoidMethod(
-                    mObject,
-                    env->GetMethodID(clazz, "onPriorityReported", "(B)V"),
+                    frontend,
+                    env->GetMethodID(clazz, "onPriorityReported", "(Z)V"),
                     isHighPriority);
             break;
         }
         case FrontendScanMessageTypeExt1_1::DVBC_ANNEX: {
             jint dvbcAnnex = (jint) message.annex();
             env->CallVoidMethod(
-                    mObject,
+                    frontend,
                     env->GetMethodID(clazz, "onDvbcAnnexReported", "(I)V"),
                     dvbcAnnex);
             break;
@@ -1083,6 +1145,14 @@
     }
 }
 
+FrontendClientCallbackImpl::~FrontendClientCallbackImpl() {
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    if (mObject != NULL) {
+        env->DeleteWeakGlobalRef(mObject);
+        mObject = NULL;
+    }
+}
+
 /////////////// Tuner ///////////////////////
 
 sp<TunerClient> JTuner::mTunerClient;
@@ -1158,15 +1228,22 @@
     if (mDemuxClient != NULL) {
         mDemuxClient->setFrontendDataSource(mFeClient);
     }
-    sp<FrontendClientCallbackImpl> feClientCb = new FrontendClientCallbackImpl(mObject);
-    mFeClient->setCallback(feClientCb);
 
     JNIEnv *env = AndroidRuntime::getJNIEnv();
+    jobject tuner(env->NewLocalRef(mObject));
+    if (env->IsSameObject(tuner, nullptr)) {
+        ALOGE("openFrontendByHandle"
+                "Tuner object has been freed. Failed to open frontend.");
+        return NULL;
+    }
+
+    sp<FrontendClientCallbackImpl> feClientCb = new FrontendClientCallbackImpl(mObject);
+    mFeClient->setCallback(feClientCb);
     // TODO: add more fields to frontend
     return env->NewObject(
             env->FindClass("android/media/tv/tuner/Tuner$Frontend"),
             gFields.frontendInitID,
-            mObject,
+            tuner,
             (jint) mFeId);
 }
 
@@ -1714,16 +1791,14 @@
         dvrObj =
                 env->NewObject(
                         env->FindClass("android/media/tv/tuner/dvr/DvrRecorder"),
-                        gFields.dvrRecorderInitID,
-                        mObject);
+                        gFields.dvrRecorderInitID);
         dvrClient->incStrong(dvrObj);
         env->SetLongField(dvrObj, gFields.dvrRecorderContext, (jlong)dvrClient.get());
     } else {
         dvrObj =
                 env->NewObject(
                         env->FindClass("android/media/tv/tuner/dvr/DvrPlayback"),
-                        gFields.dvrPlaybackInitID,
-                        mObject);
+                        gFields.dvrPlaybackInitID);
         dvrClient->incStrong(dvrObj);
         env->SetLongField(dvrObj, gFields.dvrPlaybackContext, (jlong)dvrClient.get());
     }
@@ -2126,6 +2201,10 @@
                         intBandwidth = static_cast<jint>(bandwidth.dvbt());
                         break;
                     }
+                    case FrontendBandwidth::hidl_discriminator::dvbc: {
+                        intBandwidth = static_cast<jint>(bandwidth.dvbc());
+                        break;
+                    }
                     case FrontendBandwidth::hidl_discriminator::isdbt: {
                         intBandwidth = static_cast<jint>(bandwidth.isdbt());
                         break;
@@ -2646,12 +2725,10 @@
     FrontendDvbsVcmMode vcmMode =
             static_cast<FrontendDvbsVcmMode>(
                     env->GetIntField(settings, env->GetFieldID(clazz, "mVcmMode", "I")));
-    FrontendDvbsCodeRate coderate = getDvbsCodeRate(env, settings);
 
     FrontendDvbsSettings frontendDvbsSettings {
             .frequency = freq,
             .modulation = modulation,
-            .coderate = coderate,
             .symbolRate = symbolRate,
             .rolloff = rolloff,
             .pilot = pilot,
@@ -2659,6 +2736,13 @@
             .standard = standard,
             .vcmMode = vcmMode,
     };
+
+    jobject jcodeRate = env->GetObjectField(settings, env->GetFieldID(clazz, "mCodeRate",
+            "Landroid/media/tv/tuner/frontend/DvbsCodeRate;"));
+    if (jcodeRate != NULL) {
+        frontendDvbsSettings.coderate = getDvbsCodeRate(env, settings);
+    }
+
     frontendSettings.dvbs(frontendDvbsSettings);
     return frontendSettings;
 }
@@ -2670,7 +2754,7 @@
             static_cast<FrontendDvbsScanType>(
                     env->GetIntField(settings, env->GetFieldID(clazz, "mScanType", "I")));
     bool isDiseqcRxMessage = static_cast<bool>(env->GetBooleanField(
-            settings, env->GetFieldID(clazz, "mIsDiseqcRxMessage", "B")));
+            settings, env->GetFieldID(clazz, "mIsDiseqcRxMessage", "Z")));
 
     FrontendDvbsSettingsExt1_1 dvbsExt1_1 {
         .scanType = scanType,
@@ -2910,6 +2994,10 @@
 static FrontendSettings getFrontendSettings(JNIEnv *env, int type, jobject settings) {
     ALOGD("getFrontendSettings %d", type);
 
+    if (type == static_cast<int>(::android::hardware::tv::tuner::V1_1::FrontendType::DTMB)) {
+        return FrontendSettings();
+    }
+
     FrontendType feType = static_cast<FrontendType>(type);
     switch(feType) {
         case FrontendType::ANALOG:
@@ -3483,26 +3571,28 @@
                 .tpid = tpid,
             };
 
-            DemuxTsFilterType tsType = static_cast<DemuxTsFilterType>(subtype);
-            switch (tsType) {
-                case DemuxTsFilterType::SECTION:
-                    tsFilterSettings.filterSettings.section(
-                            getFilterSectionSettings(env, settingsObj));
-                    break;
-                case DemuxTsFilterType::AUDIO:
-                case DemuxTsFilterType::VIDEO:
-                    tsFilterSettings.filterSettings.av(getFilterAvSettings(env, settingsObj));
-                    break;
-                case DemuxTsFilterType::PES:
-                    tsFilterSettings.filterSettings.pesData(
-                            getFilterPesDataSettings(env, settingsObj));
-                    break;
-                case DemuxTsFilterType::RECORD:
-                    tsFilterSettings.filterSettings.record(
-                            getFilterRecordSettings(env, settingsObj));
-                    break;
-                default:
-                    break;
+            if (settingsObj != NULL) {
+                DemuxTsFilterType tsType = static_cast<DemuxTsFilterType>(subtype);
+                switch (tsType) {
+                    case DemuxTsFilterType::SECTION:
+                        tsFilterSettings.filterSettings.section(
+                                getFilterSectionSettings(env, settingsObj));
+                        break;
+                    case DemuxTsFilterType::AUDIO:
+                    case DemuxTsFilterType::VIDEO:
+                        tsFilterSettings.filterSettings.av(getFilterAvSettings(env, settingsObj));
+                        break;
+                    case DemuxTsFilterType::PES:
+                        tsFilterSettings.filterSettings.pesData(
+                                getFilterPesDataSettings(env, settingsObj));
+                        break;
+                    case DemuxTsFilterType::RECORD:
+                        tsFilterSettings.filterSettings.record(
+                                getFilterRecordSettings(env, settingsObj));
+                        break;
+                    default:
+                        break;
+                }
             }
             filterSettings.ts(tsFilterSettings);
             break;
@@ -3514,60 +3604,55 @@
             DemuxMmtpFilterSettings mmtpFilterSettings {
                 .mmtpPid = mmtpPid,
             };
-            DemuxMmtpFilterType mmtpType = static_cast<DemuxMmtpFilterType>(subtype);
-            switch (mmtpType) {
-                case DemuxMmtpFilterType::SECTION:
-                    mmtpFilterSettings.filterSettings.section(
-                            getFilterSectionSettings(env, settingsObj));
-                    break;
-                case DemuxMmtpFilterType::AUDIO:
-                case DemuxMmtpFilterType::VIDEO:
-                    mmtpFilterSettings.filterSettings.av(getFilterAvSettings(env, settingsObj));
-                    break;
-                case DemuxMmtpFilterType::PES:
-                    mmtpFilterSettings.filterSettings.pesData(
-                            getFilterPesDataSettings(env, settingsObj));
-                    break;
-                case DemuxMmtpFilterType::RECORD:
-                    mmtpFilterSettings.filterSettings.record(
-                            getFilterRecordSettings(env, settingsObj));
-                    break;
-                case DemuxMmtpFilterType::DOWNLOAD:
-                    mmtpFilterSettings.filterSettings.download(
-                            getFilterDownloadSettings(env, settingsObj));
-                    break;
-                default:
-                    break;
+
+            if (settingsObj != NULL) {
+                DemuxMmtpFilterType mmtpType = static_cast<DemuxMmtpFilterType>(subtype);
+                switch (mmtpType) {
+                    case DemuxMmtpFilterType::SECTION:
+                        mmtpFilterSettings.filterSettings.section(
+                                getFilterSectionSettings(env, settingsObj));
+                        break;
+                    case DemuxMmtpFilterType::AUDIO:
+                    case DemuxMmtpFilterType::VIDEO:
+                        mmtpFilterSettings.filterSettings.av(getFilterAvSettings(env, settingsObj));
+                        break;
+                    case DemuxMmtpFilterType::PES:
+                        mmtpFilterSettings.filterSettings.pesData(
+                                getFilterPesDataSettings(env, settingsObj));
+                        break;
+                    case DemuxMmtpFilterType::RECORD:
+                        mmtpFilterSettings.filterSettings.record(
+                                getFilterRecordSettings(env, settingsObj));
+                        break;
+                    case DemuxMmtpFilterType::DOWNLOAD:
+                        mmtpFilterSettings.filterSettings.download(
+                                getFilterDownloadSettings(env, settingsObj));
+                        break;
+                    default:
+                        break;
+                }
             }
             filterSettings.mmtp(mmtpFilterSettings);
             break;
         }
         case DemuxFilterMainType::IP: {
             DemuxIpAddress ipAddr = getDemuxIpAddress(env, filterConfigObj);
-
             DemuxIpFilterSettings ipFilterSettings {
                 .ipAddr = ipAddr,
             };
+
             DemuxIpFilterType ipType = static_cast<DemuxIpFilterType>(subtype);
-            switch (ipType) {
-                case DemuxIpFilterType::SECTION: {
-                    ipFilterSettings.filterSettings.section(
-                            getFilterSectionSettings(env, settingsObj));
-                    break;
-                }
-                case DemuxIpFilterType::IP: {
-                    jclass clazz = env->FindClass(
-                            "android/media/tv/tuner/filter/IpFilterConfiguration");
-                    bool bPassthrough = static_cast<bool>(
-                            env->GetBooleanField(
-                                    filterConfigObj, env->GetFieldID(
-                                            clazz, "mPassthrough", "Z")));
-                    ipFilterSettings.filterSettings.bPassthrough(bPassthrough);
-                    break;
-                }
-                default: {
-                    break;
-                }
+            if (ipType == DemuxIpFilterType::SECTION && settingsObj != NULL) {
+                ipFilterSettings.filterSettings.section(
+                                getFilterSectionSettings(env, settingsObj));
+            } else if (ipType == DemuxIpFilterType::IP) {
+                jclass clazz = env->FindClass(
+                        "android/media/tv/tuner/filter/IpFilterConfiguration");
+                bool bPassthrough = static_cast<bool>(
+                        env->GetBooleanField(
+                                filterConfigObj, env->GetFieldID(
+                                        clazz, "mPassthrough", "Z")));
+                ipFilterSettings.filterSettings.bPassthrough(bPassthrough);
             }
             filterSettings.ip(ipFilterSettings);
             break;
@@ -3584,24 +3669,17 @@
                 .packetType = packetType,
                 .isCompressedIpPacket = isCompressedIpPacket,
             };
+
             DemuxTlvFilterType tlvType = static_cast<DemuxTlvFilterType>(subtype);
-            switch (tlvType) {
-                case DemuxTlvFilterType::SECTION: {
-                    tlvFilterSettings.filterSettings.section(
-                            getFilterSectionSettings(env, settingsObj));
-                    break;
-                }
-                case DemuxTlvFilterType::TLV: {
-                    bool bPassthrough = static_cast<bool>(
-                            env->GetBooleanField(
-                                    filterConfigObj, env->GetFieldID(
-                                            clazz, "mPassthrough", "Z")));
-                    tlvFilterSettings.filterSettings.bPassthrough(bPassthrough);
-                    break;
-                }
-                default: {
-                    break;
-                }
+            if (tlvType == DemuxTlvFilterType::SECTION && settingsObj != NULL) {
+                tlvFilterSettings.filterSettings.section(
+                        getFilterSectionSettings(env, settingsObj));
+            } else if (tlvType == DemuxTlvFilterType::TLV) {
+                bool bPassthrough = static_cast<bool>(
+                env->GetBooleanField(
+                        filterConfigObj, env->GetFieldID(
+                                clazz, "mPassthrough", "Z")));
+                tlvFilterSettings.filterSettings.bPassthrough(bPassthrough);
             }
             filterSettings.tlv(tlvFilterSettings);
             break;
@@ -3616,14 +3694,17 @@
                 .packetType = packetType,
                 .lengthType = lengthType,
             };
-            DemuxAlpFilterType alpType = static_cast<DemuxAlpFilterType>(subtype);
-            switch (alpType) {
-                case DemuxAlpFilterType::SECTION:
-                    alpFilterSettings.filterSettings.section(
-                            getFilterSectionSettings(env, settingsObj));
-                    break;
-                default:
-                    break;
+
+            if (settingsObj != NULL) {
+                DemuxAlpFilterType alpType = static_cast<DemuxAlpFilterType>(subtype);
+                switch (alpType) {
+                    case DemuxAlpFilterType::SECTION:
+                        alpFilterSettings.filterSettings.section(
+                                getFilterSectionSettings(env, settingsObj));
+                        break;
+                    default:
+                        break;
+                }
             }
             filterSettings.alp(alpFilterSettings);
             break;
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index 0e30b18e..fafef42 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -118,6 +118,7 @@
 };
 
 struct FilterClientCallbackImpl : public FilterClientCallback {
+    ~FilterClientCallbackImpl();
     virtual void onFilterEvent_1_1(const DemuxFilterEvent& filterEvent,
             const DemuxFilterEventExt& filterEventExt);
     virtual void onFilterEvent(const DemuxFilterEvent& filterEvent);
@@ -155,7 +156,7 @@
 
 struct FrontendClientCallbackImpl : public FrontendClientCallback {
     FrontendClientCallbackImpl(jweak tunerObj);
-
+    ~FrontendClientCallbackImpl();
     virtual void onEvent(FrontendEventType frontendEventType);
     virtual void onScanMessage(
             FrontendScanMessageType type, const FrontendScanMessage& message);
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 4efdcac..ffed474 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -32,6 +32,7 @@
 
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/Log.h>
+#include "core_jni_helpers.h"
 #include <jni.h>
 #include <media/stagefright/NuMediaExtractor.h>
 #include <nativehelper/JNIHelp.h>
@@ -48,6 +49,7 @@
 
 // ----------------------------------------------------------------------------
 
+// MtpDatabase methods
 static jmethodID method_beginSendObject;
 static jmethodID method_endSendObject;
 static jmethodID method_rescanFile;
@@ -75,6 +77,7 @@
 static jmethodID method_getObjectReferences;
 static jmethodID method_setObjectReferences;
 
+// MtpDatabase fields.
 static jfieldID field_context;
 
 // MtpPropertyList methods
@@ -86,6 +89,59 @@
 static jmethodID method_getLongValues;
 static jmethodID method_getStringValues;
 
+// Initializer for the jfieldIDs and jmethodIDs above. This method must be invoked
+// before using these static fields and methods for JNI accesses.
+static void initializeJavaIDs(JNIEnv* env) {
+    static std::once_flag sJniInitialized;
+
+#define GET_METHOD_ID(name, jclass, signature)                              \
+    method_##name = GetMethodIDOrDie(env, jclass, #name, signature);
+
+    std::call_once(sJniInitialized, [](JNIEnv* env) {
+        const jclass mdb_class = FindClassOrDie(env, "android/mtp/MtpDatabase");
+        GET_METHOD_ID(beginSendObject, mdb_class, "(Ljava/lang/String;III)I");
+        GET_METHOD_ID(endSendObject, mdb_class, "(IZ)V");
+        GET_METHOD_ID(rescanFile, mdb_class, "(Ljava/lang/String;II)V");
+        GET_METHOD_ID(getObjectList, mdb_class, "(III)[I");
+        GET_METHOD_ID(getNumObjects, mdb_class, "(III)I");
+        GET_METHOD_ID(getSupportedPlaybackFormats, mdb_class, "()[I");
+        GET_METHOD_ID(getSupportedCaptureFormats, mdb_class, "()[I");
+        GET_METHOD_ID(getSupportedObjectProperties, mdb_class, "(I)[I");
+        GET_METHOD_ID(getSupportedDeviceProperties, mdb_class, "()[I");
+        GET_METHOD_ID(setObjectProperty, mdb_class, "(IIJLjava/lang/String;)I");
+        GET_METHOD_ID(getDeviceProperty, mdb_class, "(I[J[C)I");
+        GET_METHOD_ID(setDeviceProperty, mdb_class, "(IJLjava/lang/String;)I");
+        GET_METHOD_ID(getObjectPropertyList, mdb_class, "(IIIII)Landroid/mtp/MtpPropertyList;");
+        GET_METHOD_ID(getObjectInfo, mdb_class, "(I[I[C[J)Z");
+        GET_METHOD_ID(getObjectFilePath, mdb_class, "(I[C[J)I");
+        GET_METHOD_ID(openFilePath, mdb_class, "(Ljava/lang/String;Z)I");
+        GET_METHOD_ID(getThumbnailInfo, mdb_class, "(I[J)Z");
+        GET_METHOD_ID(getThumbnailData, mdb_class, "(I)[B");
+        GET_METHOD_ID(beginDeleteObject, mdb_class, "(I)I");
+        GET_METHOD_ID(endDeleteObject, mdb_class, "(IZ)V");
+        GET_METHOD_ID(beginMoveObject, mdb_class, "(III)I");
+        GET_METHOD_ID(endMoveObject, mdb_class, "(IIIIIZ)V");
+        GET_METHOD_ID(beginCopyObject, mdb_class, "(III)I");
+        GET_METHOD_ID(endCopyObject, mdb_class, "(IZ)V");
+        GET_METHOD_ID(getObjectReferences, mdb_class, "(I)[I");
+        GET_METHOD_ID(setObjectReferences, mdb_class, "(I[I)I");
+        field_context = GetFieldIDOrDie(env, mdb_class, "mNativeContext", "J");
+
+        const jclass mpl_class = FindClassOrDie(env, "android/mtp/MtpPropertyList");
+        GET_METHOD_ID(getCode, mpl_class, "()I");
+        GET_METHOD_ID(getCount, mpl_class, "()I");
+        GET_METHOD_ID(getObjectHandles, mpl_class, "()[I");
+        GET_METHOD_ID(getPropertyCodes, mpl_class, "()[I");
+        GET_METHOD_ID(getDataTypes, mpl_class, "()[I");
+        GET_METHOD_ID(getLongValues, mpl_class, "()[J");
+        GET_METHOD_ID(getStringValues, mpl_class, "()[Ljava/lang/String;");
+
+        return 0;
+    }, env);
+
+#undef GET_METHOD_ID
+}
+
 
 IMtpDatabase* getMtpDatabase(JNIEnv *env, jobject database) {
     return (IMtpDatabase *)env->GetLongField(database, field_context);
@@ -1280,6 +1336,7 @@
 static void
 android_mtp_MtpDatabase_setup(JNIEnv *env, jobject thiz)
 {
+    initializeJavaIDs(env);
     MtpDatabase* database = new MtpDatabase(env, thiz);
     env->SetLongField(thiz, field_context, (jlong)database);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
@@ -1314,69 +1371,9 @@
     {"format_date_time",        "(J)Ljava/lang/String;",
                                         (void *)android_mtp_MtpPropertyGroup_format_date_time},
 };
-
-#define GET_METHOD_ID(name, jclass, signature)                              \
-    method_##name = env->GetMethodID(jclass, #name, signature);             \
-    if (method_##name == NULL) {                                            \
-        ALOGE("Can't find " #name);                                         \
-        return -1;                                                          \
-    }                                                                       \
-
+                                                                   \
 int register_android_mtp_MtpDatabase(JNIEnv *env)
 {
-    jclass clazz;
-
-    clazz = env->FindClass("android/mtp/MtpDatabase");
-    if (clazz == NULL) {
-        ALOGE("Can't find android/mtp/MtpDatabase");
-        return -1;
-    }
-    GET_METHOD_ID(beginSendObject, clazz, "(Ljava/lang/String;III)I");
-    GET_METHOD_ID(endSendObject, clazz, "(IZ)V");
-    GET_METHOD_ID(rescanFile, clazz, "(Ljava/lang/String;II)V");
-    GET_METHOD_ID(getObjectList, clazz, "(III)[I");
-    GET_METHOD_ID(getNumObjects, clazz, "(III)I");
-    GET_METHOD_ID(getSupportedPlaybackFormats, clazz, "()[I");
-    GET_METHOD_ID(getSupportedCaptureFormats, clazz, "()[I");
-    GET_METHOD_ID(getSupportedObjectProperties, clazz, "(I)[I");
-    GET_METHOD_ID(getSupportedDeviceProperties, clazz, "()[I");
-    GET_METHOD_ID(setObjectProperty, clazz, "(IIJLjava/lang/String;)I");
-    GET_METHOD_ID(getDeviceProperty, clazz, "(I[J[C)I");
-    GET_METHOD_ID(setDeviceProperty, clazz, "(IJLjava/lang/String;)I");
-    GET_METHOD_ID(getObjectPropertyList, clazz, "(IIIII)Landroid/mtp/MtpPropertyList;");
-    GET_METHOD_ID(getObjectInfo, clazz, "(I[I[C[J)Z");
-    GET_METHOD_ID(getObjectFilePath, clazz, "(I[C[J)I");
-    GET_METHOD_ID(openFilePath, clazz, "(Ljava/lang/String;Z)I");
-    GET_METHOD_ID(getThumbnailInfo, clazz, "(I[J)Z");
-    GET_METHOD_ID(getThumbnailData, clazz, "(I)[B");
-    GET_METHOD_ID(beginDeleteObject, clazz, "(I)I");
-    GET_METHOD_ID(endDeleteObject, clazz, "(IZ)V");
-    GET_METHOD_ID(beginMoveObject, clazz, "(III)I");
-    GET_METHOD_ID(endMoveObject, clazz, "(IIIIIZ)V");
-    GET_METHOD_ID(beginCopyObject, clazz, "(III)I");
-    GET_METHOD_ID(endCopyObject, clazz, "(IZ)V");
-    GET_METHOD_ID(getObjectReferences, clazz, "(I)[I");
-    GET_METHOD_ID(setObjectReferences, clazz, "(I[I)I");
-
-    field_context = env->GetFieldID(clazz, "mNativeContext", "J");
-    if (field_context == NULL) {
-        ALOGE("Can't find MtpDatabase.mNativeContext");
-        return -1;
-    }
-
-    clazz = env->FindClass("android/mtp/MtpPropertyList");
-    if (clazz == NULL) {
-        ALOGE("Can't find android/mtp/MtpPropertyList");
-        return -1;
-    }
-    GET_METHOD_ID(getCode, clazz, "()I");
-    GET_METHOD_ID(getCount, clazz, "()I");
-    GET_METHOD_ID(getObjectHandles, clazz, "()[I");
-    GET_METHOD_ID(getPropertyCodes, clazz, "()[I");
-    GET_METHOD_ID(getDataTypes, clazz, "()[I");
-    GET_METHOD_ID(getLongValues, clazz, "()[J");
-    GET_METHOD_ID(getStringValues, clazz, "()[Ljava/lang/String;");
-
     if (AndroidRuntime::registerNativeMethods(env,
                 "android/mtp/MtpDatabase", gMtpDatabaseMethods, NELEM(gMtpDatabaseMethods)))
         return -1;
diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp
index 060eaf9..3d2b00fe 100644
--- a/media/jni/android_mtp_MtpDevice.cpp
+++ b/media/jni/android_mtp_MtpDevice.cpp
@@ -34,6 +34,7 @@
 
 #include "android_runtime/AndroidRuntime.h"
 #include "android_runtime/Log.h"
+#include "core_jni_helpers.h"
 #include "nativehelper/ScopedLocalRef.h"
 #include "private/android_filesystem_config.h"
 
@@ -107,6 +108,95 @@
 static jfieldID field_event_parameter2;
 static jfieldID field_event_parameter3;
 
+// Initializer for  the jclasses, jfieldIDs and jmethodIDs declared above. This method must be
+// invoked before using these static fields for JNI accesses.
+static void initializeJavaIDs(JNIEnv* env) {
+    static std::once_flag sJniInitialized;
+
+    std::call_once(sJniInitialized, [](JNIEnv* env) {
+        clazz_deviceInfo =
+            (jclass)env->NewGlobalRef(FindClassOrDie(env, "android/mtp/MtpDeviceInfo"));
+        constructor_deviceInfo = GetMethodIDOrDie(env, clazz_deviceInfo, "<init>", "()V");
+        field_deviceInfo_manufacturer =
+            GetFieldIDOrDie(env, clazz_deviceInfo, "mManufacturer", "Ljava/lang/String;");
+        field_deviceInfo_model =
+            GetFieldIDOrDie(env, clazz_deviceInfo, "mModel", "Ljava/lang/String;");
+        field_deviceInfo_version =
+            GetFieldIDOrDie(env, clazz_deviceInfo, "mVersion", "Ljava/lang/String;");
+        field_deviceInfo_serialNumber =
+            GetFieldIDOrDie(env, clazz_deviceInfo, "mSerialNumber", "Ljava/lang/String;");
+        field_deviceInfo_operationsSupported =
+            GetFieldIDOrDie(env, clazz_deviceInfo, "mOperationsSupported", "[I");
+        field_deviceInfo_eventsSupported =
+            GetFieldIDOrDie(env, clazz_deviceInfo, "mEventsSupported", "[I");
+
+        clazz_storageInfo =
+            (jclass)env->NewGlobalRef(FindClassOrDie(env, "android/mtp/MtpStorageInfo"));
+        constructor_storageInfo = GetMethodIDOrDie(env, clazz_storageInfo, "<init>", "()V");
+        field_storageInfo_storageId = GetFieldIDOrDie(env, clazz_storageInfo, "mStorageId", "I");
+        field_storageInfo_maxCapacity =
+            GetFieldIDOrDie(env, clazz_storageInfo, "mMaxCapacity", "J");
+        field_storageInfo_freeSpace =
+            GetFieldIDOrDie(env, clazz_storageInfo, "mFreeSpace", "J");
+        field_storageInfo_description =
+            GetFieldIDOrDie(env, clazz_storageInfo, "mDescription", "Ljava/lang/String;");
+        field_storageInfo_volumeIdentifier =
+            GetFieldIDOrDie(env, clazz_storageInfo, "mVolumeIdentifier", "Ljava/lang/String;");
+
+        clazz_objectInfo =
+            (jclass)env->NewGlobalRef(FindClassOrDie(env, "android/mtp/MtpObjectInfo"));
+        constructor_objectInfo = GetMethodIDOrDie(env, clazz_objectInfo, "<init>", "()V");
+        field_objectInfo_handle = GetFieldIDOrDie(env, clazz_objectInfo, "mHandle", "I");
+        field_objectInfo_storageId = GetFieldIDOrDie(env, clazz_objectInfo, "mStorageId", "I");
+        field_objectInfo_format = GetFieldIDOrDie(env, clazz_objectInfo, "mFormat", "I");
+        field_objectInfo_protectionStatus =
+            GetFieldIDOrDie(env, clazz_objectInfo, "mProtectionStatus", "I");
+        field_objectInfo_compressedSize =
+            GetFieldIDOrDie(env, clazz_objectInfo, "mCompressedSize", "I");
+        field_objectInfo_thumbFormat = GetFieldIDOrDie(env, clazz_objectInfo, "mThumbFormat", "I");
+        field_objectInfo_thumbCompressedSize =
+            GetFieldIDOrDie(env, clazz_objectInfo, "mThumbCompressedSize", "I");
+        field_objectInfo_thumbPixWidth =
+            GetFieldIDOrDie(env, clazz_objectInfo, "mThumbPixWidth", "I");
+        field_objectInfo_thumbPixHeight =
+            GetFieldIDOrDie(env, clazz_objectInfo, "mThumbPixHeight", "I");
+        field_objectInfo_imagePixWidth =
+            GetFieldIDOrDie(env, clazz_objectInfo, "mImagePixWidth", "I");
+        field_objectInfo_imagePixHeight =
+            GetFieldIDOrDie(env, clazz_objectInfo, "mImagePixHeight", "I");
+        field_objectInfo_imagePixDepth =
+                GetFieldIDOrDie(env, clazz_objectInfo, "mImagePixDepth", "I");
+        field_objectInfo_parent = GetFieldIDOrDie(env, clazz_objectInfo, "mParent", "I");
+        field_objectInfo_associationType =
+                GetFieldIDOrDie(env, clazz_objectInfo, "mAssociationType", "I");
+        field_objectInfo_associationDesc =
+                GetFieldIDOrDie(env, clazz_objectInfo, "mAssociationDesc", "I");
+        field_objectInfo_sequenceNumber =
+                GetFieldIDOrDie(env, clazz_objectInfo, "mSequenceNumber", "I");
+        field_objectInfo_name =
+                GetFieldIDOrDie(env, clazz_objectInfo, "mName", "Ljava/lang/String;");
+        field_objectInfo_dateCreated = GetFieldIDOrDie(env, clazz_objectInfo, "mDateCreated", "J");
+        field_objectInfo_dateModified =
+                GetFieldIDOrDie(env, clazz_objectInfo, "mDateModified", "J");
+        field_objectInfo_keywords =
+                GetFieldIDOrDie(env, clazz_objectInfo, "mKeywords", "Ljava/lang/String;");
+
+        clazz_event = (jclass)env->NewGlobalRef(FindClassOrDie(env, "android/mtp/MtpEvent"));
+        constructor_event = GetMethodIDOrDie(env, clazz_event, "<init>", "()V");
+        field_event_eventCode = GetFieldIDOrDie(env, clazz_event, "mEventCode", "I");
+        field_event_parameter1 = GetFieldIDOrDie(env, clazz_event, "mParameter1", "I");
+        field_event_parameter2 = GetFieldIDOrDie(env, clazz_event, "mParameter2", "I");
+        field_event_parameter3 = GetFieldIDOrDie(env, clazz_event, "mParameter3", "I");
+
+        const jclass clazz = FindClassOrDie(env, "android/mtp/MtpDevice");
+        field_context = GetFieldIDOrDie(env, clazz, "mNativeContext", "J");
+
+        clazz_io_exception = (jclass)env->NewGlobalRef(FindClassOrDie(env, "java/io/IOException"));
+        clazz_operation_canceled_exception =
+            (jclass)env->NewGlobalRef(FindClassOrDie(env, "android/os/OperationCanceledException"));
+    }, env);
+}
+
 class JavaArrayWriter {
 public:
     JavaArrayWriter(JNIEnv* env, jbyteArray array) :
@@ -132,6 +222,11 @@
 
 MtpDevice* get_device_from_object(JNIEnv* env, jobject javaDevice)
 {
+    // get_device_from_object() is called by the majority of JNI methods in this file. Call
+    // `initializeJavaIDs()` here to ensure JNI methodID's, fieldIDs and classes are initialized
+    // before use.
+    initializeJavaIDs(env);
+
     return (MtpDevice*)env->GetLongField(javaDevice, field_context);
 }
 
@@ -200,6 +295,8 @@
     MtpDevice* device = MtpDevice::open(deviceNameStr, fd);
     env->ReleaseStringUTFChars(deviceName, deviceNameStr);
 
+    // The jfieldID `field_context` needs to be initialized before use below.
+    initializeJavaIDs(env);
     if (device)
         env->SetLongField(thiz, field_context,  (jlong)device);
     return (jboolean)(device != NULL);
@@ -781,256 +878,7 @@
 
 int register_android_mtp_MtpDevice(JNIEnv *env)
 {
-    jclass clazz;
-
     ALOGD("register_android_mtp_MtpDevice\n");
-
-    clazz = env->FindClass("android/mtp/MtpDeviceInfo");
-    if (clazz == NULL) {
-        ALOGE("Can't find android/mtp/MtpDeviceInfo");
-        return -1;
-    }
-    constructor_deviceInfo = env->GetMethodID(clazz, "<init>", "()V");
-    if (constructor_deviceInfo == NULL) {
-        ALOGE("Can't find android/mtp/MtpDeviceInfo constructor");
-        return -1;
-    }
-    field_deviceInfo_manufacturer = env->GetFieldID(clazz, "mManufacturer", "Ljava/lang/String;");
-    if (field_deviceInfo_manufacturer == NULL) {
-        ALOGE("Can't find MtpDeviceInfo.mManufacturer");
-        return -1;
-    }
-    field_deviceInfo_model = env->GetFieldID(clazz, "mModel", "Ljava/lang/String;");
-    if (field_deviceInfo_model == NULL) {
-        ALOGE("Can't find MtpDeviceInfo.mModel");
-        return -1;
-    }
-    field_deviceInfo_version = env->GetFieldID(clazz, "mVersion", "Ljava/lang/String;");
-    if (field_deviceInfo_version == NULL) {
-        ALOGE("Can't find MtpDeviceInfo.mVersion");
-        return -1;
-    }
-    field_deviceInfo_serialNumber = env->GetFieldID(clazz, "mSerialNumber", "Ljava/lang/String;");
-    if (field_deviceInfo_serialNumber == NULL) {
-        ALOGE("Can't find MtpDeviceInfo.mSerialNumber");
-        return -1;
-    }
-    field_deviceInfo_operationsSupported = env->GetFieldID(clazz, "mOperationsSupported", "[I");
-    if (field_deviceInfo_operationsSupported == NULL) {
-        ALOGE("Can't find MtpDeviceInfo.mOperationsSupported");
-        return -1;
-    }
-    field_deviceInfo_eventsSupported = env->GetFieldID(clazz, "mEventsSupported", "[I");
-    if (field_deviceInfo_eventsSupported == NULL) {
-        ALOGE("Can't find MtpDeviceInfo.mEventsSupported");
-        return -1;
-    }
-    clazz_deviceInfo = (jclass)env->NewGlobalRef(clazz);
-
-    clazz = env->FindClass("android/mtp/MtpStorageInfo");
-    if (clazz == NULL) {
-        ALOGE("Can't find android/mtp/MtpStorageInfo");
-        return -1;
-    }
-    constructor_storageInfo = env->GetMethodID(clazz, "<init>", "()V");
-    if (constructor_storageInfo == NULL) {
-        ALOGE("Can't find android/mtp/MtpStorageInfo constructor");
-        return -1;
-    }
-    field_storageInfo_storageId = env->GetFieldID(clazz, "mStorageId", "I");
-    if (field_storageInfo_storageId == NULL) {
-        ALOGE("Can't find MtpStorageInfo.mStorageId");
-        return -1;
-    }
-    field_storageInfo_maxCapacity = env->GetFieldID(clazz, "mMaxCapacity", "J");
-    if (field_storageInfo_maxCapacity == NULL) {
-        ALOGE("Can't find MtpStorageInfo.mMaxCapacity");
-        return -1;
-    }
-    field_storageInfo_freeSpace = env->GetFieldID(clazz, "mFreeSpace", "J");
-    if (field_storageInfo_freeSpace == NULL) {
-        ALOGE("Can't find MtpStorageInfo.mFreeSpace");
-        return -1;
-    }
-    field_storageInfo_description = env->GetFieldID(clazz, "mDescription", "Ljava/lang/String;");
-    if (field_storageInfo_description == NULL) {
-        ALOGE("Can't find MtpStorageInfo.mDescription");
-        return -1;
-    }
-    field_storageInfo_volumeIdentifier = env->GetFieldID(clazz, "mVolumeIdentifier", "Ljava/lang/String;");
-    if (field_storageInfo_volumeIdentifier == NULL) {
-        ALOGE("Can't find MtpStorageInfo.mVolumeIdentifier");
-        return -1;
-    }
-    clazz_storageInfo = (jclass)env->NewGlobalRef(clazz);
-
-    clazz = env->FindClass("android/mtp/MtpObjectInfo");
-    if (clazz == NULL) {
-        ALOGE("Can't find android/mtp/MtpObjectInfo");
-        return -1;
-    }
-    constructor_objectInfo = env->GetMethodID(clazz, "<init>", "()V");
-    if (constructor_objectInfo == NULL) {
-        ALOGE("Can't find android/mtp/MtpObjectInfo constructor");
-        return -1;
-    }
-    field_objectInfo_handle = env->GetFieldID(clazz, "mHandle", "I");
-    if (field_objectInfo_handle == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mHandle");
-        return -1;
-    }
-    field_objectInfo_storageId = env->GetFieldID(clazz, "mStorageId", "I");
-    if (field_objectInfo_storageId == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mStorageId");
-        return -1;
-    }
-    field_objectInfo_format = env->GetFieldID(clazz, "mFormat", "I");
-    if (field_objectInfo_format == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mFormat");
-        return -1;
-    }
-    field_objectInfo_protectionStatus = env->GetFieldID(clazz, "mProtectionStatus", "I");
-    if (field_objectInfo_protectionStatus == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mProtectionStatus");
-        return -1;
-    }
-    field_objectInfo_compressedSize = env->GetFieldID(clazz, "mCompressedSize", "I");
-    if (field_objectInfo_compressedSize == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mCompressedSize");
-        return -1;
-    }
-    field_objectInfo_thumbFormat = env->GetFieldID(clazz, "mThumbFormat", "I");
-    if (field_objectInfo_thumbFormat == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mThumbFormat");
-        return -1;
-    }
-    field_objectInfo_thumbCompressedSize = env->GetFieldID(clazz, "mThumbCompressedSize", "I");
-    if (field_objectInfo_thumbCompressedSize == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mThumbCompressedSize");
-        return -1;
-    }
-    field_objectInfo_thumbPixWidth = env->GetFieldID(clazz, "mThumbPixWidth", "I");
-    if (field_objectInfo_thumbPixWidth == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mThumbPixWidth");
-        return -1;
-    }
-    field_objectInfo_thumbPixHeight = env->GetFieldID(clazz, "mThumbPixHeight", "I");
-    if (field_objectInfo_thumbPixHeight == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mThumbPixHeight");
-        return -1;
-    }
-    field_objectInfo_imagePixWidth = env->GetFieldID(clazz, "mImagePixWidth", "I");
-    if (field_objectInfo_imagePixWidth == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mImagePixWidth");
-        return -1;
-    }
-    field_objectInfo_imagePixHeight = env->GetFieldID(clazz, "mImagePixHeight", "I");
-    if (field_objectInfo_imagePixHeight == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mImagePixHeight");
-        return -1;
-    }
-    field_objectInfo_imagePixDepth = env->GetFieldID(clazz, "mImagePixDepth", "I");
-    if (field_objectInfo_imagePixDepth == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mImagePixDepth");
-        return -1;
-    }
-    field_objectInfo_parent = env->GetFieldID(clazz, "mParent", "I");
-    if (field_objectInfo_parent == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mParent");
-        return -1;
-    }
-    field_objectInfo_associationType = env->GetFieldID(clazz, "mAssociationType", "I");
-    if (field_objectInfo_associationType == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mAssociationType");
-        return -1;
-    }
-    field_objectInfo_associationDesc = env->GetFieldID(clazz, "mAssociationDesc", "I");
-    if (field_objectInfo_associationDesc == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mAssociationDesc");
-        return -1;
-    }
-    field_objectInfo_sequenceNumber = env->GetFieldID(clazz, "mSequenceNumber", "I");
-    if (field_objectInfo_sequenceNumber == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mSequenceNumber");
-        return -1;
-    }
-    field_objectInfo_name = env->GetFieldID(clazz, "mName", "Ljava/lang/String;");
-    if (field_objectInfo_name == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mName");
-        return -1;
-    }
-    field_objectInfo_dateCreated = env->GetFieldID(clazz, "mDateCreated", "J");
-    if (field_objectInfo_dateCreated == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mDateCreated");
-        return -1;
-    }
-    field_objectInfo_dateModified = env->GetFieldID(clazz, "mDateModified", "J");
-    if (field_objectInfo_dateModified == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mDateModified");
-        return -1;
-    }
-    field_objectInfo_keywords = env->GetFieldID(clazz, "mKeywords", "Ljava/lang/String;");
-    if (field_objectInfo_keywords == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mKeywords");
-        return -1;
-    }
-    clazz_objectInfo = (jclass)env->NewGlobalRef(clazz);
-
-    clazz = env->FindClass("android/mtp/MtpEvent");
-    if (clazz == NULL) {
-        ALOGE("Can't find android/mtp/MtpEvent");
-        return -1;
-    }
-    constructor_event = env->GetMethodID(clazz, "<init>", "()V");
-    if (constructor_event == NULL) {
-        ALOGE("Can't find android/mtp/MtpEvent constructor");
-        return -1;
-    }
-    field_event_eventCode = env->GetFieldID(clazz, "mEventCode", "I");
-    if (field_event_eventCode == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mEventCode");
-        return -1;
-    }
-    field_event_parameter1 = env->GetFieldID(clazz, "mParameter1", "I");
-    if (field_event_parameter1 == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mParameter1");
-        return -1;
-    }
-    field_event_parameter2 = env->GetFieldID(clazz, "mParameter2", "I");
-    if (field_event_parameter2 == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mParameter2");
-        return -1;
-    }
-    field_event_parameter3 = env->GetFieldID(clazz, "mParameter3", "I");
-    if (field_event_parameter3 == NULL) {
-        ALOGE("Can't find MtpObjectInfo.mParameter3");
-        return -1;
-    }
-    clazz_event = (jclass)env->NewGlobalRef(clazz);
-
-    clazz = env->FindClass("android/mtp/MtpDevice");
-    if (clazz == NULL) {
-        ALOGE("Can't find android/mtp/MtpDevice");
-        return -1;
-    }
-    field_context = env->GetFieldID(clazz, "mNativeContext", "J");
-    if (field_context == NULL) {
-        ALOGE("Can't find MtpDevice.mNativeContext");
-        return -1;
-    }
-    clazz = env->FindClass("java/io/IOException");
-    if (clazz == NULL) {
-        ALOGE("Can't find java.io.IOException");
-        return -1;
-    }
-    clazz_io_exception = (jclass)env->NewGlobalRef(clazz);
-    clazz = env->FindClass("android/os/OperationCanceledException");
-    if (clazz == NULL) {
-        ALOGE("Can't find android.os.OperationCanceledException");
-        return -1;
-    }
-    clazz_operation_canceled_exception = (jclass)env->NewGlobalRef(clazz);
-
     return AndroidRuntime::registerNativeMethods(env,
                 "android/mtp/MtpDevice", gMethods, NELEM(gMethods));
 }
diff --git a/media/jni/android_mtp_MtpServer.cpp b/media/jni/android_mtp_MtpServer.cpp
index 8a1ae92..b4844f7 100644
--- a/media/jni/android_mtp_MtpServer.cpp
+++ b/media/jni/android_mtp_MtpServer.cpp
@@ -24,6 +24,7 @@
 #include <fcntl.h>
 #include <utils/threads.h>
 
+#include "core_jni_helpers.h"
 #include "jni.h"
 #include <nativehelper/JNIPlatformHelp.h>
 #include "android_runtime/AndroidRuntime.h"
@@ -34,6 +35,8 @@
 
 using namespace android;
 
+static Mutex sMutex;
+
 // MtpServer fields
 static jfieldID field_MtpServer_nativeContext;
 
@@ -44,7 +47,25 @@
 static jfieldID field_MtpStorage_removable;
 static jfieldID field_MtpStorage_maxFileSize;
 
-static Mutex sMutex;
+// Initializer for the jfieldIDs above. This method must be invoked before accessing MtpServer and
+// MtpStorage fields.
+static void initializeJavaIDs(JNIEnv* env) {
+    static std::once_flag sJniInitialized;
+
+    std::call_once(sJniInitialized, [](JNIEnv *env) {
+        const jclass storage_clazz = FindClassOrDie(env, "android/mtp/MtpStorage");
+        field_MtpStorage_storageId = GetFieldIDOrDie(env, storage_clazz, "mStorageId", "I");
+        field_MtpStorage_path =
+                GetFieldIDOrDie(env, storage_clazz, "mPath", "Ljava/lang/String;");
+        field_MtpStorage_description =
+                GetFieldIDOrDie(env, storage_clazz, "mDescription", "Ljava/lang/String;");
+        field_MtpStorage_removable = GetFieldIDOrDie(env, storage_clazz, "mRemovable", "Z");
+        field_MtpStorage_maxFileSize = GetFieldIDOrDie(env, storage_clazz, "mMaxFileSize", "J");
+
+        const jclass server_clazz = FindClassOrDie(env, "android/mtp/MtpServer");
+        field_MtpServer_nativeContext = GetFieldIDOrDie(env, server_clazz, "mNativeContext", "J");
+    }, env);
+}
 
 // ----------------------------------------------------------------------------
 
@@ -52,6 +73,7 @@
 extern IMtpDatabase* getMtpDatabase(JNIEnv *env, jobject database);
 
 static inline MtpServer* getMtpServer(JNIEnv *env, jobject thiz) {
+    initializeJavaIDs(env);
     return (MtpServer*)env->GetLongField(thiz, field_MtpServer_nativeContext);
 }
 
@@ -60,6 +82,8 @@
         jboolean usePtp, jstring deviceInfoManufacturer, jstring deviceInfoModel,
         jstring deviceInfoDeviceVersion, jstring deviceInfoSerialNumber)
 {
+    initializeJavaIDs(env);
+
     const char *deviceInfoManufacturerStr = env->GetStringUTFChars(deviceInfoManufacturer, NULL);
     const char *deviceInfoModelStr = env->GetStringUTFChars(deviceInfoModel, NULL);
     const char *deviceInfoDeviceVersionStr = env->GetStringUTFChars(deviceInfoDeviceVersion, NULL);
@@ -224,50 +248,6 @@
 
 int register_android_mtp_MtpServer(JNIEnv *env)
 {
-    jclass clazz;
-
-    clazz = env->FindClass("android/mtp/MtpStorage");
-    if (clazz == NULL) {
-        ALOGE("Can't find android/mtp/MtpStorage");
-        return -1;
-    }
-    field_MtpStorage_storageId = env->GetFieldID(clazz, "mStorageId", "I");
-    if (field_MtpStorage_storageId == NULL) {
-        ALOGE("Can't find MtpStorage.mStorageId");
-        return -1;
-    }
-    field_MtpStorage_path = env->GetFieldID(clazz, "mPath", "Ljava/lang/String;");
-    if (field_MtpStorage_path == NULL) {
-        ALOGE("Can't find MtpStorage.mPath");
-        return -1;
-    }
-    field_MtpStorage_description = env->GetFieldID(clazz, "mDescription", "Ljava/lang/String;");
-    if (field_MtpStorage_description == NULL) {
-        ALOGE("Can't find MtpStorage.mDescription");
-        return -1;
-    }
-    field_MtpStorage_removable = env->GetFieldID(clazz, "mRemovable", "Z");
-    if (field_MtpStorage_removable == NULL) {
-        ALOGE("Can't find MtpStorage.mRemovable");
-        return -1;
-    }
-    field_MtpStorage_maxFileSize = env->GetFieldID(clazz, "mMaxFileSize", "J");
-    if (field_MtpStorage_maxFileSize == NULL) {
-        ALOGE("Can't find MtpStorage.mMaxFileSize");
-        return -1;
-    }
-
-    clazz = env->FindClass("android/mtp/MtpServer");
-    if (clazz == NULL) {
-        ALOGE("Can't find android/mtp/MtpServer");
-        return -1;
-    }
-    field_MtpServer_nativeContext = env->GetFieldID(clazz, "mNativeContext", "J");
-    if (field_MtpServer_nativeContext == NULL) {
-        ALOGE("Can't find MtpServer.mNativeContext");
-        return -1;
-    }
-
     return AndroidRuntime::registerNativeMethods(env,
                 "android/mtp/MtpServer", gMethods, NELEM(gMethods));
 }
diff --git a/media/jni/audioeffect/Android.bp b/media/jni/audioeffect/Android.bp
index 40e4c54..c2fc91d 100644
--- a/media/jni/audioeffect/Android.bp
+++ b/media/jni/audioeffect/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_media_jni_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_media_jni_license"],
+}
+
 cc_library_shared {
     name: "libaudioeffect_jni",
 
diff --git a/media/jni/soundpool/Android.bp b/media/jni/soundpool/Android.bp
index 6141308..b3406cd 100644
--- a/media/jni/soundpool/Android.bp
+++ b/media/jni/soundpool/Android.bp
@@ -1,3 +1,22 @@
+package {
+    default_applicable_licenses: [
+        "frameworks_base_media_jni_soundpool_license",
+    ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_media_jni_soundpool_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 tidy_errors = [
     // https://clang.llvm.org/extra/clang-tidy/checks/list.html
     // For many categories, the checks are too many to specify individually.
@@ -26,26 +45,30 @@
     "modernize-return-braced-init-list",
     "modernize-shrink-to-fit",
     "modernize-unary-static-assert",
-    "modernize-use-auto",  // debatable - auto can obscure type
+    // "modernize-use-auto",  // found in StreamManager.h, debatable - auto can obscure type
     "modernize-use-bool-literals",
     "modernize-use-default-member-init",
     "modernize-use-emplace",
     "modernize-use-equals-default",
     "modernize-use-equals-delete",
-    "modernize-use-nodiscard",
+    // "modernize-use-nodiscard", // found in SteamManager.h
     "modernize-use-noexcept",
     "modernize-use-nullptr",
     "modernize-use-override",
     //"modernize-use-trailing-return-type", // not necessarily more readable
     "modernize-use-transparent-functors",
     "modernize-use-uncaught-exceptions",
-    "modernize-use-using",
+    //"modernize-use-using", // found in SoundManager.h
     "performance-*",
 
     // Remove some pedantic stylistic requirements.
     "-google-readability-casting", // C++ casts not always necessary and may be verbose
     "-google-readability-todo",    // do not require TODO(info)
     "-google-build-using-namespace", // Reenable and fix later.
+
+    "-google-explicit-constructor", // found in StreamManager.h
+    "-misc-non-private-member-variables-in-classes", // found in SoundManager.h
+    "-performance-unnecessary-value-param", // found in StreamManager.h
 ]
 
 cc_defaults {
@@ -77,8 +100,7 @@
     tidy_checks: tidy_errors,
     tidy_checks_as_errors: tidy_errors,
     tidy_flags: [
-      "-format-style='file'",
-      "--header-filter='frameworks/base/media/jni/soundpool'",
+      "-format-style=file",
     ],
 }
 
diff --git a/media/jni/soundpool/tests/Android.bp b/media/jni/soundpool/tests/Android.bp
index 52f59ed..7d31c10 100644
--- a/media/jni/soundpool/tests/Android.bp
+++ b/media/jni/soundpool/tests/Android.bp
@@ -1,3 +1,14 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_media_jni_soundpool_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: [
+        "frameworks_base_media_jni_soundpool_license",
+    ],
+}
+
 cc_binary {
     name: "soundpool_stress",
     host_supported: false,
diff --git a/media/jni/tuner/DemuxClient.cpp b/media/jni/tuner/DemuxClient.cpp
index 359ef36..78cb5b0 100644
--- a/media/jni/tuner/DemuxClient.cpp
+++ b/media/jni/tuner/DemuxClient.cpp
@@ -216,7 +216,7 @@
 Result DemuxClient::close() {
     if (mTunerDemux != NULL) {
         Status s = mTunerDemux->close();
-        mDemux = NULL;
+        mTunerDemux = NULL;
         return ClientHelper::getServiceSpecificErrorCode(s);
     }
 
diff --git a/media/jni/tuner/FilterClient.h b/media/jni/tuner/FilterClient.h
index bbabc28..736b8f9 100644
--- a/media/jni/tuner/FilterClient.h
+++ b/media/jni/tuner/FilterClient.h
@@ -267,9 +267,6 @@
     AidlMQ* mFilterMQ;
     EventFlag* mFilterMQEventFlag;
 
-    sp<FilterClientCallback> mCallback;
-    sp<HidlFilterCallback> mHidlCallback;
-
     native_handle_t* mAvSharedHandle;
     uint64_t mAvSharedMemSize;
     bool mIsMediaFilter;
diff --git a/media/jni/tuner/FrontendClient.cpp b/media/jni/tuner/FrontendClient.cpp
index 9e36642..f54e266 100644
--- a/media/jni/tuner/FrontendClient.cpp
+++ b/media/jni/tuner/FrontendClient.cpp
@@ -78,8 +78,6 @@
 
 FrontendClient::FrontendClient(shared_ptr<ITunerFrontend> tunerFrontend, int type) {
     mTunerFrontend = tunerFrontend;
-    mAidlCallback = NULL;
-    mHidlCallback = NULL;
     mType = type;
 }
 
@@ -87,22 +85,21 @@
     mTunerFrontend = NULL;
     mFrontend = NULL;
     mFrontend_1_1 = NULL;
-    mAidlCallback = NULL;
-    mHidlCallback = NULL;
     mId = -1;
     mType = -1;
 }
 
 Result FrontendClient::setCallback(sp<FrontendClientCallback> frontendClientCallback) {
     if (mTunerFrontend != NULL) {
-        mAidlCallback = ::ndk::SharedRefBase::make<TunerFrontendCallback>(frontendClientCallback);
-        mAidlCallback->setFrontendType(mType);
-        Status s = mTunerFrontend->setCallback(mAidlCallback);
+        shared_ptr<TunerFrontendCallback> aidlCallback =
+                ::ndk::SharedRefBase::make<TunerFrontendCallback>(frontendClientCallback);
+        aidlCallback->setFrontendType(mType);
+        Status s = mTunerFrontend->setCallback(aidlCallback);
         return ClientHelper::getServiceSpecificErrorCode(s);
     }
 
-    mHidlCallback = new HidlFrontendCallback(frontendClientCallback);
-    return mFrontend->setCallback(mHidlCallback);
+    sp<HidlFrontendCallback> hidlCallback = new HidlFrontendCallback(frontendClientCallback);
+    return mFrontend->setCallback(hidlCallback);
 }
 
 void FrontendClient::setHidlFrontend(sp<IFrontend> frontend) {
@@ -591,14 +588,15 @@
                 break;
             }
             case TunerFrontendStatus::codeRates: {
-                int size = s.get<TunerFrontendStatus::codeRates>().size();
-                status.codeRates().resize(size);
-                for (int i = 0; i < size; i++) {
-                    auto aidlCodeRate = s.get<TunerFrontendStatus::codeRates>()[i];
-                    status.codeRates()[i] =
-                            static_cast<hardware::tv::tuner::V1_1::FrontendInnerFec>(aidlCodeRate);
+                vector<hardware::tv::tuner::V1_1::FrontendInnerFec> codeRates;
+                for (auto aidlCodeRate : s.get<TunerFrontendStatus::codeRates>()) {
+                    codeRates.push_back(
+                            static_cast<hardware::tv::tuner::V1_1::FrontendInnerFec>(aidlCodeRate));
                 }
-                hidlStatus.push_back(status);
+                if (codeRates.size() > 0) {
+                    status.codeRates(codeRates);
+                    hidlStatus.push_back(status);
+                }
                 break;
             }
             case TunerFrontendStatus::bandwidth: {
diff --git a/media/jni/tuner/FrontendClient.h b/media/jni/tuner/FrontendClient.h
index f71616c..1dd950e 100644
--- a/media/jni/tuner/FrontendClient.h
+++ b/media/jni/tuner/FrontendClient.h
@@ -226,9 +226,6 @@
      */
     sp<::android::hardware::tv::tuner::V1_1::IFrontend> mFrontend_1_1;
 
-    shared_ptr<TunerFrontendCallback> mAidlCallback;
-    sp<HidlFrontendCallback> mHidlCallback;
-
     int mId;
     int mType;
 };
diff --git a/media/jni/tuner/LnbClient.cpp b/media/jni/tuner/LnbClient.cpp
index 5b6e46e..073c49a 100644
--- a/media/jni/tuner/LnbClient.cpp
+++ b/media/jni/tuner/LnbClient.cpp
@@ -45,14 +45,15 @@
 
 Result LnbClient::setCallback(sp<LnbClientCallback> cb) {
     if (mTunerLnb != NULL) {
-        mAidlCallback = ::ndk::SharedRefBase::make<TunerLnbCallback>(cb);
-        Status s = mTunerLnb->setCallback(mAidlCallback);
+        shared_ptr<TunerLnbCallback> aidlCallback =
+                ::ndk::SharedRefBase::make<TunerLnbCallback>(cb);
+        Status s = mTunerLnb->setCallback(aidlCallback);
         return ClientHelper::getServiceSpecificErrorCode(s);
     }
 
     if (mLnb != NULL) {
-        mHidlCallback = new HidlLnbCallback(cb);
-        return mLnb->setCallback(mHidlCallback);
+        sp<HidlLnbCallback> hidlCallback = new HidlLnbCallback(cb);
+        return mLnb->setCallback(hidlCallback);
     }
 
     return Result::INVALID_STATE;
diff --git a/media/jni/tuner/LnbClient.h b/media/jni/tuner/LnbClient.h
index 465dc23..7c6118c 100644
--- a/media/jni/tuner/LnbClient.h
+++ b/media/jni/tuner/LnbClient.h
@@ -126,9 +126,6 @@
      */
     sp<ILnb> mLnb;
 
-    shared_ptr<TunerLnbCallback> mAidlCallback;
-    sp<HidlLnbCallback> mHidlCallback;
-
     LnbId mId;
 };
 }  // namespace android
diff --git a/media/jni/tuner/TunerClient.cpp b/media/jni/tuner/TunerClient.cpp
index cf17ed6..c9a7e83 100644
--- a/media/jni/tuner/TunerClient.cpp
+++ b/media/jni/tuner/TunerClient.cpp
@@ -49,8 +49,6 @@
     if (mTunerService == NULL) {
         ALOGE("Failed to get tuner service");
     } else {
-        // TODO: b/178124017 update TRM in TunerService independently.
-        mTunerService->updateTunerResources();
         mTunerService->getTunerHalVersion(&mTunerVersion);
     }
 }
diff --git a/media/lib/remotedisplay/Android.bp b/media/lib/remotedisplay/Android.bp
index 5f4b930..bfb0cb8 100644
--- a/media/lib/remotedisplay/Android.bp
+++ b/media/lib/remotedisplay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_sdk_library {
     name: "com.android.media.remotedisplay",
     srcs: ["java/**/*.java"],
diff --git a/media/lib/signer/Android.bp b/media/lib/signer/Android.bp
index 3b25787..6504176 100644
--- a/media/lib/signer/Android.bp
+++ b/media/lib/signer/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_sdk_library {
     name: "com.android.mediadrm.signer",
     srcs: ["java/**/*.java"],
diff --git a/media/lib/tvremote/Android.bp b/media/lib/tvremote/Android.bp
index c5d1419..a58f677 100644
--- a/media/lib/tvremote/Android.bp
+++ b/media/lib/tvremote/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_sdk_library {
     name: "com.android.media.tv.remoteprovider",
     srcs: ["java/**/*.java"],
diff --git a/media/lib/tvremote/tests/Android.bp b/media/lib/tvremote/tests/Android.bp
index f00eed0..f02cfc3 100644
--- a/media/lib/tvremote/tests/Android.bp
+++ b/media/lib/tvremote/tests/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "TvRemoteTests",
     srcs: ["src/**/*.java"],
diff --git a/media/mca/filterfw/Android.bp b/media/mca/filterfw/Android.bp
index 0e0ecf3..ef3583f 100644
--- a/media/mca/filterfw/Android.bp
+++ b/media/mca/filterfw/Android.bp
@@ -13,6 +13,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_library_shared {
     name: "libfilterfw",
 
diff --git a/media/mca/filterfw/native/Android.bp b/media/mca/filterfw/native/Android.bp
index 7a8a6a1..7e4a34e 100644
--- a/media/mca/filterfw/native/Android.bp
+++ b/media/mca/filterfw/native/Android.bp
@@ -16,6 +16,15 @@
 //####################
 // Build module libfilterfw_static
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_library_static {
     name: "libfilterfw_native",
 
diff --git a/media/mca/filterpacks/Android.bp b/media/mca/filterpacks/Android.bp
index 34fb27d..b50df6e 100644
--- a/media/mca/filterpacks/Android.bp
+++ b/media/mca/filterpacks/Android.bp
@@ -13,6 +13,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_library_static {
     name: "libfilterpack_base",
     srcs: [
diff --git a/media/mca/samples/CameraEffectsRecordingSample/Android.bp b/media/mca/samples/CameraEffectsRecordingSample/Android.bp
index 96e81ab..541660c 100644
--- a/media/mca/samples/CameraEffectsRecordingSample/Android.bp
+++ b/media/mca/samples/CameraEffectsRecordingSample/Android.bp
@@ -15,6 +15,15 @@
 
 // Build activity
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "CameraEffectsRecordingSample",
     srcs: ["**/*.java"],
@@ -23,4 +32,3 @@
         enabled: false,
     },
 }
-
diff --git a/media/mca/tests/Android.bp b/media/mca/tests/Android.bp
index 6b11dd9..f02b4c0 100644
--- a/media/mca/tests/Android.bp
+++ b/media/mca/tests/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "CameraEffectsTests",
     libs: [
diff --git a/media/native/midi/Android.bp b/media/native/midi/Android.bp
index 2da45b6..7acb8c7 100644
--- a/media/native/midi/Android.bp
+++ b/media/native/midi/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_library_shared {
     name: "libamidi",
 
diff --git a/media/packages/BluetoothMidiService/Android.bp b/media/packages/BluetoothMidiService/Android.bp
index 25c34c3..94a7a17 100644
--- a/media/packages/BluetoothMidiService/Android.bp
+++ b/media/packages/BluetoothMidiService/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "BluetoothMidiLib",
     srcs: [
diff --git a/media/packages/BluetoothMidiService/tests/unit/Android.bp b/media/packages/BluetoothMidiService/tests/unit/Android.bp
index fa4612b..67c7e42 100644
--- a/media/packages/BluetoothMidiService/tests/unit/Android.bp
+++ b/media/packages/BluetoothMidiService/tests/unit/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "BluetoothMidiTests",
     srcs: ["src/**/*.java"],
diff --git a/media/tests/AudioPolicyTest/Android.bp b/media/tests/AudioPolicyTest/Android.bp
index ed338375..95d1c6c 100644
--- a/media/tests/AudioPolicyTest/Android.bp
+++ b/media/tests/AudioPolicyTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "audiopolicytest",
     srcs: ["**/*.java"],
diff --git a/media/tests/CameraBrowser/Android.bp b/media/tests/CameraBrowser/Android.bp
index 8e3ca19..1408640 100644
--- a/media/tests/CameraBrowser/Android.bp
+++ b/media/tests/CameraBrowser/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "CameraBrowser",
     srcs: ["**/*.java"],
diff --git a/media/tests/EffectsTest/Android.bp b/media/tests/EffectsTest/Android.bp
index 214e8c0..644e453 100644
--- a/media/tests/EffectsTest/Android.bp
+++ b/media/tests/EffectsTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "EffectsTest",
     srcs: ["**/*.java"],
diff --git a/media/tests/MediaDump/Android.bp b/media/tests/MediaDump/Android.bp
index 0eba8b2..f54b97a 100644
--- a/media/tests/MediaDump/Android.bp
+++ b/media/tests/MediaDump/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "MediaDump",
     // Only compile source java files in this apk.
diff --git a/media/tests/MediaFrameworkTest/Android.bp b/media/tests/MediaFrameworkTest/Android.bp
index 3f1954a..48d56d8 100644
--- a/media/tests/MediaFrameworkTest/Android.bp
+++ b/media/tests/MediaFrameworkTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "mediaframeworktest",
     srcs: ["**/*.java"],
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioAttributesUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioAttributesUnitTest.java
new file mode 100644
index 0000000..3a4bec0
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioAttributesUnitTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import static org.junit.Assert.assertEquals;
+
+import android.media.AudioAttributes;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class AudioAttributesUnitTest {
+
+    @Test
+    public void testUsageToString_returnCorrectStrings() {
+        assertEquals("USAGE_UNKNOWN", AudioAttributes.usageToString(AudioAttributes.USAGE_UNKNOWN));
+        assertEquals("USAGE_MEDIA", AudioAttributes.usageToString(AudioAttributes.USAGE_MEDIA));
+        assertEquals("USAGE_VOICE_COMMUNICATION",
+                AudioAttributes.usageToString(AudioAttributes.USAGE_VOICE_COMMUNICATION));
+        assertEquals("USAGE_VOICE_COMMUNICATION_SIGNALLING",
+                AudioAttributes.usageToString(
+                        AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING));
+        assertEquals("USAGE_ALARM", AudioAttributes.usageToString(AudioAttributes.USAGE_ALARM));
+        assertEquals("USAGE_NOTIFICATION",
+                AudioAttributes.usageToString(AudioAttributes.USAGE_NOTIFICATION));
+        assertEquals("USAGE_NOTIFICATION_RINGTONE",
+                AudioAttributes.usageToString(AudioAttributes.USAGE_NOTIFICATION_RINGTONE));
+        assertEquals("USAGE_NOTIFICATION_COMMUNICATION_REQUEST",
+                AudioAttributes.usageToString(
+                        AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST));
+        assertEquals("USAGE_NOTIFICATION_COMMUNICATION_INSTANT",
+                AudioAttributes.usageToString(
+                        AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT));
+        assertEquals("USAGE_NOTIFICATION_COMMUNICATION_DELAYED",
+                AudioAttributes.usageToString(
+                        AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_DELAYED));
+        assertEquals("USAGE_NOTIFICATION_EVENT",
+                AudioAttributes.usageToString(AudioAttributes.USAGE_NOTIFICATION_EVENT));
+        assertEquals("USAGE_ASSISTANCE_ACCESSIBILITY",
+                AudioAttributes.usageToString(AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY));
+        assertEquals("USAGE_ASSISTANCE_NAVIGATION_GUIDANCE",
+                AudioAttributes.usageToString(
+                        AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE));
+        assertEquals("USAGE_ASSISTANCE_SONIFICATION",
+                AudioAttributes.usageToString(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION));
+        assertEquals("USAGE_GAME", AudioAttributes.usageToString(AudioAttributes.USAGE_GAME));
+        assertEquals("USAGE_ASSISTANT",
+                AudioAttributes.usageToString(AudioAttributes.USAGE_ASSISTANT));
+        assertEquals("USAGE_CALL_ASSISTANT",
+                AudioAttributes.usageToString(AudioAttributes.USAGE_CALL_ASSISTANT));
+        assertEquals("USAGE_EMERGENCY",
+                AudioAttributes.usageToString(AudioAttributes.USAGE_EMERGENCY));
+        assertEquals("USAGE_SAFETY", AudioAttributes.usageToString(AudioAttributes.USAGE_SAFETY));
+        assertEquals("USAGE_VEHICLE_STATUS",
+                AudioAttributes.usageToString(AudioAttributes.USAGE_VEHICLE_STATUS));
+        assertEquals("USAGE_ANNOUNCEMENT",
+                AudioAttributes.usageToString(AudioAttributes.USAGE_ANNOUNCEMENT));
+    }
+
+    @Test
+    public void testUsageToString_unknownUsage() {
+        assertEquals("unknown usage -1", AudioAttributes.usageToString(-1));
+    }
+}
diff --git a/media/tests/MediaRouter/Android.bp b/media/tests/MediaRouter/Android.bp
index a439b79..d41bc02 100644
--- a/media/tests/MediaRouter/Android.bp
+++ b/media/tests/MediaRouter/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "mediaroutertest",
 
@@ -17,4 +26,4 @@
 
     platform_apis: true,
     certificate: "platform",
-}
\ No newline at end of file
+}
diff --git a/media/tests/MtpTests/Android.bp b/media/tests/MtpTests/Android.bp
index 7d2c7c6..3016873 100644
--- a/media/tests/MtpTests/Android.bp
+++ b/media/tests/MtpTests/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "MtpTests",
     srcs: ["**/*.java"],
diff --git a/media/tests/ScoAudioTest/Android.bp b/media/tests/ScoAudioTest/Android.bp
index ad2b9171..f8a893b 100644
--- a/media/tests/ScoAudioTest/Android.bp
+++ b/media/tests/ScoAudioTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "scoaudiotest",
     platform_apis: true,
diff --git a/media/tests/SoundPoolTest/Android.bp b/media/tests/SoundPoolTest/Android.bp
index 473f531..0a50106d 100644
--- a/media/tests/SoundPoolTest/Android.bp
+++ b/media/tests/SoundPoolTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "SoundPoolTest",
     srcs: ["**/*.java"],
diff --git a/media/tests/TunerTest/Android.bp b/media/tests/TunerTest/Android.bp
index 5c3e9ab..8e8816c 100644
--- a/media/tests/TunerTest/Android.bp
+++ b/media/tests/TunerTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "mediatunertest",
 
diff --git a/media/tests/audiotests/Android.bp b/media/tests/audiotests/Android.bp
index 5db0ab0..c52c033 100644
--- a/media/tests/audiotests/Android.bp
+++ b/media/tests/audiotests/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_test {
     name: "shared_mem_test",
     gtest: false,
diff --git a/media/tests/players/Android.bp b/media/tests/players/Android.bp
index 23c5f04..3b6df70 100644
--- a/media/tests/players/Android.bp
+++ b/media/tests/players/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_test_library {
     name: "invoke_mock_media_player",
     srcs: ["invoke_mock_media_player.cpp"],
diff --git a/mime/Android.bp b/mime/Android.bp
index 23a8fbf..a3ea65c 100644
--- a/mime/Android.bp
+++ b/mime/Android.bp
@@ -13,6 +13,15 @@
 // limitations under the License.
 
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_defaults {
     name: "mimemap-defaults",
     srcs: [
diff --git a/native/android/Android.bp b/native/android/Android.bp
index 253ef67..9566b92 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -13,6 +13,15 @@
 // limitations under the License.
 
 // The headers module is in frameworks/native/Android.bp.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 ndk_library {
     name: "libandroid",
     symbol_file: "libandroid.map.txt",
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index e51add2..e8cf63f 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -27,14 +27,13 @@
 #include <gui/SurfaceComposerClient.h>
 #include <gui/SurfaceControl.h>
 
-#include <ui/HdrCapabilities.h>
+#include <ui/DynamicDisplayInfo.h>
 
 #include <utils/Timers.h>
 
 using namespace android::hardware::configstore;
 using namespace android::hardware::configstore::V1_0;
 using namespace android;
-using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
 
 using Transaction = SurfaceComposerClient::Transaction;
 
@@ -72,14 +71,13 @@
         return false;
     }
 
-    HdrCapabilities hdrCapabilities;
-    status_t err = client->getHdrCapabilities(display, &hdrCapabilities);
-    if (err) {
+    ui::DynamicDisplayInfo info;
+    if (status_t err = client->getDynamicDisplayInfo(display, &info); err != NO_ERROR) {
         ALOGE("unable to get hdr capabilities");
-        return false;
+        return err;
     }
 
-    return !hdrCapabilities.getSupportedHdrTypes().empty();
+    return !info.hdrCapabilities.getSupportedHdrTypes().empty();
 }
 
 static bool isDataSpaceValid(const sp<SurfaceControl>& surfaceControl, ADataSpace dataSpace) {
diff --git a/native/android/tests/activitymanager/UidImportanceHelperApps/Android.bp b/native/android/tests/activitymanager/UidImportanceHelperApps/Android.bp
index 1a51218..fdca3fa 100644
--- a/native/android/tests/activitymanager/UidImportanceHelperApps/Android.bp
+++ b/native/android/tests/activitymanager/UidImportanceHelperApps/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "UidImportanceHelperApp",
     manifest: "HelperAppManifest.xml",
@@ -8,4 +17,3 @@
         "general-tests",
     ],
 }
-
diff --git a/native/android/tests/activitymanager/nativeTests/Android.bp b/native/android/tests/activitymanager/nativeTests/Android.bp
index d4b5015..528ac12 100644
--- a/native/android/tests/activitymanager/nativeTests/Android.bp
+++ b/native/android/tests/activitymanager/nativeTests/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_test {
     name: "ActivityManagerNativeTestCases",
 
diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp
index 3d633ea..1709dfd 100644
--- a/native/graphics/jni/Android.bp
+++ b/native/graphics/jni/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_library_shared {
     name: "libjnigraphics",
 
diff --git a/native/webview/loader/Android.bp b/native/webview/loader/Android.bp
index dfa5bdd..bb9b890 100644
--- a/native/webview/loader/Android.bp
+++ b/native/webview/loader/Android.bp
@@ -17,6 +17,15 @@
 
 // Loader library which handles address space reservation and relro sharing.
 // Does NOT link any native chromium code.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_library_shared {
     name: "libwebviewchromium_loader",
 
diff --git a/native/webview/plat_support/Android.bp b/native/webview/plat_support/Android.bp
index 1a3b36d..2e94e84 100644
--- a/native/webview/plat_support/Android.bp
+++ b/native/webview/plat_support/Android.bp
@@ -18,6 +18,38 @@
 
 // Native support library (libwebviewchromium_plat_support.so) - does NOT link
 // any native chromium code.
+package {
+    default_applicable_licenses: [
+        "frameworks_base_native_webview_plat_support_license",
+    ],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_native_webview_plat_support_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+        "SPDX-license-identifier-BSD",
+    ],
+    license_text: [
+        "LICENSE",
+    ],
+}
+
 cc_library_shared {
     name: "libwebviewchromium_plat_support",
 
diff --git a/nfc-extras/Android.bp b/nfc-extras/Android.bp
index cbacd48..43b2830 100644
--- a/nfc-extras/Android.bp
+++ b/nfc-extras/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_sdk_library {
     name: "com.android.nfc_extras",
     srcs: ["java/**/*.java"],
diff --git a/nfc-extras/tests/Android.bp b/nfc-extras/tests/Android.bp
index fc52006..4c1f2fb 100644
--- a/nfc-extras/tests/Android.bp
+++ b/nfc-extras/tests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "NfcExtrasTests",
 
diff --git a/obex/Android.bp b/obex/Android.bp
index 6558eb3..95eac81 100644
--- a/obex/Android.bp
+++ b/obex/Android.bp
@@ -14,6 +14,36 @@
 // limitations under the License.
 //
 
+package {
+    default_applicable_licenses: ["frameworks_base_obex_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_obex_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+        "SPDX-license-identifier-BSD",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 java_sdk_library {
     name: "javax.obex",
     srcs: ["javax/**/*.java"],
diff --git a/packages/AppPredictionLib/Android.bp b/packages/AppPredictionLib/Android.bp
index e0f4ded..5a68fdc 100644
--- a/packages/AppPredictionLib/Android.bp
+++ b/packages/AppPredictionLib/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "app_prediction",
 
diff --git a/packages/BackupEncryption/Android.bp b/packages/BackupEncryption/Android.bp
index 3a078d2..0244f28 100644
--- a/packages/BackupEncryption/Android.bp
+++ b/packages/BackupEncryption/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "BackupEncryption",
     defaults: ["platform_app_defaults"],
diff --git a/packages/BackupEncryption/test/robolectric-integration/Android.bp b/packages/BackupEncryption/test/robolectric-integration/Android.bp
index 67365df..c842e42 100644
--- a/packages/BackupEncryption/test/robolectric-integration/Android.bp
+++ b/packages/BackupEncryption/test/robolectric-integration/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_robolectric_test {
     name: "BackupEncryptionRoboIntegTests",
     srcs: [
diff --git a/packages/BackupEncryption/test/robolectric/Android.bp b/packages/BackupEncryption/test/robolectric/Android.bp
index 2a36dcf..7665d8f 100644
--- a/packages/BackupEncryption/test/robolectric/Android.bp
+++ b/packages/BackupEncryption/test/robolectric/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_robolectric_test {
     name: "BackupEncryptionRoboTests",
     srcs: [
diff --git a/packages/BackupEncryption/test/unittest/Android.bp b/packages/BackupEncryption/test/unittest/Android.bp
index d7c510b..f005170 100644
--- a/packages/BackupEncryption/test/unittest/Android.bp
+++ b/packages/BackupEncryption/test/unittest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "BackupEncryptionUnitTests",
     srcs: ["src/**/*.java"],
@@ -19,4 +28,4 @@
     test_suites: ["device-tests"],
     instrumentation_for: "BackupEncryption",
     certificate: "platform",
-}
\ No newline at end of file
+}
diff --git a/packages/BackupRestoreConfirmation/Android.bp b/packages/BackupRestoreConfirmation/Android.bp
index 6fe039d..ad3f4c1 100644
--- a/packages/BackupRestoreConfirmation/Android.bp
+++ b/packages/BackupRestoreConfirmation/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "BackupRestoreConfirmation",
     defaults: ["platform_app_defaults"],
diff --git a/packages/CarrierDefaultApp/Android.bp b/packages/CarrierDefaultApp/Android.bp
index c1b0b2d..fc753da 100644
--- a/packages/CarrierDefaultApp/Android.bp
+++ b/packages/CarrierDefaultApp/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "CarrierDefaultApp",
     srcs: ["src/**/*.java"],
diff --git a/packages/CarrierDefaultApp/tests/unit/Android.bp b/packages/CarrierDefaultApp/tests/unit/Android.bp
index 5655abb..54c9016 100644
--- a/packages/CarrierDefaultApp/tests/unit/Android.bp
+++ b/packages/CarrierDefaultApp/tests/unit/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "CarrierDefaultAppUnitTests",
     certificate: "platform",
diff --git a/packages/CompanionDeviceManager/Android.bp b/packages/CompanionDeviceManager/Android.bp
index 354d2c7..4a52650 100644
--- a/packages/CompanionDeviceManager/Android.bp
+++ b/packages/CompanionDeviceManager/Android.bp
@@ -12,6 +12,25 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: [
+        "frameworks_base_packages_CompanionDeviceManager_license",
+    ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_packages_CompanionDeviceManager_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 android_app {
     name: "CompanionDeviceManager",
     defaults: ["platform_app_defaults"],
diff --git a/packages/CompanionDeviceManager/AndroidManifest.xml b/packages/CompanionDeviceManager/AndroidManifest.xml
index 91bad7b..f9795c6 100644
--- a/packages/CompanionDeviceManager/AndroidManifest.xml
+++ b/packages/CompanionDeviceManager/AndroidManifest.xml
@@ -41,13 +41,13 @@
         android:supportsRtl="true">
 
         <service
-            android:name=".DeviceDiscoveryService"
+            android:name=".CompanionDeviceDiscoveryService"
             android:permission="android.permission.BIND_COMPANION_DEVICE_MANAGER_SERVICE"
             android:exported="true">
         </service>
 
         <activity
-            android:name=".DeviceChooserActivity"
+            android:name=".CompanionDeviceActivity"
             android:theme="@style/ChooserActivity"
             android:permission="android.permission.BIND_COMPANION_DEVICE_MANAGER_SERVICE"
             android:exported="true">
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
similarity index 62%
rename from packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
rename to packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
index c30d4bf..f1a98ad 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
@@ -24,6 +24,7 @@
 
 import static java.util.Objects.requireNonNull;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.Activity;
 import android.companion.AssociationRequest;
@@ -31,41 +32,52 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
+import android.content.res.TypedArray;
 import android.database.DataSetObserver;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.text.Html;
 import android.util.Log;
+import android.util.SparseArray;
+import android.util.TypedValue;
 import android.view.Gravity;
 import android.view.View;
-import android.widget.AdapterView;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
 import android.widget.ListView;
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
-import com.android.companiondevicemanager.DeviceDiscoveryService.DeviceFilterPair;
+import com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DeviceFilterPair;
 import com.android.internal.util.Preconditions;
 
-public class DeviceChooserActivity extends Activity {
+public class CompanionDeviceActivity extends Activity {
 
     private static final boolean DEBUG = false;
-    private static final String LOG_TAG = "DeviceChooserActivity";
+    private static final String LOG_TAG = CompanionDeviceActivity.class.getSimpleName();
+
+    static CompanionDeviceActivity sInstance;
 
     View mLoadingIndicator = null;
     ListView mDeviceListView;
     private View mPairButton;
     private View mCancelButton;
 
+    DevicesAdapter mDevicesAdapter;
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        if (DEBUG) Log.i(LOG_TAG, "Started with intent " + getIntent());
+        Log.i(LOG_TAG, "Starting UI for " + getService().mRequest);
 
         if (getService().mDevicesFound.isEmpty()) {
             Log.e(LOG_TAG, "About to show UI, but no devices to show");
         }
 
         getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+        sInstance = this;
 
         String deviceProfile = getRequest().getDeviceProfile();
         String profilePrivacyDisclaimer = emptyIfNull(getRequest()
@@ -96,17 +108,14 @@
                     profileName,
                     getCallingAppName()), 0));
             mDeviceListView = findViewById(R.id.device_list);
-            final DeviceDiscoveryService.DevicesAdapter adapter = getService().mDevicesAdapter;
-            mDeviceListView.setAdapter(adapter);
-            mDeviceListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
-                @Override
-                public void onItemClick(AdapterView<?> adapterView, View view, int pos, long l) {
-                    getService().mSelectedDevice =
-                            (DeviceFilterPair) adapterView.getItemAtPosition(pos);
-                    adapter.notifyDataSetChanged();
-                }
+            mDevicesAdapter = new DevicesAdapter();
+            mDeviceListView.setAdapter(mDevicesAdapter);
+            mDeviceListView.setOnItemClickListener((adapterView, view, pos, l) -> {
+                getService().mSelectedDevice =
+                        (DeviceFilterPair) adapterView.getItemAtPosition(pos);
+                mDevicesAdapter.notifyDataSetChanged();
             });
-            adapter.registerDataSetObserver(new DataSetObserver() {
+            mDevicesAdapter.registerDataSetObserver(new DataSetObserver() {
                 @Override
                 public void onChanged() {
                     onSelectionUpdate();
@@ -133,6 +142,12 @@
         mCancelButton.setOnClickListener(v -> cancel());
     }
 
+    static void notifyDevicesChanged() {
+        if (sInstance != null && sInstance.mDevicesAdapter != null && !sInstance.isFinishing()) {
+            sInstance.mDevicesAdapter.notifyDataSetChanged();
+        }
+    }
+
     private AssociationRequest getRequest() {
         return getService().mRequest;
     }
@@ -156,6 +171,7 @@
     }
 
     private void cancel() {
+        Log.i(LOG_TAG, "cancel()");
         getService().onCancel();
         setResult(RESULT_CANCELED);
         finish();
@@ -170,6 +186,14 @@
         }
     }
 
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        if (sInstance == this) {
+            sInstance = null;
+        }
+    }
+
     private CharSequence getCallingAppName() {
         try {
             final PackageManager packageManager = getPackageManager();
@@ -217,15 +241,91 @@
         }
     }
 
-    private DeviceDiscoveryService getService() {
-        return DeviceDiscoveryService.sInstance;
+    private CompanionDeviceDiscoveryService getService() {
+        return CompanionDeviceDiscoveryService.sInstance;
     }
 
-   protected void onDeviceConfirmed(DeviceFilterPair selectedDevice) {
+    protected void onDeviceConfirmed(DeviceFilterPair selectedDevice) {
+        Log.i(LOG_TAG, "onDeviceConfirmed(selectedDevice = " + selectedDevice + ")");
         getService().onDeviceSelected(
                 getCallingPackage(), getDeviceMacAddress(selectedDevice.device));
         setResult(RESULT_OK,
                 new Intent().putExtra(CompanionDeviceManager.EXTRA_DEVICE, selectedDevice.device));
         finish();
     }
+
+    class DevicesAdapter extends BaseAdapter {
+        private final Drawable mBluetoothIcon = icon(android.R.drawable.stat_sys_data_bluetooth);
+        private final Drawable mWifiIcon = icon(com.android.internal.R.drawable.ic_wifi_signal_3);
+
+        private SparseArray<Integer> mColors = new SparseArray();
+
+        private Drawable icon(int drawableRes) {
+            Drawable icon = getResources().getDrawable(drawableRes, null);
+            icon.setTint(Color.DKGRAY);
+            return icon;
+        }
+
+        @Override
+        public View getView(
+                int position,
+                @Nullable View convertView,
+                @NonNull ViewGroup parent) {
+            TextView view = convertView instanceof TextView
+                    ? (TextView) convertView
+                    : newView();
+            bind(view, getItem(position));
+            return view;
+        }
+
+        private void bind(TextView textView, DeviceFilterPair device) {
+            textView.setText(device.getDisplayName());
+            textView.setBackgroundColor(
+                    device.equals(getService().mSelectedDevice)
+                            ? getColor(android.R.attr.colorControlHighlight)
+                            : Color.TRANSPARENT);
+            textView.setCompoundDrawablesWithIntrinsicBounds(
+                    device.device instanceof android.net.wifi.ScanResult
+                            ? mWifiIcon
+                            : mBluetoothIcon,
+                    null, null, null);
+            textView.getCompoundDrawables()[0].setTint(getColor(android.R.attr.colorForeground));
+        }
+
+        private TextView newView() {
+            final TextView textView = new TextView(CompanionDeviceActivity.this);
+            textView.setTextColor(getColor(android.R.attr.colorForeground));
+            final int padding = CompanionDeviceActivity.getPadding(getResources());
+            textView.setPadding(padding, padding, padding, padding);
+            textView.setCompoundDrawablePadding(padding);
+            return textView;
+        }
+
+        private int getColor(int colorAttr) {
+            if (mColors.contains(colorAttr)) {
+                return mColors.get(colorAttr);
+            }
+            TypedValue typedValue = new TypedValue();
+            TypedArray a = obtainStyledAttributes(typedValue.data, new int[] { colorAttr });
+            int result = a.getColor(0, 0);
+            a.recycle();
+            mColors.put(colorAttr, result);
+            return result;
+        }
+
+        @Override
+        public int getCount() {
+            return getService().mDevicesFound.size();
+        }
+
+        @Override
+        public DeviceFilterPair getItem(int position) {
+            return getService().mDevicesFound.get(position);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+    }
 }
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
similarity index 80%
rename from packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
rename to packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
index 67d4b41..e620dfb 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
@@ -50,9 +50,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.res.TypedArray;
-import android.graphics.Color;
-import android.graphics.drawable.Drawable;
 import android.net.wifi.WifiManager;
 import android.os.Handler;
 import android.os.IBinder;
@@ -60,12 +57,6 @@
 import android.os.RemoteException;
 import android.text.TextUtils;
 import android.util.Log;
-import android.util.SparseArray;
-import android.util.TypedValue;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.TextView;
 
 import com.android.internal.infra.AndroidFuture;
 import com.android.internal.util.ArrayUtils;
@@ -76,14 +67,14 @@
 import java.util.List;
 import java.util.Objects;
 
-public class DeviceDiscoveryService extends Service {
+public class CompanionDeviceDiscoveryService extends Service {
 
     private static final boolean DEBUG = false;
-    private static final String LOG_TAG = "DeviceDiscoveryService";
+    private static final String LOG_TAG = CompanionDeviceDiscoveryService.class.getSimpleName();
 
     private static final long SCAN_TIMEOUT = 20000;
 
-    static DeviceDiscoveryService sInstance;
+    static CompanionDeviceDiscoveryService sInstance;
 
     private BluetoothManager mBluetoothManager;
     private BluetoothAdapter mBluetoothAdapter;
@@ -102,12 +93,12 @@
     AssociationRequest mRequest;
     List<DeviceFilterPair> mDevicesFound;
     DeviceFilterPair mSelectedDevice;
-    DevicesAdapter mDevicesAdapter;
     IFindDeviceCallback mFindCallback;
 
     AndroidFuture<Association> mServiceCallback;
     boolean mIsScanning = false;
-    @Nullable DeviceChooserActivity mActivity = null;
+    @Nullable
+    CompanionDeviceActivity mActivity = null;
 
     private final ICompanionDeviceDiscoveryService mBinder =
             new ICompanionDeviceDiscoveryService.Stub() {
@@ -125,7 +116,8 @@
             mFindCallback = findCallback;
             mServiceCallback = serviceCallback;
             Handler.getMain().sendMessage(obtainMessage(
-                    DeviceDiscoveryService::startDiscovery, DeviceDiscoveryService.this, request));
+                    CompanionDeviceDiscoveryService::startDiscovery,
+                    CompanionDeviceDiscoveryService.this, request));
         }
     };
 
@@ -151,7 +143,6 @@
         mWifiManager = getSystemService(WifiManager.class);
 
         mDevicesFound = new ArrayList<>();
-        mDevicesAdapter = new DevicesAdapter();
 
         sInstance = this;
     }
@@ -165,7 +156,8 @@
             mWifiFilters = CollectionUtils.filter(mFilters, WifiDeviceFilter.class);
             mBluetoothFilters = CollectionUtils.filter(mFilters, BluetoothDeviceFilter.class);
             mBLEFilters = CollectionUtils.filter(mFilters, BluetoothLeDeviceFilter.class);
-            mBLEScanFilters = CollectionUtils.map(mBLEFilters, BluetoothLeDeviceFilter::getScanFilter);
+            mBLEScanFilters
+                    = CollectionUtils.map(mBLEFilters, BluetoothLeDeviceFilter::getScanFilter);
 
             reset();
         } else if (DEBUG) Log.i(LOG_TAG, "startDiscovery: duplicate request: " + request);
@@ -223,7 +215,7 @@
         }
         mIsScanning = true;
         Handler.getMain().sendMessageDelayed(
-                obtainMessage(DeviceDiscoveryService::stopScan, this),
+                obtainMessage(CompanionDeviceDiscoveryService::stopScan, this),
                 SCAN_TIMEOUT);
     }
 
@@ -237,7 +229,7 @@
         stopScan();
         mDevicesFound.clear();
         mSelectedDevice = null;
-        mDevicesAdapter.notifyDataSetChanged();
+        CompanionDeviceActivity.notifyDevicesChanged();
     }
 
     @Override
@@ -252,7 +244,7 @@
         if (!mIsScanning) return;
         mIsScanning = false;
 
-        DeviceChooserActivity activity = mActivity;
+        CompanionDeviceActivity activity = mActivity;
         if (activity != null) {
             if (activity.mDeviceListView != null) {
                 activity.mDeviceListView.removeFooterView(activity.mLoadingIndicator);
@@ -276,7 +268,7 @@
         if (device == null) return;
 
         Handler.getMain().sendMessage(obtainMessage(
-                DeviceDiscoveryService::onDeviceFoundMainThread, this, device));
+                CompanionDeviceDiscoveryService::onDeviceFoundMainThread, this, device));
     }
 
     @MainThread
@@ -292,7 +284,7 @@
             onReadyToShowUI();
         }
         mDevicesFound.add(device);
-        mDevicesAdapter.notifyDataSetChanged();
+        CompanionDeviceActivity.notifyDevicesChanged();
     }
 
     //TODO also, on timeout -> call onFailure
@@ -300,7 +292,7 @@
         try {
             mFindCallback.onSuccess(PendingIntent.getActivity(
                     this, 0,
-                    new Intent(this, DeviceChooserActivity.class),
+                    new Intent(this, CompanionDeviceActivity.class),
                     PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT
                             | PendingIntent.FLAG_IMMUTABLE));
         } catch (RemoteException e) {
@@ -311,13 +303,13 @@
     private void onDeviceLost(@Nullable DeviceFilterPair device) {
         Log.i(LOG_TAG, "Lost device " + device.getDisplayName());
         Handler.getMain().sendMessage(obtainMessage(
-                DeviceDiscoveryService::onDeviceLostMainThread, this, device));
+                CompanionDeviceDiscoveryService::onDeviceLostMainThread, this, device));
     }
 
     @MainThread
     void onDeviceLostMainThread(@Nullable DeviceFilterPair device) {
         mDevicesFound.remove(device);
-        mDevicesAdapter.notifyDataSetChanged();
+        CompanionDeviceActivity.notifyDevicesChanged();
     }
 
     void onDeviceSelected(String callingPackage, String deviceAddress) {
@@ -331,81 +323,6 @@
         mServiceCallback.cancel(true);
     }
 
-    class DevicesAdapter extends BaseAdapter {
-        private Drawable BLUETOOTH_ICON = icon(android.R.drawable.stat_sys_data_bluetooth);
-        private Drawable WIFI_ICON = icon(com.android.internal.R.drawable.ic_wifi_signal_3);
-
-        private SparseArray<Integer> mColors = new SparseArray();
-
-        private Drawable icon(int drawableRes) {
-            Drawable icon = getResources().getDrawable(drawableRes, null);
-            icon.setTint(Color.DKGRAY);
-            return icon;
-        }
-
-        @Override
-        public View getView(
-                int position,
-                @Nullable View convertView,
-                @NonNull ViewGroup parent) {
-            TextView view = convertView instanceof TextView
-                    ? (TextView) convertView
-                    : newView();
-            bind(view, getItem(position));
-            return view;
-        }
-
-        private void bind(TextView textView, DeviceFilterPair device) {
-            textView.setText(device.getDisplayName());
-            textView.setBackgroundColor(
-                    device.equals(mSelectedDevice)
-                            ? getColor(android.R.attr.colorControlHighlight)
-                            : Color.TRANSPARENT);
-            textView.setCompoundDrawablesWithIntrinsicBounds(
-                    device.device instanceof android.net.wifi.ScanResult
-                        ? WIFI_ICON
-                        : BLUETOOTH_ICON,
-                    null, null, null);
-            textView.getCompoundDrawables()[0].setTint(getColor(android.R.attr.colorForeground));
-        }
-
-        private TextView newView() {
-            final TextView textView = new TextView(DeviceDiscoveryService.this);
-            textView.setTextColor(getColor(android.R.attr.colorForeground));
-            final int padding = DeviceChooserActivity.getPadding(getResources());
-            textView.setPadding(padding, padding, padding, padding);
-            textView.setCompoundDrawablePadding(padding);
-            return textView;
-        }
-
-        private int getColor(int colorAttr) {
-            if (mColors.contains(colorAttr)) {
-                return mColors.get(colorAttr);
-            }
-            TypedValue typedValue = new TypedValue();
-            TypedArray a = obtainStyledAttributes(typedValue.data, new int[] { colorAttr });
-            int result = a.getColor(0, 0);
-            a.recycle();
-            mColors.put(colorAttr, result);
-            return result;
-        }
-
-        @Override
-        public int getCount() {
-            return mDevicesFound.size();
-        }
-
-        @Override
-        public DeviceFilterPair getItem(int position) {
-            return mDevicesFound.get(position);
-        }
-
-        @Override
-        public long getItemId(int position) {
-            return position;
-        }
-    }
-
     /**
      * A pair of device and a filter that matched this device if any.
      *
diff --git a/packages/Connectivity/framework/Android.bp b/packages/Connectivity/framework/Android.bp
index 73e1511..86b85e83 100644
--- a/packages/Connectivity/framework/Android.bp
+++ b/packages/Connectivity/framework/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "framework-connectivity-internal-sources",
     srcs: [
@@ -48,4 +57,29 @@
         "//frameworks/base",
         "//packages/modules/Connectivity:__subpackages__",
     ],
-}
\ No newline at end of file
+}
+
+java_sdk_library {
+    name: "framework-connectivity",
+    api_only: true,
+    defaults: ["framework-module-defaults"],
+    // TODO: build against module API
+    platform_apis: true,
+    srcs: [
+        ":framework-connectivity-sources",
+    ],
+    aidl: {
+        include_dirs: [
+            // Include directories for parcelables that are part of the stable API, and need a
+            // one-line "parcelable X" .aidl declaration to be used in AIDL interfaces.
+            // TODO(b/180293679): remove these dependencies as they should not be necessary once
+            // the module builds against API (the parcelable declarations exist in framework.aidl)
+            "frameworks/base/core/java", // For framework parcelables
+            "frameworks/native/aidl/binder", // For PersistableBundle.aidl
+        ],
+    },
+    libs: [
+        "unsupportedappusage",
+    ],
+    permitted_packages: ["android.net", "com.android.connectivity.aidl"],
+}
diff --git a/packages/Connectivity/framework/api/current.txt b/packages/Connectivity/framework/api/current.txt
new file mode 100644
index 0000000..31b8fc8
--- /dev/null
+++ b/packages/Connectivity/framework/api/current.txt
@@ -0,0 +1,470 @@
+// Signature format: 2.0
+package android.net {
+
+  public class CaptivePortal implements android.os.Parcelable {
+    method public int describeContents();
+    method public void ignoreNetwork();
+    method public void reportCaptivePortalDismissed();
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.CaptivePortal> CREATOR;
+  }
+
+  public class ConnectivityDiagnosticsManager {
+    method public void registerConnectivityDiagnosticsCallback(@NonNull android.net.NetworkRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback);
+    method public void unregisterConnectivityDiagnosticsCallback(@NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback);
+  }
+
+  public abstract static class ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback {
+    ctor public ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback();
+    method public void onConnectivityReportAvailable(@NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityReport);
+    method public void onDataStallSuspected(@NonNull android.net.ConnectivityDiagnosticsManager.DataStallReport);
+    method public void onNetworkConnectivityReported(@NonNull android.net.Network, boolean);
+  }
+
+  public static final class ConnectivityDiagnosticsManager.ConnectivityReport implements android.os.Parcelable {
+    ctor public ConnectivityDiagnosticsManager.ConnectivityReport(@NonNull android.net.Network, long, @NonNull android.net.LinkProperties, @NonNull android.net.NetworkCapabilities, @NonNull android.os.PersistableBundle);
+    method public int describeContents();
+    method @NonNull public android.os.PersistableBundle getAdditionalInfo();
+    method @NonNull public android.net.LinkProperties getLinkProperties();
+    method @NonNull public android.net.Network getNetwork();
+    method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities();
+    method public long getReportTimestamp();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.ConnectivityDiagnosticsManager.ConnectivityReport> CREATOR;
+    field public static final String KEY_NETWORK_PROBES_ATTEMPTED_BITMASK = "networkProbesAttempted";
+    field public static final String KEY_NETWORK_PROBES_SUCCEEDED_BITMASK = "networkProbesSucceeded";
+    field public static final String KEY_NETWORK_VALIDATION_RESULT = "networkValidationResult";
+    field public static final int NETWORK_PROBE_DNS = 4; // 0x4
+    field public static final int NETWORK_PROBE_FALLBACK = 32; // 0x20
+    field public static final int NETWORK_PROBE_HTTP = 8; // 0x8
+    field public static final int NETWORK_PROBE_HTTPS = 16; // 0x10
+    field public static final int NETWORK_PROBE_PRIVATE_DNS = 64; // 0x40
+    field public static final int NETWORK_VALIDATION_RESULT_INVALID = 0; // 0x0
+    field public static final int NETWORK_VALIDATION_RESULT_PARTIALLY_VALID = 2; // 0x2
+    field public static final int NETWORK_VALIDATION_RESULT_SKIPPED = 3; // 0x3
+    field public static final int NETWORK_VALIDATION_RESULT_VALID = 1; // 0x1
+  }
+
+  public static final class ConnectivityDiagnosticsManager.DataStallReport implements android.os.Parcelable {
+    ctor public ConnectivityDiagnosticsManager.DataStallReport(@NonNull android.net.Network, long, int, @NonNull android.net.LinkProperties, @NonNull android.net.NetworkCapabilities, @NonNull android.os.PersistableBundle);
+    method public int describeContents();
+    method public int getDetectionMethod();
+    method @NonNull public android.net.LinkProperties getLinkProperties();
+    method @NonNull public android.net.Network getNetwork();
+    method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities();
+    method public long getReportTimestamp();
+    method @NonNull public android.os.PersistableBundle getStallDetails();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.ConnectivityDiagnosticsManager.DataStallReport> CREATOR;
+    field public static final int DETECTION_METHOD_DNS_EVENTS = 1; // 0x1
+    field public static final int DETECTION_METHOD_TCP_METRICS = 2; // 0x2
+    field public static final String KEY_DNS_CONSECUTIVE_TIMEOUTS = "dnsConsecutiveTimeouts";
+    field public static final String KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS = "tcpMetricsCollectionPeriodMillis";
+    field public static final String KEY_TCP_PACKET_FAIL_RATE = "tcpPacketFailRate";
+  }
+
+  public class ConnectivityManager {
+    method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
+    method public boolean bindProcessToNetwork(@Nullable android.net.Network);
+    method @NonNull public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull android.net.IpSecManager.UdpEncapsulationSocket, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
+    method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network getActiveNetwork();
+    method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getActiveNetworkInfo();
+    method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo[] getAllNetworkInfo();
+    method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network[] getAllNetworks();
+    method @Deprecated public boolean getBackgroundDataSetting();
+    method @Nullable public android.net.Network getBoundNetworkForProcess();
+    method public int getConnectionOwnerUid(int, @NonNull java.net.InetSocketAddress, @NonNull java.net.InetSocketAddress);
+    method @Nullable public android.net.ProxyInfo getDefaultProxy();
+    method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.LinkProperties getLinkProperties(@Nullable android.net.Network);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public int getMultipathPreference(@Nullable android.net.Network);
+    method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkCapabilities getNetworkCapabilities(@Nullable android.net.Network);
+    method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getNetworkInfo(int);
+    method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getNetworkInfo(@Nullable android.net.Network);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public int getNetworkPreference();
+    method @Nullable public byte[] getNetworkWatchlistConfigHash();
+    method @Deprecated @Nullable public static android.net.Network getProcessDefaultNetwork();
+    method public int getRestrictBackgroundStatus();
+    method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public boolean isActiveNetworkMetered();
+    method public boolean isDefaultNetworkActive();
+    method @Deprecated public static boolean isNetworkTypeValid(int);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.app.PendingIntent);
+    method public void releaseNetworkRequest(@NonNull android.app.PendingIntent);
+    method public void removeDefaultNetworkActiveListener(@NonNull android.net.ConnectivityManager.OnNetworkActiveListener);
+    method @Deprecated public void reportBadNetwork(@Nullable android.net.Network);
+    method public void reportNetworkConnectivity(@Nullable android.net.Network, boolean);
+    method public boolean requestBandwidthUpdate(@NonNull android.net.Network);
+    method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback);
+    method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
+    method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, int);
+    method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler, int);
+    method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.app.PendingIntent);
+    method @Deprecated public void setNetworkPreference(int);
+    method @Deprecated public static boolean setProcessDefaultNetwork(@Nullable android.net.Network);
+    method public void unregisterNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback);
+    method public void unregisterNetworkCallback(@NonNull android.app.PendingIntent);
+    field @Deprecated public static final String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
+    field public static final String ACTION_CAPTIVE_PORTAL_SIGN_IN = "android.net.conn.CAPTIVE_PORTAL";
+    field public static final String ACTION_RESTRICT_BACKGROUND_CHANGED = "android.net.conn.RESTRICT_BACKGROUND_CHANGED";
+    field @Deprecated public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
+    field @Deprecated public static final int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1
+    field public static final String EXTRA_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL";
+    field public static final String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL";
+    field @Deprecated public static final String EXTRA_EXTRA_INFO = "extraInfo";
+    field @Deprecated public static final String EXTRA_IS_FAILOVER = "isFailover";
+    field public static final String EXTRA_NETWORK = "android.net.extra.NETWORK";
+    field @Deprecated public static final String EXTRA_NETWORK_INFO = "networkInfo";
+    field public static final String EXTRA_NETWORK_REQUEST = "android.net.extra.NETWORK_REQUEST";
+    field @Deprecated public static final String EXTRA_NETWORK_TYPE = "networkType";
+    field public static final String EXTRA_NO_CONNECTIVITY = "noConnectivity";
+    field @Deprecated public static final String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
+    field public static final String EXTRA_REASON = "reason";
+    field public static final int MULTIPATH_PREFERENCE_HANDOVER = 1; // 0x1
+    field public static final int MULTIPATH_PREFERENCE_PERFORMANCE = 4; // 0x4
+    field public static final int MULTIPATH_PREFERENCE_RELIABILITY = 2; // 0x2
+    field public static final int RESTRICT_BACKGROUND_STATUS_DISABLED = 1; // 0x1
+    field public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3; // 0x3
+    field public static final int RESTRICT_BACKGROUND_STATUS_WHITELISTED = 2; // 0x2
+    field @Deprecated public static final int TYPE_BLUETOOTH = 7; // 0x7
+    field @Deprecated public static final int TYPE_DUMMY = 8; // 0x8
+    field @Deprecated public static final int TYPE_ETHERNET = 9; // 0x9
+    field @Deprecated public static final int TYPE_MOBILE = 0; // 0x0
+    field @Deprecated public static final int TYPE_MOBILE_DUN = 4; // 0x4
+    field @Deprecated public static final int TYPE_MOBILE_HIPRI = 5; // 0x5
+    field @Deprecated public static final int TYPE_MOBILE_MMS = 2; // 0x2
+    field @Deprecated public static final int TYPE_MOBILE_SUPL = 3; // 0x3
+    field @Deprecated public static final int TYPE_VPN = 17; // 0x11
+    field @Deprecated public static final int TYPE_WIFI = 1; // 0x1
+    field @Deprecated public static final int TYPE_WIMAX = 6; // 0x6
+  }
+
+  public static class ConnectivityManager.NetworkCallback {
+    ctor public ConnectivityManager.NetworkCallback();
+    method public void onAvailable(@NonNull android.net.Network);
+    method public void onBlockedStatusChanged(@NonNull android.net.Network, boolean);
+    method public void onCapabilitiesChanged(@NonNull android.net.Network, @NonNull android.net.NetworkCapabilities);
+    method public void onLinkPropertiesChanged(@NonNull android.net.Network, @NonNull android.net.LinkProperties);
+    method public void onLosing(@NonNull android.net.Network, int);
+    method public void onLost(@NonNull android.net.Network);
+    method public void onUnavailable();
+  }
+
+  public static interface ConnectivityManager.OnNetworkActiveListener {
+    method public void onNetworkActive();
+  }
+
+  public class DhcpInfo implements android.os.Parcelable {
+    ctor public DhcpInfo();
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.DhcpInfo> CREATOR;
+    field public int dns1;
+    field public int dns2;
+    field public int gateway;
+    field public int ipAddress;
+    field public int leaseDuration;
+    field public int netmask;
+    field public int serverAddress;
+  }
+
+  public final class DnsResolver {
+    method @NonNull public static android.net.DnsResolver getInstance();
+    method public void query(@Nullable android.net.Network, @NonNull String, int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback<? super java.util.List<java.net.InetAddress>>);
+    method public void query(@Nullable android.net.Network, @NonNull String, int, int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback<? super java.util.List<java.net.InetAddress>>);
+    method public void rawQuery(@Nullable android.net.Network, @NonNull byte[], int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback<? super byte[]>);
+    method public void rawQuery(@Nullable android.net.Network, @NonNull String, int, int, int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback<? super byte[]>);
+    field public static final int CLASS_IN = 1; // 0x1
+    field public static final int ERROR_PARSE = 0; // 0x0
+    field public static final int ERROR_SYSTEM = 1; // 0x1
+    field public static final int FLAG_EMPTY = 0; // 0x0
+    field public static final int FLAG_NO_CACHE_LOOKUP = 4; // 0x4
+    field public static final int FLAG_NO_CACHE_STORE = 2; // 0x2
+    field public static final int FLAG_NO_RETRY = 1; // 0x1
+    field public static final int TYPE_A = 1; // 0x1
+    field public static final int TYPE_AAAA = 28; // 0x1c
+  }
+
+  public static interface DnsResolver.Callback<T> {
+    method public void onAnswer(@NonNull T, int);
+    method public void onError(@NonNull android.net.DnsResolver.DnsException);
+  }
+
+  public static class DnsResolver.DnsException extends java.lang.Exception {
+    field public final int code;
+  }
+
+  public class InetAddresses {
+    method public static boolean isNumericAddress(@NonNull String);
+    method @NonNull public static java.net.InetAddress parseNumericAddress(@NonNull String);
+  }
+
+  public final class IpPrefix implements android.os.Parcelable {
+    method public boolean contains(@NonNull java.net.InetAddress);
+    method public int describeContents();
+    method @NonNull public java.net.InetAddress getAddress();
+    method @IntRange(from=0, to=128) public int getPrefixLength();
+    method @NonNull public byte[] getRawAddress();
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.IpPrefix> CREATOR;
+  }
+
+  public class LinkAddress implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.net.InetAddress getAddress();
+    method public int getFlags();
+    method @IntRange(from=0, to=128) public int getPrefixLength();
+    method public int getScope();
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.LinkAddress> CREATOR;
+  }
+
+  public final class LinkProperties implements android.os.Parcelable {
+    ctor public LinkProperties();
+    method public boolean addRoute(@NonNull android.net.RouteInfo);
+    method public void clear();
+    method public int describeContents();
+    method @Nullable public java.net.Inet4Address getDhcpServerAddress();
+    method @NonNull public java.util.List<java.net.InetAddress> getDnsServers();
+    method @Nullable public String getDomains();
+    method @Nullable public android.net.ProxyInfo getHttpProxy();
+    method @Nullable public String getInterfaceName();
+    method @NonNull public java.util.List<android.net.LinkAddress> getLinkAddresses();
+    method public int getMtu();
+    method @Nullable public android.net.IpPrefix getNat64Prefix();
+    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 setDhcpServerAddress(@Nullable java.net.Inet4Address);
+    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);
+    method public void setInterfaceName(@Nullable String);
+    method public void setLinkAddresses(@NonNull java.util.Collection<android.net.LinkAddress>);
+    method public void setMtu(int);
+    method public void setNat64Prefix(@Nullable android.net.IpPrefix);
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.LinkProperties> CREATOR;
+  }
+
+  public final class MacAddress implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public static android.net.MacAddress fromBytes(@NonNull byte[]);
+    method @NonNull public static android.net.MacAddress fromString(@NonNull String);
+    method public int getAddressType();
+    method @Nullable public java.net.Inet6Address getLinkLocalIpv6FromEui48Mac();
+    method public boolean isLocallyAssigned();
+    method public boolean matches(@NonNull android.net.MacAddress, @NonNull android.net.MacAddress);
+    method @NonNull public byte[] toByteArray();
+    method @NonNull public String toOuiString();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.net.MacAddress BROADCAST_ADDRESS;
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.MacAddress> CREATOR;
+    field public static final int TYPE_BROADCAST = 3; // 0x3
+    field public static final int TYPE_MULTICAST = 2; // 0x2
+    field public static final int TYPE_UNICAST = 1; // 0x1
+  }
+
+  public class Network implements android.os.Parcelable {
+    method public void bindSocket(java.net.DatagramSocket) throws java.io.IOException;
+    method public void bindSocket(java.net.Socket) throws java.io.IOException;
+    method public void bindSocket(java.io.FileDescriptor) throws java.io.IOException;
+    method public int describeContents();
+    method public static android.net.Network fromNetworkHandle(long);
+    method public java.net.InetAddress[] getAllByName(String) throws java.net.UnknownHostException;
+    method public java.net.InetAddress getByName(String) throws java.net.UnknownHostException;
+    method public long getNetworkHandle();
+    method public javax.net.SocketFactory getSocketFactory();
+    method public java.net.URLConnection openConnection(java.net.URL) throws java.io.IOException;
+    method public java.net.URLConnection openConnection(java.net.URL, java.net.Proxy) throws java.io.IOException;
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.Network> CREATOR;
+  }
+
+  public final class NetworkCapabilities implements android.os.Parcelable {
+    ctor public NetworkCapabilities();
+    ctor public NetworkCapabilities(android.net.NetworkCapabilities);
+    method public int describeContents();
+    method public int getLinkDownstreamBandwidthKbps();
+    method public int getLinkUpstreamBandwidthKbps();
+    method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier();
+    method public int getOwnerUid();
+    method public int getSignalStrength();
+    method @Nullable public android.net.TransportInfo getTransportInfo();
+    method public boolean hasCapability(int);
+    method public boolean hasTransport(int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkCapabilities> CREATOR;
+    field public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17; // 0x11
+    field public static final int NET_CAPABILITY_CBS = 5; // 0x5
+    field public static final int NET_CAPABILITY_DUN = 2; // 0x2
+    field public static final int NET_CAPABILITY_EIMS = 10; // 0xa
+    field public static final int NET_CAPABILITY_ENTERPRISE = 29; // 0x1d
+    field public static final int NET_CAPABILITY_FOREGROUND = 19; // 0x13
+    field public static final int NET_CAPABILITY_FOTA = 3; // 0x3
+    field public static final int NET_CAPABILITY_IA = 7; // 0x7
+    field public static final int NET_CAPABILITY_IMS = 4; // 0x4
+    field public static final int NET_CAPABILITY_INTERNET = 12; // 0xc
+    field public static final int NET_CAPABILITY_MCX = 23; // 0x17
+    field public static final int NET_CAPABILITY_MMS = 0; // 0x0
+    field public static final int NET_CAPABILITY_NOT_CONGESTED = 20; // 0x14
+    field public static final int NET_CAPABILITY_NOT_METERED = 11; // 0xb
+    field public static final int NET_CAPABILITY_NOT_RESTRICTED = 13; // 0xd
+    field public static final int NET_CAPABILITY_NOT_ROAMING = 18; // 0x12
+    field public static final int NET_CAPABILITY_NOT_SUSPENDED = 21; // 0x15
+    field public static final int NET_CAPABILITY_NOT_VPN = 15; // 0xf
+    field public static final int NET_CAPABILITY_RCS = 8; // 0x8
+    field public static final int NET_CAPABILITY_SUPL = 1; // 0x1
+    field public static final int NET_CAPABILITY_TEMPORARILY_NOT_METERED = 25; // 0x19
+    field public static final int NET_CAPABILITY_TRUSTED = 14; // 0xe
+    field public static final int NET_CAPABILITY_VALIDATED = 16; // 0x10
+    field public static final int NET_CAPABILITY_WIFI_P2P = 6; // 0x6
+    field public static final int NET_CAPABILITY_XCAP = 9; // 0x9
+    field public static final int SIGNAL_STRENGTH_UNSPECIFIED = -2147483648; // 0x80000000
+    field public static final int TRANSPORT_BLUETOOTH = 2; // 0x2
+    field public static final int TRANSPORT_CELLULAR = 0; // 0x0
+    field public static final int TRANSPORT_ETHERNET = 3; // 0x3
+    field public static final int TRANSPORT_LOWPAN = 6; // 0x6
+    field public static final int TRANSPORT_VPN = 4; // 0x4
+    field public static final int TRANSPORT_WIFI = 1; // 0x1
+    field public static final int TRANSPORT_WIFI_AWARE = 5; // 0x5
+  }
+
+  @Deprecated public class NetworkInfo implements android.os.Parcelable {
+    ctor @Deprecated public NetworkInfo(int, int, @Nullable String, @Nullable String);
+    method @Deprecated public int describeContents();
+    method @Deprecated @NonNull public android.net.NetworkInfo.DetailedState getDetailedState();
+    method @Deprecated public String getExtraInfo();
+    method @Deprecated public String getReason();
+    method @Deprecated public android.net.NetworkInfo.State getState();
+    method @Deprecated public int getSubtype();
+    method @Deprecated public String getSubtypeName();
+    method @Deprecated public int getType();
+    method @Deprecated public String getTypeName();
+    method @Deprecated public boolean isAvailable();
+    method @Deprecated public boolean isConnected();
+    method @Deprecated public boolean isConnectedOrConnecting();
+    method @Deprecated public boolean isFailover();
+    method @Deprecated public boolean isRoaming();
+    method @Deprecated public void setDetailedState(@NonNull android.net.NetworkInfo.DetailedState, @Nullable String, @Nullable String);
+    method @Deprecated public void writeToParcel(android.os.Parcel, int);
+    field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkInfo> CREATOR;
+  }
+
+  @Deprecated public enum NetworkInfo.DetailedState {
+    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState AUTHENTICATING;
+    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState BLOCKED;
+    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState CAPTIVE_PORTAL_CHECK;
+    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState CONNECTED;
+    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState CONNECTING;
+    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState DISCONNECTED;
+    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState DISCONNECTING;
+    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState FAILED;
+    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState IDLE;
+    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState OBTAINING_IPADDR;
+    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState SCANNING;
+    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState SUSPENDED;
+    enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState VERIFYING_POOR_LINK;
+  }
+
+  @Deprecated public enum NetworkInfo.State {
+    enum_constant @Deprecated public static final android.net.NetworkInfo.State CONNECTED;
+    enum_constant @Deprecated public static final android.net.NetworkInfo.State CONNECTING;
+    enum_constant @Deprecated public static final android.net.NetworkInfo.State DISCONNECTED;
+    enum_constant @Deprecated public static final android.net.NetworkInfo.State DISCONNECTING;
+    enum_constant @Deprecated public static final android.net.NetworkInfo.State SUSPENDED;
+    enum_constant @Deprecated public static final android.net.NetworkInfo.State UNKNOWN;
+  }
+
+  public class NetworkRequest implements android.os.Parcelable {
+    method public boolean canBeSatisfiedBy(@Nullable android.net.NetworkCapabilities);
+    method public int describeContents();
+    method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier();
+    method public boolean hasCapability(int);
+    method public boolean hasTransport(int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkRequest> CREATOR;
+  }
+
+  public static class NetworkRequest.Builder {
+    ctor public NetworkRequest.Builder();
+    method public android.net.NetworkRequest.Builder addCapability(int);
+    method public android.net.NetworkRequest.Builder addTransportType(int);
+    method public android.net.NetworkRequest build();
+    method @NonNull public android.net.NetworkRequest.Builder clearCapabilities();
+    method public android.net.NetworkRequest.Builder removeCapability(int);
+    method public android.net.NetworkRequest.Builder removeTransportType(int);
+    method @Deprecated public android.net.NetworkRequest.Builder setNetworkSpecifier(String);
+    method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier);
+  }
+
+  public final class Proxy {
+    ctor public Proxy();
+    method @Deprecated public static String getDefaultHost();
+    method @Deprecated public static int getDefaultPort();
+    method @Deprecated public static String getHost(android.content.Context);
+    method @Deprecated public static int getPort(android.content.Context);
+    field @Deprecated public static final String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO";
+    field public static final String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE";
+  }
+
+  public class ProxyInfo implements android.os.Parcelable {
+    ctor public ProxyInfo(@Nullable android.net.ProxyInfo);
+    method public static android.net.ProxyInfo buildDirectProxy(String, int);
+    method public static android.net.ProxyInfo buildDirectProxy(String, int, java.util.List<java.lang.String>);
+    method public static android.net.ProxyInfo buildPacProxy(android.net.Uri);
+    method @NonNull public static android.net.ProxyInfo buildPacProxy(@NonNull android.net.Uri, int);
+    method public int describeContents();
+    method public String[] getExclusionList();
+    method public String getHost();
+    method public android.net.Uri getPacFileUrl();
+    method public int getPort();
+    method public boolean isValid();
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.ProxyInfo> CREATOR;
+  }
+
+  public final class RouteInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public android.net.IpPrefix getDestination();
+    method @Nullable public java.net.InetAddress getGateway();
+    method @Nullable public String getInterface();
+    method public boolean hasGateway();
+    method public boolean isDefaultRoute();
+    method public boolean matches(java.net.InetAddress);
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.RouteInfo> CREATOR;
+  }
+
+  public abstract class SocketKeepalive implements java.lang.AutoCloseable {
+    method public final void close();
+    method public final void start(@IntRange(from=0xa, to=0xe10) int);
+    method public final void stop();
+    field public static final int ERROR_HARDWARE_ERROR = -31; // 0xffffffe1
+    field public static final int ERROR_INSUFFICIENT_RESOURCES = -32; // 0xffffffe0
+    field public static final int ERROR_INVALID_INTERVAL = -24; // 0xffffffe8
+    field public static final int ERROR_INVALID_IP_ADDRESS = -21; // 0xffffffeb
+    field public static final int ERROR_INVALID_LENGTH = -23; // 0xffffffe9
+    field public static final int ERROR_INVALID_NETWORK = -20; // 0xffffffec
+    field public static final int ERROR_INVALID_PORT = -22; // 0xffffffea
+    field public static final int ERROR_INVALID_SOCKET = -25; // 0xffffffe7
+    field public static final int ERROR_SOCKET_NOT_IDLE = -26; // 0xffffffe6
+    field public static final int ERROR_UNSUPPORTED = -30; // 0xffffffe2
+  }
+
+  public static class SocketKeepalive.Callback {
+    ctor public SocketKeepalive.Callback();
+    method public void onDataReceived();
+    method public void onError(int);
+    method public void onStarted();
+    method public void onStopped();
+  }
+
+  public interface TransportInfo {
+  }
+
+}
+
diff --git a/packages/Connectivity/framework/api/lint-baseline.txt b/packages/Connectivity/framework/api/lint-baseline.txt
new file mode 100644
index 0000000..2f4004a
--- /dev/null
+++ b/packages/Connectivity/framework/api/lint-baseline.txt
@@ -0,0 +1,4 @@
+// Baseline format: 1.0
+VisiblySynchronized: android.net.NetworkInfo#toString():
+    Internal locks must not be exposed (synchronizing on this or class is still
+    externally observable): method android.net.NetworkInfo.toString()
diff --git a/packages/Connectivity/framework/api/module-lib-current.txt b/packages/Connectivity/framework/api/module-lib-current.txt
new file mode 100644
index 0000000..3af855e
--- /dev/null
+++ b/packages/Connectivity/framework/api/module-lib-current.txt
@@ -0,0 +1,66 @@
+// Signature format: 2.0
+package android.net {
+
+  public final class ConnectivityFrameworkInitializer {
+    method public static void registerServiceWrappers();
+  }
+
+  public class ConnectivityManager {
+    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @Nullable android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback);
+    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle);
+  }
+
+  public final class NetworkAgentConfig implements android.os.Parcelable {
+    method @Nullable public String getSubscriberId();
+  }
+
+  public static final class NetworkAgentConfig.Builder {
+    method @NonNull public android.net.NetworkAgentConfig.Builder setSubscriberId(@Nullable String);
+  }
+
+  public final class NetworkCapabilities implements android.os.Parcelable {
+    field public static final int TRANSPORT_TEST = 7; // 0x7
+  }
+
+  public final class Proxy {
+    method public static void setHttpProxyConfiguration(@Nullable android.net.ProxyInfo);
+  }
+
+  public final class TcpRepairWindow {
+    ctor public TcpRepairWindow(int, int, int, int, int, int);
+    field public final int maxWindow;
+    field public final int rcvWnd;
+    field public final int rcvWndScale;
+    field public final int rcvWup;
+    field public final int sndWl1;
+    field public final int sndWnd;
+  }
+
+  public final class TestNetworkInterface implements android.os.Parcelable {
+    ctor public TestNetworkInterface(@NonNull android.os.ParcelFileDescriptor, @NonNull String);
+    method public int describeContents();
+    method @NonNull public android.os.ParcelFileDescriptor getFileDescriptor();
+    method @NonNull public String getInterfaceName();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.TestNetworkInterface> CREATOR;
+  }
+
+  public class TestNetworkManager {
+    method @NonNull public android.net.TestNetworkInterface createTapInterface();
+    method @NonNull public android.net.TestNetworkInterface createTunInterface(@NonNull java.util.Collection<android.net.LinkAddress>);
+    method public void setupTestNetwork(@NonNull String, @NonNull android.os.IBinder);
+    method public void teardownTestNetwork(@NonNull android.net.Network);
+    field public static final String TEST_TAP_PREFIX = "testtap";
+  }
+
+  public final class VpnTransportInfo implements android.os.Parcelable android.net.TransportInfo {
+    ctor public VpnTransportInfo(int);
+    method public int describeContents();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.VpnTransportInfo> CREATOR;
+    field public final int type;
+  }
+
+}
+
diff --git a/packages/Connectivity/framework/api/module-lib-removed.txt b/packages/Connectivity/framework/api/module-lib-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/packages/Connectivity/framework/api/module-lib-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/packages/Connectivity/framework/api/removed.txt b/packages/Connectivity/framework/api/removed.txt
new file mode 100644
index 0000000..303a1e61
--- /dev/null
+++ b/packages/Connectivity/framework/api/removed.txt
@@ -0,0 +1,11 @@
+// Signature format: 2.0
+package android.net {
+
+  public class ConnectivityManager {
+    method @Deprecated public boolean requestRouteToHost(int, int);
+    method @Deprecated public int startUsingNetworkFeature(int, String);
+    method @Deprecated public int stopUsingNetworkFeature(int, String);
+  }
+
+}
+
diff --git a/packages/Connectivity/framework/api/system-current.txt b/packages/Connectivity/framework/api/system-current.txt
new file mode 100644
index 0000000..41ebc57
--- /dev/null
+++ b/packages/Connectivity/framework/api/system-current.txt
@@ -0,0 +1,407 @@
+// Signature format: 2.0
+package android.net {
+
+  public class CaptivePortal implements android.os.Parcelable {
+    method public void logEvent(int, @NonNull String);
+    method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void reevaluateNetwork();
+    method public void useNetwork();
+    field public static final int APP_REQUEST_REEVALUATION_REQUIRED = 100; // 0x64
+    field public static final int APP_RETURN_DISMISSED = 0; // 0x0
+    field public static final int APP_RETURN_UNWANTED = 1; // 0x1
+    field public static final int APP_RETURN_WANTED_AS_IS = 2; // 0x2
+  }
+
+  public final class CaptivePortalData implements android.os.Parcelable {
+    method public int describeContents();
+    method public long getByteLimit();
+    method public long getExpiryTimeMillis();
+    method public long getRefreshTimeMillis();
+    method @Nullable public android.net.Uri getUserPortalUrl();
+    method public int getUserPortalUrlSource();
+    method @Nullable public String getVenueFriendlyName();
+    method @Nullable public android.net.Uri getVenueInfoUrl();
+    method public int getVenueInfoUrlSource();
+    method public boolean isCaptive();
+    method public boolean isSessionExtendable();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field public static final int CAPTIVE_PORTAL_DATA_SOURCE_OTHER = 0; // 0x0
+    field public static final int CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT = 1; // 0x1
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.CaptivePortalData> CREATOR;
+  }
+
+  public static class CaptivePortalData.Builder {
+    ctor public CaptivePortalData.Builder();
+    ctor public CaptivePortalData.Builder(@Nullable android.net.CaptivePortalData);
+    method @NonNull public android.net.CaptivePortalData build();
+    method @NonNull public android.net.CaptivePortalData.Builder setBytesRemaining(long);
+    method @NonNull public android.net.CaptivePortalData.Builder setCaptive(boolean);
+    method @NonNull public android.net.CaptivePortalData.Builder setExpiryTime(long);
+    method @NonNull public android.net.CaptivePortalData.Builder setRefreshTime(long);
+    method @NonNull public android.net.CaptivePortalData.Builder setSessionExtendable(boolean);
+    method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri);
+    method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri, int);
+    method @NonNull public android.net.CaptivePortalData.Builder setVenueFriendlyName(@Nullable String);
+    method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri);
+    method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri, int);
+  }
+
+  public class ConnectivityManager {
+    method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createNattKeepalive(@NonNull android.net.Network, @NonNull android.os.ParcelFileDescriptor, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
+    method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull java.net.Socket, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public String getCaptivePortalServerUrl();
+    method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEntitlementResultListener);
+    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported();
+    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_FACTORY}) public int registerNetworkProvider(@NonNull android.net.NetworkProvider);
+    method public void registerQosCallback(@NonNull android.net.QosSocketInfo, @NonNull android.net.QosCallback, @NonNull java.util.concurrent.Executor);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
+    method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void requestNetwork(@NonNull android.net.NetworkRequest, int, int, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback);
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_AIRPLANE_MODE, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void setAirplaneMode(boolean);
+    method @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) public void setOemNetworkPreference(@NonNull android.net.OemNetworkPreferences, @Nullable java.util.concurrent.Executor, @Nullable android.net.ConnectivityManager.OnSetOemNetworkPreferenceListener);
+    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public boolean shouldAvoidBadWifi();
+    method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopTethering(int);
+    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_FACTORY}) public void unregisterNetworkProvider(@NonNull android.net.NetworkProvider);
+    method public void unregisterQosCallback(@NonNull android.net.QosCallback);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void unregisterTetheringEventCallback(@NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
+    field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC";
+    field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT";
+    field public static final int TETHERING_BLUETOOTH = 2; // 0x2
+    field public static final int TETHERING_USB = 1; // 0x1
+    field public static final int TETHERING_WIFI = 0; // 0x0
+    field @Deprecated public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13; // 0xd
+    field @Deprecated public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0
+    field @Deprecated public static final int TETHER_ERROR_PROVISION_FAILED = 11; // 0xb
+    field public static final int TYPE_NONE = -1; // 0xffffffff
+    field @Deprecated public static final int TYPE_PROXY = 16; // 0x10
+    field @Deprecated public static final int TYPE_WIFI_P2P = 13; // 0xd
+  }
+
+  public static interface ConnectivityManager.OnSetOemNetworkPreferenceListener {
+    method public void onComplete();
+  }
+
+  @Deprecated public abstract static class ConnectivityManager.OnStartTetheringCallback {
+    ctor @Deprecated public ConnectivityManager.OnStartTetheringCallback();
+    method @Deprecated public void onTetheringFailed();
+    method @Deprecated public void onTetheringStarted();
+  }
+
+  @Deprecated public static interface ConnectivityManager.OnTetheringEntitlementResultListener {
+    method @Deprecated public void onTetheringEntitlementResult(int);
+  }
+
+  @Deprecated public abstract static class ConnectivityManager.OnTetheringEventCallback {
+    ctor @Deprecated public ConnectivityManager.OnTetheringEventCallback();
+    method @Deprecated public void onUpstreamChanged(@Nullable android.net.Network);
+  }
+
+  public final class InvalidPacketException extends java.lang.Exception {
+    ctor public InvalidPacketException(int);
+    method public int getError();
+    field public static final int ERROR_INVALID_IP_ADDRESS = -21; // 0xffffffeb
+    field public static final int ERROR_INVALID_LENGTH = -23; // 0xffffffe9
+    field public static final int ERROR_INVALID_PORT = -22; // 0xffffffea
+  }
+
+  public final class IpConfiguration implements android.os.Parcelable {
+    ctor public IpConfiguration();
+    ctor public IpConfiguration(@NonNull android.net.IpConfiguration);
+    method public int describeContents();
+    method @Nullable public android.net.ProxyInfo getHttpProxy();
+    method @NonNull public android.net.IpConfiguration.IpAssignment getIpAssignment();
+    method @NonNull public android.net.IpConfiguration.ProxySettings getProxySettings();
+    method @Nullable public android.net.StaticIpConfiguration getStaticIpConfiguration();
+    method public void setHttpProxy(@Nullable android.net.ProxyInfo);
+    method public void setIpAssignment(@NonNull android.net.IpConfiguration.IpAssignment);
+    method public void setProxySettings(@NonNull android.net.IpConfiguration.ProxySettings);
+    method public void setStaticIpConfiguration(@Nullable android.net.StaticIpConfiguration);
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.IpConfiguration> CREATOR;
+  }
+
+  public enum IpConfiguration.IpAssignment {
+    enum_constant public static final android.net.IpConfiguration.IpAssignment DHCP;
+    enum_constant public static final android.net.IpConfiguration.IpAssignment STATIC;
+    enum_constant public static final android.net.IpConfiguration.IpAssignment UNASSIGNED;
+  }
+
+  public enum IpConfiguration.ProxySettings {
+    enum_constant public static final android.net.IpConfiguration.ProxySettings NONE;
+    enum_constant public static final android.net.IpConfiguration.ProxySettings PAC;
+    enum_constant public static final android.net.IpConfiguration.ProxySettings STATIC;
+    enum_constant public static final android.net.IpConfiguration.ProxySettings UNASSIGNED;
+  }
+
+  public final class IpPrefix implements android.os.Parcelable {
+    ctor public IpPrefix(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int);
+    ctor public IpPrefix(@NonNull String);
+  }
+
+  public class KeepalivePacketData {
+    ctor protected KeepalivePacketData(@NonNull java.net.InetAddress, @IntRange(from=0, to=65535) int, @NonNull java.net.InetAddress, @IntRange(from=0, to=65535) int, @NonNull byte[]) throws android.net.InvalidPacketException;
+    method @NonNull public java.net.InetAddress getDstAddress();
+    method public int getDstPort();
+    method @NonNull public byte[] getPacket();
+    method @NonNull public java.net.InetAddress getSrcAddress();
+    method public int getSrcPort();
+  }
+
+  public class LinkAddress implements android.os.Parcelable {
+    ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int);
+    ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int, long, long);
+    ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int);
+    ctor public LinkAddress(@NonNull String);
+    ctor public LinkAddress(@NonNull String, int, int);
+    method public long getDeprecationTime();
+    method public long getExpirationTime();
+    method public boolean isGlobalPreferred();
+    method public boolean isIpv4();
+    method public boolean isIpv6();
+    method public boolean isSameAddressAs(@Nullable android.net.LinkAddress);
+    field public static final long LIFETIME_PERMANENT = 9223372036854775807L; // 0x7fffffffffffffffL
+    field public static final long LIFETIME_UNKNOWN = -1L; // 0xffffffffffffffffL
+  }
+
+  public final class LinkProperties implements android.os.Parcelable {
+    ctor public LinkProperties(@Nullable android.net.LinkProperties);
+    ctor public LinkProperties(@Nullable android.net.LinkProperties, boolean);
+    method public boolean addDnsServer(@NonNull java.net.InetAddress);
+    method public boolean addLinkAddress(@NonNull android.net.LinkAddress);
+    method public boolean addPcscfServer(@NonNull java.net.InetAddress);
+    method @NonNull public java.util.List<java.net.InetAddress> getAddresses();
+    method @NonNull public java.util.List<java.lang.String> getAllInterfaceNames();
+    method @NonNull public java.util.List<android.net.LinkAddress> getAllLinkAddresses();
+    method @NonNull public java.util.List<android.net.RouteInfo> getAllRoutes();
+    method @Nullable public android.net.Uri getCaptivePortalApiUrl();
+    method @Nullable public android.net.CaptivePortalData getCaptivePortalData();
+    method @NonNull public java.util.List<java.net.InetAddress> getPcscfServers();
+    method @Nullable public String getTcpBufferSizes();
+    method @NonNull public java.util.List<java.net.InetAddress> getValidatedPrivateDnsServers();
+    method public boolean hasGlobalIpv6Address();
+    method public boolean hasIpv4Address();
+    method public boolean hasIpv4DefaultRoute();
+    method public boolean hasIpv4DnsServer();
+    method public boolean hasIpv6DefaultRoute();
+    method public boolean hasIpv6DnsServer();
+    method public boolean isIpv4Provisioned();
+    method public boolean isIpv6Provisioned();
+    method public boolean isProvisioned();
+    method public boolean isReachable(@NonNull java.net.InetAddress);
+    method public boolean removeDnsServer(@NonNull java.net.InetAddress);
+    method public boolean removeLinkAddress(@NonNull android.net.LinkAddress);
+    method public boolean removeRoute(@NonNull android.net.RouteInfo);
+    method public void setCaptivePortalApiUrl(@Nullable android.net.Uri);
+    method public void setCaptivePortalData(@Nullable android.net.CaptivePortalData);
+    method public void setPcscfServers(@NonNull java.util.Collection<java.net.InetAddress>);
+    method public void setPrivateDnsServerName(@Nullable String);
+    method public void setTcpBufferSizes(@Nullable String);
+    method public void setUsePrivateDns(boolean);
+    method public void setValidatedPrivateDnsServers(@NonNull java.util.Collection<java.net.InetAddress>);
+  }
+
+  public final class NattKeepalivePacketData extends android.net.KeepalivePacketData implements android.os.Parcelable {
+    ctor public NattKeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[]) throws android.net.InvalidPacketException;
+    method public int describeContents();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.NattKeepalivePacketData> CREATOR;
+  }
+
+  public class Network implements android.os.Parcelable {
+    ctor public Network(@NonNull android.net.Network);
+    method public int getNetId();
+    method @NonNull public android.net.Network getPrivateDnsBypassingCopy();
+  }
+
+  public abstract class NetworkAgent {
+    ctor public NetworkAgent(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String, @NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties, int, @NonNull android.net.NetworkAgentConfig, @Nullable android.net.NetworkProvider);
+    method @Nullable public android.net.Network getNetwork();
+    method public void markConnected();
+    method public void onAddKeepalivePacketFilter(int, @NonNull android.net.KeepalivePacketData);
+    method public void onAutomaticReconnectDisabled();
+    method public void onNetworkUnwanted();
+    method public void onQosCallbackRegistered(int, @NonNull android.net.QosFilter);
+    method public void onQosCallbackUnregistered(int);
+    method public void onRemoveKeepalivePacketFilter(int);
+    method public void onSaveAcceptUnvalidated(boolean);
+    method public void onSignalStrengthThresholdsUpdated(@NonNull int[]);
+    method public void onStartSocketKeepalive(int, @NonNull java.time.Duration, @NonNull android.net.KeepalivePacketData);
+    method public void onStopSocketKeepalive(int);
+    method public void onValidationStatus(int, @Nullable android.net.Uri);
+    method @NonNull public android.net.Network register();
+    method public final void sendLinkProperties(@NonNull android.net.LinkProperties);
+    method public final void sendNetworkCapabilities(@NonNull android.net.NetworkCapabilities);
+    method public final void sendNetworkScore(@IntRange(from=0, to=99) int);
+    method public final void sendQosCallbackError(int, int);
+    method public final void sendQosSessionAvailable(int, int, @NonNull android.telephony.data.EpsBearerQosSessionAttributes);
+    method public final void sendQosSessionLost(int, int);
+    method public final void sendSocketKeepaliveEvent(int, int);
+    method public final void setUnderlyingNetworks(@Nullable java.util.List<android.net.Network>);
+    method public void unregister();
+    field public static final int VALIDATION_STATUS_NOT_VALID = 2; // 0x2
+    field public static final int VALIDATION_STATUS_VALID = 1; // 0x1
+  }
+
+  public final class NetworkAgentConfig implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getLegacyType();
+    method @NonNull public String getLegacyTypeName();
+    method public boolean isExplicitlySelected();
+    method public boolean isPartialConnectivityAcceptable();
+    method public boolean isUnvalidatedConnectivityAcceptable();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkAgentConfig> CREATOR;
+  }
+
+  public static final class NetworkAgentConfig.Builder {
+    ctor public NetworkAgentConfig.Builder();
+    method @NonNull public android.net.NetworkAgentConfig build();
+    method @NonNull public android.net.NetworkAgentConfig.Builder setExplicitlySelected(boolean);
+    method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyType(int);
+    method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyTypeName(@NonNull String);
+    method @NonNull public android.net.NetworkAgentConfig.Builder setPartialConnectivityAcceptable(boolean);
+    method @NonNull public android.net.NetworkAgentConfig.Builder setUnvalidatedConnectivityAcceptable(boolean);
+  }
+
+  public final class NetworkCapabilities implements android.os.Parcelable {
+    ctor public NetworkCapabilities(@Nullable android.net.NetworkCapabilities, boolean);
+    method @NonNull public int[] getAdministratorUids();
+    method @Nullable public String getSsid();
+    method @NonNull public int[] getTransportTypes();
+    method public boolean isPrivateDnsBroken();
+    method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities);
+    field public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28; // 0x1c
+    field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16
+    field public static final int NET_CAPABILITY_OEM_PRIVATE = 26; // 0x1a
+    field public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; // 0x18
+    field public static final int NET_CAPABILITY_VEHICLE_INTERNAL = 27; // 0x1b
+  }
+
+  public static final class NetworkCapabilities.Builder {
+    ctor public NetworkCapabilities.Builder();
+    ctor public NetworkCapabilities.Builder(@NonNull android.net.NetworkCapabilities);
+    method @NonNull public android.net.NetworkCapabilities.Builder addCapability(int);
+    method @NonNull public android.net.NetworkCapabilities.Builder addTransportType(int);
+    method @NonNull public android.net.NetworkCapabilities build();
+    method @NonNull public android.net.NetworkCapabilities.Builder clearAll();
+    method @NonNull public android.net.NetworkCapabilities.Builder removeCapability(int);
+    method @NonNull public android.net.NetworkCapabilities.Builder removeTransportType(int);
+    method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setAdministratorUids(@NonNull int[]);
+    method @NonNull public android.net.NetworkCapabilities.Builder setLinkDownstreamBandwidthKbps(int);
+    method @NonNull public android.net.NetworkCapabilities.Builder setLinkUpstreamBandwidthKbps(int);
+    method @NonNull public android.net.NetworkCapabilities.Builder setNetworkSpecifier(@Nullable android.net.NetworkSpecifier);
+    method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setOwnerUid(int);
+    method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorPackageName(@Nullable String);
+    method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorUid(int);
+    method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkCapabilities.Builder setSignalStrength(int);
+    method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setSsid(@Nullable String);
+    method @NonNull public android.net.NetworkCapabilities.Builder setTransportInfo(@Nullable android.net.TransportInfo);
+  }
+
+  public class NetworkProvider {
+    ctor public NetworkProvider(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String);
+    method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void declareNetworkRequestUnfulfillable(@NonNull android.net.NetworkRequest);
+    method public int getProviderId();
+    method public void onNetworkRequestWithdrawn(@NonNull android.net.NetworkRequest);
+    method public void onNetworkRequested(@NonNull android.net.NetworkRequest, @IntRange(from=0, to=99) int, int);
+    field public static final int ID_NONE = -1; // 0xffffffff
+  }
+
+  public class NetworkRequest implements android.os.Parcelable {
+    method @Nullable public String getRequestorPackageName();
+    method public int getRequestorUid();
+  }
+
+  public static class NetworkRequest.Builder {
+    method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkRequest.Builder setSignalStrength(int);
+  }
+
+  public final class RouteInfo implements android.os.Parcelable {
+    ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int);
+    ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int, int);
+    method public int getMtu();
+    method public int getType();
+    field public static final int RTN_THROW = 9; // 0x9
+    field public static final int RTN_UNICAST = 1; // 0x1
+    field public static final int RTN_UNREACHABLE = 7; // 0x7
+  }
+
+  public abstract class SocketKeepalive implements java.lang.AutoCloseable {
+    field public static final int SUCCESS = 0; // 0x0
+  }
+
+  public final class StaticIpConfiguration implements android.os.Parcelable {
+    ctor public StaticIpConfiguration();
+    ctor public StaticIpConfiguration(@Nullable android.net.StaticIpConfiguration);
+    method public void addDnsServer(@NonNull java.net.InetAddress);
+    method public void clear();
+    method public int describeContents();
+    method @NonNull public java.util.List<java.net.InetAddress> getDnsServers();
+    method @Nullable public String getDomains();
+    method @Nullable public java.net.InetAddress getGateway();
+    method @Nullable public android.net.LinkAddress getIpAddress();
+    method @NonNull public java.util.List<android.net.RouteInfo> getRoutes(@Nullable String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.StaticIpConfiguration> CREATOR;
+  }
+
+  public static final class StaticIpConfiguration.Builder {
+    ctor public StaticIpConfiguration.Builder();
+    method @NonNull public android.net.StaticIpConfiguration build();
+    method @NonNull public android.net.StaticIpConfiguration.Builder setDnsServers(@NonNull Iterable<java.net.InetAddress>);
+    method @NonNull public android.net.StaticIpConfiguration.Builder setDomains(@Nullable String);
+    method @NonNull public android.net.StaticIpConfiguration.Builder setGateway(@Nullable java.net.InetAddress);
+    method @NonNull public android.net.StaticIpConfiguration.Builder setIpAddress(@Nullable android.net.LinkAddress);
+  }
+
+  public final class TcpKeepalivePacketData extends android.net.KeepalivePacketData implements android.os.Parcelable {
+    ctor public TcpKeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[], int, int, int, int, int, int) throws android.net.InvalidPacketException;
+    method public int describeContents();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.TcpKeepalivePacketData> CREATOR;
+    field public final int ipTos;
+    field public final int ipTtl;
+    field public final int tcpAck;
+    field public final int tcpSeq;
+    field public final int tcpWindow;
+    field public final int tcpWindowScale;
+  }
+
+  public interface TransportInfo {
+    method public default boolean hasLocationSensitiveFields();
+    method @NonNull public default android.net.TransportInfo makeCopy(boolean);
+  }
+
+}
+
+package android.net.apf {
+
+  public final class ApfCapabilities implements android.os.Parcelable {
+    ctor public ApfCapabilities(int, int, int);
+    method public int describeContents();
+    method public static boolean getApfDrop8023Frames();
+    method @NonNull public static int[] getApfEtherTypeBlackList();
+    method public boolean hasDataAccess();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.net.apf.ApfCapabilities> CREATOR;
+    field public final int apfPacketFormat;
+    field public final int apfVersionSupported;
+    field public final int maximumApfProgramSize;
+  }
+
+}
+
+package android.net.util {
+
+  public final class SocketUtils {
+    method public static void bindSocketToInterface(@NonNull java.io.FileDescriptor, @NonNull String) throws android.system.ErrnoException;
+    method public static void closeSocket(@Nullable java.io.FileDescriptor) throws java.io.IOException;
+    method @NonNull public static java.net.SocketAddress makeNetlinkSocketAddress(int, int);
+    method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int);
+    method @Deprecated @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]);
+    method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int, @NonNull byte[]);
+  }
+
+}
+
diff --git a/packages/Connectivity/framework/api/system-lint-baseline.txt b/packages/Connectivity/framework/api/system-lint-baseline.txt
new file mode 100644
index 0000000..9a97707
--- /dev/null
+++ b/packages/Connectivity/framework/api/system-lint-baseline.txt
@@ -0,0 +1 @@
+// Baseline format: 1.0
diff --git a/packages/Connectivity/framework/api/system-removed.txt b/packages/Connectivity/framework/api/system-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/packages/Connectivity/framework/api/system-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/packages/Connectivity/framework/src/android/net/CaptivePortalData.java b/packages/Connectivity/framework/src/android/net/CaptivePortalData.java
index f4b46e9..eafda4d 100644
--- a/packages/Connectivity/framework/src/android/net/CaptivePortalData.java
+++ b/packages/Connectivity/framework/src/android/net/CaptivePortalData.java
@@ -44,7 +44,7 @@
     private final boolean mCaptive;
     private final String mVenueFriendlyName;
     private final int mVenueInfoUrlSource;
-    private final int mTermsAndConditionsSource;
+    private final int mUserPortalUrlSource;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -65,7 +65,7 @@
 
     private CaptivePortalData(long refreshTimeMillis, Uri userPortalUrl, Uri venueInfoUrl,
             boolean isSessionExtendable, long byteLimit, long expiryTimeMillis, boolean captive,
-            String venueFriendlyName, int venueInfoUrlSource, int termsAndConditionsSource) {
+            String venueFriendlyName, int venueInfoUrlSource, int userPortalUrlSource) {
         mRefreshTimeMillis = refreshTimeMillis;
         mUserPortalUrl = userPortalUrl;
         mVenueInfoUrl = venueInfoUrl;
@@ -75,7 +75,7 @@
         mCaptive = captive;
         mVenueFriendlyName = venueFriendlyName;
         mVenueInfoUrlSource = venueInfoUrlSource;
-        mTermsAndConditionsSource = termsAndConditionsSource;
+        mUserPortalUrlSource = userPortalUrlSource;
     }
 
     private CaptivePortalData(Parcel p) {
@@ -100,7 +100,7 @@
         dest.writeBoolean(mCaptive);
         dest.writeString(mVenueFriendlyName);
         dest.writeInt(mVenueInfoUrlSource);
-        dest.writeInt(mTermsAndConditionsSource);
+        dest.writeInt(mUserPortalUrlSource);
     }
 
     /**
@@ -130,7 +130,7 @@
         public Builder(@Nullable CaptivePortalData data) {
             if (data == null) return;
             setRefreshTime(data.mRefreshTimeMillis)
-                    .setUserPortalUrl(data.mUserPortalUrl, data.mTermsAndConditionsSource)
+                    .setUserPortalUrl(data.mUserPortalUrl, data.mUserPortalUrlSource)
                     .setVenueInfoUrl(data.mVenueInfoUrl, data.mVenueInfoUrlSource)
                     .setSessionExtendable(data.mIsSessionExtendable)
                     .setBytesRemaining(data.mByteLimit)
@@ -314,7 +314,7 @@
      * @return The source that the user portal URL was obtained from
      */
     public @CaptivePortalDataSource int getUserPortalUrlSource() {
-        return mTermsAndConditionsSource;
+        return mUserPortalUrlSource;
     }
 
     /**
@@ -342,7 +342,7 @@
     public int hashCode() {
         return Objects.hash(mRefreshTimeMillis, mUserPortalUrl, mVenueInfoUrl,
                 mIsSessionExtendable, mByteLimit, mExpiryTimeMillis, mCaptive, mVenueFriendlyName,
-                mVenueInfoUrlSource, mTermsAndConditionsSource);
+                mVenueInfoUrlSource, mUserPortalUrlSource);
     }
 
     @Override
@@ -358,7 +358,7 @@
                 && mCaptive == other.mCaptive
                 && Objects.equals(mVenueFriendlyName, other.mVenueFriendlyName)
                 && mVenueInfoUrlSource == other.mVenueInfoUrlSource
-                && mTermsAndConditionsSource == other.mTermsAndConditionsSource;
+                && mUserPortalUrlSource == other.mUserPortalUrlSource;
     }
 
     @Override
@@ -373,7 +373,7 @@
                 + ", captive: " + mCaptive
                 + ", venueFriendlyName: " + mVenueFriendlyName
                 + ", venueInfoUrlSource: " + mVenueInfoUrlSource
-                + ", termsAndConditionsSource: " + mTermsAndConditionsSource
+                + ", userPortalUrlSource: " + mUserPortalUrlSource
                 + "}";
     }
 }
diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
index d7c8291..e7ab0a1 100644
--- a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
+++ b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
@@ -49,8 +49,6 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.INetworkActivityListener;
-import android.os.INetworkManagementService;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Messenger;
@@ -835,7 +833,6 @@
 
     private final Context mContext;
 
-    private INetworkManagementService mNMService;
     private INetworkPolicyManager mNPManager;
     private final TetheringManager mTetheringManager;
 
@@ -1070,58 +1067,6 @@
     }
 
     /**
-     * Calls VpnManager#isAlwaysOnVpnPackageSupportedForUser.
-     * @deprecated TODO: remove when callers have migrated to VpnManager.
-     * @hide
-     */
-    @Deprecated
-    public boolean isAlwaysOnVpnPackageSupportedForUser(int userId, @Nullable String vpnPackage) {
-        return getVpnManager().isAlwaysOnVpnPackageSupportedForUser(userId, vpnPackage);
-    }
-
-    /**
-    * Calls VpnManager#setAlwaysOnVpnPackageForUser.
-     * @deprecated TODO: remove when callers have migrated to VpnManager.
-     * @hide
-     */
-    @Deprecated
-    public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage,
-            boolean lockdownEnabled, @Nullable List<String> lockdownAllowlist) {
-        return getVpnManager().setAlwaysOnVpnPackageForUser(userId, vpnPackage, lockdownEnabled,
-                lockdownAllowlist);
-    }
-
-    /**
-     * Calls VpnManager#getAlwaysOnVpnPackageForUser.
-     * @deprecated TODO: remove when callers have migrated to VpnManager.
-     * @hide
-     */
-    @Deprecated
-    public String getAlwaysOnVpnPackageForUser(int userId) {
-        return getVpnManager().getAlwaysOnVpnPackageForUser(userId);
-    }
-
-    /**
-     * Calls VpnManager#isVpnLockdownEnabled.
-     * @deprecated TODO: remove when callers have migrated to VpnManager.
-     * @hide
-     */
-    @Deprecated
-    public boolean isVpnLockdownEnabled(int userId) {
-        return getVpnManager().isVpnLockdownEnabled(userId);
-    }
-
-    /**
-     * Calls VpnManager#getVpnLockdownAllowlist.
-     * @deprecated TODO: remove when callers have migrated to VpnManager.
-     * @hide
-     */
-    @Deprecated
-    public List<String> getVpnLockdownAllowlist(int userId) {
-        return getVpnManager().getVpnLockdownAllowlist(userId);
-    }
-
-    /**
      * Adds or removes a requirement for given UID ranges to use the VPN.
      *
      * If set to {@code true}, informs the system that the UIDs in the specified ranges must not
@@ -2211,17 +2156,6 @@
         void onNetworkActive();
     }
 
-    private INetworkManagementService getNetworkManagementService() {
-        synchronized (this) {
-            if (mNMService != null) {
-                return mNMService;
-            }
-            IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
-            mNMService = INetworkManagementService.Stub.asInterface(b);
-            return mNMService;
-        }
-    }
-
     private final ArrayMap<OnNetworkActiveListener, INetworkActivityListener>
             mNetworkActivityListeners = new ArrayMap<>();
 
@@ -2246,7 +2180,7 @@
         };
 
         try {
-            getNetworkManagementService().registerNetworkActivityListener(rl);
+            mService.registerNetworkActivityListener(rl);
             mNetworkActivityListeners.put(l, rl);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -2263,7 +2197,7 @@
         INetworkActivityListener rl = mNetworkActivityListeners.get(l);
         Preconditions.checkArgument(rl != null, "Listener was not registered.");
         try {
-            getNetworkManagementService().unregisterNetworkActivityListener(rl);
+            mService.registerNetworkActivityListener(rl);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -2279,7 +2213,7 @@
      */
     public boolean isDefaultNetworkActive() {
         try {
-            return getNetworkManagementService().isNetworkActive();
+            return mService.isDefaultNetworkActive();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -3167,16 +3101,6 @@
     }
 
     /**
-     * Calls VpnManager#updateLockdownVpn.
-     * @deprecated TODO: remove when callers have migrated to VpnManager.
-     * @hide
-     */
-    @Deprecated
-    public boolean updateLockdownVpn() {
-        return getVpnManager().updateLockdownVpn();
-    }
-
-    /**
      * Set sign in error notification to visible or invisible
      *
      * @hide
@@ -4537,8 +4461,6 @@
         try {
             mService.factoryReset();
             mTetheringManager.stopAllTethering();
-            // TODO: Migrate callers to VpnManager#factoryReset.
-            getVpnManager().factoryReset();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -4832,15 +4754,6 @@
         return new TestNetworkManager(ITestNetworkManager.Stub.asInterface(tnBinder));
     }
 
-    /**
-     * Temporary hack to shim calls from ConnectivityManager to VpnManager. We cannot store a
-     * private final mVpnManager because ConnectivityManager is initialized before VpnManager.
-     * @hide TODO: remove.
-     */
-    public VpnManager getVpnManager() {
-        return mContext.getSystemService(VpnManager.class);
-    }
-
     /** @hide */
     public ConnectivityDiagnosticsManager createDiagnosticsManager() {
         return new ConnectivityDiagnosticsManager(mContext, mService);
diff --git a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl
index 6391802..160338d 100644
--- a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl
+++ b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl
@@ -21,6 +21,7 @@
 import android.net.ConnectivityDiagnosticsManager;
 import android.net.IConnectivityDiagnosticsCallback;
 import android.net.IOnSetOemNetworkPreferenceListener;
+import android.net.INetworkActivityListener;
 import android.net.IQosCallback;
 import android.net.ISocketKeepaliveCallback;
 import android.net.LinkProperties;
@@ -36,7 +37,6 @@
 import android.net.QosSocketInfo;
 import android.os.Bundle;
 import android.os.IBinder;
-import android.os.INetworkActivityListener;
 import android.os.Messenger;
 import android.os.ParcelFileDescriptor;
 import android.os.PersistableBundle;
diff --git a/core/java/android/os/INetworkActivityListener.aidl b/packages/Connectivity/framework/src/android/net/INetworkActivityListener.aidl
similarity index 96%
rename from core/java/android/os/INetworkActivityListener.aidl
rename to packages/Connectivity/framework/src/android/net/INetworkActivityListener.aidl
index 24e6e55..79687dd 100644
--- a/core/java/android/os/INetworkActivityListener.aidl
+++ b/packages/Connectivity/framework/src/android/net/INetworkActivityListener.aidl
@@ -13,7 +13,7 @@
 ** limitations under the License.
 */
 
-package android.os;
+package android.net;
 
 /**
  * @hide
diff --git a/packages/Connectivity/framework/src/android/net/IpPrefix.java b/packages/Connectivity/framework/src/android/net/IpPrefix.java
index bcb65fa..d2ee7d1 100644
--- a/packages/Connectivity/framework/src/android/net/IpPrefix.java
+++ b/packages/Connectivity/framework/src/android/net/IpPrefix.java
@@ -24,6 +24,8 @@
 import android.os.Parcelable;
 import android.util.Pair;
 
+import com.android.net.module.util.NetUtils;
+
 import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.InetAddress;
@@ -59,7 +61,7 @@
             throw new IllegalArgumentException(
                     "IpPrefix has " + address.length + " bytes which is neither 4 nor 16");
         }
-        NetworkUtils.maskRawAddress(address, prefixLength);
+        NetUtils.maskRawAddress(address, prefixLength);
     }
 
     /**
@@ -190,7 +192,7 @@
         if (addrBytes == null || addrBytes.length != this.address.length) {
             return false;
         }
-        NetworkUtils.maskRawAddress(addrBytes, prefixLength);
+        NetUtils.maskRawAddress(addrBytes, prefixLength);
         return Arrays.equals(this.address, addrBytes);
     }
 
@@ -204,7 +206,7 @@
     public boolean containsPrefix(@NonNull IpPrefix otherPrefix) {
         if (otherPrefix.getPrefixLength() < prefixLength) return false;
         final byte[] otherAddress = otherPrefix.getRawAddress();
-        NetworkUtils.maskRawAddress(otherAddress, prefixLength);
+        NetUtils.maskRawAddress(otherAddress, prefixLength);
         return Arrays.equals(otherAddress, address);
     }
 
diff --git a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
index 26d14cb..cd76f40 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
@@ -205,6 +205,7 @@
             NET_CAPABILITY_OEM_PRIVATE,
             NET_CAPABILITY_VEHICLE_INTERNAL,
             NET_CAPABILITY_NOT_VCN_MANAGED,
+            NET_CAPABILITY_ENTERPRISE,
     })
     public @interface NetCapability { }
 
@@ -415,8 +416,17 @@
     @SystemApi
     public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28;
 
+    /**
+     * Indicates that this network is intended for enterprise use.
+     * <p>
+     * 5G URSP rules may indicate that all data should use a connection dedicated for enterprise
+     * use. If the enterprise capability is requested, all enterprise traffic will be routed over
+     * the connection with this capability.
+     */
+    public static final int NET_CAPABILITY_ENTERPRISE = 29;
+
     private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
-    private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_NOT_VCN_MANAGED;
+    private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_ENTERPRISE;
 
     /**
      * Network capabilities that are expected to be mutable, i.e., can change while a particular
@@ -474,7 +484,8 @@
             | (1 << NET_CAPABILITY_MCX)
             | (1 << NET_CAPABILITY_RCS)
             | (1 << NET_CAPABILITY_VEHICLE_INTERNAL)
-            | (1 << NET_CAPABILITY_XCAP);
+            | (1 << NET_CAPABILITY_XCAP)
+            | (1 << NET_CAPABILITY_ENTERPRISE);
 
     /**
      * Capabilities that force network to be restricted.
@@ -2028,8 +2039,9 @@
             case NET_CAPABILITY_PARTIAL_CONNECTIVITY: return "PARTIAL_CONNECTIVITY";
             case NET_CAPABILITY_TEMPORARILY_NOT_METERED:    return "TEMPORARILY_NOT_METERED";
             case NET_CAPABILITY_OEM_PRIVATE:          return "OEM_PRIVATE";
-            case NET_CAPABILITY_VEHICLE_INTERNAL:     return "NET_CAPABILITY_VEHICLE_INTERNAL";
+            case NET_CAPABILITY_VEHICLE_INTERNAL:     return "VEHICLE_INTERNAL";
             case NET_CAPABILITY_NOT_VCN_MANAGED:      return "NOT_VCN_MANAGED";
+            case NET_CAPABILITY_ENTERPRISE:           return "ENTERPRISE";
             default:                                  return Integer.toString(capability);
         }
     }
diff --git a/packages/Connectivity/framework/src/android/net/NetworkRequest.java b/packages/Connectivity/framework/src/android/net/NetworkRequest.java
index 4e3085f..b4a651c 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkRequest.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkRequest.java
@@ -16,6 +16,22 @@
 
 package android.net;
 
+import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -30,6 +46,8 @@
 import android.text.TextUtils;
 import android.util.proto.ProtoOutputStream;
 
+import java.util.Arrays;
+import java.util.List;
 import java.util.Objects;
 import java.util.Set;
 
@@ -154,8 +172,30 @@
      * needed in terms of {@link NetworkCapabilities} features
      */
     public static class Builder {
+        /**
+         * Capabilities that are currently compatible with VCN networks.
+         */
+        private static final List<Integer> VCN_SUPPORTED_CAPABILITIES = Arrays.asList(
+                NET_CAPABILITY_CAPTIVE_PORTAL,
+                NET_CAPABILITY_DUN,
+                NET_CAPABILITY_FOREGROUND,
+                NET_CAPABILITY_INTERNET,
+                NET_CAPABILITY_NOT_CONGESTED,
+                NET_CAPABILITY_NOT_METERED,
+                NET_CAPABILITY_NOT_RESTRICTED,
+                NET_CAPABILITY_NOT_ROAMING,
+                NET_CAPABILITY_NOT_SUSPENDED,
+                NET_CAPABILITY_NOT_VPN,
+                NET_CAPABILITY_PARTIAL_CONNECTIVITY,
+                NET_CAPABILITY_TEMPORARILY_NOT_METERED,
+                NET_CAPABILITY_TRUSTED,
+                NET_CAPABILITY_VALIDATED);
+
         private final NetworkCapabilities mNetworkCapabilities;
 
+        // A boolean that represents the user modified NOT_VCN_MANAGED capability.
+        private boolean mModifiedNotVcnManaged = false;
+
         /**
          * Default constructor for Builder.
          */
@@ -177,6 +217,7 @@
             // maybeMarkCapabilitiesRestricted() doesn't add back.
             final NetworkCapabilities nc = new NetworkCapabilities(mNetworkCapabilities);
             nc.maybeMarkCapabilitiesRestricted();
+            deduceNotVcnManagedCapability(nc);
             return new NetworkRequest(nc, ConnectivityManager.TYPE_NONE,
                     ConnectivityManager.REQUEST_ID_UNSET, Type.NONE);
         }
@@ -193,6 +234,9 @@
          */
         public Builder addCapability(@NetworkCapabilities.NetCapability int capability) {
             mNetworkCapabilities.addCapability(capability);
+            if (capability == NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) {
+                mModifiedNotVcnManaged = true;
+            }
             return this;
         }
 
@@ -204,6 +248,9 @@
          */
         public Builder removeCapability(@NetworkCapabilities.NetCapability int capability) {
             mNetworkCapabilities.removeCapability(capability);
+            if (capability == NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) {
+                mModifiedNotVcnManaged = true;
+            }
             return this;
         }
 
@@ -261,6 +308,9 @@
         @NonNull
         public Builder clearCapabilities() {
             mNetworkCapabilities.clearAll();
+            // If the caller explicitly clear all capabilities, the NOT_VCN_MANAGED capabilities
+            // should not be add back later.
+            mModifiedNotVcnManaged = true;
             return this;
         }
 
@@ -380,6 +430,25 @@
             mNetworkCapabilities.setSignalStrength(signalStrength);
             return this;
         }
+
+        /**
+         * Deduce the NET_CAPABILITY_NOT_VCN_MANAGED capability from other capabilities
+         * and user intention, which includes:
+         *   1. For the requests that don't have anything besides
+         *      {@link #VCN_SUPPORTED_CAPABILITIES}, add the NET_CAPABILITY_NOT_VCN_MANAGED to
+         *      allow the callers automatically utilize VCN networks if available.
+         *   2. For the requests that explicitly add or remove NET_CAPABILITY_NOT_VCN_MANAGED,
+         *      do not alter them to allow user fire request that suits their need.
+         *
+         * @hide
+         */
+        private void deduceNotVcnManagedCapability(final NetworkCapabilities nc) {
+            if (mModifiedNotVcnManaged) return;
+            for (final int cap : nc.getCapabilities()) {
+                if (!VCN_SUPPORTED_CAPABILITIES.contains(cap)) return;
+            }
+            nc.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
+        }
     }
 
     // implement the Parcelable interface
diff --git a/packages/Connectivity/framework/src/android/net/NetworkUtils.java b/packages/Connectivity/framework/src/android/net/NetworkUtils.java
index 8be4af7..b5e8a61 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkUtils.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkUtils.java
@@ -29,7 +29,6 @@
 import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.net.SocketException;
-import java.net.UnknownHostException;
 import java.util.Locale;
 import java.util.TreeSet;
 
@@ -92,7 +91,8 @@
      * this socket will go directly to the underlying network, so its traffic will not be
      * forwarded through the VPN.
      */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553,
+            publicAlternatives = "Use {@link android.net.VpnService#protect} instead.")
     public static native boolean protectFromVpn(FileDescriptor fd);
 
     /**
@@ -232,46 +232,6 @@
     }
 
     /**
-     *  Masks a raw IP address byte array with the specified prefix length.
-     */
-    public static void maskRawAddress(byte[] array, int prefixLength) {
-        if (prefixLength < 0 || prefixLength > array.length * 8) {
-            throw new RuntimeException("IP address with " + array.length +
-                    " bytes has invalid prefix length " + prefixLength);
-        }
-
-        int offset = prefixLength / 8;
-        int remainder = prefixLength % 8;
-        byte mask = (byte)(0xFF << (8 - remainder));
-
-        if (offset < array.length) array[offset] = (byte)(array[offset] & mask);
-
-        offset++;
-
-        for (; offset < array.length; offset++) {
-            array[offset] = 0;
-        }
-    }
-
-    /**
-     * Get InetAddress masked with prefixLength.  Will never return null.
-     * @param address the IP address to mask with
-     * @param prefixLength the prefixLength used to mask the IP
-     */
-    public static InetAddress getNetworkPart(InetAddress address, int prefixLength) {
-        byte[] array = address.getAddress();
-        maskRawAddress(array, prefixLength);
-
-        InetAddress netPart = null;
-        try {
-            netPart = InetAddress.getByAddress(array);
-        } catch (UnknownHostException e) {
-            throw new RuntimeException("getNetworkPart error - " + e.toString());
-        }
-        return netPart;
-    }
-
-    /**
      * Returns the implicit netmask of an IPv4 address, as was the custom before 1993.
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
diff --git a/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java b/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java
index 0242ba0..340141b 100644
--- a/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java
+++ b/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/packages/Connectivity/framework/src/android/net/util/MultinetworkPolicyTracker.java b/packages/Connectivity/framework/src/android/net/util/MultinetworkPolicyTracker.java
index 85e3fa3..43fffd7 100644
--- a/packages/Connectivity/framework/src/android/net/util/MultinetworkPolicyTracker.java
+++ b/packages/Connectivity/framework/src/android/net/util/MultinetworkPolicyTracker.java
@@ -40,6 +40,8 @@
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.concurrent.RejectedExecutionException;
 
 /**
  * A class to encapsulate management of the "Smart Networking" capability of
@@ -73,6 +75,32 @@
     private volatile int mMeteredMultipathPreference;
     private int mActiveSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
+    // Mainline module can't use internal HandlerExecutor, so add an identical executor here.
+    private static class HandlerExecutor implements Executor {
+        @NonNull
+        private final Handler mHandler;
+
+        HandlerExecutor(@NonNull Handler handler) {
+            mHandler = handler;
+        }
+        @Override
+        public void execute(Runnable command) {
+            if (!mHandler.post(command)) {
+                throw new RejectedExecutionException(mHandler + " is shutting down");
+            }
+        }
+    }
+
+    @VisibleForTesting
+    protected class ActiveDataSubscriptionIdChangedListener extends PhoneStateListener
+            implements PhoneStateListener.ActiveDataSubscriptionIdChangedListener {
+        @Override
+        public void onActiveDataSubscriptionIdChanged(int subId) {
+            mActiveSubId = subId;
+            reevaluateInternal();
+        }
+    }
+
     public MultinetworkPolicyTracker(Context ctx, Handler handler) {
         this(ctx, handler, null);
     }
@@ -93,14 +121,8 @@
             }
         };
 
-        ctx.getSystemService(TelephonyManager.class).listen(
-                new PhoneStateListener(handler.getLooper()) {
-            @Override
-            public void onActiveDataSubscriptionIdChanged(int subId) {
-                mActiveSubId = subId;
-                reevaluateInternal();
-            }
-        }, PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
+        ctx.getSystemService(TelephonyManager.class).registerPhoneStateListener(
+                new HandlerExecutor(handler), new ActiveDataSubscriptionIdChangedListener());
 
         updateAvoidBadWifi();
         updateMeteredMultipathPreference();
diff --git a/packages/Connectivity/service/Android.bp b/packages/Connectivity/service/Android.bp
index ed1716f..f20b89f 100644
--- a/packages/Connectivity/service/Android.bp
+++ b/packages/Connectivity/service/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_library_shared {
     name: "libservice-connectivity",
     // TODO: build against the NDK (sdk_version: "30" for example)
diff --git a/packages/CtsShim/Android.bp b/packages/CtsShim/Android.bp
index 49608b3..31cd760 100644
--- a/packages/CtsShim/Android.bp
+++ b/packages/CtsShim/Android.bp
@@ -17,6 +17,15 @@
 //##########################################################
 // Variant: Privileged app
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app_import {
     name: "CtsShimPrivPrebuilt",
 
diff --git a/packages/CtsShim/build/Android.bp b/packages/CtsShim/build/Android.bp
index 14a3376..0b3f9bb 100644
--- a/packages/CtsShim/build/Android.bp
+++ b/packages/CtsShim/build/Android.bp
@@ -17,6 +17,15 @@
 //##########################################################
 // Variant: Privileged app upgrade
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "CtsShimPrivUpgrade",
     // this needs to be a privileged application
diff --git a/packages/CtsShim/build/jni/Android.bp b/packages/CtsShim/build/jni/Android.bp
index 4a1973c..ba586db 100644
--- a/packages/CtsShim/build/jni/Android.bp
+++ b/packages/CtsShim/build/jni/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_library_shared {
     name: "libshim_jni",
     srcs: ["Shim.c"],
diff --git a/packages/DynamicSystemInstallationService/Android.bp b/packages/DynamicSystemInstallationService/Android.bp
index a8cf5d6..ad86f46 100644
--- a/packages/DynamicSystemInstallationService/Android.bp
+++ b/packages/DynamicSystemInstallationService/Android.bp
@@ -1,3 +1,22 @@
+package {
+    default_applicable_licenses: [
+        "frameworks_base_packages_DynamicSystemInstallationService_license",
+    ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_packages_DynamicSystemInstallationService_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 android_app {
     name: "DynamicSystemInstallationService",
     defaults: ["platform_app_defaults"],
diff --git a/packages/DynamicSystemInstallationService/res/values-eu/strings.xml b/packages/DynamicSystemInstallationService/res/values-eu/strings.xml
index 6576edd..b0d45e1d0 100644
--- a/packages/DynamicSystemInstallationService/res/values-eu/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-eu/strings.xml
@@ -5,7 +5,7 @@
     <string name="notification_install_completed" msgid="6252047868415172643">"Prest dago sistema dinamikoa. Erabiltzen hasteko, berrabiarazi gailua."</string>
     <string name="notification_install_inprogress" msgid="7383334330065065017">"Instalatzen"</string>
     <string name="notification_install_failed" msgid="4066039210317521404">"Ezin izan da instalatu"</string>
-    <string name="notification_image_validation_failed" msgid="2720357826403917016">"Ezin izan da balidatu irudia. Utzi bertan behera instalazioa."</string>
+    <string name="notification_image_validation_failed" msgid="2720357826403917016">"Ezin izan da baliozkotu irudia. Utzi bertan behera instalazioa."</string>
     <string name="notification_dynsystem_in_use" msgid="1053194595682188396">"Sistema dinamiko bat abian da. Berrabiarazi Android-en jatorrizko bertsioa erabiltzeko."</string>
     <string name="notification_action_cancel" msgid="5929299408545961077">"Utzi"</string>
     <string name="notification_action_discard" msgid="1817481003134947493">"Baztertu"</string>
diff --git a/packages/DynamicSystemInstallationService/tests/Android.bp b/packages/DynamicSystemInstallationService/tests/Android.bp
index 3bdf829..50b65b4 100644
--- a/packages/DynamicSystemInstallationService/tests/Android.bp
+++ b/packages/DynamicSystemInstallationService/tests/Android.bp
@@ -1,3 +1,14 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_packages_DynamicSystemInstallationService_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: [
+        "frameworks_base_packages_DynamicSystemInstallationService_license",
+    ],
+}
+
 android_test {
     name: "DynamicSystemInstallationServiceTests",
 
diff --git a/packages/EasterEgg/Android.bp b/packages/EasterEgg/Android.bp
index b858ab0..f8785f2 100644
--- a/packages/EasterEgg/Android.bp
+++ b/packages/EasterEgg/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     // the build system in pi-dev can't quite handle R.java in kt
     // so we will have a mix of java and kotlin files
diff --git a/packages/EncryptedLocalTransport/Android.bp b/packages/EncryptedLocalTransport/Android.bp
index 00e9c71..09e5630 100644
--- a/packages/EncryptedLocalTransport/Android.bp
+++ b/packages/EncryptedLocalTransport/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "EncryptedLocalTransport",
     defaults: ["platform_app_defaults"],
diff --git a/packages/ExtShared/Android.bp b/packages/ExtShared/Android.bp
index 279ac9d..b1fd7f6 100644
--- a/packages/ExtShared/Android.bp
+++ b/packages/ExtShared/Android.bp
@@ -12,6 +12,23 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: ["frameworks_base_packages_ExtShared_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_packages_ExtShared_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 android_app {
     name: "ExtShared",
     defaults: ["platform_app_defaults"],
diff --git a/packages/ExternalStorageProvider/Android.bp b/packages/ExternalStorageProvider/Android.bp
index f1e6299..0bbdf7a 100644
--- a/packages/ExternalStorageProvider/Android.bp
+++ b/packages/ExternalStorageProvider/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "ExternalStorageProvider",
     defaults: ["platform_app_defaults"],
diff --git a/packages/ExternalStorageProvider/tests/Android.bp b/packages/ExternalStorageProvider/tests/Android.bp
index 04cf01a..633f186 100644
--- a/packages/ExternalStorageProvider/tests/Android.bp
+++ b/packages/ExternalStorageProvider/tests/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ExternalStorageProviderTests",
 
diff --git a/packages/FakeOemFeatures/Android.bp b/packages/FakeOemFeatures/Android.bp
index b63e3a1..25e3a86 100644
--- a/packages/FakeOemFeatures/Android.bp
+++ b/packages/FakeOemFeatures/Android.bp
@@ -1,3 +1,22 @@
+package {
+    default_applicable_licenses: [
+        "frameworks_base_packages_FakeOemFeatures_license",
+    ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_packages_FakeOemFeatures_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 android_app {
     name: "FakeOemFeatures",
     defaults: ["platform_app_defaults"],
diff --git a/packages/FusedLocation/Android.bp b/packages/FusedLocation/Android.bp
index ada463a..64b4c54 100644
--- a/packages/FusedLocation/Android.bp
+++ b/packages/FusedLocation/Android.bp
@@ -12,6 +12,25 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: [
+        "frameworks_base_packages_FusedLocation_license",
+    ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_packages_FusedLocation_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 android_app {
     name: "FusedLocation",
     defaults: ["platform_app_defaults"],
diff --git a/packages/InputDevices/Android.bp b/packages/InputDevices/Android.bp
index 5afbe72..477acc5 100644
--- a/packages/InputDevices/Android.bp
+++ b/packages/InputDevices/Android.bp
@@ -12,6 +12,25 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: [
+        "frameworks_base_packages_InputDevices_license",
+    ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_packages_InputDevices_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 android_app {
     name: "InputDevices",
     defaults: ["platform_app_defaults"],
diff --git a/packages/InputDevices/OWNERS b/packages/InputDevices/OWNERS
index 0313a40..f0d6db8 100644
--- a/packages/InputDevices/OWNERS
+++ b/packages/InputDevices/OWNERS
@@ -1,2 +1 @@
-michaelwr@google.com
-svv@google.com
+include /services/core/java/com/android/server/input/OWNERS
diff --git a/packages/InputDevices/res/values-eu/strings.xml b/packages/InputDevices/res/values-eu/strings.xml
index 0346d74..513eba2 100644
--- a/packages/InputDevices/res/values-eu/strings.xml
+++ b/packages/InputDevices/res/values-eu/strings.xml
@@ -42,7 +42,7 @@
     <string name="keyboard_layout_greek" msgid="7289253560162386040">"Greziarra"</string>
     <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebrearra"</string>
     <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituaniera"</string>
-    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Espainiera (Latinoamerika)"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Espainiarra (Latinoamerika)"</string>
     <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Letoniera"</string>
     <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persiarra"</string>
     <string name="keyboard_layout_azerbaijani" msgid="7315895417176467567">"Azerbaijandarra"</string>
diff --git a/packages/LocalTransport/Android.bp b/packages/LocalTransport/Android.bp
index 9a98a86..d4fa191 100644
--- a/packages/LocalTransport/Android.bp
+++ b/packages/LocalTransport/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "LocalTransport",
     defaults: ["platform_app_defaults"],
diff --git a/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
index c9d8a81..139c8e5 100644
--- a/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
+++ b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
@@ -162,6 +162,9 @@
         if (mParameters.isFakeEncryptionFlag()) {
             flags |= BackupAgent.FLAG_FAKE_CLIENT_SIDE_ENCRYPTION_ENABLED;
         }
+        if (mParameters.isDeviceTransfer()) {
+            flags |= BackupAgent.FLAG_DEVICE_TO_DEVICE_TRANSFER;
+        }
         return flags;
     }
 
diff --git a/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java b/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java
index 8b4db92..2946db3 100644
--- a/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java
+++ b/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java
@@ -27,9 +27,11 @@
     private static final String SETTING = Settings.Secure.BACKUP_LOCAL_TRANSPORT_PARAMETERS;
     private static final String KEY_FAKE_ENCRYPTION_FLAG = "fake_encryption_flag";
     private static final String KEY_NON_INCREMENTAL_ONLY = "non_incremental_only";
+    private static final String KEY_IS_DEVICE_TRANSFER = "is_device_transfer";
 
     private boolean mFakeEncryptionFlag;
     private boolean mIsNonIncrementalOnly;
+    private boolean mIsDeviceTransfer;
 
     public LocalTransportParameters(Handler handler, ContentResolver resolver) {
         super(handler, resolver, Settings.Secure.getUriFor(SETTING));
@@ -43,6 +45,10 @@
         return mIsNonIncrementalOnly;
     }
 
+    boolean isDeviceTransfer() {
+        return mIsDeviceTransfer;
+    }
+
     public String getSettingValue(ContentResolver resolver) {
         return Settings.Secure.getString(resolver, SETTING);
     }
@@ -50,5 +56,6 @@
     public void update(KeyValueListParser parser) {
         mFakeEncryptionFlag = parser.getBoolean(KEY_FAKE_ENCRYPTION_FLAG, false);
         mIsNonIncrementalOnly = parser.getBoolean(KEY_NON_INCREMENTAL_ONLY, false);
+        mIsDeviceTransfer = parser.getBoolean(KEY_IS_DEVICE_TRANSFER, false);
     }
 }
diff --git a/packages/PackageInstaller/Android.bp b/packages/PackageInstaller/Android.bp
index 4d9c675..4106ac5 100644
--- a/packages/PackageInstaller/Android.bp
+++ b/packages/PackageInstaller/Android.bp
@@ -12,6 +12,25 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: [
+        "frameworks_base_packages_PackageInstaller_license",
+    ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_packages_PackageInstaller_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 android_app {
     name: "PackageInstaller",
     defaults: ["platform_app_defaults"],
diff --git a/packages/PackageInstaller/res/values-eu/strings.xml b/packages/PackageInstaller/res/values-eu/strings.xml
index d411831..65e75cd 100644
--- a/packages/PackageInstaller/res/values-eu/strings.xml
+++ b/packages/PackageInstaller/res/values-eu/strings.xml
@@ -83,9 +83,9 @@
     <string name="untrusted_external_source_warning" product="tablet" msgid="6539403649459942547">"Segurtasuna bermatzeko, ezin dira instalatu iturburu honetako aplikazio ezezagunak tableta honetan."</string>
     <string name="untrusted_external_source_warning" product="tv" msgid="1206648674551321364">"Segurtasuna bermatzeko, ezin dira instalatu iturburu honetako aplikazio ezezagunak telebista honetan."</string>
     <string name="untrusted_external_source_warning" product="default" msgid="7279739265754475165">"Segurtasuna bermatzeko, ezin dira instalatu iturburu honetako aplikazio ezezagunak telefono honetan."</string>
-    <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"Telefonoak eta datu pertsonalek aplikazio ezezagunen erasoak jaso ditzakete. Aplikazio hau instalatzen baduzu, onartuko duzu zeu zarela hura erabiltzeagatik telefonoak jasan ditzakeen kalteen edo datu-galeren erantzulea."</string>
-    <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Tabletak eta datu pertsonalek aplikazio ezezagunen erasoak jaso ditzakete. Aplikazio hau instalatzen baduzu, onartuko duzu zeu zarela hura erabiltzeagatik tabletak jasan ditzakeen kalteen edo datu-galeren erantzulea."</string>
-    <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Telebistak eta datu pertsonalek aplikazio ezezagunen erasoak jaso ditzakete. Aplikazio hau instalatzen baduzu, onartuko duzu zeu zarela hura erabiltzeagatik telebistak jasan ditzakeen kalteen edo datu-galeren erantzulea."</string>
+    <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"Telefonoak eta datu pertsonalek aplikazio ezezagunen erasoak jaso ditzakete. Aplikazio hau instalatzen baduzu, onartu egingo duzu zeu zarela hura erabiltzeagatik telefonoak jasan ditzakeen kalteen edo datu-galeren erantzulea."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Tabletak eta datu pertsonalek aplikazio ezezagunen erasoak jaso ditzakete. Aplikazio hau instalatzen baduzu, onartu egingo duzu zeu zarela hura erabiltzeagatik tabletak jasan ditzakeen kalteen edo datu-galeren erantzulea."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Telebistak eta datu pertsonalek aplikazio ezezagunen erasoak jaso ditzakete. Aplikazio hau instalatzen baduzu, onartu egingo duzu zeu zarela hura erabiltzeagatik telebistak jasan ditzakeen kalteen edo datu-galeren erantzulea."</string>
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Egin aurrera"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Ezarpenak"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear aplikazioak instalatzea/desinstalatzea"</string>
diff --git a/packages/PrintRecommendationService/Android.bp b/packages/PrintRecommendationService/Android.bp
index d368f3c..084dd99 100644
--- a/packages/PrintRecommendationService/Android.bp
+++ b/packages/PrintRecommendationService/Android.bp
@@ -12,6 +12,25 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: [
+        "frameworks_base_packages_PrintRecommendationService_license",
+    ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_packages_PrintRecommendationService_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 android_app {
     name: "PrintRecommendationService",
     defaults: ["platform_app_defaults"],
diff --git a/packages/PrintSpooler/Android.bp b/packages/PrintSpooler/Android.bp
index d38fd02..772c69f 100644
--- a/packages/PrintSpooler/Android.bp
+++ b/packages/PrintSpooler/Android.bp
@@ -12,6 +12,25 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: [
+        "frameworks_base_packages_PrintSpooler_license",
+    ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_packages_PrintSpooler_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 android_app {
     name: "PrintSpooler",
     defaults: ["platform_app_defaults"],
diff --git a/packages/PrintSpooler/jni/Android.bp b/packages/PrintSpooler/jni/Android.bp
index 789312e..44df70e 100644
--- a/packages/PrintSpooler/jni/Android.bp
+++ b/packages/PrintSpooler/jni/Android.bp
@@ -1,3 +1,14 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_packages_PrintSpooler_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: [
+        "frameworks_base_packages_PrintSpooler_license",
+    ],
+}
+
 cc_library_shared {
     name: "libprintspooler_jni",
 
diff --git a/packages/PrintSpooler/res/values-fa/strings.xml b/packages/PrintSpooler/res/values-fa/strings.xml
index 719fc92..e69ca76 100644
--- a/packages/PrintSpooler/res/values-fa/strings.xml
+++ b/packages/PrintSpooler/res/values-fa/strings.xml
@@ -50,8 +50,8 @@
     <string name="search" msgid="5421724265322228497">"جستجو"</string>
     <string name="all_printers_label" msgid="3178848870161526399">"همه چاپگرها"</string>
     <string name="add_print_service_label" msgid="5356702546188981940">"افزودن سرویس"</string>
-    <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"کادر جستجو نمایان شد"</string>
-    <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"کادر جستجو پنهان شد"</string>
+    <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"چارگوش جستجو نمایان شد"</string>
+    <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"چارگوش جستجو پنهان شد"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"افزودن چاپگر"</string>
     <string name="print_select_printer" msgid="7388760939873368698">"انتخاب چاپگر"</string>
     <string name="print_forget_printer" msgid="5035287497291910766">"فراموش کردن چاپگر"</string>
diff --git a/packages/PrintSpooler/tests/outofprocess/Android.bp b/packages/PrintSpooler/tests/outofprocess/Android.bp
index 0e028b0..69a1d7f 100644
--- a/packages/PrintSpooler/tests/outofprocess/Android.bp
+++ b/packages/PrintSpooler/tests/outofprocess/Android.bp
@@ -12,6 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_packages_PrintSpooler_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: [
+        "frameworks_base_packages_PrintSpooler_license",
+    ],
+}
+
 android_test {
     name: "PrintSpoolerOutOfProcessTests",
 
diff --git a/packages/SettingsLib/ActionBarShadow/Android.bp b/packages/SettingsLib/ActionBarShadow/Android.bp
index d2848564..800ab67 100644
--- a/packages/SettingsLib/ActionBarShadow/Android.bp
+++ b/packages/SettingsLib/ActionBarShadow/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibActionBarShadow",
 
diff --git a/packages/SettingsLib/ActionButtonsPreference/Android.bp b/packages/SettingsLib/ActionButtonsPreference/Android.bp
index cd3fb0c..51c9c39 100644
--- a/packages/SettingsLib/ActionButtonsPreference/Android.bp
+++ b/packages/SettingsLib/ActionButtonsPreference/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibActionButtonsPreference",
 
diff --git a/packages/SettingsLib/AdaptiveIcon/Android.bp b/packages/SettingsLib/AdaptiveIcon/Android.bp
index 7f4442d..934aacf 100644
--- a/packages/SettingsLib/AdaptiveIcon/Android.bp
+++ b/packages/SettingsLib/AdaptiveIcon/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibAdaptiveIcon",
 
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index 0d4e746..f2a0e1c 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
 
     name: "SettingsLib",
@@ -57,6 +66,7 @@
         "SettingsLibBannerMessagePreference",
         "SettingsLibFooterPreference",
         "SettingsLibUsageProgressBarPreference",
+        "SettingsLibCollapsingToolbarBaseActivity",
     ],
 }
 
diff --git a/packages/SettingsLib/AppPreference/Android.bp b/packages/SettingsLib/AppPreference/Android.bp
index b07176a..1817a77 100644
--- a/packages/SettingsLib/AppPreference/Android.bp
+++ b/packages/SettingsLib/AppPreference/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibAppPreference",
 
diff --git a/packages/SettingsLib/BannerMessagePreference/Android.bp b/packages/SettingsLib/BannerMessagePreference/Android.bp
index 095975a..82e837b 100644
--- a/packages/SettingsLib/BannerMessagePreference/Android.bp
+++ b/packages/SettingsLib/BannerMessagePreference/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibBannerMessagePreference",
 
diff --git a/packages/SettingsLib/BarChartPreference/Android.bp b/packages/SettingsLib/BarChartPreference/Android.bp
index 477e897..ae26066 100644
--- a/packages/SettingsLib/BarChartPreference/Android.bp
+++ b/packages/SettingsLib/BarChartPreference/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibBarChartPreference",
 
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/Android.bp b/packages/SettingsLib/CollapsingToolbarBaseActivity/Android.bp
new file mode 100644
index 0000000..ed49bf4
--- /dev/null
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/Android.bp
@@ -0,0 +1,23 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_library {
+    name: "SettingsLibCollapsingToolbarBaseActivity",
+
+    srcs: ["src/**/*.java"],
+    resource_dirs: ["res"],
+
+    static_libs: [
+        "androidx.annotation_annotation",
+        "androidx.core_core",
+        "com.google.android.material_material",
+    ],
+    sdk_version: "system_current",
+    min_sdk_version: "21",
+}
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/AndroidManifest.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/AndroidManifest.xml
new file mode 100644
index 0000000..dabba68
--- /dev/null
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.settingslib.collapsingtoolbar">
+
+    <uses-sdk android:minSdkVersion="21" />
+
+</manifest>
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/layout/collapsing_toolbar_base_layout.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/layout/collapsing_toolbar_base_layout.xml
new file mode 100644
index 0000000..e376930
--- /dev/null
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/layout/collapsing_toolbar_base_layout.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<androidx.coordinatorlayout.widget.CoordinatorLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/content_parent"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:transitionGroup="true">
+
+    <com.google.android.material.appbar.AppBarLayout
+        android:id="@+id/app_bar"
+        android:layout_width="match_parent"
+        android:layout_height="180dp"
+        android:theme="@style/Theme.CollapsingToolbar.Settings">
+
+        <com.android.settingslib.collapsingtoolbar.AdjustableToolbarLayout
+            android:id="@+id/collapsing_toolbar"
+            android:background="?android:attr/colorPrimary"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            app:maxLines="3"
+            app:contentScrim="?android:attr/colorPrimary"
+            app:collapsedTitleTextAppearance="@style/CollapsingToolbarTitle.Collapsed"
+            app:statusBarScrim="?android:attr/colorPrimary"
+            app:layout_scrollFlags="scroll|exitUntilCollapsed"
+            app:expandedTitleMarginStart="18dp"
+            app:expandedTitleMarginEnd="18dp"
+            app:toolbarId="@id/action_bar">
+
+            <Toolbar
+                android:id="@+id/action_bar"
+                android:layout_width="match_parent"
+                android:layout_height="?attr/actionBarSize"
+                android:theme="?android:attr/actionBarTheme"
+                app:layout_collapseMode="pin"/>
+
+        </com.android.settingslib.collapsingtoolbar.AdjustableToolbarLayout>
+    </com.google.android.material.appbar.AppBarLayout>
+
+    <FrameLayout
+        android:id="@+id/content_frame"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-night/themes.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-night/themes.xml
new file mode 100644
index 0000000..e20775e
--- /dev/null
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-night/themes.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<resources>
+    <style name="Theme.CollapsingToolbar.Settings"
+           parent="@style/Theme.MaterialComponents.DayNight">
+        <item name="colorPrimary">@*android:color/primary_dark_device_default_settings</item>
+        <item name="colorAccent">@*android:color/accent_device_default_dark</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values/styles.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values/styles.xml
new file mode 100644
index 0000000..e1a64d4
--- /dev/null
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values/styles.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<resources>
+    <style name="CollapsingToolbarTitle.Collapsed"
+           parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title">
+    </style>
+
+    <style name="CollapsingToolbarTitle"
+           parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title">
+        <item name="android:textSize">36sp</item>
+    </style>
+
+    <style name="CollapsingToolbarTitle.MoreThanTwoLines">
+        <item name="android:textSize">24sp</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values/themes.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values/themes.xml
new file mode 100644
index 0000000..de545b0
--- /dev/null
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values/themes.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<resources>
+    <style name="Theme.CollapsingToolbar.Settings"
+           parent="@style/Theme.MaterialComponents.DayNight">
+        <item name="colorPrimary">@*android:color/primary_device_default_settings_light</item>
+        <item name="colorAccent">@*android:color/accent_device_default_light</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/AdjustableToolbarLayout.java b/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/AdjustableToolbarLayout.java
new file mode 100644
index 0000000..e75a978
--- /dev/null
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/AdjustableToolbarLayout.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.collapsingtoolbar;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.google.android.material.appbar.CollapsingToolbarLayout;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * A customized version of CollapsingToolbarLayout that can apply different font size based on
+ * the line count of its title.
+ */
+public class AdjustableToolbarLayout extends CollapsingToolbarLayout {
+
+    private static final int TOOLBAR_MAX_LINE_NUMBER = 2;
+
+    public AdjustableToolbarLayout(@NonNull Context context) {
+        this(context, null);
+
+    }
+
+    public AdjustableToolbarLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public AdjustableToolbarLayout(@NonNull Context context, @Nullable AttributeSet attrs,
+            int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        initCollapsingToolbar();
+    }
+
+    private void initCollapsingToolbar() {
+        this.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+            @Override
+            public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                    int oldLeft, int oldTop, int oldRight, int oldBottom) {
+                v.removeOnLayoutChangeListener(this);
+                final int count = getLineCount();
+                if (count > TOOLBAR_MAX_LINE_NUMBER) {
+                    setExpandedTitleTextAppearance(R.style.CollapsingToolbarTitle_MoreThanTwoLines);
+                } else {
+                    setExpandedTitleTextAppearance(R.style.CollapsingToolbarTitle);
+                }
+            }
+        });
+    }
+
+    /**
+     * Returns a number of title line count for CollapsingToolbarLayout so that facilitates the
+     * determination to apply what kind of font size. Since the title of CollapsingToolbarLayout is
+     * drawn in a canvas and the text process is wrapped in a CollapsingTextHelper, the way we used
+     * here is to get the line count from the CollapsingTextHelper via Java Reflection.
+     */
+    private int getLineCount() {
+        try {
+            final Field textHelperField = this.getClass().getDeclaredField("collapsingTextHelper");
+            textHelperField.setAccessible(true);
+            final Object textHelperObj = textHelperField.get(this);
+
+            final Field layoutField = textHelperObj.getClass().getDeclaredField("textLayout");
+            layoutField.setAccessible(true);
+            final Object layoutObj = layoutField.get(textHelperObj);
+
+            final Method method = layoutObj.getClass().getDeclaredMethod("getLineCount");
+            return (int) method.invoke(layoutObj);
+        } catch (Exception e) {
+            return 0;
+        }
+    }
+}
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/CollapsingToolbarBaseActivity.java b/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/CollapsingToolbarBaseActivity.java
new file mode 100644
index 0000000..637805f
--- /dev/null
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/CollapsingToolbarBaseActivity.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.collapsingtoolbar;
+
+import android.app.ActionBar;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Toolbar;
+
+import androidx.annotation.Nullable;
+import androidx.fragment.app.FragmentActivity;
+
+import com.google.android.material.appbar.CollapsingToolbarLayout;
+
+/**
+ * A base Activity that has a collapsing toolbar layout is used for the activities intending to
+ * enable the collapsing toolbar function.
+ */
+public class CollapsingToolbarBaseActivity extends FragmentActivity {
+
+    private CollapsingToolbarLayout mCollapsingToolbarLayout;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        super.setContentView(R.layout.collapsing_toolbar_base_layout);
+        mCollapsingToolbarLayout = findViewById(R.id.collapsing_toolbar);
+
+        final Toolbar toolbar = findViewById(R.id.action_bar);
+        setActionBar(toolbar);
+
+        // Enable title and home button by default
+        final ActionBar actionBar = getActionBar();
+        if (actionBar != null) {
+            actionBar.setDisplayHomeAsUpEnabled(true);
+            actionBar.setHomeButtonEnabled(true);
+            actionBar.setDisplayShowTitleEnabled(true);
+        }
+    }
+
+    @Override
+    public void setContentView(int layoutResID) {
+        final ViewGroup parent = findViewById(R.id.content_frame);
+        if (parent != null) {
+            parent.removeAllViews();
+        }
+        LayoutInflater.from(this).inflate(layoutResID, parent);
+    }
+
+    @Override
+    public void setContentView(View view) {
+        ((ViewGroup) findViewById(R.id.content_frame)).addView(view);
+    }
+
+    @Override
+    public void setContentView(View view, ViewGroup.LayoutParams params) {
+        ((ViewGroup) findViewById(R.id.content_frame)).addView(view, params);
+    }
+
+    @Override
+    public void setTitle(CharSequence title) {
+        if (mCollapsingToolbarLayout != null) {
+            mCollapsingToolbarLayout.setTitle(title);
+        }
+        super.setTitle(title);
+    }
+
+    @Override
+    public void setTitle(int titleId) {
+        if (mCollapsingToolbarLayout != null) {
+            mCollapsingToolbarLayout.setTitle(getText(titleId));
+        }
+        super.setTitle(titleId);
+    }
+
+    /**
+     * Returns an instance of collapsing toolbar.
+     */
+    public CollapsingToolbarLayout getCollapsingToolbarLayout() {
+        return mCollapsingToolbarLayout;
+    }
+}
diff --git a/packages/SettingsLib/DisplayDensityUtils/Android.bp b/packages/SettingsLib/DisplayDensityUtils/Android.bp
index 27d0cb5..b7bfb5f 100644
--- a/packages/SettingsLib/DisplayDensityUtils/Android.bp
+++ b/packages/SettingsLib/DisplayDensityUtils/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibDisplayDensityUtils",
 
diff --git a/packages/SettingsLib/EmergencyNumber/Android.bp b/packages/SettingsLib/EmergencyNumber/Android.bp
index 3c41f78..25b4905 100644
--- a/packages/SettingsLib/EmergencyNumber/Android.bp
+++ b/packages/SettingsLib/EmergencyNumber/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibEmergencyNumber",
 
diff --git a/packages/SettingsLib/EmergencyNumber/src/com/android/settingslib/emergencynumber/EmergencyNumberUtils.java b/packages/SettingsLib/EmergencyNumber/src/com/android/settingslib/emergencynumber/EmergencyNumberUtils.java
index 4d45494..b0a9b95 100644
--- a/packages/SettingsLib/EmergencyNumber/src/com/android/settingslib/emergencynumber/EmergencyNumberUtils.java
+++ b/packages/SettingsLib/EmergencyNumber/src/com/android/settingslib/emergencynumber/EmergencyNumberUtils.java
@@ -45,13 +45,22 @@
 
     public static final Uri EMERGENCY_NUMBER_OVERRIDE_AUTHORITY = new Uri.Builder().scheme(
             ContentResolver.SCHEME_CONTENT)
-            .authority("com.android.emergency.numbers")
+            .authority("com.android.emergency.gesture")
             .build();
     public static final String METHOD_NAME_GET_EMERGENCY_NUMBER_OVERRIDE =
             "GET_EMERGENCY_NUMBER_OVERRIDE";
     public static final String METHOD_NAME_SET_EMERGENCY_NUMBER_OVERRIDE =
             "SET_EMERGENCY_NUMBER_OVERRIDE";
+    public static final String METHOD_NAME_SET_EMERGENCY_GESTURE = "SET_EMERGENCY_GESTURE";
+    public static final String METHOD_NAME_SET_EMERGENCY_SOUND = "SET_EMERGENCY_SOUND";
+    public static final String METHOD_NAME_GET_EMERGENCY_GESTURE_ENABLED = "GET_EMERGENCY_GESTURE";
+    public static final String METHOD_NAME_GET_EMERGENCY_GESTURE_SOUND_ENABLED =
+            "GET_EMERGENCY_SOUND";
     public static final String EMERGENCY_GESTURE_CALL_NUMBER = "emergency_gesture_call_number";
+    public static final String EMERGENCY_SETTING_VALUE = "emergency_setting_value";
+    public static final int EMERGENCY_SETTING_ON = 1;
+    public static final int EMERGENCY_SETTING_OFF = 0;
+
     @VisibleForTesting
     static final String FALL_BACK_NUMBER = "112";
 
@@ -103,6 +112,51 @@
                 METHOD_NAME_SET_EMERGENCY_NUMBER_OVERRIDE, null /* args */, bundle);
     }
 
+    /**
+     * Enable/disable the emergency gesture setting
+     */
+    public void setEmergencyGestureEnabled(boolean enabled) {
+        final Bundle bundle = new Bundle();
+        bundle.putInt(EMERGENCY_SETTING_VALUE,
+                enabled ? EMERGENCY_SETTING_ON : EMERGENCY_SETTING_OFF);
+        mContext.getContentResolver().call(EMERGENCY_NUMBER_OVERRIDE_AUTHORITY,
+                METHOD_NAME_SET_EMERGENCY_GESTURE, null /* args */, bundle);
+    }
+
+    /**
+     * Enable/disable the emergency gesture sound setting
+     */
+    public void setEmergencySoundEnabled(boolean enabled) {
+        final Bundle bundle = new Bundle();
+        bundle.putInt(EMERGENCY_SETTING_VALUE,
+                enabled ? EMERGENCY_SETTING_ON : EMERGENCY_SETTING_OFF);
+        mContext.getContentResolver().call(EMERGENCY_NUMBER_OVERRIDE_AUTHORITY,
+                METHOD_NAME_SET_EMERGENCY_SOUND, null /* args */, bundle);
+    }
+
+    /**
+     * Whether or not emergency gesture is enabled.
+     */
+    public boolean getEmergencyGestureEnabled() {
+        final Bundle bundle = mContext.getContentResolver().call(
+                EMERGENCY_NUMBER_OVERRIDE_AUTHORITY,
+                METHOD_NAME_GET_EMERGENCY_GESTURE_ENABLED, null /* args */, null /* bundle */);
+        return bundle == null ? true : bundle.getInt(EMERGENCY_SETTING_VALUE, EMERGENCY_SETTING_ON)
+                == EMERGENCY_SETTING_ON;
+    }
+
+    /**
+     * Whether or not emergency gesture sound is enabled.
+     */
+    public boolean getEmergencyGestureSoundEnabled() {
+        final Bundle bundle = mContext.getContentResolver().call(
+                EMERGENCY_NUMBER_OVERRIDE_AUTHORITY,
+                METHOD_NAME_GET_EMERGENCY_GESTURE_SOUND_ENABLED, null /* args */,
+                null /* bundle */);
+        return bundle == null ? true : bundle.getInt(EMERGENCY_SETTING_VALUE, EMERGENCY_SETTING_OFF)
+                == EMERGENCY_SETTING_ON;
+    }
+
     private String getEmergencyNumberOverride() {
         final Bundle bundle = mContext.getContentResolver().call(
                 EMERGENCY_NUMBER_OVERRIDE_AUTHORITY,
diff --git a/packages/SettingsLib/EntityHeaderWidgets/Android.bp b/packages/SettingsLib/EntityHeaderWidgets/Android.bp
index 280848a..bd83cdc 100644
--- a/packages/SettingsLib/EntityHeaderWidgets/Android.bp
+++ b/packages/SettingsLib/EntityHeaderWidgets/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibEntityHeaderWidgets",
 
diff --git a/packages/SettingsLib/FooterPreference/Android.bp b/packages/SettingsLib/FooterPreference/Android.bp
index 1af967f..11f39e7 100644
--- a/packages/SettingsLib/FooterPreference/Android.bp
+++ b/packages/SettingsLib/FooterPreference/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibFooterPreference",
 
diff --git a/packages/SettingsLib/HelpUtils/Android.bp b/packages/SettingsLib/HelpUtils/Android.bp
index 285131d..5826047 100644
--- a/packages/SettingsLib/HelpUtils/Android.bp
+++ b/packages/SettingsLib/HelpUtils/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibHelpUtils",
 
diff --git a/packages/SettingsLib/LayoutPreference/Android.bp b/packages/SettingsLib/LayoutPreference/Android.bp
index a1f9a76..8a4e53d 100644
--- a/packages/SettingsLib/LayoutPreference/Android.bp
+++ b/packages/SettingsLib/LayoutPreference/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibLayoutPreference",
 
diff --git a/packages/SettingsLib/MainSwitchPreference/Android.bp b/packages/SettingsLib/MainSwitchPreference/Android.bp
index 1dc18f5..1feec21 100644
--- a/packages/SettingsLib/MainSwitchPreference/Android.bp
+++ b/packages/SettingsLib/MainSwitchPreference/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibMainSwitchPreference",
 
diff --git a/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml b/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml
index 52779bc..85c01c5 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml
@@ -19,6 +19,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_height="wrap_content"
     android:layout_width="match_parent"
+    android:background="?android:attr/colorBackground"
     android:orientation="vertical">
 
     <LinearLayout
diff --git a/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchBar.java b/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchBar.java
index 74b6578..1c9298e 100644
--- a/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchBar.java
+++ b/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchBar.java
@@ -17,6 +17,7 @@
 package com.android.settingslib.widget;
 
 import android.content.Context;
+import android.content.res.TypedArray;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.AttributeSet;
@@ -29,6 +30,7 @@
 import android.widget.TextView;
 
 import androidx.annotation.VisibleForTesting;
+import androidx.core.content.res.TypedArrayUtils;
 
 import com.android.settingslib.RestrictedLockUtils;
 
@@ -88,6 +90,17 @@
         });
 
         setChecked(mSwitch.isChecked());
+
+        if (attrs != null) {
+            final TypedArray a = context.obtainStyledAttributes(attrs,
+                    androidx.preference.R.styleable.Preference, 0 /*defStyleAttr*/,
+                    0 /*defStyleRes*/);
+            final CharSequence title = TypedArrayUtils.getText(a,
+                    androidx.preference.R.styleable.Preference_title,
+                    androidx.preference.R.styleable.Preference_android_title);
+            setTitle(title);
+            a.recycle();
+        }
     }
 
     @Override
@@ -126,7 +139,7 @@
     /**
      * Set the title text
      */
-    public void setTitle(String text) {
+    public void setTitle(CharSequence text) {
         if (mTextView != null) {
             mTextView.setText(text);
         }
diff --git a/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java b/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java
index 274bf8d..35afec3 100644
--- a/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java
+++ b/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.text.TextUtils;
 import android.util.AttributeSet;
 
 import androidx.core.content.res.TypedArrayUtils;
@@ -40,7 +39,7 @@
     private final List<OnMainSwitchChangeListener> mSwitchChangeListeners = new ArrayList<>();
 
     private MainSwitchBar mMainSwitchBar;
-    private String mTitle;
+    private CharSequence mTitle;
 
     private RestrictedLockUtils.EnforcedAdmin mEnforcedAdmin;
 
@@ -81,24 +80,28 @@
         setLayoutResource(R.layout.main_switch_layout);
 
         if (attrs != null) {
-            TypedArray a = context.obtainStyledAttributes(attrs,
+            final TypedArray a = context.obtainStyledAttributes(attrs,
                     androidx.preference.R.styleable.Preference, 0 /*defStyleAttr*/,
                     0 /*defStyleRes*/);
             final CharSequence title = TypedArrayUtils.getText(a,
                     androidx.preference.R.styleable.Preference_title,
                     androidx.preference.R.styleable.Preference_android_title);
-            if (!TextUtils.isEmpty(title)) {
-                setTitle(title.toString());
-            }
+            setTitle(title);
             a.recycle();
         }
     }
 
-    /**
-     * Set the preference title text
-     */
-    public void setTitle(String text) {
-        mTitle = text;
+    @Override
+    public void setChecked(boolean checked) {
+        super.setChecked(checked);
+        if (mMainSwitchBar != null) {
+            mMainSwitchBar.setChecked(checked);
+        }
+    }
+
+    @Override
+    public void setTitle(CharSequence title) {
+        mTitle = title;
         if (mMainSwitchBar != null) {
             mMainSwitchBar.setTitle(mTitle);
         }
diff --git a/packages/SettingsLib/ProgressBar/Android.bp b/packages/SettingsLib/ProgressBar/Android.bp
index eae21d8..b5bc8f7 100644
--- a/packages/SettingsLib/ProgressBar/Android.bp
+++ b/packages/SettingsLib/ProgressBar/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibProgressBar",
 
@@ -6,4 +15,4 @@
 
     sdk_version: "system_current",
     min_sdk_version: "21",
-}
\ No newline at end of file
+}
diff --git a/packages/SettingsLib/RadioButtonPreference/Android.bp b/packages/SettingsLib/RadioButtonPreference/Android.bp
index 136d6da..b309c01 100644
--- a/packages/SettingsLib/RadioButtonPreference/Android.bp
+++ b/packages/SettingsLib/RadioButtonPreference/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibRadioButtonPreference",
 
diff --git a/packages/SettingsLib/RestrictedLockUtils/Android.bp b/packages/SettingsLib/RestrictedLockUtils/Android.bp
index b2f0882..c0623ed 100644
--- a/packages/SettingsLib/RestrictedLockUtils/Android.bp
+++ b/packages/SettingsLib/RestrictedLockUtils/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibRestrictedLockUtils",
 
@@ -10,4 +19,4 @@
 
     sdk_version: "system_current",
     min_sdk_version: "21",
-}
\ No newline at end of file
+}
diff --git a/packages/SettingsLib/SchedulesProvider/Android.bp b/packages/SettingsLib/SchedulesProvider/Android.bp
index ef59252..c4373bb 100644
--- a/packages/SettingsLib/SchedulesProvider/Android.bp
+++ b/packages/SettingsLib/SchedulesProvider/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibSchedulesProvider",
 
diff --git a/packages/SettingsLib/SearchProvider/Android.bp b/packages/SettingsLib/SearchProvider/Android.bp
index 5254dde..f96011a 100644
--- a/packages/SettingsLib/SearchProvider/Android.bp
+++ b/packages/SettingsLib/SearchProvider/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibSearchProvider",
 
diff --git a/packages/SettingsLib/SearchWidget/Android.bp b/packages/SettingsLib/SearchWidget/Android.bp
index 7541ca45..b7367b4 100644
--- a/packages/SettingsLib/SearchWidget/Android.bp
+++ b/packages/SettingsLib/SearchWidget/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibSearchWidget",
 
diff --git a/packages/SettingsLib/SettingsSpinner/Android.bp b/packages/SettingsLib/SettingsSpinner/Android.bp
index ca23616..c5b2fe6 100644
--- a/packages/SettingsLib/SettingsSpinner/Android.bp
+++ b/packages/SettingsLib/SettingsSpinner/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibSettingsSpinner",
 
diff --git a/packages/SettingsLib/SettingsTheme/Android.bp b/packages/SettingsLib/SettingsTheme/Android.bp
index 6579fd9..bda863a 100644
--- a/packages/SettingsLib/SettingsTheme/Android.bp
+++ b/packages/SettingsLib/SettingsTheme/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibSettingsTheme",
 
diff --git a/packages/SettingsLib/Tile/Android.bp b/packages/SettingsLib/Tile/Android.bp
index bf16ef3..cc570cc 100644
--- a/packages/SettingsLib/Tile/Android.bp
+++ b/packages/SettingsLib/Tile/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibTile",
 
diff --git a/packages/SettingsLib/TopIntroPreference/Android.bp b/packages/SettingsLib/TopIntroPreference/Android.bp
index 03becbd..9577281 100644
--- a/packages/SettingsLib/TopIntroPreference/Android.bp
+++ b/packages/SettingsLib/TopIntroPreference/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibTopIntroPreference",
 
diff --git a/packages/SettingsLib/TopIntroPreference/res/layout/top_intro_preference.xml b/packages/SettingsLib/TopIntroPreference/res/layout/top_intro_preference.xml
index 19fa91f..0287b1f 100644
--- a/packages/SettingsLib/TopIntroPreference/res/layout/top_intro_preference.xml
+++ b/packages/SettingsLib/TopIntroPreference/res/layout/top_intro_preference.xml
@@ -20,27 +20,11 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
-    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingStart="20dp"
     android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
     android:background="?android:attr/selectableItemBackground"
     android:clipToPadding="false">
 
-    <LinearLayout
-        android:id="@+id/icon_frame"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:minWidth="56dp"
-        android:gravity="start|top"
-        android:orientation="horizontal"
-        android:paddingEnd="12dp"
-        android:paddingTop="16dp"
-        android:paddingBottom="4dp">
-        <ImageView
-            android:id="@android:id/icon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
-    </LinearLayout>
-
     <TextView
         android:id="@android:id/title"
         android:layout_width="wrap_content"
@@ -50,5 +34,5 @@
         android:clickable="false"
         android:longClickable="false"
         android:maxLines="10"
-        android:textColor="?android:attr/textColorSecondary"/>
+        android:textAppearance="@style/TextAppearance.TopIntroText"/>
 </LinearLayout>
\ No newline at end of file
diff --git a/packages/SettingsLib/TopIntroPreference/res/values/styles.xml b/packages/SettingsLib/TopIntroPreference/res/values/styles.xml
new file mode 100644
index 0000000..e7eb9f4
--- /dev/null
+++ b/packages/SettingsLib/TopIntroPreference/res/values/styles.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<resources>
+    <style name="TextAppearance.TopIntroText"
+           parent="@*android:style/TextAppearance.DeviceDefault">
+        <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+        <item name="android:textSize">14sp</item>
+        <item name="android:textColor">?android:attr/textColorSecondary</item>
+    </style>
+</resources>
diff --git a/packages/SettingsLib/UsageProgressBarPreference/Android.bp b/packages/SettingsLib/UsageProgressBarPreference/Android.bp
index 3331550..ad6e7ab 100644
--- a/packages/SettingsLib/UsageProgressBarPreference/Android.bp
+++ b/packages/SettingsLib/UsageProgressBarPreference/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibUsageProgressBarPreference",
 
diff --git a/packages/SettingsLib/Utils/Android.bp b/packages/SettingsLib/Utils/Android.bp
index c5f0ee6..1cf42ff 100644
--- a/packages/SettingsLib/Utils/Android.bp
+++ b/packages/SettingsLib/Utils/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibUtils",
 
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 577fb66..eafc614 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Ignoreer kodewisselingverstekke"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Aktiveer kodewisseling"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Aanvaar dat programme moderne formate steun"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Wys kodewisselingkennisgewings"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Lopende dienste"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Sien en beheer dienste wat tans aktief is"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementering"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Datasein vol."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet is ontkoppel."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Geen oproepe nie."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index c554e2e..547d0af 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"የትራንስኮዲንግ ነባሪዎችን ሻር"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"ትራንስኮዲንግን ያንቁ"</string>
     <string name="transcode_default" msgid="3784803084573509491">"መተግበሪያዎች ዘመናዊ ቅርጸቶችን እንደሚደግፉ አድርገው ይቁጠሩ"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"ትራንስኮዲንግ ማሳወቂያዎችን አሳይ"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"አሂድ አገልግሎቶች"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"በአሁኑጊዜ እየሄዱ ያሉ አገልግሎቶችን ተቆጣጠር እና እይ"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"የWebView ትግበራ"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"የውሂብ አመልካች ሙሉ ነው።"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ኤተርኔት ተነቅሏል።"</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ኢተርኔት።"</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"መደወል የለም።"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index b23cebd..c6a1d18f 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"إلغاء الإعدادات التلقائية لتحويل الترميز"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"تفعيل تحويل الترميز"</string>
     <string name="transcode_default" msgid="3784803084573509491">"افتراض أن التطبيق يتوافق مع التنسيقات الحديثة"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"إظهار إشعارات تحويل الترميز"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"الخدمات قيد التشغيل"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"عرض الخدمات قيد التشغيل في الوقت الحالي والتحكم فيها"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"‏تطبيق WebView"</string>
@@ -596,6 +597,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"إشارة البيانات كاملة."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"‏تم قطع اتصال Ethernet."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"إيثرنت"</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"لا يتم الاتصال."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 2380b2f..e9deb46 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"ট্ৰেন্সক’ডিং ডিফ’ল্ট অ’ভাৰৰাইড কৰক"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"ট্ৰেন্সক’ডিং সক্ষম কৰক"</string>
     <string name="transcode_default" msgid="3784803084573509491">"এপে আধুনিক ফৰ্মেট সমৰ্থন কৰে বুলি ধৰি লওক"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"ট্ৰান্সক\'ডিঙৰ জাননী দেখুৱাওক"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"চলিত সেৱা"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"বৰ্তমান চলি থকা সেৱাসমূহ চাওক আৰু নিয়ন্ত্ৰণ কৰক"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"ৱেবভিউ প্ৰয়োগ"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ডেটা ছিগনেল পূৰা আছে।"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ইথাৰনেট সংযোগ বিচ্ছিন্ন হৈছে।"</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ইথাৰনেট।"</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"কল কৰা নহয়"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index f70bb84..d04409c 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Yenidən kodlaşdırma defoltlarını əvəzləyin"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Yenidən kodlaşdırmanı aktiv edin"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Tətbiqlərin müasir formatları dəstəklədiyini qəbul edin"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Kod dəyişmə bildirişlərini göstərin"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"İşləyən xidmətlər"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Hazırda prosesdə olan xidmətləri görüntüləyin və onlara nəzarət edin"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView icrası"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Data siqnalı tamdır."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet bağlantısı kəsilib."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Zəng yoxdur."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 749f864..ecd70a2 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Zameni podrazumevana podešavanja transkodiranja"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Omogući transkodiranje"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Podrazumevaj da aplikacije podržavaju moderne formate"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Prikazuj obaveštenja o transkodiranju"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Pokrenute usluge"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Prikaz i kontrola trenutno pokrenutih usluga"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Primena WebView-a"</string>
@@ -593,6 +594,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Signal za podatke je najjači."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Veza sa eternetom je prekinuta."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Eternet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Bez pozivanja."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 6b2740d..6a3b961 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Перавызначыць стандартныя налады перакадзіравання"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Уключыць перакадзіраванне"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Лічыца, што праграмы падтрымліваюць сучасныя фарматы"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Паказваць апавяшчэнні пра перакадзіраванне"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Запушчаныя службы"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Прагляд запушчаных службаў i кіраванне iмi"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Рэалізацыя WebView"</string>
@@ -594,6 +595,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Поўны сігнал перадачы дадзеных."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet адлучаны."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Ніякіх выклікаў."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 1a24b9e..d2bf705 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Отмяна на стандартните настройки за прекодирането"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Активиране на прекодирането"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Предполагане, че приложенията поддържат съвременни формати"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Показване на известията за прекодиране"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Изпълнявани услуги"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Преглед и контрол върху изпълняващите се понастоящем услуги"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Внедряване на WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Сигналът за данни е пълен."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Връзката с Ethernet е прекратена."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Без обаждания."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 1c9f84f..3ccf0e4 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"ট্রান্সকোডিং ডিফল্ট সেটিংস ওভাররাইড করুন"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"ট্রান্সকোডিং চালু করুন"</string>
     <string name="transcode_default" msgid="3784803084573509491">"অ্যাপ মর্ডার্ন ফর্ম্যাটে কাজ করবে বলে ধরে নিন"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"ট্রান্সকোডিং বিজ্ঞপ্তি দেখুন"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"এখন চলছে যে পরিষেবাগুলি"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"বর্তমান চলমান পরিষেবাগুলি দেখুন এবং নিয়ন্ত্রণ করুন"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"ওয়েবভিউ প্রয়োগ"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"পূর্ণ ডেটার সংকেত রয়েছে৷"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ইথারনেটের সংযোগ বিচ্ছিন্ন হয়েছে৷"</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ইথারনেট।"</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"কল করবেন না।"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index f701421..f01eef3 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Zaobiđi zadane postavke transkodiranja"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Omogući transkodiranje"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Pretpostavi da aplikacije podržavaju moderne formate"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Prikaži obavještenja o transkodiranju"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Pokrenute usluge"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Prikaz i kontrola trenutno pokrenutih usluga"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Postavljanje WebViewa"</string>
@@ -593,6 +594,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Signal za prijenos podataka pun."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Veza sa Ethernetom je prekinuta."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Nema pozivanja."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 78ef109..7069999 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Substitueix els valors predeterminats de la transcodificació"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Activa la transcodificació"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Assumeix que les aplicacions són compatibles amb formats moderns"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Mostra les notificacions de transcodificació"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Serveis en execució"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualitza i controla els serveis en execució"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementació de WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Senyal de dades: complet."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"S\'ha desconnectat l\'Ethernet."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Sense trucades."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 8ca9800..c677fef 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Přepsat výchozí nastavení překódování"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Povolit překódování"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Předpokládat, že aplikace podporují moderní formáty"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Zobrazit oznámení o překódování"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Spuštěné služby"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Umožňuje zobrazit a ovládat aktuálně spuštěné služby"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementace WebView"</string>
@@ -594,6 +595,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Plný signál datové sítě."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Síť ethernet je odpojena."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Bez volání."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 5d55a12..84247a6 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Tilsidesæt standardindstillingerne for omkodning"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Aktivér omkodning"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Gå ud fra, at apps understøtter moderne formater"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Vis notifikationer for omkodning"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Kørende tjenester"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Vis og administrer kørende tjenester"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementering"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Datasignal fuldt."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet er ikke tilsluttet."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Opkald er deaktiveret."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 1fbb391..4cc79d3 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Standardeinstellungen für Transcodierung überschreiben"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Transcodierung aktivieren"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Voraussetzen, dass Apps moderne Formate unterstützen"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Benachrichtigungen zur Transcodierung anzeigen"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Aktive Dienste"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Momentan ausgeführte Dienste anzeigen und steuern"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-Implementierung"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Volle Datensignalstärke"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet nicht verbunden"</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Keine Anrufe."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 32bcf87..30705a1 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Παράκαμψη προεπιλογών διακωδικοποίησης"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Ενεργοποίηση διακωδικοποίησης"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Να θεωρείται ότι οι εφαρμογές χρησιμοποιούν σύγχρονες μορφές"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Εμφάνιση ειδοποιήσεων διακωδικοποίησης"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Υπηρεσίες που εκτελούνται"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Προβολή και έλεγχος των εφαρμογών που εκτελούνται αυτή τη στιγμή"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Υλοποίηση WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Πλήρες σήμα δεδομένων."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Το Ethernet αποσυνδέθηκε."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Χωρίς κλήσεις."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 6241953..b3d80ab 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Override transcoding defaults"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Enable transcoding"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Assume apps support modern formats"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Show transcoding notifications"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 198fee4..ecf97ad 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Override transcoding defaults"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Enable transcoding"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Assume apps support modern formats"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Show transcoding notifications"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 6241953..b3d80ab 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Override transcoding defaults"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Enable transcoding"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Assume apps support modern formats"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Show transcoding notifications"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 6241953..b3d80ab 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Override transcoding defaults"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Enable transcoding"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Assume apps support modern formats"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Show transcoding notifications"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 27cd8b3..c3a3f3f 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‏‎‏‏‎‏‏‎‏‏‏‏‎‎‏‏‏‎‏‏‏‏‎‏‏‏‎‏‏‏‏‎‎‎‎‎‏‏‏‎‏‎‏‏‎‏‏‏‏‎‎‏‎‎Override transcoding defaults‎‏‎‎‏‎"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‏‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‎‏‎‎‎‏‏‏‏‎‎‏‏‏‎‏‏‎‎‏‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎Enable transcoding‎‏‎‎‏‎"</string>
     <string name="transcode_default" msgid="3784803084573509491">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‎‏‏‎‎‏‎‏‎‎‏‎‎‏‎‏‏‎‏‎‎‏‎‎‏‎‎‎‏‏‎‎‏‏‏‎‏‎‎‎‎‏‏‏‎‏‏‏‎‎‏‏‎Assume apps support modern formats‎‏‎‎‏‎"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‎‏‎‏‎‏‏‏‎‏‎‏‏‏‏‎‏‎‎‏‎‏‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎‏‎‎‎‏‏‏‎‎‎‎‎‏‎‎‎‎Show transcoding notifications‎‏‎‎‏‎"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‎‏‏‎‏‏‏‎‎‎‏‎‎‎‎‏‎‎‏‏‏‏‎‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‎‎‏‏‎Running services‎‏‎‎‏‎"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‏‎‎‎‎‏‎‎‎‏‏‎‏‏‎‎‏‏‎‎‏‏‎‏‎‏‏‏‏‏‎‎‎‎‎‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎‎‎‏‏‏‏‎View and control currently running services‎‏‎‎‏‎"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‏‏‏‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎‎‎‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‏‎‏‎‏‎‏‏‏‏‏‏‏‏‎WebView implementation‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 0f76576..eb2a23b 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Anular los valores predeterminados de transcodificación"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Habilitar la transcodificación"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Suponer que las apps admiten formatos modernos"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Mostrar notificaciones de transcodificación"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"En ejecución"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ver y controlar servicios actuales en ejecución"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementación de WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Señal de datos completa"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet desconectada"</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Sin llamadas."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index abd209c..fe9984b 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Anular valores predeterminados de transcodificación"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Habilitar transcodificación"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Considerar que las aplicaciones admiten formatos modernos"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Mostrar notificaciones de transcodificación"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Servicios en ejecución"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ver y controlar los servicios en ejecución"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementación de WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Señal de datos al máximo"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Conexión Ethernet desconectada."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet"</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Sin llamadas."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 2e9f3b8..c70700d 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Alista transkodeerimise vaikeseaded"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Luba transkodeerimine"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Oleta, et rakendused toetavad kaasaegseid vorminguid"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Kuva transkodeerimise märguanded"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Käitatud teenused"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Praegu käitatud teenuste vaatamine ja juhtimine"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView\' rakendamine"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Andmesignaal on tugev."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Etherneti-ühendus on katkestatud."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Helistamine pole võimalik."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index ecb4f75..09c964a 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Ez erabili transkodetzearen balio lehenetsiak"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Gaitu transkodetzea"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Arduratu aplikazioek formatu modernoak onartzeaz"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Erakutsi transkodetze-jakinarazpenak"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Abian diren zerbitzuak"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ikusi eta kontrolatu une honetan abian diren zerbitzuak"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView inplementazioa"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Datu-seinale osoa."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet bidezko konexioa eten da."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Deirik ez."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 56ade54..22cd6ae 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"ملغی کردن پیش‌فرض‌های تراتبدیل"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"فعال کردن تراتبدیل"</string>
     <string name="transcode_default" msgid="3784803084573509491">"فرض شود برنامه‌ها از قالب‌های مدرن پشتیبانی می‌کنند"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"نمایش اعلان‌های تراتبدیل"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"سرویس‌های در حال اجرا"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"مشاهده و کنترل سرویس‌های در حال اجرای فعلی"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"اجرای وب‌نما"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"قدرت سیگنال داده کامل است."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"اترنت قطع شد."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"اترنت."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"تماس گرفته نشود."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index e26ecb7..22dde69 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Ohita transkoodauksen oletukset"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Salli transkoodaus"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Oleta, että sovellukset tukevat nykyaikaisia formaatteja"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Näytä transkoodausilmoituksia"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Käynnissä olevat palvelut"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Tarkastele ja hallitse käynnissä olevia palveluita."</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-käyttöönotto"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Vahva kuuluvuus."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet on irrotettu."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet"</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Ei puheluita."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index d61ebc0..d189f72 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Remplacer les valeurs par défaut de transcodage"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Activer le transcodage"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Présumer que les applications prennent en charge les formats modernes"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Afficher les notifications de transcodage"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Services en cours d\'exécution"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Afficher et contrôler les services en cours d\'exécution"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Mise en œuvre WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Signal excellent"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet déconnecté."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Aucun appel."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 64c06fa..49d7faa 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Ignorer les paramètres de transcodage par défaut"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Activer le transcodage"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Supposer que les applications sont compatibles avec les formats modernes"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Afficher les notifications de transcodage"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Services en cours d\'exécution"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Afficher et contrôler les services en cours d\'exécution"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Mise en œuvre WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Signal excellent"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet déconnecté"</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Pas d\'appels."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index cf63dd7..0922c3d 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Anular valores predeterminados de transcodificación"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Activar transcodificación"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Considerar que as aplicacións admiten formatos modernos"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Mostrar notificacións de transcodificación"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Servizos en uso"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Comproba e controla os servizos actualmente en uso"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementación de WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Sinal de datos: completo"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Desconectouse a Ethernet."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Sen chamadas."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 427ce56..10c5cc8 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"ફૉર્મેટ બદલવાની પ્રક્રિયાના ડિફૉલ્ટ સેટિંગ ઓવરરાઇડ કરો"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"ફૉર્મેટ બદલવાની પ્રક્રિયા ચાલુ કરો"</string>
     <string name="transcode_default" msgid="3784803084573509491">"ધારો કે ઍપ આધુનિક ફૉર્મેટ પર કામ કરે છે"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"ફૉર્મેટ બદલવાની પ્રક્રિયાના નોટિફિકેશન બતાવો"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"ચાલુ સેવાઓ"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"હાલમાં ચાલતી સેવાઓ જુઓ અને નિયંત્રિત કરો"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView અમલીકરણ"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ડેટા સિગ્નલ પૂર્ણ."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ઇથરનેટ ડિસ્કનેક્ટ થયું."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ઇથરનેટ."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"કોઈ કૉલિંગ નહીં."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 159d2db..ea25406 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"ट्रांसकोडिंग की डिफ़ॉल्ट सेटिंग बदलें"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"ट्रांसकोडिंग चालू करें"</string>
     <string name="transcode_default" msgid="3784803084573509491">"मानकर चलें कि ऐप्लिकेशन, नए फ़ॉर्मैट के साथ काम करेंगे"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"ट्रांसकोडिंग की सूचनाएं दिखाएं"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"चल रही सेवाएं"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"इस समय चल रही सेवाओं को देखें और नियंत्रित करें"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"वेबव्यू लागू करें"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"डेटा सि‍ग्‍नल पूरा."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ईथरनेट डिस्‍कनेक्‍ट किया गया."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ईथरनेट."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"वॉइस कॉल की सुविधा उपलब्ध नहीं है."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 5e33ef3..27a7a6e 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Nadjačaj zadane postavke konvertiranja"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Omogući konvertiranje"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Pretpostavi da aplikacije podržavaju moderne formate"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Prikaži obavijesti o konvertiranju"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Pokrenute usluge"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Pregledajte i kontrolirajte pokrenute usluge"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementacija WebViewa"</string>
@@ -593,6 +594,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Podatkovni signal pun."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Prekinuta je veza s ethernetom."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Bez poziva."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 28975be..70a48b6 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Az átkódolás alapértelmezett beállításainak felülbírálása"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Átkódolás engedélyezése"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Annak feltételezése, hogy az alkalmazások támogatják a modern formátumokat"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Átkódolási értesítések megjelenítése"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Futó szolgáltatások"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"A jelenleg futó szolgáltatások megtekintése és vezérlése"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-megvalósítás"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Adatjel teljes."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet leválasztva."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Nem kezdeményezhet hanghívást."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index a207526..c39e966 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Չեղարկել վերակոդավորման կանխադրված կարգավորումները"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Միացնել վերակոդավորումը"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Ենթադրել, որ հավելվածներն աջակցում են ժամանակակից ձևաչափեր"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Ցուցադրել անդրկոդավորման ծանուցումներ"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Աշխատող ծառայություններ"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Դիտել և վերահսկել ընթացիկ աշխատող ծառայությունները"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ծառայություն"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Տվյալների ազդանշանը լրիվ է:"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet-ը անջատված է:"</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet։"</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Զանգել հնարավոր չէ։"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index c4d752d..037c1b3 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Ganti default transcoding"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Aktifkan transcoding"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Asumsikan aplikasi mendukung format modern"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Tampilkan notifikasi transcoding"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Layanan yang sedang berjalan"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Melihat dan mengontrol layanan yang sedang berjalan"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Penerapan WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Sinyal data penuh."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet terputus."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Tidak ada panggilan."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 56b0a81..3f87830 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Hnekkja sjálfgefinni umkóðun"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Kveikja á umkóðun"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Gera ráð fyrir að forrit styðji nútímasnið"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Sýna umkóðunartilkynningar"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Þjónustur í gangi"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Skoða og stjórna þjónustum í gangi"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Innleiðing WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Fullur sendistyrkur gagnatengingar."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet aftengt."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Engin símtöl."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index f045d27..80ab57b 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Sostituisci impostazioni predefinite transcodifica"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Attiva transcodifica"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Presupponi che le app supportino i formati moderni"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Mostra notifiche relative alla transcodifica"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Servizi in esecuzione"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualizza e controlla i servizi attualmente in esecuzione"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementazione di WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Massimo segnale dati."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Connessione Ethernet annullata."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Chiamate non disponibili."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index ba3a467..4355f31 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"ביטול ברירות המחדל של המרת קידוד"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"הפעלת המרת קידוד"</string>
     <string name="transcode_default" msgid="3784803084573509491">"הנחת העבודה היא שאפליקציות תומכות בפורמטים מודרניים"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"הצגת התראות לגבי המרת קידוד"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"שירותים פועלים"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"הצגת השירותים הפועלים כעת ושליטה בהם"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"‏יישום WebView"</string>
@@ -594,6 +595,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"אות הנתונים מלא."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"אתרנט מנותק."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"אתרנט."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"אין שיחות."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 6f398b6..ea4a683 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"デフォルトのコード変換をオーバーライド"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"コード変換を有効にする"</string>
     <string name="transcode_default" msgid="3784803084573509491">"アプリによる最新形式のサポートを想定"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"コード変換に関する通知の表示"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"実行中のサービス"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"現在実行中のサービスを表示して制御する"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView の実装"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"データ信号:フル"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"イーサネット接続を解除しました。"</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"イーサネット。"</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"通話なし。"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 5bf1dd0..5798a46 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"ტრანსკოდირების ნაგულისხმევების უგულებელყოფა"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"ტრანსკოდირების ჩართვა"</string>
     <string name="transcode_default" msgid="3784803084573509491">"დაშვება, რომ აპებს აქვთ თანამედროვე ფორმატების მხარდაჭერა"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"ტრანსკოდირების შეტყობინებების ჩვენება"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"მიმდინარე სერვისები"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"ამჟამად მოქმედი სერვისების ნახვა და მართვა"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView რეალიზაცია"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"მონაცემთა გადაცემის საიმედო სიგნალი."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet კავშირი შეწყვეტილია."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"ზარების გარეშე."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index c7c3837..5ce4e3a 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Қайта қодтаудың әдепкі параметрлерін қайта анықтау"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Қайта кодтауды қосу"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Қолданбалар қазіргі заманғы форматтарды қолдайды делік"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Қайта кодтау хабарландыруларын көрсету"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Қосылып тұрған қызметтер"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Қазір істеп тұрған қызметтерді көру және басқару"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView қызметі"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Дерекқор сигналы толы."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet ажыратылған."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Қоңырау шалу мүмкін емес."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 99a73e1..e6f2cb0 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"លុបពីលើលំនាំដើម​នៃការបំប្លែងកូដ"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"បើក​ការបំប្លែងកូដ"</string>
     <string name="transcode_default" msgid="3784803084573509491">"សន្មតថាកម្មវិធី​អាចប្រើ​ទម្រង់ទំនើបបាន"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"បង្ហាញការជូនដំណឹង​អំពីការបំប្លែងកូដ"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"សេវាកម្ម​កំពុង​ដំណើរការ"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"មើល និង​គ្រប់គ្រង​សេវាកម្ម​កំពុង​ដំណើរការ​បច្ចុប្បន្ន"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"ការអនុវត្ត WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"សញ្ញា​ទិន្នន័យ​ពេញ។"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"បានផ្តាច់អ៊ីសឺរណិត។"</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"អ៊ីសឺរណិត។"</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"គ្មាន​ការហៅ​ទូរសព្ទទេ​។"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 54a42a8..561e6be 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -404,6 +404,8 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"ಟ್ರಾನ್ಸ್‌ಕೋಡಿಂಗ್ ಡೀಫಾಲ್ಟ್‌ಗಳನ್ನು ಅತಿಕ್ರಮಿಸಿ"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"ಟ್ರಾನ್ಸ್‌ಕೋಡಿಂಗ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
     <string name="transcode_default" msgid="3784803084573509491">"ಆ್ಯಪ್‌ಗಳು ಆಧುನಿಕ ಫಾರ್ಮ್ಯಾಟ್‌ಗಳನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ ಎಂದು ಊಹಿಸಿ"</string>
+    <!-- no translation found for transcode_notification (5560515979793436168) -->
+    <skip />
     <string name="runningservices_settings_title" msgid="6460099290493086515">"ರನ್‌ ಆಗುತ್ತಿರುವ ಸೇವೆಗಳು"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"ಈಗ ರನ್‌ ಆಗುತ್ತಿರುವ ಸೇವೆಗಳನ್ನು ವೀಕ್ಷಿಸಿ ಮತ್ತು ನಿಯಂತ್ರಿಸಿ"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ಹೊಂದಿಸಿ"</string>
@@ -592,6 +594,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ಡೇಟಾ ಸಂಕೇತ ತುಂಬಿದೆ."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ಇಥರ್ನೆಟ್ ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ಇಥರ್ನೆಟ್."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"ಕರೆ ಮಾಡಲಾಗುವುದಿಲ್ಲ."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 9e9fea9..cd3b8b8 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"트랜스코딩 기본값 재정의"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"트랜스코딩 사용"</string>
     <string name="transcode_default" msgid="3784803084573509491">"앱이 최신 형식을 지원하는 것으로 가정"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"트랜스코딩 알림 표시"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"실행 중인 서비스"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"현재 실행 중인 서비스 보기 및 제어"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView 구현"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"데이터 신호가 강합니다."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"이더넷에서 연결 해제되었습니다."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"이더넷에 연결되었습니다."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"통화 모드가 없습니다."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 2aec5cb..1990353 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Демейки жүргүзүлгөн транскоддоону өзгөртүп коюу"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Транскоддоо жүргүзүүнү иштетүү"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Колдонмолордо заманбап форматтар колдоого алынат"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Транскоддоо билдирмелерин көрсөтүү"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Иштеп жаткан кызматтар"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Учурда иштеп жаткан кызматтарды көрүп, көзөмөлдөп турасыз"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView кызматы"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Мобилдик интернеттин сигналы толук."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet ажырады."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Чалуу жок."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index e199e1f..4997ea1 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"ຍົກເລີກຄ່າເລີ່ມຕົ້ນການ​ປ່ຽນ​ຮູບ​ແບບ​ລະ​ຫັດ"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"ເປີດການນຳໃຊ້ການ​ປ່ຽນ​ຮູບ​ແບບ​ລະ​ຫັດ"</string>
     <string name="transcode_default" msgid="3784803084573509491">"ສົມມຸດວ່າແອັບຮອງຮັບຮູບແບບສະໄໝໃໝ່"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"ສະແດງການແຈ້ງເຕືອນການ​ປ່ຽນ​ຮູບ​ແບບ​ລະ​ຫັດ"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"ບໍລິການທີ່ເຮັດວຽກຢູ່"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"ເບິ່ງ ແລະຈັດການບໍລິການທີ່ກຳລັງເຮັດວຽກຢູ່ໃນປັດຈຸບັນ"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"ການຈັດຕັ້ງປະຕິບັດ WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ສັນ​ຍານຂໍ້ມູນ​ເຕັມ."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ອີ​ເທີ​ເນັດ​ຕັດ​ເຊື່ອມ​ຕໍ່​ແລ້ວ."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ອີເທີເນັດ."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"ບໍ່ສາມາດໂທສຽງໄດ້."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index a25c59f5..ec3cb0d 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Perkodavimo numatytųjų nustatymų nepaisymas"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Perkodavimo įgalinimas"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Manoma, kad programos palaiko modernius formatus"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Rodyti perkodavimo pranešimus"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Vykdomos paslaugos"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Žiūrėti ir valdyti dabar vykdomas paslaugas"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"„WebView“ diegimas"</string>
@@ -594,6 +595,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Stiprus duomenų signalas."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Atsijungta nuo eterneto."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Eternetas."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Nekviečiama."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index f360c90..ff9f0a1 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Ignorēt pārkodēšanas noklusējuma iestatījumus"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Iespējot pārkodēšanu"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Pieņemt, ka lietotnēs tiek atbalstīti moderni formāti"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Rādīt paziņojumus par pārkodēšanu"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Aktīvie pakalpojumi"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Pašreiz darbojošos pakalpojumu skatīšana un vadība"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ieviešana"</string>
@@ -593,6 +594,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Pilna piekļuve datu signālam."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Pārtraukts savienojums ar tīklu Ethernet."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Tīkls Ethernet"</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Zvanīšana nav pieejama."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index a32d00b..507f65c 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Отфрли стандардни вредности за транскодирање"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Овозможи транскодирање"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Претпостави дека апликациите поддржуваат модерни формати"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Прикажувај известувања за транскодирање"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Активни услуги"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Погледнете и контролирајте услуги што се моментално активни"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Воведување WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Сигналот за податоци е исполнет."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Етернетот е исклучен."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Етернет."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Без повици."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 902507d..8a09801 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"ട്രാൻസ്കോഡ് ചെയ്യൽ ഡിഫോൾട്ടുകൾ അസാധുവാക്കുക"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"ട്രാൻസ്കോഡ് ചെയ്യൽ പ്രവർത്തനക്ഷമമാക്കുക"</string>
     <string name="transcode_default" msgid="3784803084573509491">"ആപ്പുകൾ ആധുനിക ഫോർമാറ്റുകളെ പിന്തുണയ്ക്കുമെന്ന് കരുതുക"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"ട്രാൻസ്കോഡ് ചെയ്യൽ അറിയിപ്പുകൾ കാണിക്കുക"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"പ്രവർത്തിക്കുന്ന സേവനങ്ങൾ"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"നിലവിൽ പ്രവർത്തിക്കുന്ന സേവനങ്ങൾ കാണുക, നിയന്ത്രിക്കുക"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView നടപ്പാക്കൽ"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ഡാറ്റ സിഗ്‌നൽ പൂർണ്ണമാണ്."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ഇതർനെറ്റ് വിച്ഛേദിച്ചു."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ഇതർനെറ്റ്."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"വോയ്‌സ് കോൾ ലഭ്യമല്ല."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 83009b7..27ca8f5 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Хөрвүүлгийн өгөгдмөлийг дарах"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Хөрвүүлгийг идэвхжүүлэх"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Аппыг орчин үеийн форматыг дэмждэг гэж үздэг"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Хөрвүүлгийн мэдэгдэл харуулах"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Ажиллаж байгаа үйлчилгээнүүд"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Одоо ажиллаж байгаа үйлчилгээнүүдийг харах болон хянах"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView хэрэгжилт"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Дата дохио дүүрэн."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet саллаа."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Этернэт."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Дуудлага байхгүй."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 359f525..b6c5460 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -404,6 +404,8 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"ट्रान्सकोडिंग डीफॉल्ट ओव्हरराइड करा"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"ट्रान्सकोडिंग सुरू करा"</string>
     <string name="transcode_default" msgid="3784803084573509491">"असे गृहीत धरा की, ॲप्स आधुनिक फॉरमॅटना सपोर्ट करतात"</string>
+    <!-- no translation found for transcode_notification (5560515979793436168) -->
+    <skip />
     <string name="runningservices_settings_title" msgid="6460099290493086515">"सुरू सेवा"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"सध्या सुरू असलेल्या सेवा पहा आणि नियंत्रित करा"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"वेबदृश्य अंमलबजावणी"</string>
@@ -592,6 +594,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"डेटा सिग्नल पूर्ण."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"इथरनेट डिस्कनेक्ट केले."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"इथरनेट."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"कॉलिंग उपलब्ध नाही."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index eba89da..53a4398 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Batalkan transpengekodan lalai"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Dayakan transpengekodan"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Mengambil alih sokongan apl format moden"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Tunjukkan pemberitahuan transpengekodan"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Perkhidmatan dijalankan"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Lihat dan kawal perkhidmatan yang sedang dijalankan"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Pelaksanaan WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Isyarat data penuh."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet diputuskan sambungan."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Tiada panggilan."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index e982aa9..0fef5ab 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -307,7 +307,7 @@
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"သင် ယခင်က ခွင့်ပြုခဲ့သော ကွန်ပျူတာအားလုံးမှ ယူအက်စ်ဘီ အမှားစစ်ခွင့်ကို ရုတ်သိမ်းမည်လား ?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"တည်ဆောက်ပြုပြင်ရန်ဆက်တင်များကို အသုံးပြုခွင့်ပေးမည်လား?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"ဤဆက်တင်းများကို တည်ဆောက်ပြုပြင်ရာတွင် သုံးရန်အတွက်သာ ရည်ရွယ်သည်။ ၎င်းတို့သည် သင်၏စက်နှင့် အပလီကေးရှင်းများကို ရပ်စေခြင်း သို့ လုပ်ဆောင်ချက်မမှန်ကန်ခြင်းများ ဖြစ်ပေါ်စေနိုင်သည်။"</string>
-    <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"USB ဖြင့် အက်ပ်များကို အတည်ပြုစိစစ်ရန်"</string>
+    <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"USB ဖြင့် အက်ပ်များစိစစ်ရန်"</string>
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT မှတစ်ဆင့် ထည့်သွင်းသော အက်ပ်များ အန္တရာယ်ဖြစ်နိုင်ခြင်း ရှိမရှိ စစ်ဆေးသည်။"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"အမည်မရှိသော (MAC လိပ်စာများသာပါသော) ဘလူးတုသ်စက်ပစ္စည်းများကို ပြသပါမည်"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"ချိတ်ဆက်ထားသည့် ကိရိယာတွင် လက်မခံနိုင်လောက်အောင် ဆူညံ သို့မဟုတ် ထိန်းညှိမရနိုင်သော အသံပိုင်းပြဿနာ ရှိခဲ့လျှင် ဘလူးတုသ် ပကတိ အသံနှုန်းကို ပိတ်ပါ။"</string>
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"အမျိုးအစားပြောင်းခြင်း၏ မူရင်းဆက်တင်များကို အစားထိုးရန်"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"အမျိုးအစားပြောင်းခြင်းကို ဖွင့်ရန်"</string>
     <string name="transcode_default" msgid="3784803084573509491">"ဤအက်ပ်များက ဖော်မက်အသစ်များကို ပံ့ပိုးသည်"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"အမျိုးအစားပြောင်းခြင်း အကြောင်းကြားချက်များကို ပြရန်"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"အလုပ်လုပ်နေသောဝန်ဆောင်မှုများ"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"လက်ရှိ ဝန်ဆောင်မှုများကို ကြည့်ရှု ထိန်းသိမ်းသည်"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView အကောင်အထည်ဖော်မှု"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ဒေတာထုတ်လွှင့်မှုအပြည့်ဖမ်းမိခြင်း"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet နှင့်ချိတ်ဆက်မှုပြတ်တောက်"</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"အီသာနက်။"</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"ခေါ်ဆိုမှု မရှိပါ။"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index abbb5e7..0ca8d51 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Overstyr omkodingsstandarder"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Slå på omkoding"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Anta at apper støtter moderne formater"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Vis omkodingsvarsler"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Aktive tjenester"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Se og kontrollér tjenester som kjører"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementering"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Datasignal er fullt."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet er frakoblet."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Ingen ringing."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index d7a32bf..75b4537 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -404,6 +404,8 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"ट्रान्सकोडिङसम्बन्धी पूर्वनिर्धारित सेटिङ परिवर्तन गर्नुहोस्"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"ट्रान्सकोडिङ अन गर्नुहोस्"</string>
     <string name="transcode_default" msgid="3784803084573509491">"एपहरूमा आधुनिक फर्म्याट प्रयोग गर्न मिल्छ भनी मान्नुहोस्"</string>
+    <!-- no translation found for transcode_notification (5560515979793436168) -->
+    <skip />
     <string name="runningservices_settings_title" msgid="6460099290493086515">"चलिरहेका सेवाहरू"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"हाल चालु भइरहेका सेवाहरू हेर्नुहोस् र नियन्त्रण गर्नुहोस्"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView कार्यान्वयन"</string>
@@ -592,6 +594,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"डेटा संकेत पूर्ण।"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"इथरनेट विच्छेद भयो।"</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"इथरनेट।"</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"कल गर्ने सुविधा उपलब्ध छैन।"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 7e739bc..71d6acc 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Standaardwaarden voor transcodering overschrijven"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Transcodering inschakelen"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Aannemen dat apps moderne indelingen ondersteunen"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Transcoderingsmeldingen laten zien"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Actieve services"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Services die momenteel actief zijn, weergeven en beheren"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementatie"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Gegevenssignaal is op volle sterkte."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernetverbinding verbroken."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Geen gesprekken."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 1e842b7..1d6e34f 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"ଟ୍ରାନ୍ସକୋଡିଂ ଡିଫଲ୍ଟଗୁଡ଼ିକୁ ଓଭରରାଇଡ୍ କରନ୍ତୁ"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"ଟ୍ରାନ୍ସକୋଡିଂକୁ ସକ୍ଷମ କରନ୍ତୁ"</string>
     <string name="transcode_default" msgid="3784803084573509491">"ଧରିନିଅନ୍ତୁ ଆପଗୁଡ଼ିକ ଆଧୁନିକ ଫର୍ମାଟଗୁଡ଼ିକୁ ସମର୍ଥନ କରେ"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"ଟ୍ରାନ୍ସକୋଡିଂ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ଦେଖାନ୍ତୁ"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"ଚାଲୁଥିବା ସେବାଗୁଡ଼ିକ"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"ଏବେ ଚାଲୁଥିବା ସେବାଗୁଡ଼ିକୁ ଦେଖନ୍ତୁ ଓ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"ୱେବ୍‌ଭ୍ୟୁ ପ୍ରୟୋଗ"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ଡାଟା ସିଗ୍ନାଲ୍ ପୂର୍ଣ୍ଣ ଅଛି।"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ଇଥରନେଟ୍‍ ବିଚ୍ଛିନ୍ନ ହୋଇଛି।"</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ଇଥରନେଟ୍।"</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"କୌଣସି କଲିଂ ନାହିଁ।"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index d035fc0..9d91aae 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -404,6 +404,8 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਦੀਆਂ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਸੈਟਿੰਗਾਂ ਨੂੰ ਓਵਰਰਾਈਡ ਕਰੋ"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਚਾਲੂ ਕਰੋ"</string>
     <string name="transcode_default" msgid="3784803084573509491">"ਮੰਨ ਲਓ ਕਿ ਐਪਾਂ ਆਧੁਨਿਕ ਫਾਰਮੈਟਾਂ ਦਾ ਸਮਰਥਨ ਕਰਦੀਆਂ ਹਨ"</string>
+    <!-- no translation found for transcode_notification (5560515979793436168) -->
+    <skip />
     <string name="runningservices_settings_title" msgid="6460099290493086515">"ਚੱਲ ਰਹੀਆਂ ਸੇਵਾਵਾਂ"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"ਇਸ ਵੇਲੇ ਚੱਲ ਰਹੀਆਂ ਸੇਵਾਵਾਂ ਦੇਖੋ ਅਤੇ ਇਹਨਾਂ ਨੂੰ ਕੰਟਰੋਲ ਕਰੋ"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ਅਮਲ"</string>
@@ -592,6 +594,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">" ਡਾਟਾ  ਸਿਗਨਲ ਪੂਰਾ।"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ਈਥਰਨੈੱਟ ਡਿਸਕਨੈਕਟ ਹੋ ਗਿਆ।"</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ਈਥਰਨੈੱਟ।"</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"ਕਾਲਿੰਗ ਸੇਵਾ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 8a732cb..f48b05f 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Zastąp ustawienia domyślne transkodowania"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Włącz transkodowanie"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Zakładaj, że aplikacje obsługują nowoczesne formaty"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Pokaż powiadomienia transkodowania"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Uruchomione usługi"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Wyświetl obecnie uruchomione usługi i nimi zarządzaj"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementacja WebView"</string>
@@ -594,6 +595,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Dane: pełna moc sygnału."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Rozłączono z siecią Ethernet."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Brak połączenia."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index a63b9b5..b9c9191 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Substituir os padrões de transcodificação"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Ativar transcodificação"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Considerar que os apps são compatíveis com formatos modernos"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Mostrar notificações de transcodificação"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Serviços em execução"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualizar e controlar os serviços em execução no momento"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementação do WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Sinal de dados cheio."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet desconectada."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Sem chamadas."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index ab23059..57e38c078 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Substituir as predefinições da transcodificação"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Ativar a transcodificação"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Assumir que as apps suportam formatos modernos"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Mostrar notificações de transcodificação"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Serviços em execução"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ver e controlar os serviços actualmente em execução"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementação WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Sinal de dados completo."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet desligada."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Sem chamadas."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index a63b9b5..b9c9191 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Substituir os padrões de transcodificação"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Ativar transcodificação"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Considerar que os apps são compatíveis com formatos modernos"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Mostrar notificações de transcodificação"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Serviços em execução"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualizar e controlar os serviços em execução no momento"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementação do WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Sinal de dados cheio."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet desconectada."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Sem chamadas."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 98edb32..c2da73c 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Modificați setările prestabilite de transcodare"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Activați transcodarea"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Presupuneți că aplicațiile acceptă formatele moderne"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Vedeți notificările privind transcodarea"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Servicii în curs de funcționare"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Vedeți și controlați serviciile care funcționează în prezent"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementare WebView"</string>
@@ -593,6 +594,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Semnal pentru date: complet."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet deconectat."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Apelarea nu este disponibilă."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 972dc20..efcce75 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Переопределять настройки транскодирования по умолчанию"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Включить перекодирование"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Считать, что приложения поддерживают современные форматы кодирования"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Показывать уведомления о перекодировании"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Работающие службы"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Просмотр и управление работающими службами"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Сервис WebView"</string>
@@ -594,6 +595,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Надежный сигнал передачи данных."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Устройство отключено от Ethernet."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Совершение вызовов невозможно."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 0dee8e1..590e0e4 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"ට්‍රාන්ස්කෝඩින් පෙරනිමි ප්‍රතික්ෂේප කරන්න"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"ට්‍රාන්ස්කෝඩින් සබල කරන්න"</string>
     <string name="transcode_default" msgid="3784803084573509491">"යෙදුම් නවීන ආකෘති සඳහා සහාය දක්වයි යැයි උපකල්පනය කරමු"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"ට්‍රාන්ස්කෝඩින් දැනුම්දීම් පෙන්වන්න"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"ධාවනය වන සේවා"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"දැනට ධාවනය වන සේවා බලන්න සහ පාලනය කරන්න"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ක්‍රියාත්මක කිරීම"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"දත්ත සංඥාව පිරී ඇත."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ඊතර්නෙට් විසන්ධි කරන ලදී."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ඊතර්නෙට්."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"ඇමතුම් නැත."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 7d49ca3..c817ed0 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Prepísať predvolené nastavenia prekódovania"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Povoliť prekódovanie"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Prepdokladať, že aplikácie podporujú moderné formáty"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Zobraziť upozornenia prekódovania"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Spustené služby"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Zobrazovať a riadiť aktuálne spustené služby"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementácia WebView"</string>
@@ -594,6 +595,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Plný signál dátovej siete."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Sieť ethernet je odpojená"</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Žiadne volanie."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 48e5dcc..464b235 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Preglasi privzete nastavitve prekodiranja"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Omogoči prekodiranje"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Aplikacije naj bi podpirale sodobne oblike zapisov"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Prikaz obvestil o prekodiranju"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Zagnane storitve"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Preglejte in nadzorujte storitve, ki so trenutno zagnane"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Izvedba spletnega pogleda"</string>
@@ -594,6 +595,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Podatkovni signal poln."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernetna povezava je prekinjena."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet"</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Klicanje ni mogoče."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 0bc905e..a2a63e1 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Anulo parazgjedhjet e transkodimit"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Aktivizo transkodimin"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Supozo se aplikacionet i mbështetin formatet moderne"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Shfaq njoftimet e transkodimit"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Shërbimet në ekzekutim"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Shiko dhe kontrollo shërbimet që po ekzekutohen aktualisht"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Zbatimi i WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Sinjali i të dhënave është i plotë."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Lidhja e eternetit u shkëput."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Eternet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Telefonatat nuk ofrohen"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 6d19af8..2119303 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Замени подразумевана подешавања транскодирања"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Омогући транскодирање"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Подразумевај да апликације подржавају модерне формате"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Приказуј обавештења о транскодирању"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Покренуте услуге"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Приказ и контрола тренутно покренутих услуга"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Примена WebView-а"</string>
@@ -593,6 +594,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Сигнал за податке је најјачи."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Веза са етернетом је прекинута."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Етернет."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Без позивања."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 944c423..c7a2169 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Åsidosätta standardinställningar för omkodning"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Aktivera omkodning"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Anta att appar har stöd för moderna format"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Visa aviseringar för omkodning"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Aktiva tjänster"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Visa och styr aktiva tjänster"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementering"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Datasignalen är full."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet har kopplats från."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Inga anrop."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 442f54b..60014f4 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Batilisha chaguomsingi za kubadilisha miundo ya faili"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Ruhusu ubadilishaji wa miundo ya faili"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Chukulia kuwa programu zinatumia miundo ya kisasa"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Onyesha arifa za kubadilisha muundo wa faili"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Huduma zinazoendeshwa"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Onyesha na udhibiti huduma zinazoendeshwa kwa sasa"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Utekelezaji wa WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Ishara ya data imejaa."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethaneti imeondolewa."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethaneti."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Huwezi kupiga wala kupokea simu."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 561a122..82cce12 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"இயல்புநிலை குறிமாற்றங்களை மீறிச் செயல்படு"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"குறிமாற்றத்தை இயக்கு"</string>
     <string name="transcode_default" msgid="3784803084573509491">"ஆப்ஸ் மாடர்ன் வடிவங்களை ஆதரிக்கும்படி அமை"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"குறிமாற்ற அறிவிப்புகளைக் காட்டு"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"இயங்கும் சேவைகள்"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"தற்போது இயக்கத்தில் இருக்கும் சேவைகளைப் பார்த்து கட்டுப்படுத்து"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView செயல்படுத்தல்"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"தரவு சிக்னல் முழுமையாக உள்ளது."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ஈத்தர்நெட் துண்டிக்கப்பட்டது."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ஈதர்நெட்."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"அழைப்பை மேற்கொள்ள முடியவில்லை."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 18d7f28..3b04eb4 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"ట్రాన్స్‌కోడింగ్ ఆటోమేటిక్ సెట్టింగ్‌లను ఓవర్‌రైడ్ చేయండి"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"ట్రాన్స్‌కోడింగ్‌ను ఎనేబుల్ చేయండి"</string>
     <string name="transcode_default" msgid="3784803084573509491">"యాప్‌లు ఆధునిక ఫార్మాట్‌లకు సపోర్ట్ చేస్తాయని అనుకోండి"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"ట్రాన్స్‌కోడింగ్ నోటిఫికేషన్‌లను చూపండి"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"అమలులో ఉన్న సేవలు"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"ప్రస్తుతం అమలులో ఉన్న సేవలను వీక్షించండి మరియు నియంత్రించండి"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"వెబ్ వీక్షణ అమలు"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"డేటా సిగ్నల్ సంపూర్ణంగా ఉంది."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ఈథర్‌నెట్ డిస్‌కనెక్ట్ చేయబడింది."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ఈథర్‌నెట్."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"కాలింగ్ మోడ్ ఆఫ్‌లో ఉంది."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index ceab26c..a970321 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"ลบล้างค่าเริ่มต้นของการแปลง"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"เปิดใช้การแปลง"</string>
     <string name="transcode_default" msgid="3784803084573509491">"ถือว่าแอปรองรับรูปแบบสมัยใหม่"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"แสดงการแจ้งเตือนการแปลง"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"บริการที่ทำงานอยู่"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"ดูและควบคุมบริการที่ทำงานอยู่"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"การใช้งาน WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"สัญญาณข้อมูลเต็ม"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ยกเลิกการเชื่อมต่ออีเทอร์เน็ตแล้ว"</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"อีเทอร์เน็ต"</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"ไม่มีการโทร"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 671fa14..bedd005 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"I-override ang mga default ng pagta-transcode"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"I-enable ang pagta-transcode"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Ipagpalagay na sinusuportahan ng mga app ang mga modernong format"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Ipakita ang mga notification sa pag-transcode"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Mga tumatakbong serbisyo"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Tingnan at kontrolin ang mga kasalukuyang tumatakbong serbisyo"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Pagpapatupad sa WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Puno ang signal ng data."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Nadiskonekta ang Ethernet."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Hindi makakatawag."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 98d89f3..2b2b44e 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Kod dönüştürme varsayılanlarını geçersiz kıl"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Kod dönüştürmeyi etkinleştir"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Uygulamaların modern biçimleri desteklediğini varsay"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Kod dönüştürme bildirimlerini göster"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Çalışan hizmetler"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Şu anda çalışan hizmetleri görüntüle ve denetle"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Web Görünümü kullanımı"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Veri sinyali tam."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet bağlantısı kesildi."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Çağrı yok."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 4e739ac..9c5e2aa 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Замінити стандартні налаштування перекодування"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Увімкнути перекодування"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Вважати, що додатки підтримують сучасні формати"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Показувати сповіщення про перекодування"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Запущені сервіси"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Переглянути й налаштувати запущені сервіси"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Застосування WebView"</string>
@@ -594,6 +595,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Максимальний сигнал даних."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet відключено."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Виклики недоступні."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index c7dee95..ee06623 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"ٹرانسکوڈنگ ڈیفالٹس کو اوور رائیڈ کریں"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"ٹرانسکوڈنگ فعال کریں"</string>
     <string name="transcode_default" msgid="3784803084573509491">"فرض کریں کہ ایپس جدید فارمیٹس کو سپورٹ کرتی ہیں"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"ٹرانسکوڈنگ اطلاعات دکھائیں"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"چل رہی سروسز"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"فی الحال چل رہی سروسز دیکھیں اور انہیں کنٹرول کریں"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"‏WebView کا نفاذ"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ڈیٹا سگنل بھرا ہوا ہے۔"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ایتھرنیٹ منقطع ہے۔"</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ایتھرنیٹ۔"</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"کوئی کالنگ نہیں ہے۔"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 433096b..29c0f91 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Transkripsiya parametrlarini almashtirish"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Transkripsiyasini yoqish"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Ilovalarda zamonaviy kodlash formatlari ishlaydi deb hisoblash"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Transkripsiya bildirishnomalarini chiqarish"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Ishlab turgan ilovalar"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ishlab turgan ilovalarni ko‘rish va boshqarish"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ta’minotchisi"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Internet signali butun."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Qurilma Ethernet tarmog‘idan uzildi."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Chaqiruv imkonsiz."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index a14462b..39beecd 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Ghi đè tùy chọn chuyển mã mặc định"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Bật tính năng chuyển mã"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Giả định rằng các ứng dụng hỗ trợ định dạng hiện đại"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Hiển thị thông báo chuyển mã"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Các dịch vụ đang chạy"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Xem và kiểm soát các dịch vụ đang chạy"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Triển khai WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Tín hiệu dữ liệu đầy đủ."</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Đã ngắt kết nối Ethernet."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Không thể gọi điện."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index f6bea91..010a4dc 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"覆盖转码默认设置"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"启用转码"</string>
     <string name="transcode_default" msgid="3784803084573509491">"假设应用支持现代格式"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"显示转码通知"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"正在运行的服务"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"查看和控制当前正在运行的服务"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView 实现"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"数据信号满格。"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"以太网已断开连接。"</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"以太网。"</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"不启用通话。"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 3cf15a9..1e06a91 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"覆寫轉碼預設設定"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"啟用轉碼功能"</string>
     <string name="transcode_default" msgid="3784803084573509491">"假設應用程式支援新型格式"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"顯示轉碼通知"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"執行中的服務"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"查看並控制目前正在執行中的服務"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView 設置"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"數據網絡訊號滿格。"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"以太網連接中斷。"</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"以太網絡。"</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"不啟用通話。"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 7cf0297..2c077e7 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"覆寫轉碼預設設定"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"啟用轉碼"</string>
     <string name="transcode_default" msgid="3784803084573509491">"假設應用程式支援新格式"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"顯示轉碼通知"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"正在運作的服務"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"查看並管理目前正在執行的服務"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView 實作"</string>
@@ -434,9 +435,9 @@
     <skip />
     <string name="power_discharge_by_enhanced" msgid="563438403581662942">"根據你的使用情形,目前電量為 <xliff:g id="LEVEL">%2$s</xliff:g>,預估可持續使用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_discharge_by_only_enhanced" msgid="3268796172652988877">"根據你的使用情形,預估可持續使用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_discharge_by" msgid="4113180890060388350">"目前電量 <xliff:g id="LEVEL">%2$s</xliff:g>,預估還能持續使用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_discharge_by" msgid="4113180890060388350">"目前電量 <xliff:g id="LEVEL">%2$s</xliff:g>,預估可用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_discharge_by_only" msgid="92545648425937000">"預估電力大約可使用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_discharge_by_only_short" msgid="5883041507426914446">"還能持續使用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_discharge_by_only_short" msgid="5883041507426914446">"可用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"電池電力可能於<xliff:g id="TIME">%1$s</xliff:g> 前耗盡"</string>
     <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"電池可用時間不到 <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration" msgid="318215464914990578">"電池可用時間不到 <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"數據網路訊號滿格。"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"未連上乙太網路。"</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"乙太網路。"</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"不顯示在螢幕上。"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index d950d58..87cf75b 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -404,6 +404,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"Khipha okuzenzakalelayo kokudlulisela ikhodi"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"Nika amandla ukudlulisela ikhodi"</string>
     <string name="transcode_default" msgid="3784803084573509491">"Kuthathe njengokungathi izinhlelo zokusebenza zisekela amafomethi esimanje"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"Bonisa izaziso zokudlulisela ikhodi"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Amasevisi asebenzayo"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Buka futhi ulawule amasevisi  asebenzayo okwamanje"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Ukufakwa ke-WebView"</string>
@@ -592,6 +593,5 @@
     <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Igcwele i-signal yedatha"</string>
     <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"I-Ethernet inqanyuliwe."</string>
     <string name="accessibility_ethernet_connected" msgid="6175942685957461563">"I-Ethernet."</string>
-    <!-- no translation found for accessibility_no_calling (3540827068323895748) -->
-    <skip />
+    <string name="accessibility_no_calling" msgid="3540827068323895748">"Akukho ukwenza ikholi"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 3866151..79fbcc3 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1007,6 +1007,9 @@
     <!-- Settings item title to select the default behavior for transcoding if an encodig is not supported by an app. [CHAR LIMIT=85] -->
     <string name="transcode_default">Assume apps support modern formats</string>
 
+    <!-- Settings item title to select whether to show transcoding notifications. [CHAR LIMIT=85] -->
+    <string name="transcode_notification">Show transcoding notifications</string>
+
     <!-- Services settings screen, setting option name for the user to go to the screen to view running services -->
     <string name="runningservices_settings_title">Running services</string>
     <!-- Services settings screen, setting option summary for the user to go to the screen to view running services  -->
diff --git a/packages/SettingsLib/search/Android.bp b/packages/SettingsLib/search/Android.bp
index d398aa5..45746d9 100644
--- a/packages/SettingsLib/search/Android.bp
+++ b/packages/SettingsLib/search/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLib-search",
     srcs: ["src/**/*.java"],
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 4c80b91..5e2d21b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -851,11 +851,12 @@
         if (BluetoothUuid.containsAnyUuid(uuids, PbapServerProfile.PBAB_CLIENT_UUIDS)) {
             // The pairing dialog now warns of phone-book access for paired devices.
             // No separate prompt is displayed after pairing.
+            final BluetoothClass bluetoothClass = mDevice.getBluetoothClass();
             if (mDevice.getPhonebookAccessPermission() == BluetoothDevice.ACCESS_UNKNOWN) {
-                if (mDevice.getBluetoothClass().getDeviceClass()
-                        == BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE ||
-                    mDevice.getBluetoothClass().getDeviceClass()
-                        == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET) {
+                if (bluetoothClass != null && (bluetoothClass.getDeviceClass()
+                        == BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE
+                        || bluetoothClass.getDeviceClass()
+                        == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET)) {
                     EventLog.writeEvent(0x534e4554, "138529441", -1, "");
                 }
                 mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_REJECTED);
diff --git a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
index 81ca9ea..228de03 100644
--- a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
+++ b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
@@ -163,8 +163,12 @@
         long locationAccessFinishTime = 0L;
         // Earliest time for a location access to end and still be shown in list.
         long recentLocationCutoffTime = now - RECENT_TIME_INTERVAL_MILLIS;
+        // Compute the most recent access time from all op entries.
         for (AppOpsManager.OpEntry entry : entries) {
-            locationAccessFinishTime = entry.getLastAccessTime(TRUSTED_STATE_FLAGS);
+            long lastAccessTime = entry.getLastAccessTime(TRUSTED_STATE_FLAGS);
+            if (lastAccessTime > locationAccessFinishTime) {
+                locationAccessFinishTime = lastAccessTime;
+            }
         }
         // Bail out if the entry is out of date.
         if (locationAccessFinishTime < recentLocationCutoffTime) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index 32419f4..1f3e0e9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -205,7 +205,6 @@
 
     void dispatchDeviceListUpdate() {
         final List<MediaDevice> mediaDevices = new ArrayList<>(mMediaDevices);
-        Collections.sort(mediaDevices, COMPARATOR);
         for (DeviceCallback callback : getCallbacks()) {
             callback.onDeviceListUpdate(mediaDevices);
         }
@@ -472,6 +471,7 @@
             synchronized (mMediaDevicesLock) {
                 mMediaDevices.clear();
                 mMediaDevices.addAll(devices);
+                Collections.sort(devices, COMPARATOR);
                 // Add disconnected bluetooth devices only when phone output device is available.
                 for (MediaDevice device : devices) {
                     final int type = device.getDeviceType();
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputConstants.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputConstants.java
index 647fd2a..552fa11 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputConstants.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputConstants.java
@@ -39,8 +39,7 @@
     /**
      * A string extra specifying a media package name.
      */
-    public static final String EXTRA_PACKAGE_NAME =
-            "com.android.settings.panel.extra.PACKAGE_NAME";
+    public static final String EXTRA_PACKAGE_NAME = "package_name";
 
     /**
      * An intent action to launch media output dialog.
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java b/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
index ecd4066..f9584a3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
@@ -38,6 +38,7 @@
 import android.os.UserManager;
 import android.provider.ContactsContract.DisplayPhoto;
 import android.provider.MediaStore;
+import android.util.EventLog;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.View;
@@ -126,6 +127,14 @@
         }
         final Uri pictureUri = data != null && data.getData() != null
                 ? data.getData() : mTakePictureUri;
+
+        // Check if the result is a content uri
+        if (!ContentResolver.SCHEME_CONTENT.equals(pictureUri.getScheme())) {
+            Log.e(TAG, "Invalid pictureUri scheme: " + pictureUri.getScheme());
+            EventLog.writeEvent(0x534e4554, "172939189", -1, pictureUri.getPath());
+            return false;
+        }
+
         switch (requestCode) {
             case REQUEST_CODE_CROP_PHOTO:
                 onPhotoCropped(pictureUri);
diff --git a/packages/SettingsLib/tests/integ/Android.bp b/packages/SettingsLib/tests/integ/Android.bp
index 92e32d9..64563be 100644
--- a/packages/SettingsLib/tests/integ/Android.bp
+++ b/packages/SettingsLib/tests/integ/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "SettingsLibTests",
     defaults: [
diff --git a/packages/SettingsLib/tests/robotests/Android.bp b/packages/SettingsLib/tests/robotests/Android.bp
index 3756c3b..dc661c2 100644
--- a/packages/SettingsLib/tests/robotests/Android.bp
+++ b/packages/SettingsLib/tests/robotests/Android.bp
@@ -16,6 +16,15 @@
 // SettingsLib Shell app just for Robolectric test target.  #
 //###########################################################
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "SettingsLibShell",
     defaults: ["SettingsLibDefaults"],
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index 53ff1a1..53a99ab 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -27,12 +27,14 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 import android.media.AudioManager;
 
 import com.android.settingslib.R;
+import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -41,8 +43,11 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
 
 @RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothAdapter.class})
 public class CachedBluetoothDeviceTest {
     private static final String DEVICE_NAME = "TestName";
     private static final String DEVICE_ALIAS = "TestAlias";
@@ -72,12 +77,14 @@
     private AudioManager mAudioManager;
     private Context mContext;
     private int mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
+    private ShadowBluetoothAdapter mShadowBluetoothAdapter;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = RuntimeEnvironment.application;
         mAudioManager = mContext.getSystemService(AudioManager.class);
+        mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
         when(mDevice.getAddress()).thenReturn(DEVICE_ADDRESS);
         when(mHfpProfile.isProfileReady()).thenReturn(true);
         when(mA2dpProfile.isProfileReady()).thenReturn(true);
@@ -937,4 +944,17 @@
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
                 mContext.getString(R.string.profile_connect_timeout_subtext));
     }
+
+    @Test
+    public void onUuidChanged_bluetoothClassIsNull_shouldNotCrash() {
+        mShadowBluetoothAdapter.setUuids(PbapServerProfile.PBAB_CLIENT_UUIDS);
+        when(mDevice.getUuids()).thenReturn(PbapServerProfile.PBAB_CLIENT_UUIDS);
+        when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(mDevice.getPhonebookAccessPermission()).thenReturn(BluetoothDevice.ACCESS_UNKNOWN);
+        when(mDevice.getBluetoothClass()).thenReturn(null);
+
+        mCachedDevice.onUuidChanged();
+
+        // Should not crash
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java b/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java
index b265d46..3b7fbc7 100644
--- a/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java
+++ b/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java
@@ -24,6 +24,7 @@
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
+import android.os.ParcelUuid;
 
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
@@ -36,6 +37,7 @@
     private List<Integer> mSupportedProfiles;
     private List<BluetoothDevice> mMostRecentlyConnectedDevices;
     private BluetoothProfile.ServiceListener mServiceListener;
+    private ParcelUuid[] mParcelUuids;
 
     @Implementation
     protected boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
@@ -87,4 +89,13 @@
         }
         return true;
     }
+
+    @Implementation
+    protected ParcelUuid[] getUuids() {
+        return mParcelUuids;
+    }
+
+    public void setUuids(ParcelUuid[] uuids) {
+        mParcelUuids = uuids;
+    }
 }
diff --git a/packages/SettingsProvider/Android.bp b/packages/SettingsProvider/Android.bp
index 2e53478..f490c87 100644
--- a/packages/SettingsProvider/Android.bp
+++ b/packages/SettingsProvider/Android.bp
@@ -1,3 +1,22 @@
+package {
+    default_applicable_licenses: [
+        "frameworks_base_packages_SettingsProvider_license",
+    ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_packages_SettingsProvider_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 android_app {
     name: "SettingsProvider",
     defaults: ["platform_app_defaults"],
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index 66165b6..ad6a531 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -147,5 +147,10 @@
         VALIDATORS.put(Global.DEVELOPMENT_SETTINGS_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Global.NOTIFICATION_FEEDBACK_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Global.RESTRICTED_NETWORKING_MODE, BOOLEAN_VALIDATOR);
+        VALIDATORS.put(
+                Global.ONE_HANDED_KEYGUARD_SIDE,
+                new InclusiveIntegerRangeValidator(
+                        /* first= */Global.ONE_HANDED_KEYGUARD_SIDE_LEFT,
+                        /* last= */Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT));
     }
 }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 1ce738e..a0b9528 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -551,9 +551,6 @@
                 Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS,
                 GlobalSettingsProto.Development.FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS);
         dumpSetting(s, p,
-                Settings.Global.DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM,
-                GlobalSettingsProto.Development.ENABLE_SIZECOMPAT_FREEFORM);
-        dumpSetting(s, p,
                 Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW,
                 GlobalSettingsProto.Development.ENABLE_NON_RESIZABLE_MULTI_WINDOW);
         p.end(developmentToken);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index a1fd7ee..e427981 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -4780,17 +4780,23 @@
                 }
 
                 if (currentVersion == 192) {
-                    // Version 192: set the default value for magnification capabilities. If
-                    // magnification is enabled by the user, set it to full-screen, and set a value
-                    // to show a prompt when using the magnification first time after upgrading.
+                    // Version 192: set the default value for magnification capabilities.
+                    // If the device supports magnification area and magnification is enabled
+                    // by the user, set it to full-screen, and set a value to show a prompt
+                    // when using the magnification first time after upgrading.
                     final SettingsState secureSettings = getSecureSettingsLocked(userId);
                     final Setting magnificationCapabilities = secureSettings.getSettingLocked(
                             Secure.ACCESSIBILITY_MAGNIFICATION_CAPABILITY);
+                    final boolean supportMagnificationArea = getContext().getResources().getBoolean(
+                            com.android.internal.R.bool.config_magnification_area);
+                    final int capability = supportMagnificationArea
+                            ? R.integer.def_accessibility_magnification_capabilities
+                            : Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
+                    final String supportShowPrompt = supportMagnificationArea ? "1" : "0";
                     if (magnificationCapabilities.isNull()) {
                         secureSettings.insertSettingLocked(
                                 Secure.ACCESSIBILITY_MAGNIFICATION_CAPABILITY,
-                                String.valueOf(getContext().getResources().getInteger(
-                                        R.integer.def_accessibility_magnification_capabilities)),
+                                String.valueOf(getContext().getResources().getInteger(capability)),
                                 null, true, SettingsState.SYSTEM_PACKAGE_NAME);
 
                         if (isMagnificationSettingsOn(secureSettings)) {
@@ -4800,7 +4806,8 @@
                                     null, false  /* makeDefault */,
                                     SettingsState.SYSTEM_PACKAGE_NAME);
                             secureSettings.insertSettingLocked(
-                                    Secure.ACCESSIBILITY_SHOW_WINDOW_MAGNIFICATION_PROMPT, "1",
+                                    Secure.ACCESSIBILITY_SHOW_WINDOW_MAGNIFICATION_PROMPT,
+                                    supportShowPrompt,
                                     null, false /* makeDefault */,
                                     SettingsState.SYSTEM_PACKAGE_NAME);
                         }
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 6719f17..4dc6d14 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -227,7 +227,6 @@
                     Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS,
                     Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES,
                     Settings.Global.DEVELOPMENT_FORCE_RTL,
-                    Settings.Global.DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM,
                     Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW,
                     Settings.Global.DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR,
                     Settings.Global.DEVELOPMENT_USE_BLAST_ADAPTER_SV,
@@ -283,6 +282,7 @@
                     Settings.Global.EUICC_REMOVING_INVISIBLE_PROFILES_TIMEOUT_MILLIS,
                     Settings.Global.EUICC_SWITCH_SLOT_TIMEOUT_MILLIS,
                     Settings.Global.FANCY_IME_ANIMATIONS,
+                    Settings.Global.ONE_HANDED_KEYGUARD_SIDE,
                     Settings.Global.FORCE_ALLOW_ON_EXTERNAL,
                     Settings.Global.FORCED_APP_STANDBY_ENABLED,
                     Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED,
@@ -298,7 +298,6 @@
                     Settings.Global.GNSS_SATELLITE_BLOCKLIST,
                     Settings.Global.GPRS_REGISTER_CHECK_PERIOD_MS,
                     Settings.Global.HDMI_CEC_SWITCH_ENABLED,
-                    Settings.Global.HDMI_CEC_VERSION,
                     Settings.Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED,
                     Settings.Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED,
                     Settings.Global.HDMI_CONTROL_ENABLED,
diff --git a/packages/SharedStorageBackup/Android.bp b/packages/SharedStorageBackup/Android.bp
index d02f480..21516fa 100644
--- a/packages/SharedStorageBackup/Android.bp
+++ b/packages/SharedStorageBackup/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "SharedStorageBackup",
     defaults: ["platform_app_defaults"],
diff --git a/packages/Shell/Android.bp b/packages/Shell/Android.bp
index 546642d..c87916f 100644
--- a/packages/Shell/Android.bp
+++ b/packages/Shell/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 // used both for the android_app and android_library
 shell_srcs = ["src/**/*.java",":dumpstate_aidl"]
 shell_static_libs = ["androidx.legacy_legacy-support-v4"]
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 50c7e08..1393116 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -84,8 +84,7 @@
     <uses-permission android:name="android.permission.READ_INPUT_STATE" />
     <uses-permission android:name="android.permission.SET_ORIENTATION" />
     <uses-permission android:name="android.permission.INSTALL_PACKAGES" />
-    <!--  TODO(b/152310230): remove once APIs are confirmed to be sufficient -->
-    <uses-permission android:name="com.android.permission.USE_INSTALLER_V2" />
+    <uses-permission android:name="com.android.permission.USE_SYSTEM_DATA_LOADERS" />
     <uses-permission android:name="android.permission.MOVE_PACKAGE" />
     <uses-permission android:name="android.permission.KEEP_UNINSTALLED_PACKAGES" />
     <uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />
@@ -124,6 +123,8 @@
     <uses-permission android:name="android.permission.MANAGE_CREDENTIAL_MANAGEMENT_APP" />
     <uses-permission android:name="android.permission.MANAGE_DEVICE_ADMINS" />
     <uses-permission android:name="android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS" />
+    <uses-permission android:name="android.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS" />
+    <uses-permission android:name="android.permission.CLEAR_FREEZE_PERIOD" />
     <uses-permission android:name="android.permission.QUERY_USERS" />
     <uses-permission android:name="android.permission.MODIFY_QUIET_MODE" />
     <uses-permission android:name="android.permission.ACCESS_LOWPAN_STATE"/>
@@ -398,6 +399,7 @@
 
     <!-- Permission required for CTS to test sensor privacy behavior -->
     <uses-permission android:name="android.permission.MANAGE_SENSOR_PRIVACY" />
+    <uses-permission android:name="android.permission.OBSERVE_SENSOR_PRIVACY" />
 
     <!-- Permission needed for CTS test - CallLogTest -->
     <uses-permission android:name="com.android.voicemail.permission.READ_VOICEMAIL" />
diff --git a/packages/Shell/OWNERS b/packages/Shell/OWNERS
index 34901f5..6d738f8 100644
--- a/packages/Shell/OWNERS
+++ b/packages/Shell/OWNERS
@@ -9,3 +9,4 @@
 toddke@google.com
 cbrubaker@google.com
 omakoto@google.com
+michaelwr@google.com
diff --git a/packages/Shell/res/values-ky/strings.xml b/packages/Shell/res/values-ky/strings.xml
index 3567ac2..d73ee2f 100644
--- a/packages/Shell/res/values-ky/strings.xml
+++ b/packages/Shell/res/values-ky/strings.xml
@@ -25,7 +25,7 @@
     <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"Мүчүлүштүктөр жөнүндө кабар жакында телефонго чыгат"</string>
     <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"Мүчүлүштүк тууралуу кабарды жөнөтүү үчүн таптап коюңуз"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Мүчүлүштүк тууралуу билдирүүңүздү бөлүшүү үчүн таптап коюңуз"</string>
-    <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Мүчүлүштүк тууралуу кабарды скриншотсуз жөнөтүү үчүн солго серпиңиз же скриншот даяр болгуча күтүңүз"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Мүчүлүштүк тууралуу кабарды скриншотсуз жөнөтүү үчүн солго сүрүңүз же скриншот даяр болгуча күтүңүз"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Мүчүлүштүк тууралуу билдирүүңүздү скриншотсуз бөлүшүү үчүн таптап коюңуз же скриншот даяр болгуча күтө туруңуз"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Мүчүлүштүк тууралуу билдирүүңүздү скриншотсуз бөлүшүү үчүн таптап коюңуз же скриншот даяр болгуча күтө туруңуз"</string>
     <string name="bugreport_confirm" msgid="5917407234515812495">"Мүчүлүштүктөр тууралуу билдирүүлөрдө тутумдун ар кандай таржымалдарынан алынган дайындар, ошондой эле купуя маалымат камтылышы мүмкүн (мисалы, жайгашкан жер сыяктуу). Мындай билдирүүлөрдү бир гана ишеничтүү адамдар жана колдонмолор менен бөлүшүңүз."</string>
diff --git a/packages/Shell/tests/Android.bp b/packages/Shell/tests/Android.bp
index 8536c4f..70e8c10 100644
--- a/packages/Shell/tests/Android.bp
+++ b/packages/Shell/tests/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ShellTests",
     srcs: ["src/**/*.java"],
diff --git a/packages/SimAppDialog/Android.bp b/packages/SimAppDialog/Android.bp
index 9c0d78c..a9fe3ad 100644
--- a/packages/SimAppDialog/Android.bp
+++ b/packages/SimAppDialog/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "SimAppDialog",
     defaults: ["platform_app_defaults"],
diff --git a/packages/SoundPicker/Android.bp b/packages/SoundPicker/Android.bp
index 56e7cd1..2c89d6d 100644
--- a/packages/SoundPicker/Android.bp
+++ b/packages/SoundPicker/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "SoundPicker",
     defaults: ["platform_app_defaults"],
diff --git a/packages/StatementService/Android.bp b/packages/StatementService/Android.bp
index 2664a03..32defc8 100644
--- a/packages/StatementService/Android.bp
+++ b/packages/StatementService/Android.bp
@@ -11,6 +11,15 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "StatementService",
     defaults: ["platform_app_defaults"],
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index bf5198e..b6fd286 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -14,6 +14,23 @@
 // limitations under the License.
 //
 
+package {
+    default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_packages_SystemUI_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 java_library {
     name: "SystemUI-proto",
 
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 2faca8d..b6d942a 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -87,6 +87,7 @@
     <uses-permission android:name="android.permission.MASTER_CLEAR" />
     <uses-permission android:name="android.permission.VIBRATE" />
     <uses-permission android:name="android.permission.MANAGE_SENSOR_PRIVACY" />
+    <uses-permission android:name="android.permission.OBSERVE_SENSOR_PRIVACY" />
 
     <!-- ActivityManager -->
     <uses-permission android:name="android.permission.REAL_GET_TASKS" />
@@ -334,6 +335,12 @@
             </intent-filter>
         </receiver>
 
+        <activity android:name=".screenshot.LongScreenshotActivity"
+                  android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
+                  android:process=":screenshot"
+                  android:exported="false"
+                  android:finishOnTaskLaunch="true" />
+
         <activity android:name=".screenrecord.ScreenRecordDialog"
             android:theme="@style/ScreenRecord"
             android:showForAllUsers="true"
diff --git a/packages/SystemUI/plugin/Android.bp b/packages/SystemUI/plugin/Android.bp
index ab4f800..9e67e4b 100644
--- a/packages/SystemUI/plugin/Android.bp
+++ b/packages/SystemUI/plugin/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"],
+}
+
 java_library {
 
     name: "SystemUIPluginLib",
diff --git a/packages/SystemUI/plugin/ExamplePlugin/Android.bp b/packages/SystemUI/plugin/ExamplePlugin/Android.bp
index c6c80f3..3f0fded 100644
--- a/packages/SystemUI/plugin/ExamplePlugin/Android.bp
+++ b/packages/SystemUI/plugin/ExamplePlugin/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"],
+}
+
 android_app {
 
     name: "ExamplePlugin",
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java
index bcd28a6..53f7e44 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java
@@ -50,6 +50,4 @@
     public abstract void onStateChanged(State state);
 
     public abstract int getDetailY();
-
-    public void setShowLabels(boolean show) {}
 }
diff --git a/packages/SystemUI/plugin_core/Android.bp b/packages/SystemUI/plugin_core/Android.bp
index 581fef7..34d31d9 100644
--- a/packages/SystemUI/plugin_core/Android.bp
+++ b/packages/SystemUI/plugin_core/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"],
+}
+
 java_library {
     sdk_version: "current",
     name: "PluginCoreLib",
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
index f3ec39d..b6a41c2 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -64,7 +64,7 @@
         android:id="@+id/new_lockscreen_clock_view"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_alignParentEnd="true"
+        android:layout_alignParentStart="true"
         android:layout_alignParentTop="true"
         android:visibility="gone">
         <com.android.keyguard.AnimatableClockView
@@ -73,7 +73,7 @@
             android:layout_height="wrap_content"
             android:layout_gravity="center_horizontal"
             android:gravity="center_horizontal"
-            android:textSize="100dp"
+            android:textSize="60dp"
             android:fontFamily="@font/clock"
             android:typeface="monospace"
             android:elegantTextHeight="false"
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 2a5784a..115a156 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -47,26 +47,25 @@
     <dimen name="eca_overlap">-10dip</dimen>
 
     <!-- Slice header -->
-    <dimen name="widget_title_font_size">24dp</dimen>
-    <dimen name="header_subtitle_padding">12dp</dimen>
+    <dimen name="widget_title_font_size">20dp</dimen>
+    <dimen name="widget_title_line_height">24dp</dimen>
     <dimen name="header_icon_size">16dp</dimen>
     <!-- Slice subtitle -->
-    <dimen name="widget_label_font_size">18dp</dimen>
+    <dimen name="widget_label_font_size">16dp</dimen>
+    <dimen name="widget_label_line_height">20dp</dimen>
     <!-- Clock without header -->
     <dimen name="widget_big_font_size">54dp</dimen>
     <dimen name="bottom_text_spacing_digital">0dp</dimen>
     <dimen name="title_clock_padding">4dp</dimen>
     <!-- Clock with header -->
     <dimen name="widget_small_font_size">@dimen/widget_title_font_size</dimen>
-    <dimen name="widget_vertical_padding">17dp</dimen>
+    <dimen name="widget_vertical_padding">5dp</dimen>
     <dimen name="widget_vertical_padding_with_header">25dp</dimen>
     <dimen name="widget_vertical_padding_clock">12dp</dimen>
     <!-- Subtitle paddings -->
     <dimen name="widget_horizontal_padding">8dp</dimen>
-    <dimen name="widget_icon_size">20dp</dimen>
+    <dimen name="widget_icon_size">18dp</dimen>
     <dimen name="widget_icon_padding">8dp</dimen>
-    <dimen name="subtitle_clock_padding">0dp</dimen>
-    <dimen name="header_row_font_size">14dp</dimen>
     <!-- Notification shelf padding when dark -->
     <dimen name="widget_bottom_separator_padding">-6dp</dimen>
 
diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml
index 2391803..8f42cbe 100644
--- a/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/packages/SystemUI/res-keyguard/values/styles.xml
@@ -120,6 +120,7 @@
 
     <style name="TextAppearance.Keyguard">
         <item name="android:textSize">@dimen/widget_title_font_size</item>
+        <item name="android:lineHeight">@dimen/widget_title_line_height</item>
         <item name="android:gravity">center</item>
         <item name="android:ellipsize">end</item>
         <item name="android:maxLines">2</item>
@@ -133,6 +134,7 @@
         <item name="android:layout_height">wrap_content</item>
         <item name="android:lines">1</item>
         <item name="android:textSize">@dimen/widget_label_font_size</item>
+        <item name="android:lineHeight">@dimen/widget_label_line_height</item>
     </style>
 
     <style name="TextAppearance.Keyguard.BottomArea">
diff --git a/packages/SystemUI/res-product/values-az/strings.xml b/packages/SystemUI/res-product/values-az/strings.xml
index ee86ae2..c0668db 100644
--- a/packages/SystemUI/res-product/values-az/strings.xml
+++ b/packages/SystemUI/res-product/values-az/strings.xml
@@ -38,8 +38,8 @@
     <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Telefonun kilidini açmaq üçün <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış cəhd etmisiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra iş profili silinəcək və bütün profil datası ləğv ediləcək."</string>
     <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Planşetin kilidini açmaq üçün <xliff:g id="NUMBER">%d</xliff:g> dəfə yanlış cəhd etmisiniz. İş profili silinəcək və bütün data ləğv ediləcək."</string>
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Telefonun kilidini açmaq üçün <xliff:g id="NUMBER">%d</xliff:g> dəfə yanlış cəhd etmisiniz. İş profili silinəcək və bütün data ləğv ediləcək."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Kilid açma modelini <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış çəkmisiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra planşet kilidini e-poçt hesabınızla açmaq tələb olunacaq.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniyə sonra yenidən cəhd edin."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Kilid açma modelini artıq <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış çəkmisiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra telefon kilidini e-poçt hesabınızla açmaq tələb olunacaq.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniyə sonra yenidən cəhd edin."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Kilid açma modelini <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış çəkmisiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra planşet kilidini e-poçt hesabınızla açmaq tələb olunacaq.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniyə sonra cəhd edin."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Kilid açma modelini artıq <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış çəkmisiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra telefon kilidini e-poçt hesabınızla açmaq tələb olunacaq.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniyə sonra cəhd edin."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Daha çox seçim üçün telefonu kiliddən çıxarın"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Daha çox seçim üçün planşeti kiliddən çıxarın"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Daha çox seçim üçün cihazı kiliddən çıxarın"</string>
diff --git a/packages/SystemUI/res/drawable/brightness_progress_drawable_thick.xml b/packages/SystemUI/res/drawable/brightness_progress_drawable_thick.xml
index d097472..8efe053 100644
--- a/packages/SystemUI/res/drawable/brightness_progress_drawable_thick.xml
+++ b/packages/SystemUI/res/drawable/brightness_progress_drawable_thick.xml
@@ -41,8 +41,10 @@
     </item>
     <item android:id="@android:id/progress"
           android:gravity="center_vertical|fill_horizontal">
-            <com.android.systemui.util.RoundedCornerProgressDrawable
+            <clip
                 android:drawable="@drawable/brightness_progress_full_drawable"
+                android:clipOrientation="horizontal"
+                android:gravity="left"
             />
     </item>
 </layer-list>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml b/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
index 41140a7..5bc2773 100644
--- a/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
+++ b/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
@@ -26,10 +26,10 @@
     </item>
     <item
         android:id="@+id/slider_icon"
-        android:gravity="center_vertical|right"
+        android:gravity="center_vertical|left"
         android:height="@dimen/rounded_slider_icon_size"
         android:width="@dimen/rounded_slider_icon_size"
-        android:right="@dimen/rounded_slider_icon_inset">
+        android:left="@dimen/rounded_slider_icon_inset">
         <com.android.systemui.util.AlphaTintDrawableWrapper
             android:drawable="@drawable/ic_brightness"
             android:tint="?android:attr/colorBackground"
diff --git a/packages/SystemUI/res/drawable/control_no_favorites_background.xml b/packages/SystemUI/res/drawable/control_no_favorites_background.xml
index d895dd0..2165b12 100644
--- a/packages/SystemUI/res/drawable/control_no_favorites_background.xml
+++ b/packages/SystemUI/res/drawable/control_no_favorites_background.xml
@@ -26,12 +26,4 @@
             <corners android:radius="@dimen/control_corner_radius" />
         </shape>
     </item>
-    <item>
-        <shape>
-            <stroke
-                android:width="1dp"
-                android:color="#4DFFFFFF" />
-            <corners android:radius="@dimen/control_corner_radius"/>
-        </shape>
-    </item>
 </ripple>
diff --git a/packages/SystemUI/res/drawable/controls_dialog_bg.xml b/packages/SystemUI/res/drawable/controls_dialog_bg.xml
index cb4686dd..1ccb176 100644
--- a/packages/SystemUI/res/drawable/controls_dialog_bg.xml
+++ b/packages/SystemUI/res/drawable/controls_dialog_bg.xml
@@ -16,6 +16,6 @@
 -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
-    <solid android:color="?android:attr/colorBackgroundFloating" />
+    <solid android:color="?android:attr/colorBackground" />
     <corners android:radius="@dimen/notification_corner_radius" />
 </shape>
diff --git a/packages/SystemUI/res/drawable/horizontal_ellipsis.xml b/packages/SystemUI/res/drawable/horizontal_ellipsis.xml
new file mode 100644
index 0000000..1800857
--- /dev/null
+++ b/packages/SystemUI/res/drawable/horizontal_ellipsis.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0"
+    android:tint="?android:attr/colorBackgroundFloating" >
+
+    <path
+        android:pathData="M6 10c-1.1 0-2 0.9-2 2s0.9 2 2 2 2-0.9 2-2-0.9-2-2-2zm12 0c-1.1 0-2 0.9-2 2s0.9 2 2 2 2-0.9 2-2-0.9-2-2-2zm-6 0c-1.1 0-2 0.9-2 2s0.9 2 2 2 2-0.9 2-2-0.9-2-2-2z"
+        android:fillColor="@android:color/white" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml b/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml
index 9f66581..96e0193 100644
--- a/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml
+++ b/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml
@@ -36,8 +36,4 @@
         </vector>
     </item>
 
-    <item>
-        <ripple android:color="@color/GM2_grey_600"></ripple>
-    </item>
-
 </layer-list>
diff --git a/packages/SystemUI/res/drawable/ic_open_in_new_window.xml b/packages/SystemUI/res/drawable/ic_open_in_new_window.xml
index 659b020..368c8df 100644
--- a/packages/SystemUI/res/drawable/ic_open_in_new_window.xml
+++ b/packages/SystemUI/res/drawable/ic_open_in_new_window.xml
@@ -50,28 +50,7 @@
                     android:strokeWidth="1"
                     android:pathData="M 12.5 13.92 L 15.59 17 L 17 15.59 L 13.91 12.5 L 16.5 12.5 L 16.5 10.5 L 10.5 10.5 L 10.5 16.5 L 12.5 16.5 Z" />
             </group>
-            <group
-                android:translateX="22.000000"
-                android:translateY="2.000000">
-                <group
-                    android:translateX="3.000000"
-                    android:translateY="3.000000">
-                    <group
-                        android:translateX="-3.000000"
-                        android:translateY="-3.000000">
-                        <path
-                            android:fillColor="#80868B"
-                            android:fillType="evenOdd"
-                            android:strokeWidth="1"
-                            android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
-                    </group>
-                </group>
-            </group>
         </vector>
     </item>
 
-    <item>
-        <ripple android:color="@color/GM2_grey_600"></ripple>
-    </item>
-
 </layer-list>
diff --git a/packages/SystemUI/res/drawable/ic_phone_missed.xml b/packages/SystemUI/res/drawable/ic_phone_missed.xml
new file mode 100644
index 0000000..72e67d4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_phone_missed.xml
@@ -0,0 +1,24 @@
+<!--
+Copyright (C) 2021 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M6.5,5.5L12,11l7,-7 -1,-1 -6,6 -4.5,-4.5L11,4.5L11,3L5,3v6h1.5L6.5,5.5zM23.71,16.67C20.66,13.78 16.54,12 12,12 7.46,12 3.34,13.78 0.29,16.67c-0.18,0.18 -0.29,0.43 -0.29,0.71s0.11,0.53 0.29,0.71l2.48,2.48c0.18,0.18 0.43,0.29 0.71,0.29 0.27,0 0.52,-0.11 0.7,-0.28 0.79,-0.74 1.69,-1.36 2.66,-1.85 0.33,-0.16 0.56,-0.5 0.56,-0.9v-3.1c1.45,-0.48 3,-0.73 4.6,-0.73 1.6,0 3.15,0.25 4.6,0.72v3.1c0,0.39 0.23,0.74 0.56,0.9 0.98,0.49 1.87,1.12 2.67,1.85 0.18,0.18 0.43,0.28 0.7,0.28 0.28,0 0.53,-0.11 0.71,-0.29l2.48,-2.48c0.18,-0.18 0.29,-0.43 0.29,-0.71s-0.12,-0.52 -0.3,-0.7z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/people_space_content_background.xml b/packages/SystemUI/res/drawable/people_space_content_background.xml
index 32314d2..30519ae 100644
--- a/packages/SystemUI/res/drawable/people_space_content_background.xml
+++ b/packages/SystemUI/res/drawable/people_space_content_background.xml
@@ -15,6 +15,6 @@
   ~ limitations under the License.
   -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android" >
-    <solid android:color="?android:attr/colorControlHighlight" />
+    <solid android:color="?android:attr/colorBackground" />
     <corners android:radius="@dimen/people_space_image_radius" />
 </shape>
diff --git a/packages/SystemUI/res/drawable/toast_background.xml b/packages/SystemUI/res/drawable/volume_drawer_bg.xml
similarity index 74%
copy from packages/SystemUI/res/drawable/toast_background.xml
copy to packages/SystemUI/res/drawable/volume_drawer_bg.xml
index 5c45e83..f0e2292 100644
--- a/packages/SystemUI/res/drawable/toast_background.xml
+++ b/packages/SystemUI/res/drawable/volume_drawer_bg.xml
@@ -15,7 +15,8 @@
   ~ limitations under the License.
   -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-    <solid android:color="#FFFFFFFF" />
-    <corners android:radius="@dimen/toast_bg_radius" />
-</shape>
+            android:paddingMode="stack" >
+    <size android:width="@dimen/volume_ringer_drawer_item_size" />
+    <solid android:color="?android:attr/colorBackgroundFloating" />
+    <corners android:radius="@dimen/volume_ringer_drawer_item_size_half" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/toast_background.xml b/packages/SystemUI/res/drawable/volume_drawer_selection_bg.xml
similarity index 70%
copy from packages/SystemUI/res/drawable/toast_background.xml
copy to packages/SystemUI/res/drawable/volume_drawer_selection_bg.xml
index 5c45e83..5e7cb12 100644
--- a/packages/SystemUI/res/drawable/toast_background.xml
+++ b/packages/SystemUI/res/drawable/volume_drawer_selection_bg.xml
@@ -15,7 +15,10 @@
   ~ limitations under the License.
   -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-    <solid android:color="#FFFFFFFF" />
-    <corners android:radius="@dimen/toast_bg_radius" />
-</shape>
+            android:paddingMode="stack" >
+    <size
+        android:height="@dimen/volume_ringer_drawer_item_size"
+        android:width="@dimen/volume_ringer_drawer_item_size" />
+    <solid android:color="?android:attr/colorAccent" />
+    <corners android:radius="@dimen/volume_ringer_drawer_item_size_half" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/volume_row_seekbar.xml b/packages/SystemUI/res/drawable/volume_row_seekbar.xml
new file mode 100644
index 0000000..b0e0ed5
--- /dev/null
+++ b/packages/SystemUI/res/drawable/volume_row_seekbar.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<!-- SeekBar drawable for volume rows. This contains a background layer (with a solid round rect,
+     and a bottom-aligned icon) and a progress layer (with an accent-colored round rect and icon)
+     that moves up and down with the progress value. -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
+            android:paddingMode="stack" >
+    <item android:id="@android:id/background"
+        android:gravity="center_vertical|fill_horizontal">
+        <layer-list>
+            <item android:id="@+id/volume_seekbar_background_solid">
+                <shape>
+                    <size android:height="@dimen/volume_dialog_panel_width" />
+                    <solid android:color="?android:attr/colorBackgroundFloating" />
+                    <corners android:radius="@dimen/volume_dialog_panel_width_half" />
+                </shape>
+            </item>
+            <item
+                android:id="@+id/volume_seekbar_background_icon"
+                android:gravity="center_vertical|left"
+                android:height="@dimen/rounded_slider_icon_size"
+                android:width="@dimen/rounded_slider_icon_size"
+                android:left="@dimen/rounded_slider_icon_inset">
+                <rotate
+                    android:fromDegrees="-270"
+                    android:toDegrees="-270">
+                    <!-- A placeholder drawable is required here - it'll be replaced in code. -->
+                    <com.android.systemui.util.AlphaTintDrawableWrapper
+                        android:drawable="@drawable/ic_volume_media"
+                        android:tint="?android:attr/colorAccent" />
+                </rotate>
+            </item>
+        </layer-list>
+    </item>
+    <item android:id="@android:id/progress"
+          android:gravity="center_vertical|fill_horizontal">
+            <com.android.systemui.util.RoundedCornerProgressDrawable
+                android:drawable="@drawable/volume_row_seekbar_progress"
+            />
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/volume_row_seekbar_progress.xml b/packages/SystemUI/res/drawable/volume_row_seekbar_progress.xml
new file mode 100644
index 0000000..ef20236
--- /dev/null
+++ b/packages/SystemUI/res/drawable/volume_row_seekbar_progress.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<!-- Progress drawable for volume row SeekBars. This is the accent-colored round rect that moves up
+     and down as the progress value changes. -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
+    android:autoMirrored="true">
+    <item android:id="@+id/volume_seekbar_progress_solid">
+        <shape>
+            <size android:height="@dimen/volume_dialog_panel_width" />
+            <solid android:color="?android:attr/colorAccent" />
+            <corners android:radius="@dimen/volume_dialog_panel_width_half"/>
+        </shape>
+    </item>
+    <item
+        android:id="@+id/volume_seekbar_progress_icon"
+        android:gravity="center_vertical|right"
+        android:height="@dimen/rounded_slider_icon_size"
+        android:width="@dimen/rounded_slider_icon_size"
+        android:right="@dimen/rounded_slider_icon_inset">
+        <rotate
+            android:fromDegrees="-270"
+            android:toDegrees="-270">
+            <!-- A placeholder drawable is required here - it'll be replaced in code. -->
+            <com.android.systemui.util.AlphaTintDrawableWrapper
+                android:drawable="@drawable/ic_volume_media"
+                android:tint="?android:attr/colorBackgroundFloating" />
+        </rotate>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout-land/volume_dialog.xml b/packages/SystemUI/res/layout-land/volume_dialog.xml
index c420117..237dc02 100644
--- a/packages/SystemUI/res/layout-land/volume_dialog.xml
+++ b/packages/SystemUI/res/layout-land/volume_dialog.xml
@@ -32,105 +32,124 @@
         android:gravity="right"
         android:layout_gravity="right"
         android:background="@android:color/transparent"
-        android:paddingRight="@dimen/volume_dialog_panel_transparent_padding_right"
-        android:paddingTop="@dimen/volume_dialog_panel_transparent_padding"
-        android:paddingBottom="@dimen/volume_dialog_panel_transparent_padding"
+        android:paddingRight="@dimen/volume_dialog_stream_padding"
         android:paddingLeft="@dimen/volume_dialog_panel_transparent_padding"
         android:clipToPadding="false">
 
-        <FrameLayout
-            android:id="@+id/ringer"
-            android:layout_width="@dimen/volume_dialog_ringer_size"
-            android:layout_height="@dimen/volume_dialog_ringer_size"
-            android:layout_marginBottom="@dimen/volume_dialog_spacer"
-            android:gravity="right"
-            android:layout_gravity="right"
-            android:translationZ="@dimen/volume_dialog_elevation"
-            android:clipToPadding="false"
-            android:background="@drawable/rounded_bg_full">
-            <com.android.keyguard.AlphaOptimizedImageButton
-                android:id="@+id/ringer_icon"
-                style="@style/VolumeButtons"
-                android:background="@drawable/rounded_ripple"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:scaleType="fitCenter"
-                android:padding="@dimen/volume_dialog_ringer_icon_padding"
-                android:tint="@color/accent_tint_color_selector"
-                android:layout_gravity="center"
-                android:soundEffectsEnabled="false" />
-
-            <include layout="@layout/volume_dnd_icon"
-                     android:layout_width="match_parent"
-                     android:layout_height="wrap_content"
-                     android:layout_marginRight="@dimen/volume_dialog_stream_padding"
-                     android:layout_marginTop="6dp"/>
-        </FrameLayout>
-
+        <!--
+            Container for a) the ringer drawer and the caption button next to b) the volume rows.
+        -->
         <LinearLayout
-            android:id="@+id/main"
             android:layout_width="wrap_content"
-            android:minWidth="@dimen/volume_dialog_panel_width"
             android:layout_height="wrap_content"
-            android:layout_marginTop="68dp"
-            android:gravity="right"
-            android:layout_gravity="right"
-            android:orientation="vertical"
-            android:translationZ="@dimen/volume_dialog_elevation"
+            android:orientation="horizontal"
             android:clipChildren="false"
-            android:clipToPadding="false"
-            android:background="@drawable/rounded_bg_full" >
-            <LinearLayout
-                android:id="@+id/volume_dialog_rows"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:minWidth="@dimen/volume_dialog_panel_width"
-                android:gravity="center"
-                android:orientation="horizontal"
-                android:paddingRight="@dimen/volume_dialog_stream_padding"
-                android:paddingLeft="@dimen/volume_dialog_stream_padding">
-                <!-- volume rows added and removed here! :-) -->
-            </LinearLayout>
-            <FrameLayout
-                android:id="@+id/settings_container"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:background="@drawable/rounded_bg_bottom_background">
-                <com.android.keyguard.AlphaOptimizedImageButton
-                    android:id="@+id/settings"
-                    android:src="@drawable/ic_tune_black_16dp"
-                    android:layout_width="@dimen/volume_dialog_tap_target_size"
-                    android:layout_height="@dimen/volume_dialog_tap_target_size"
-                    android:layout_gravity="center"
-                    android:contentDescription="@string/accessibility_volume_settings"
-                    android:background="@drawable/ripple_drawable_20dp"
-                    android:tint="?android:attr/textColorSecondary"
-                    android:soundEffectsEnabled="false" />
-            </FrameLayout>
-        </LinearLayout>
+            android:clipToPadding="false">
 
-        <FrameLayout
-            android:id="@+id/odi_captions"
-            android:layout_width="@dimen/volume_dialog_caption_size"
-            android:layout_height="@dimen/volume_dialog_caption_size"
-            android:layout_marginRight="68dp"
-            android:gravity="right"
-            android:layout_gravity="right"
-            android:clipToPadding="false"
-            android:translationZ="@dimen/volume_dialog_elevation"
-            android:background="@drawable/rounded_bg_full">
-            <com.android.systemui.volume.CaptionsToggleImageButton
-                android:id="@+id/odi_captions_icon"
-                android:src="@drawable/ic_volume_odi_captions_disabled"
-                style="@style/VolumeButtons"
-                android:background="@drawable/rounded_ripple"
-                android:layout_width="match_parent"
+            <!-- The ringer drawer and the caption button. -->
+            <FrameLayout
+                android:layout_width="wrap_content"
                 android:layout_height="match_parent"
-                android:tint="@color/caption_tint_color_selector"
-                android:layout_gravity="center"
-                android:soundEffectsEnabled="false"
-                sysui:optedOut="false"/>
-        </FrameLayout>
+                android:paddingRight="@dimen/volume_dialog_stream_padding"
+                android:clipChildren="false"
+                android:clipToPadding="false"
+                android:orientation="vertical">
+
+                <include layout="@layout/volume_ringer_drawer"
+                    android:layout_gravity="top|right"/>
+
+                <FrameLayout
+                    android:id="@+id/odi_captions"
+                    android:layout_width="@dimen/volume_dialog_caption_size"
+                    android:layout_height="@dimen/volume_dialog_caption_size"
+                    android:gravity="center"
+                    android:layout_gravity="bottom|right"
+                    android:layout_marginBottom="@dimen/volume_dialog_tap_target_size"
+                    android:clipToPadding="false">
+
+                    <com.android.systemui.volume.CaptionsToggleImageButton
+                        android:id="@+id/odi_captions_icon"
+                        android:src="@drawable/ic_volume_odi_captions_disabled"
+                        style="@style/VolumeButtons"
+                        android:background="@drawable/rounded_ripple"
+                        android:layout_width="match_parent"
+                        android:layout_height="match_parent"
+                        android:tint="@color/caption_tint_color_selector"
+                        android:layout_gravity="center"
+                        android:soundEffectsEnabled="false"
+                        sysui:optedOut="false"/>
+
+                </FrameLayout>
+
+            </FrameLayout>
+
+            <FrameLayout
+                android:visibility="gone"
+                android:id="@+id/ringer"
+                android:layout_width="@dimen/volume_dialog_ringer_size"
+                android:layout_height="@dimen/volume_dialog_ringer_size"
+                android:layout_marginBottom="@dimen/volume_dialog_spacer"
+                android:gravity="right"
+                android:layout_gravity="right"
+                android:translationZ="@dimen/volume_dialog_elevation"
+                android:clipToPadding="false"
+                android:background="@drawable/rounded_bg_full">
+                <com.android.keyguard.AlphaOptimizedImageButton
+                    android:id="@+id/ringer_icon"
+                    style="@style/VolumeButtons"
+                    android:background="@drawable/rounded_ripple"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:scaleType="fitCenter"
+                    android:padding="@dimen/volume_dialog_ringer_icon_padding"
+                    android:tint="@color/accent_tint_color_selector"
+                    android:layout_gravity="center"
+                    android:soundEffectsEnabled="false" />
+
+                <include layout="@layout/volume_dnd_icon"
+                         android:layout_width="match_parent"
+                         android:layout_height="wrap_content"
+                         android:layout_marginRight="@dimen/volume_dialog_stream_padding"
+                         android:layout_marginTop="6dp"/>
+            </FrameLayout>
+
+            <LinearLayout
+                android:id="@+id/main"
+                android:layout_width="wrap_content"
+                android:minWidth="@dimen/volume_dialog_panel_width"
+                android:layout_height="wrap_content"
+                android:gravity="right"
+                android:layout_gravity="right"
+                android:orientation="vertical"
+                android:clipChildren="false"
+                android:clipToPadding="false">
+                <LinearLayout
+                    android:id="@+id/volume_dialog_rows"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:minWidth="@dimen/volume_dialog_panel_width"
+                    android:gravity="center"
+                    android:orientation="horizontal">
+                    <!-- volume rows added and removed here! :-) -->
+                </LinearLayout>
+                <FrameLayout
+                    android:id="@+id/settings_container"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content">
+                    <com.android.keyguard.AlphaOptimizedImageButton
+                        android:id="@+id/settings"
+                        android:src="@drawable/horizontal_ellipsis"
+                        android:layout_width="@dimen/volume_dialog_tap_target_size"
+                        android:layout_height="@dimen/volume_dialog_tap_target_size"
+                        android:layout_gravity="center"
+                        android:contentDescription="@string/accessibility_volume_settings"
+                        android:background="@drawable/ripple_drawable_20dp"
+                        android:tint="?android:attr/colorBackgroundFloating"
+                        android:soundEffectsEnabled="false" />
+                </FrameLayout>
+            </LinearLayout>
+
+        </LinearLayout>
 
         <ViewStub
             android:id="@+id/odi_captions_tooltip_stub"
diff --git a/packages/SystemUI/res/layout/media_output_dialog.xml b/packages/SystemUI/res/layout/media_output_dialog.xml
index 73beefc..d996cee 100644
--- a/packages/SystemUI/res/layout/media_output_dialog.xml
+++ b/packages/SystemUI/res/layout/media_output_dialog.xml
@@ -32,7 +32,8 @@
             android:id="@+id/header_icon"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:paddingEnd="@dimen/media_output_dialog_header_icon_padding"/>
+            android:paddingEnd="@dimen/media_output_dialog_header_icon_padding"
+            android:importantForAccessibility="no"/>
 
         <LinearLayout
             android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/navigation_layout.xml b/packages/SystemUI/res/layout/navigation_layout.xml
index 0e576fb..64c7422 100644
--- a/packages/SystemUI/res/layout/navigation_layout.xml
+++ b/packages/SystemUI/res/layout/navigation_layout.xml
@@ -30,7 +30,8 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:clipChildren="false"
-        android:clipToPadding="false">
+        android:clipToPadding="false"
+        systemui:isVertical="false">
 
         <LinearLayout
             android:id="@+id/ends_group"
diff --git a/packages/SystemUI/res/layout/navigation_layout_vertical.xml b/packages/SystemUI/res/layout/navigation_layout_vertical.xml
index 4b67700..42e9324 100644
--- a/packages/SystemUI/res/layout/navigation_layout_vertical.xml
+++ b/packages/SystemUI/res/layout/navigation_layout_vertical.xml
@@ -30,7 +30,8 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:clipChildren="false"
-        android:clipToPadding="false">
+        android:clipToPadding="false"
+        systemui:isVertical="true">
 
         <com.android.systemui.navigationbar.buttons.ReverseLinearLayout
             android:id="@+id/ends_group"
diff --git a/packages/SystemUI/res/layout/pip_menu_activity.xml b/packages/SystemUI/res/layout/pip_menu_activity.xml
deleted file mode 100644
index 2b33e17..0000000
--- a/packages/SystemUI/res/layout/pip_menu_activity.xml
+++ /dev/null
@@ -1,93 +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.
--->
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/background"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <!-- Menu layout -->
-    <FrameLayout
-        android:id="@+id/menu_container"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:forceHasOverlappingRendering="false"
-        android:accessibilityTraversalAfter="@id/dismiss">
-
-        <!-- The margins for this container is calculated in the code depending on whether the
-             actions_container is visible. -->
-        <FrameLayout
-            android:id="@+id/expand_container"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent">
-            <ImageButton
-                android:id="@+id/expand_button"
-                android:layout_width="60dp"
-                android:layout_height="60dp"
-                android:layout_gravity="center"
-                android:contentDescription="@string/pip_phone_expand"
-                android:padding="10dp"
-                android:src="@drawable/pip_expand"
-                android:background="?android:selectableItemBackgroundBorderless" />
-        </FrameLayout>
-
-        <FrameLayout
-            android:id="@+id/actions_container"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/pip_action_size"
-            android:layout_gravity="bottom"
-            android:visibility="invisible">
-            <LinearLayout
-                android:id="@+id/actions_group"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
-                android:layout_gravity="center_horizontal"
-                android:orientation="horizontal"
-                android:divider="@android:color/transparent"
-                android:showDividers="middle" />
-        </FrameLayout>
-    </FrameLayout>
-
-    <ImageButton
-        android:id="@+id/settings"
-        android:layout_width="@dimen/pip_action_size"
-        android:layout_height="@dimen/pip_action_size"
-        android:layout_gravity="top|start"
-        android:padding="@dimen/pip_action_padding"
-        android:contentDescription="@string/pip_phone_settings"
-        android:src="@drawable/ic_settings"
-        android:background="?android:selectableItemBackgroundBorderless" />
-
-    <ImageButton
-        android:id="@+id/dismiss"
-        android:layout_width="@dimen/pip_action_size"
-        android:layout_height="@dimen/pip_action_size"
-        android:layout_gravity="top|end"
-        android:padding="@dimen/pip_action_padding"
-        android:contentDescription="@string/pip_phone_close"
-        android:src="@drawable/ic_close_white"
-        android:background="?android:selectableItemBackgroundBorderless" />
-
-    <!--TODO (b/156917828): Add content description for a11y purposes?-->
-    <ImageButton
-        android:id="@+id/resize_handle"
-        android:layout_width="@dimen/pip_resize_handle_size"
-        android:layout_height="@dimen/pip_resize_handle_size"
-        android:layout_gravity="top|start"
-        android:layout_margin="@dimen/pip_resize_handle_margin"
-        android:src="@drawable/pip_resize_handle"
-        android:background="?android:selectableItemBackgroundBorderless" />
-</FrameLayout>
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index 0822947..93dd1a1 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -81,6 +81,22 @@
             android:layout_height="match_parent"
             android:layout_weight="@integer/qs_footer_actions_weight"
             android:gravity="center_vertical|end" >
+
+            <com.android.systemui.statusbar.AlphaOptimizedImageView
+                android:id="@+id/pm_lite"
+                android:layout_width="@dimen/qs_footer_action_button_size"
+                android:layout_height="@dimen/qs_footer_action_button_size"
+                android:background="?android:attr/selectableItemBackgroundBorderless"
+                android:clickable="true"
+                android:clipToPadding="false"
+                android:contentDescription="@string/accessibility_quick_settings_edit"
+                android:focusable="true"
+                android:padding="@dimen/qs_footer_icon_padding"
+                android:src="@*android:drawable/ic_lock_power_off"
+                android:tint="?android:attr/colorForeground"
+                android:visibility="gone"
+                />
+
             <com.android.systemui.statusbar.phone.MultiUserSwitch
                 android:id="@+id/multi_user_switch"
                 android:layout_width="@dimen/qs_footer_action_button_size"
diff --git a/packages/SystemUI/res/layout/qs_paged_page_side_labels.xml b/packages/SystemUI/res/layout/qs_paged_page_side_labels.xml
index ee54f1d..c830773 100644
--- a/packages/SystemUI/res/layout/qs_paged_page_side_labels.xml
+++ b/packages/SystemUI/res/layout/qs_paged_page_side_labels.xml
@@ -14,4 +14,10 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<include layout="@layout/qs_paged_page" />
+<com.android.systemui.qs.SideLabelTileLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/tile_page"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:clipChildren="false"
+    android:clipToPadding="false" />
diff --git a/packages/SystemUI/res/layout/qs_tile_label.xml b/packages/SystemUI/res/layout/qs_tile_label.xml
index 571cbbc..1ce87c1 100644
--- a/packages/SystemUI/res/layout/qs_tile_label.xml
+++ b/packages/SystemUI/res/layout/qs_tile_label.xml
@@ -20,7 +20,6 @@
     android:layout_height="wrap_content"
     android:clipChildren="false"
     android:clipToPadding="false"
-    android:minHeight="48dp"
     android:paddingTop="12dp">
     <LinearLayout
         android:id="@+id/label_group"
diff --git a/packages/SystemUI/res/layout/qs_tile_label_divider.xml b/packages/SystemUI/res/layout/qs_tile_label_divider.xml
deleted file mode 100644
index 150a5b8..0000000
--- a/packages/SystemUI/res/layout/qs_tile_label_divider.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<View />
\ 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 a8ef7c3..bbb6107 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -37,12 +37,6 @@
         android:layout_height="match_parent"
         android:layout_width="match_parent" />
 
-    <ViewStub
-        android:id="@+id/keyguard_user_switcher_stub"
-        android:layout="@layout/keyguard_user_switcher"
-        android:layout_height="match_parent"
-        android:layout_width="match_parent" />
-
     <include
         layout="@layout/keyguard_status_view"
         android:visibility="gone" />
@@ -61,19 +55,21 @@
             android:id="@+id/qs_frame"
             android:layout="@layout/qs_panel"
             android:layout_width="@dimen/qs_panel_width"
-            android:layout_height="match_parent"
+            android:layout_height="0dp"
             android:clipToPadding="false"
             android:clipChildren="false"
             systemui:viewType="com.android.systemui.plugins.qs.QS"
             systemui:layout_constraintStart_toStartOf="parent"
             systemui:layout_constraintEnd_toEndOf="parent"
+            systemui:layout_constraintTop_toTopOf="parent"
+            systemui:layout_constraintBottom_toBottomOf="parent"
         />
 
         <androidx.constraintlayout.widget.Guideline
             android:id="@+id/qs_edge_guideline"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            systemui:layout_constraintGuide_percent="0.5"
+            systemui:layout_constraintGuide_percent="0.4"
             android:orientation="vertical"/>
 
         <com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
@@ -109,5 +105,11 @@
         layout="@layout/keyguard_bottom_area"
         android:visibility="gone" />
 
+    <ViewStub
+        android:id="@+id/keyguard_user_switcher_stub"
+        android:layout="@layout/keyguard_user_switcher"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent" />
+
     <include layout="@layout/status_bar_expanded_plugin_frame"/>
 </com.android.systemui.statusbar.phone.NotificationPanelView>
diff --git a/packages/SystemUI/res/layout/text_toast.xml b/packages/SystemUI/res/layout/text_toast.xml
index de4e062..ad558d8 100644
--- a/packages/SystemUI/res/layout/text_toast.xml
+++ b/packages/SystemUI/res/layout/text_toast.xml
@@ -20,32 +20,30 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
-    android:maxWidth="@dimen/toast_width"
     android:orientation="horizontal"
-    android:background="@drawable/toast_background"
-    android:backgroundTint="?android:attr/colorBackground"
+    android:gravity="center_vertical"
+    android:maxWidth="@*android:dimen/toast_width"
+    android:background="@android:drawable/toast_frame"
     android:layout_marginEnd="16dp"
     android:layout_marginStart="16dp"
-    android:gravity="center_vertical">
+    android:paddingStart="16dp"
+    android:paddingEnd="16dp">
 
-    <!-- Icon should be 24x24, make slightly larger to allow for shadowing, adjust via padding -->
     <ImageView
         android:id="@+id/icon"
-        android:alpha="@dimen/toast_icon_alpha"
-        android:padding="11.5dp"
-        android:layout_width="@dimen/toast_icon_size"
-        android:layout_height="@dimen/toast_icon_size"/>
+        android:layout_width="24dp"
+        android:layout_height="24dp"
+        android:layout_marginTop="10dp"
+        android:layout_marginBottom="10dp"
+        android:layout_marginEnd="10dp"/>
     <TextView
         android:id="@+id/text"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
         android:ellipsize="end"
         android:maxLines="2"
         android:paddingTop="12dp"
         android:paddingBottom="12dp"
-        android:paddingStart="0dp"
-        android:paddingEnd="22dp"
-        android:textSize="@dimen/toast_text_size"
-        android:textColor="?android:attr/textColorPrimary"
-        android:fontFamily="@*android:string/config_headlineFontFamily"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"/>
+        android:lineHeight="20sp"
+        android:textAppearance="@*android:style/TextAppearance.Toast"/>
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml b/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml
deleted file mode 100644
index b62018d..0000000
--- a/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content"
-              android:orientation="horizontal"
-              android:padding="12dp">
-
-    <FrameLayout
-        android:layout_width="34dp"
-        android:layout_height="24dp"
-        android:layout_gravity="center"
-        android:background="@drawable/tv_rect_shadow_rounded">
-
-        <ImageView
-            android:layout_width="13dp"
-            android:layout_height="13dp"
-            android:layout_gravity="center"
-            android:src="@drawable/tv_ic_mic_white"/>
-
-    </FrameLayout>
-
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/tv_ongoing_privacy_chip.xml b/packages/SystemUI/res/layout/tv_ongoing_privacy_chip.xml
new file mode 100644
index 0000000..dff148b
--- /dev/null
+++ b/packages/SystemUI/res/layout/tv_ongoing_privacy_chip.xml
@@ -0,0 +1,35 @@
+<?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:padding="12dp"
+    android:layout_gravity="center">
+
+    <LinearLayout
+        android:id="@+id/icons_container"
+        android:background="@drawable/tv_rect_shadow_rounded"
+        android:padding="@dimen/privacy_chip_icon_padding"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:orientation="horizontal"/>
+
+</FrameLayout>
+
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index 1810c19..6aac5a3 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -21,6 +21,8 @@
     android:layout_height="wrap_content"
     android:gravity="right"
     android:layout_gravity="right"
+    android:paddingRight="@dimen/volume_dialog_stream_padding"
+    android:clipToPadding="false"
     android:background="@android:color/transparent"
     android:theme="@style/volume_dialog_theme">
 
@@ -34,13 +36,15 @@
         android:layout_gravity="right"
         android:background="@android:color/transparent"
         android:paddingRight="@dimen/volume_dialog_panel_transparent_padding_right"
-        android:paddingTop="@dimen/volume_dialog_panel_transparent_padding"
-        android:paddingBottom="@dimen/volume_dialog_panel_transparent_padding"
         android:paddingLeft="@dimen/volume_dialog_panel_transparent_padding"
         android:orientation="vertical"
-        android:clipToPadding="false">
+        android:clipToPadding="false"
+        android:clipChildren="false">
+
+        <include layout="@layout/volume_ringer_drawer" />
 
         <FrameLayout
+            android:visibility="gone"
             android:id="@+id/ringer"
             android:layout_width="@dimen/volume_dialog_ringer_size"
             android:layout_height="@dimen/volume_dialog_ringer_size"
@@ -77,10 +81,8 @@
             android:gravity="right"
             android:layout_gravity="right"
             android:orientation="vertical"
-            android:translationZ="@dimen/volume_dialog_elevation"
             android:clipChildren="false"
-            android:clipToPadding="false"
-            android:background="@drawable/rounded_bg_full" >
+            android:clipToPadding="false" >
             <LinearLayout
                 android:id="@+id/volume_dialog_rows"
                 android:layout_width="wrap_content"
@@ -88,24 +90,22 @@
                 android:minWidth="@dimen/volume_dialog_panel_width"
                 android:gravity="center"
                 android:orientation="horizontal"
-                android:paddingRight="@dimen/volume_dialog_stream_padding"
-                android:paddingLeft="@dimen/volume_dialog_stream_padding">
+                android:layout_marginTop="@dimen/volume_row_slider_padding_start">
                     <!-- volume rows added and removed here! :-) -->
             </LinearLayout>
             <FrameLayout
                 android:id="@+id/settings_container"
                 android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:background="@drawable/rounded_bg_bottom_background">
+                android:layout_height="wrap_content">
                 <com.android.keyguard.AlphaOptimizedImageButton
                     android:id="@+id/settings"
-                    android:src="@drawable/ic_tune_black_16dp"
+                    android:src="@drawable/horizontal_ellipsis"
                     android:layout_width="@dimen/volume_dialog_tap_target_size"
                     android:layout_height="@dimen/volume_dialog_tap_target_size"
                     android:layout_gravity="center"
                     android:contentDescription="@string/accessibility_volume_settings"
                     android:background="@drawable/ripple_drawable_20dp"
-                    android:tint="?android:attr/textColorPrimary"
+                    android:tint="?android:attr/colorBackgroundFloating"
                     android:soundEffectsEnabled="false" />
             </FrameLayout>
         </LinearLayout>
@@ -118,7 +118,6 @@
             android:gravity="right"
             android:layout_gravity="right"
             android:clipToPadding="false"
-            android:translationZ="@dimen/volume_dialog_elevation"
             android:background="@drawable/rounded_bg_full">
             <com.android.systemui.volume.CaptionsToggleImageButton
                 android:id="@+id/odi_captions_icon"
@@ -127,7 +126,7 @@
                 android:background="@drawable/rounded_ripple"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
-                android:tint="?android:attr/textColorPrimary"
+                android:tint="?android:attr/colorAccent"
                 android:layout_gravity="center"
                 android:soundEffectsEnabled="false"
                 sysui:optedOut="false"/>
diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml
index b9efc5b..fda59b5 100644
--- a/packages/SystemUI/res/layout/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout/volume_dialog_row.xml
@@ -20,11 +20,12 @@
     android:layout_width="@dimen/volume_dialog_panel_width"
     android:clipChildren="false"
     android:clipToPadding="false"
+    android:translationZ="@dimen/volume_dialog_elevation"
     android:theme="@style/volume_dialog_theme">
 
     <LinearLayout
         android:layout_height="wrap_content"
-        android:layout_width="match_parent"
+        android:layout_width="@dimen/volume_dialog_panel_width"
         android:gravity="center"
         android:layout_gravity="center"
         android:orientation="vertical" >
@@ -41,21 +42,23 @@
         <FrameLayout
             android:id="@+id/volume_row_slider_frame"
             android:layout_width="match_parent"
-            android:layout_marginTop="@dimen/volume_dialog_slider_margin_top"
-            android:layout_marginBottom="@dimen/volume_dialog_slider_margin_bottom"
-            android:layoutDirection="rtl"
-            android:layout_height="@dimen/volume_dialog_slider_height">
+            android:layout_height="@dimen/volume_row_slider_height">
+            <include layout="@layout/volume_dnd_icon"/>
             <SeekBar
                 android:id="@+id/volume_row_slider"
+                android:paddingLeft="0dp"
+                android:paddingRight="0dp"
+                android:paddingStart="0dp"
+                android:paddingEnd="0dp"
                 android:clickable="true"
-                android:layout_width="@dimen/volume_dialog_slider_height"
+                android:layout_width="@dimen/volume_row_slider_height"
                 android:layout_height="match_parent"
-                android:layoutDirection="rtl"
                 android:layout_gravity="center"
-                android:rotation="90" />
+                android:rotation="270" />
         </FrameLayout>
 
         <com.android.keyguard.AlphaOptimizedImageButton
+            android:visibility="gone"
             android:id="@+id/volume_row_icon"
             style="@style/VolumeButtons"
             android:layout_width="@dimen/volume_dialog_tap_target_size"
@@ -66,6 +69,4 @@
             android:soundEffectsEnabled="false" />
     </LinearLayout>
 
-    <include layout="@layout/volume_dnd_icon"/>
-
 </FrameLayout>
diff --git a/packages/SystemUI/res/layout/volume_ringer_drawer.xml b/packages/SystemUI/res/layout/volume_ringer_drawer.xml
new file mode 100644
index 0000000..d6e1782
--- /dev/null
+++ b/packages/SystemUI/res/layout/volume_ringer_drawer.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Contains the active ringer icon and a hidden drawer containing all three ringer options. -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:gravity="center"
+    android:clipToPadding="false"
+    android:clipChildren="false">
+
+    <!-- Drawer view, invisible by default. -->
+    <FrameLayout
+        android:id="@+id/volume_drawer_container"
+        android:alpha="0.0"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@drawable/volume_drawer_bg"
+        android:orientation="vertical">
+
+        <!-- View that is animated to a tapped ringer selection, so it appears selected. -->
+        <FrameLayout
+            android:id="@+id/volume_drawer_selection_background"
+            android:alpha="0.0"
+            android:layout_width="@dimen/volume_ringer_drawer_item_size"
+            android:layout_height="@dimen/volume_ringer_drawer_item_size"
+            android:layout_gravity="bottom|right"
+            android:background="@drawable/volume_drawer_selection_bg" />
+
+        <LinearLayout
+            android:id="@+id/volume_drawer_options"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+
+            <FrameLayout
+                android:id="@+id/volume_drawer_vibrate"
+                android:layout_width="@dimen/volume_ringer_drawer_item_size"
+                android:layout_height="@dimen/volume_ringer_drawer_item_size"
+                android:description="@string/volume_ringer_hint_vibrate"
+                android:gravity="center">
+
+                <ImageView
+                    android:id="@+id/volume_drawer_vibrate_icon"
+                    android:layout_width="@dimen/volume_ringer_drawer_icon_size"
+                    android:layout_height="@dimen/volume_ringer_drawer_icon_size"
+                    android:layout_gravity="center"
+                    android:tint="?android:attr/colorAccent"
+                    android:src="@drawable/ic_volume_ringer_vibrate" />
+
+            </FrameLayout>
+
+            <FrameLayout
+                android:id="@+id/volume_drawer_mute"
+                android:layout_width="@dimen/volume_ringer_drawer_item_size"
+                android:layout_height="@dimen/volume_ringer_drawer_item_size"
+                android:description="@string/volume_ringer_hint_mute"
+                android:gravity="center">
+
+                <ImageView
+                    android:id="@+id/volume_drawer_mute_icon"
+                    android:layout_width="@dimen/volume_ringer_drawer_icon_size"
+                    android:layout_height="@dimen/volume_ringer_drawer_icon_size"
+                    android:layout_gravity="center"
+                    android:tint="?android:attr/colorAccent"
+                    android:src="@drawable/ic_volume_ringer_mute" />
+
+            </FrameLayout>
+
+            <FrameLayout
+                android:id="@+id/volume_drawer_normal"
+                android:layout_width="@dimen/volume_ringer_drawer_item_size"
+                android:layout_height="@dimen/volume_ringer_drawer_item_size"
+                android:description="@string/volume_ringer_hint_unmute"
+                android:gravity="center">
+
+                <ImageView
+                    android:id="@+id/volume_drawer_normal_icon"
+                    android:layout_width="@dimen/volume_ringer_drawer_icon_size"
+                    android:layout_height="@dimen/volume_ringer_drawer_icon_size"
+                    android:layout_gravity="center"
+                    android:tint="?android:attr/colorAccent"
+                    android:src="@drawable/ic_volume_ringer" />
+
+            </FrameLayout>
+
+        </LinearLayout>
+
+    </FrameLayout>
+
+    <!-- The current ringer selection. When the drawer is opened, this animates to the corresponding
+         position in the drawer. When the drawer is closed, it animates back. -->
+    <FrameLayout
+        android:id="@+id/volume_new_ringer_active_icon_container"
+        android:layout_width="@dimen/volume_ringer_drawer_item_size"
+        android:layout_height="@dimen/volume_ringer_drawer_item_size"
+        android:layout_gravity="bottom|right"
+        android:description="@string/volume_ringer_change"
+        android:background="@drawable/volume_drawer_selection_bg">
+
+        <ImageView
+            android:id="@+id/volume_new_ringer_active_icon"
+            android:layout_width="@dimen/volume_ringer_drawer_icon_size"
+            android:layout_height="@dimen/volume_ringer_drawer_icon_size"
+            android:layout_gravity="center"
+            android:tint="?android:attr/colorBackgroundFloating"
+            android:src="@drawable/ic_volume_media" />
+
+    </FrameLayout>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 5db7c25..c3a62b0 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Rollees skermskoot"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Maak skermkiekie toe"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Skermkiekievoorskou"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Boonste grens"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Onderste grens"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Skermopnemer"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Verwerk tans skermopname"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Deurlopende kennisgewing vir \'n skermopnamesessie"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Tot sonsopkoms"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aan om <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Tot <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is gedeaktiveer"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is geaktiveer"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ontsluit om NFC te gebruik"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Hierdie toestel behoort aan jou organisasie"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Hierdie toestel behoort aan <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Swiep vanaf ikoon vir foon"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Swiep vanaf ikoon vir stembystand"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Swiep vanaf ikoon vir kamera"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Wys profiel"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Voeg gebruiker by"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Nuwe gebruiker"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Beëindig gastesessie?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Beëindig gastesessie"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Verwyder gas?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle programme en data in hierdie sessie sal uitgevee word."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Beëindig sessie"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Verwyder"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Welkom terug, gas!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Wiil jy jou sessie voortsit?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Begin van voor af"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Jou organisasie het \'n sertifikaatoutoriteit in jou werkprofiel geïnstalleer. Jou veilige netwerkverkeer kan gemonitor of gewysig word."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"\'n Sertifikaatoutoriteit is op hierdie toestel geïnstalleer. Jou veilige netwerkverkeer kan gemonitor of gewysig word."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Jou administrateur het netwerkloginskrywing aangeskakel, wat verkeer op jou toestel monitor."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Jou administrateur het netwerkloglêers aangeskakel wat verkeer in jou werkprofiel maar nie in jou persoonlike profiel monitor nie."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Jy is gekoppel aan <xliff:g id="VPN_APP">%1$s</xliff:g>, wat jou netwerkaktiwiteit, insluitend e-posse, programme en webwerwe, kan monitor."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Jy is gekoppel aan <xliff:g id="VPN_APP_0">%1$s</xliff:g> en <xliff:g id="VPN_APP_1">%2$s</xliff:g>, wat jou netwerkaktiwiteit, insluitend e-posse, programme en webwerwe, kan monitor."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Jou werkprofiel is gekoppel aan <xliff:g id="VPN_APP">%1$s</xliff:g>, wat jou netwerkaktiwiteit, insluitend e-posse, programme en webwerwe, kan monitor."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Tik om te demp. Toeganklikheidsdienste kan dalk gedemp wees."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Tik om op vibreer te stel."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Tik om te demp."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"demp"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"ontdemp"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibreer"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Hierdie kennisgewing is outomaties deur die stelsel &lt;b&gt;na Stil gedegradeer&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Hierdie kennisgewing is outomaties &lt;b&gt;hoër gegradeer&lt;/b&gt; in jou skakering."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Hierdie kennisgewing is outomaties &lt;b&gt;laer gegradeer&lt;/b&gt; in jou skakering."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Is dit korrek?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Gee jou terugvoer aan die ontwikkelaar deur. Is dit korrek?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Dankie vir jou terugvoer!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Kennisgewingkontroles vir <xliff:g id="APP_NAME">%1$s</xliff:g> is oopgemaak"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Skuif na <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Voeg by posisie <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posisie <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Teël is bygevoeg"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Teël is verwyder"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Kitsinstellingswysiger."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>-kennisgewing: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Maak instellings oop."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> gebruik tans die <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> het onlangs die <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> gebruik"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(onderneming)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Oproep"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Oproep"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(deur <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"ligging"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensors is af"</string>
     <string name="device_services" msgid="1549944177856658705">"Toesteldienste"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Titelloos"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Tik om hierdie program te herbegin en maak volskerm oop."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Beweeg"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Stelselnavigasie is opgedateer. Gaan na Instellings toe om veranderinge te maak."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Gaan na Instellings toe om stelselnavigasie op te dateer"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Voeg by"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Voorgestel deur <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Kontroles opgedateer"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Toestel is gesluit"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN bevat letters of simbole"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Verifieer <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Verkeerde PIN"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 1af18fe..0c0487d 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"ቅጽበታዊ ገጽ ዕይታን ይሸብልሉ"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ቅጽበታዊ ገጽ ዕይታን አሰናብት"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"የቅጽበታዊ ገጽ ዕይታ ቅድመ-ዕይታ"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"የላይኛው ወሰን"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"የታችኛው ወሰን"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"የማያ መቅጃ"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"የማያ ገጽ ቀረጻን በማሰናዳት ላይ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ለአንድ የማያ ገጽ ቀረጻ ክፍለ-ጊዜ በመካሄድ ያለ ማሳወቂያ"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ጸሐይ እስክትወጣ ድረስ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> ላይ ይበራል"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"እስከ <xliff:g id="TIME">%s</xliff:g> ድረስ"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"ኤንኤፍሲ"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"ኤንኤፍሲ ተሰናክሏል"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"ኤንኤፍሲ ነቅቷል"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCን ለመጠቀም ይክፈቱ"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"ይህ መሣሪያ የድርጅትዎ ነው"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"ይህ መሳሪያ ንብረትነቱ የ<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ነው"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"ለስልክ ከአዶ ላይ ጠረግ ያድርጉ"</string>
     <string name="voice_hint" msgid="7476017460191291417">"ለድምጽ ረዳት ከአዶ ጠረግ ያድርጉ"</string>
     <string name="camera_hint" msgid="4519495795000658637">"ለካሜራ ከአዶ ላይ ጠረግ ያድርጉ"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"መገለጫ አሳይ"</string>
     <string name="user_add_user" msgid="4336657383006913022">"ተጠቃሚ አክል"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"አዲስ ተጠቃሚ"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"የእንግዳ ክፍለ-ጊዜ ይብቃ?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"የእንግዳ ክፍለ-ጊዜ ጨርስ"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"እንግዳ ይወገድ?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"በዚህ ክፍለ-ጊዜ ውስጥ ያሉ ሁሉም መተግበሪያዎች እና ውሂብ ይሰረዛሉ።"</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"ክፍለ-ጊዜን አብቃ"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"አስወግድ"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"እንኳን በደህና ተመለሱ እንግዳ!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"ክፍለ-ጊዜዎን መቀጠል ይፈልጋሉ?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"እንደገና ጀምር"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"የእርስዎ ድርጅት የእውቅና ማረጋገጫ ሰጪ ባለሥልጣን በእርስዎ የሥራ መገለጫ ላይ ጭኗል። የእርስዎ ደኅንነቱ የተጠበቀ አውታረ መረብ ትራፊክ ክትትል ሊደረግበት እና ሊሻሻል ይችላል።"</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"የእውቅና ማረጋገጫ ሰጪ ባለሥልጣን በዚህ መሣሪያ ላይ ተጭኗል። የእርስዎ ደኅንነቱ የተጠበቀ አውታረ መረብ ትራፊክ ክትትል ሊደረግበት እና ሊሻሻል ይችላል።"</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"የእርስዎ አስተዳዳሪ የአውታረ መረብ ምዝግብ ማስታወሻ መያዝን አብርተዋል፣ ይህም በመሣሪያዎ ላይ ያለውን ትራፊክ ይከታተላል።"</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"የእርስዎ አስተዳዳሪ በስራ መገለጫዎ ውስጥ፣ ግን በግል መገለጫዎ ላይ ሳይሆን፣ ትራፊክን የሚቆጣጠር የአውታረ መረብ ምዝግብ ማስታወሻ አብርተዋል።"</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"እርስዎ ኢሜይሎችን፣ መተግበሪያዎችን እና ድር ጣቢያዎችንም ጨምሮ የግል የአውታረ መረብ እንቅስቃሴዎን መከታተል ከሚችለው <xliff:g id="VPN_APP">%1$s</xliff:g> ጋር ተገናኝተዋል።"</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"ኢሜይሎችን፣ መተግበሪያዎችን እና ድር ጣቢያዎችንም ጨምሮ የግል የአውታረ መረብ እንቅስቃሴዎን መከታተል ከሚችሉት <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="368812367182387320">"የእርስዎ የሥራ መገለጫ የእርስዎን ኢሜይሎችን፣ መተግበሪያዎችን እና ድር ጣቢያዎችንም ጨምሮ የግል የአውታረ መረብ እንቅስቃሴዎን መከታተል ከሚችለው <xliff:g id="VPN_APP">%1$s</xliff:g> ጋር ተገናኝቷል።"</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s። ድምጸ-ከል ለማድረግ መታ ያድርጉ። የተደራሽነት አገልግሎቶች ድምጸ-ከል ሊደረግባቸው ይችላል።"</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s። ወደ ንዝረት ለማቀናበር መታ ያድርጉ።"</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s። ድምጸ-ከል ለማድረግ መታ ያድርጉ።"</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"ድምጸ-ከል አድርግ"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"ድምጸ-ከልን አንሳ"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"ንዘር"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"ይህ ማሳወቂያ በሥርዓቱ በራስ-ሰር &lt;b&gt;ወደ ዝምታ ዝቅ ተደርጓል &lt;/b&gt;።"</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"ይህ ማሳወቂያ በራስ-ሰር በጥላው ውስጥ &lt;b&gt;ከፍተኛ ደረጃ ተሰጥቶታል&lt;/b&gt;።"</string>
     <string name="feedback_demoted" msgid="951884763467110604">"ይህ ማሳወቂያ በራስ-ሰር በጥላው ውስጥ &lt;b&gt;ዝቅተኛ ደረጃ ተሰጥቶታል&lt;/b&gt;።"</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"ይህ ትክክል ነበር?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"ግብረመልስዎን ገንቢው እንዲያውቅ ያድርጉ። ይህ ትክክል ነበር?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"ለግብረመልስዎ እናመሰግናለን!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"እሺ"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"የ<xliff:g id="APP_NAME">%1$s</xliff:g> ማሳወቂያ መቆጣጠሪያዎች ተከፍተዋል"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"ወደ <xliff:g id="POSITION">%1$d</xliff:g> ውሰድ"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"ወደ <xliff:g id="POSITION">%1$d</xliff:g> ቦታ አክል"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"የ<xliff:g id="POSITION">%1$d</xliff:g> አቀማመጥ"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"ሰቅ ታክሏል"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"ሰቅ ተወግዷል"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"የፈጣን ቅንብሮች አርታዒ።"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"የ<xliff:g id="ID_1">%1$s</xliff:g> ማሳወቂያ፦ <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ቅንብሮችን ክፈት።"</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>ን እየተጠቀመ ነው"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> በቅርብ ጊዜ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>ን ይጠቀማል።"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(ድርጅት)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"የስልክ ጥሪ"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"የስልክ ጥሪ"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(እስከ <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"ካሜራ"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"አካባቢ"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"ዳሳሾች ጠፍተዋል"</string>
     <string name="device_services" msgid="1549944177856658705">"የመሣሪያ አገልግሎቶች"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"ርዕስ የለም"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"ይህን መተግበሪያ እንደገና ለማስጀመር መታ ያድርጉ እና ወደ ሙሉ ማያ ገጽ ይሂዱ።"</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"አንቀሳቅስ"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"የስርዓት ዳሰሳ ተዘምኗል። ለውጦችን ለማድረግ ወደ ቅንብሮች ይሂዱ።"</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"የስርዓት ዳሰሳን ለማዘመን ወደ ቅንብሮች ይሂዱ"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"አክል"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"በ<xliff:g id="APP">%s</xliff:g> የተጠቆመ"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"መቆጣጠሪያዎች ተዘምነዋል"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"መሣሪያ ተቆልፏል"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"ፒን ፊደሎችን ወይም ምልክቶችን ይይዛል"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> አረጋግጥ"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"የተሳሳተ ፒን"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index b34b39a..ae8df90 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"لقطة شاشة موصولة"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"إغلاق لقطة الشاشة"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"معاينة لقطة الشاشة"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"الحد العلوي"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"الحد السفلي"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"مسجّل الشاشة"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"جارٍ معالجة تسجيل الشاشة"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"إشعار مستمر لجلسة تسجيل شاشة"</string>
@@ -418,6 +420,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"حتى شروق الشمس"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"تفعيل الوضع في <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"حتى <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"تم إيقاف الاتصال القريب المدى"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"تم تفعيل الاتصال القريب المدى"</string>
@@ -448,9 +452,11 @@
     <string name="notification_tap_again" msgid="4477318164947497249">"انقر مرة أخرى للفتح"</string>
     <string name="keyguard_unlock" msgid="8031975796351361601">"يمكنك الفتح بالتمرير سريعًا لأعلى."</string>
     <string name="keyguard_retry" msgid="886802522584053523">"مرِّر سريعًا للأعلى لإعادة المحاولة."</string>
-    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"‏يجب فتح قفل الشاشة لاستخدام تقنية الاتصال قصير المدى (NFC)."</string>
+    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"‏افتح قفل الشاشة لاستخدام تقنية NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"هذا الجهاز يخص مؤسستك."</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"هذا الجهاز يخص <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>."</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"يمكنك التمرير سريعًا من الرمز لتشغيل الهاتف"</string>
     <string name="voice_hint" msgid="7476017460191291417">"يمكنك التمرير سريعًا من الرمز لتشغيل المساعد الصوتي"</string>
     <string name="camera_hint" msgid="4519495795000658637">"يمكنك التمرير سريعًا من الرمز لتشغيل الكاميرا"</string>
@@ -471,9 +477,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"عرض الملف الشخصي"</string>
     <string name="user_add_user" msgid="4336657383006913022">"إضافة مستخدم"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"مستخدم جديد"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"هل تريد إنهاء جلسة الضيف؟"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"إنهاء جلسة الضيف"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"هل تريد إزالة جلسة الضيف؟"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"سيتم حذف كل التطبيقات والبيانات في هذه الجلسة."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"إنهاء الجلسة"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"إزالة"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"مرحبًا بك مجددًا في جلسة الضيف"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"هل تريد متابعة جلستك؟"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"البدء من جديد"</string>
@@ -552,6 +559,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"ثبّتت مؤسستك مرجعًا مصدّقًا في ملفك الشخصي للعمل. قد تتم مراقبة حركة بيانات شبكتك الآمنة أو تعديلها."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"تم تثبيت مرجع مصدّق على هذا الجهاز. قد تتم مراقبة حركة بيانات شبكتك الآمنة أو تعديلها."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"شغَّل المشرف ميزة تسجيل بيانات الشبكة، والتي يتم من خلالها مراقبة حركة البيانات على جهازك."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"شغَّل المشرف ميزة تسجيل بيانات الشبكة، والتي يتم من خلالها مراقبة حركة البيانات في ملفك الشخصي للعمل ولكن لا تتم مراقبتها في ملفك الشخصي."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"لقد اتصلت بتطبيق <xliff:g id="VPN_APP">%1$s</xliff:g>، الذي يمكن أن يراقب نشاط شبكتك، بما في ذلك رسائل البريد الإلكتروني والتطبيقات والمواقع الإلكترونية."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"لقد اتصلت بتطبيق <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="368812367182387320">"تم ربط الملف الشخصي للعمل بـ <xliff:g id="VPN_APP">%1$s</xliff:g>، الذي يمكنه مراقبة أنشطتك الشخصية على الشبكة، بما في ذلك الرسائل الإلكترونية والتطبيقات ومواقع الويب."</string>
@@ -632,6 +640,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"‏%1$s. انقر للتجاهل. قد يتم تجاهل خدمات \"سهولة الاستخدام\"."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"‏%1$s. انقر للتعيين على الاهتزاز."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"‏%1$s. انقر لكتم الصوت."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"كتم الصوت"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"إعادة الصوت"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"اهتزاز"</string>
@@ -745,7 +755,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"‏تم تلقائيًا &lt;b&gt;خفض ترتيب هذا الإشعار إلى الوضع صامت&lt;/b&gt; من خلال النظام."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"‏تم تلقائيًا &lt;b&gt;زيادة ترتيب&lt;/b&gt; هذا الإشعار في مركز الإشعارات."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"‏تم تلقائيًا &lt;b&gt;خفض ترتيب&lt;/b&gt; هذا الإشعار في مركز الإشعارات."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"هل كان هذا صحيحًا؟"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"أخبِر مطوِّر البرامج برأيك. هل كان هذا صحيحًا؟"</string>
     <string name="feedback_response" msgid="4671729244976641339">"شكرًا على تعليقك"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"حسنًا"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"تم فتح عناصر التحكم في الإشعارات لتطبيق <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -900,6 +910,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"الانتقال إلى <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"الإضافة إلى الموضع <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"الموضع: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"تمت إضافة البطاقة."</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"تمت إزالة البطاقة."</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"برنامج تعديل الإعدادات السريعة."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"إشعار <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"فتح الإعدادات."</string>
@@ -987,10 +999,10 @@
     <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"تستخدم التطبيقات <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
     <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"، "</string>
     <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" و "</string>
-    <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"يستخدم تطبيق <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> عملية <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> الآن."</string>
-    <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"استخدَم تطبيق <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> عملية <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> مؤخرًا."</string>
+    <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"يستخدم تطبيق <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ميزة <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> الآن."</string>
+    <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"استخدَم تطبيق <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ميزة <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> مؤخرًا."</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(للمؤسسات)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"مكالمة هاتفية"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"المكالمات الهاتفية"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(من خلال <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"الكاميرا"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"الموقع"</string>
@@ -998,7 +1010,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"إيقاف أجهزة الاستشعار"</string>
     <string name="device_services" msgid="1549944177856658705">"خدمات الأجهزة"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"بلا عنوان"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"انقر لإعادة تشغيل هذا التطبيق والانتقال إلى وضع ملء الشاشة."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"نقل"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"تم تحديث التنقل داخل النظام. لإجراء التغييرات، يُرجى الانتقال إلى \"الإعدادات\"."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"الانتقال إلى \"الإعدادات\" لتعديل التنقل داخل النظام"</string>
@@ -1056,6 +1067,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"إضافة"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"اقتراح من <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"تم تعديل عناصر التحكّم."</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"الجهاز مُقفل."</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"يشتمل رقم التعريف الشخصي على أحرف أو رموز."</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"إثبات ملكية <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"رقم تعريف شخصي خاطئ"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 88b2bb2..1f92570 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"স্ক্ৰীনশ্বট স্ক্ৰ’ল কৰক"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"স্ক্ৰীনশ্বট অগ্ৰাহ্য কৰক"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"স্ক্ৰীনশ্বটৰ পূৰ্বদৰ্শন"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"ওপৰৰ সীমাৰেখা"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"তলৰ সীমাৰেখা"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"স্ক্ৰীন ৰেকৰ্ডাৰ"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"স্ক্রীন ৰেকৰ্ডিঙৰ প্ৰক্ৰিয়াকৰণ হৈ আছে"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রীণ ৰেকৰ্ডিং ছেশ্বন চলি থকা সময়ত পোৱা জাননী"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"সূৰ্যোদয়লৈকে"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>ত অন কৰক"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> পৰ্যন্ত"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC নিষ্ক্ৰিয় হৈ আছে"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC সক্ষম হৈ আছে"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ব্যৱহাৰ কৰিবলৈ আনলক কৰক"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"এই ডিভাইচটো আপোনাৰ প্ৰতিষ্ঠানৰ"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"এই ডিভাইচটো <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>ৰ"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"ফ\'নৰ বাবে আইকনৰপৰা ছোৱাইপ কৰক"</string>
     <string name="voice_hint" msgid="7476017460191291417">"কণ্ঠধ্বনিৰে সহায়ৰ বাবে আইকনৰ পৰা ছোৱাইপ কৰক"</string>
     <string name="camera_hint" msgid="4519495795000658637">"কেমেৰা খুলিবলৈ আইকনৰপৰা ছোৱাইপ কৰক"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"প্ৰ\'ফাইল দেখুৱাওক"</string>
     <string name="user_add_user" msgid="4336657383006913022">"ব্যৱহাৰকাৰী যোগ কৰক"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"নতুন ব্যৱহাৰকাৰী"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"অতিথিৰ ছেশ্বন সমাপ্ত কৰিবনে?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"অতিথিৰ ছেশ্বন সমাপ্ত কৰক"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"অতিথি আঁতৰাবনে?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"এই ছেশ্বনৰ সকলো এপ্ আৰু ডেটা মচা হ\'ব।"</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"ছেশ্বন সমাপ্ত কৰক"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"আঁতৰাওক"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"আপোনাক পুনৰাই স্বাগতম জনাইছোঁ!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"আপুনি আপোনাৰ ছেশ্বন অব্যাহত ৰাখিব বিচাৰেনে?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"আকৌ আৰম্ভ কৰক"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"আপোনাৰ প্ৰতিষ্ঠানে আপোনাৰ কৰ্মস্থানৰ প্ৰ\'ফাইলটোত এটা প্ৰমাণপত্ৰ সম্পৰ্কীয় কৰ্তৃপক্ষ ইনষ্টল কৰিছে। আপোনাৰ সুৰক্ষিত নেটৱৰ্কৰ ট্ৰেফিক পৰ্যবেক্ষণ বা সংশোধন কৰা হ\'ব পাৰে।"</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"এই ডিভাইচটোত এটা প্ৰমাণপত্ৰ সম্পৰ্কীয় কৰ্তৃপক্ষ ইনষ্টল কৰা হৈছে। আপোনাৰ সুৰক্ষিত নেটৱৰ্কৰ ট্ৰেফিক পৰ্যবেক্ষণ বা সংশোধন কৰা হ\'ব পাৰে।"</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"আপোনাৰ প্ৰশাসকে নেটৱৰ্ক লগিং অন কৰিছে, যিয়ে আপোনাৰ ডিভাইচটোত নেটৱৰ্ক ট্ৰেফিক পৰ্যবেক্ষণ কৰে।"</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"আপোনাৰ প্ৰশাসকে নেটৱৰ্ক লগিং অন কৰিছে, যিয়ে আপোনাৰ কৰ্মস্থানৰ প্ৰ’ফাইলত ট্ৰেফিক নিৰীক্ষণ কৰে কিন্তু আপোনাৰ ব্যক্তিগত প্ৰ’ফাইলত নকৰে।"</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"আপুনি <xliff:g id="VPN_APP">%1$s</xliff:g>ৰে সংযুক্ত হৈ আছে যিয়ে আপোনাৰ ইমেইল, এপ্ আৰু ৱেবছাইটকে ধৰি নেটৱর্কৰ কাৰ্যকলাপ পৰ্যবেক্ষণ কৰিব পাৰে।"</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"আপুনি <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="368812367182387320">"আপুনি <xliff:g id="VPN_APP">%1$s</xliff:g>ৰে সংযুক্ত হৈ আছে যিয়ে আপোনাৰ ইমেইল, এপ্ আৰু ৱেবছাইটকে ধৰি নেটৱর্কৰ কাৰ্যকলাপ পৰ্যবেক্ষণ কৰিব পাৰে।"</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s। মিউট কৰিবলৈ টিপক। দিব্য়াংগসকলৰ বাবে থকা সেৱা মিউট হৈ থাকিব পাৰে।"</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s। কম্পন অৱস্থাত ছেট কৰিবলৈ টিপক।"</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s। মিউট কৰিবলৈ টিপক।"</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"মিউট কৰক"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"আনমিউট কৰক"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"কম্পন কৰক"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"ছিষ্টেমটোৱে স্বয়ংক্ৰিয়ভাৱে এই জাননীটোৰ ক্ষেত্ৰত দিয়া &lt;b&gt;গুৰুত্ব নীৰৱ&lt;/b&gt;লৈ হ্ৰাস কৰিছে।"</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"আপোনাৰ শ্বেডত স্বয়ংক্ৰিয়ভাৱে এই জাননীটোৰ &lt;b&gt;স্থান ওপৰলৈ&lt;/b&gt; কৰা হৈছে।"</string>
     <string name="feedback_demoted" msgid="951884763467110604">"আপোনাৰ শ্বেডত স্বয়ংক্ৰিয়ভাৱে এই জাননীটোৰ &lt;b&gt;স্থান তললৈ&lt;/b&gt; কৰা হৈছে।"</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"এইটো শুদ্ধ আছিলনে?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"বিকাশকৰ্তাক আপোনাৰ মতামত জনাওক। এইটো শুদ্ধ আছিলনে?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"আপোনাৰ মতামতৰ বাবে ধন্যবাদ!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ঠিক আছে"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ জাননী নিয়ন্ত্ৰণসমূহ খোলা অৱস্থাত আছে"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> নম্বৰলৈ স্থানান্তৰ কৰক"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> নম্বৰ স্থানত যোগ দিয়ক"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g> নম্বৰ স্থান"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"টাইল যোগ দিয়া হৈছে"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"টাইল আঁতৰোৱা হৈছে"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ক্ষিপ্ৰ ছেটিংসমূহৰ সম্পাদক।"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> জাননী: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ছেটিংসমূহ খোলক।"</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>এ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ব্যৱহাৰ কৰি আছে"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>এ শেহতীয়াকৈ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ব্যৱহাৰ কৰিছে"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(এণ্টাৰপ্ৰাইজ)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Phonecall"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"ফ’ন কল"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g>ৰ জৰিয়তে)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"কেমেৰা"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"অৱস্থান"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"ছেন্সৰ অফ হৈ আছে"</string>
     <string name="device_services" msgid="1549944177856658705">"ডিভাইচ সেৱা"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"কোনো শিৰোনাম নাই"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"এপ্‌টো ৰিষ্টাৰ্ট কৰক আৰু পূৰ্ণ স্ক্ৰীণ ব্যৱহাৰ কৰক।"</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"আঁতৰাওক"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"ছিষ্টেম নেভিগেশ্বন আপডে’ট কৰা হ’ল। সলনি কৰিবলৈ ছেটিংসমূহ-লৈ যাওক।"</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"ছিষ্টেম নেভিগেশ্বন আপডে’ট কৰিবলৈ ছেটিংসমূহ-লৈ যাওক"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"যোগ দিয়ক"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g>এ পৰামৰ্শ হিচাপে আগবঢ়োৱা"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"নিয়ন্ত্ৰণসমূহ আপডে\'ট কৰা হৈছে"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"ডিভাইচ লক হৈ আছে"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"পিনত বৰ্ণ অথবা প্ৰতীকসমূহ থাকে"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> সত্যাপন কৰক"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"ভুল পিন"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 6f1c347..e813a90 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Sürüşdürülərək çəkilən skrinşot"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ekran şəklini ötürün"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Ekran şəklinə önbaxış"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Yuxarı hüdud"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Aşağı hüdud"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Ekran Yazıcısı"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran çəkilişi emal edilir"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekranın video çəkimi ərzində silinməyən bildiriş"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Şəfəq vaxtına qədər"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Bu vaxt aktiv olur: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Bu vaxtadək: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC deaktiv edilib"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC aktiv edilib"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC istifadə etmək üçün kiliddən çıxarın"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Bu cihaz təşkilatınıza məxsusdur"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Bu cihaz <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> təşkilatına məxsusdur"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Telefon üçün ikonadan sürüşdürün"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Səs yardımçısı üçün ikonadan sürüşdürün"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Kamera üçün ikonadan sürüşdürün"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Show profile"</string>
     <string name="user_add_user" msgid="4336657383006913022">"İstifadəçi əlavə edin"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Yeni istifadəçi"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Qonaq sessiyası bitirilsin?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Qonaq sessiyasını bitirin"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Qonaq silinsin?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bu sessiyada bütün tətbiqlər və data silinəcək."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Sessiyanı bitirin"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Yığışdır"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Xoş gəlmisiniz!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Sessiya davam etsin?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Yenidən başlayın"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Təşkilat iş profilində sertifikat səlahiyyəti quraşdırdı. Təhlükəsiz şəbəkə ötürülməsinə nəzarət edilə və ya dəyişdirilə bilər."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Bu cihazda sertifikat səlahiyyəti quraşdırıldı. Təhlükəsiz şəbəkə ötürülməsinə nəzarət edilə və ya dəyişdirilə bilər."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Admin cihazda şəbəkə ötürülməsinə nəzarət edən şəbəkə qeydlərini aktiv etdi."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Admininiz şəxsi profilinizdəki deyil, iş profilinizdəki trafikə nəzarət edən şəbəkə qeydiyyatını aktiv edib."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"E-poçt, tətbiq və veb saytlar daxil olmaqla şəbəkə fəaliyyətinə nəzarət edən <xliff:g id="VPN_APP">%1$s</xliff:g> tətbiqinə qoşulusunuz."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"E-poçt, tətbiq və veb saytlar daxil olmaqla şəbəkə fəaliyyətinə nəzarət edən <xliff:g id="VPN_APP_0">%1$s</xliff:g> və <xliff:g id="VPN_APP_1">%2$s</xliff:g> tətbiqlərinə qoşulusunuz."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"İş profili e-poçt, tətbiq və veb saytlar da daxil olmaqla şəbəkə fəaliyyətinə nəzarət edən <xliff:g id="VPN_APP">%1$s</xliff:g> tətbiqinə qoşuludur."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Səssiz etmək üçün tıklayın. Əlçatımlılıq xidmətləri səssiz edilmiş ola bilər."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Vibrasiyanı ayarlamaq üçün klikləyin."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Səssiz etmək üçün klikləyin."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"susdurun"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"səssiz rejimdən çıxarın"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrasiya"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Bu bildiriş sistem tərəfindən avtomatik olaraq &lt;b&gt;Səssiz rejimə keçirilib&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Bu bildiriş avtomatik olaraq siyahıda &lt;b&gt;yuxarı sıraya keçirilib&lt;/b&gt;."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Bu bildiriş avtomatik olaraq siyahıda &lt;b&gt;aşağı sıraya keçirilib&lt;/b&gt;."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Bu, doğru oldu?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Developerə rəyinizi bildirin. Bu, doğru idi?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Rəyiniz üçün təşəkkür edirik!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün bildiriş kontrolları açıqdır"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> mövqeyinə köçürün"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> mövqeyinə əlavə edin"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g> mövqeyi"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Mozaik əlavə edilib"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Mozaik silinib"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Sürətli ayarlar redaktoru."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> bildiriş: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Ayarları açın."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> istifadə edir"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> bu yaxınlarda <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> istifadə edib"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(korporativ)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefon zəngi"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefon zəngi"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> vasitəsilə)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"məkan"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensorlar deaktivdir"</string>
     <string name="device_services" msgid="1549944177856658705">"Cihaz Xidmətləri"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Başlıq yoxdur"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Bu tətbiqi sıfırlayaraq tam ekrana keçmək üçün klikləyin."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Hərəkət etdirin"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Sistem naviqasiyası yeniləndi. Dəyişiklik etmək üçün Ayarlara daxil olun."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Sistem naviqasiyasını yeniləmək üçün Ayarlara keçin"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Əlavə edin"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> tərəfindən təklif edilib"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Nizamlayıcılar güncəlləndi"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Cihaz kilidlənib"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN hərflər və ya simvollar ehtiva edir"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> cihazını doğrulayın"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Yanlış PIN"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 2185a66..27d4b18 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Pomerajte snimak ekrana"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Odbacite snimak ekrana"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Pregled snimka ekrana"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Gornja granica"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Donja granica"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Snimač ekrana"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrađujemo video snimka ekrana"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Obaveštenje o sesiji snimanja ekrana je aktivno"</string>
@@ -412,6 +414,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do izlaska sunca"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Uključuje se u <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je onemogućen"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je omogućen"</string>
@@ -445,6 +449,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Otključajte da biste koristili NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada organizaciji"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Prevucite od ikone za telefon"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Prevucite od ikone za glasovnu pomoć"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Prevucite od ikone za kameru"</string>
@@ -465,9 +471,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Prikaži profil"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Dodaj korisnika"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Novi korisnik"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Želite da završite sesiju gosta?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Završi sesiju gosta"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Želite li da uklonite gosta?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Sve aplikacije i podaci u ovoj sesiji će biti izbrisani."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Završi sesiju"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Ukloni"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Dobro došli nazad, goste!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Želite li da nastavite sesiju?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Počni iz početka"</string>
@@ -543,6 +550,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Organizacija je na poslovnom profilu instalirala autoritet za izdavanje sertifikata. Bezbedni mrežni saobraćaj može da se prati ili menja."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Na ovom uređaju je instaliran autoritet za izdavanje sertifikata. Bezbedni mrežni saobraćaj može da se prati ili menja."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Administrator je uključio evidentiranje mreže, koje prati saobraćaj na uređaju."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Administrator je uključio evidentiranje mreže, koje prati saobraćaj na poslovnom profilu, ali ne i na ličnom profilu."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Povezani ste sa aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>, koja može da nadgleda aktivnosti na mreži, uključujući imejlove, aplikacije i veb-sajtove."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Povezani ste sa aplikacijama <xliff:g id="VPN_APP_0">%1$s</xliff:g> i <xliff:g id="VPN_APP_1">%2$s</xliff:g>, koje mogu da nadgledaju aktivnosti na mreži, uključujući imejlove, aplikacije i veb-sajtove."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Poslovni profil je povezan sa aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>, koja može da nadgleda aktivnosti na mreži, uključujući imejlove, aplikacije i veb-sajtove."</string>
@@ -623,6 +631,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Dodirnite da biste isključili zvuk. Zvuk usluga pristupačnosti će možda biti isključen."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Dodirnite da biste podesili na vibraciju."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Dodirnite da biste isključili zvuk."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"isključite zvuk"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"uključite zvuk"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibracija"</string>
@@ -736,7 +746,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Sistem je ovo obaveštenje automatski &lt;b&gt;degradirao u Nečujno&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Ovo obaveštenje je automatski &lt;b&gt;rangirano više&lt;/b&gt; na traci sa obaveštenjima."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Ovo obaveštenje je automatski &lt;b&gt;rangirano niže&lt;/b&gt; na traci sa obaveštenjima."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Da li je to tačno?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Pošaljite programeru povratne informacije. Da li je to tačno?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Hvala vam na povratnim informacijama!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Potvrdi"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Kontrole obaveštenja za otvaranje aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -885,6 +895,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Premestite na <xliff:g id="POSITION">%1$d</xliff:g>. poziciju"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Dodajte na <xliff:g id="POSITION">%1$d</xliff:g>. poziciju"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g>. pozicija"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Pločica je dodata"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Pločica je uklonjena"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Uređivač za Brza podešavanja."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Obaveštenja za <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Otvori Podešavanja."</string>
@@ -975,7 +987,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Aplikacija <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> koristi: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Aplikacija <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> je nedavno koristila: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(za preduzeća)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonski poziv"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefonski poziv"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(preko: <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"kameru"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"lokaciju"</string>
@@ -983,7 +995,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Senzori su isključeni"</string>
     <string name="device_services" msgid="1549944177856658705">"Usluge za uređaje"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Bez naslova"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Dodirnite da biste restartovali aplikaciju i prešli u režim celog ekrana."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Premesti"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigacija sistema je ažurirana. Da biste uneli izmene, idite u Podešavanja."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Idite u Podešavanja da biste ažurirali navigaciju sistema"</string>
@@ -1038,6 +1049,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Dodaj"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Predlaže <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Kontrole su ažurirane"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Uređaj je zaključan"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN sadrži slova ili simbole"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Verifikujte: <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Pogrešan PIN"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index e5356ae..ab1cc69 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Здымак экрана з пракруткай"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Адхіліць здымак экрана"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Перадпрагляд здымка экрана"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Верхняя граніца"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Ніжняя граніца"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Запіс экрана"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Апрацоўваецца запіс экрана"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Бягучае апавяшчэнне для сеанса запісу экрана"</string>
@@ -414,6 +416,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Да ўсходу сонца"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Уключана ў <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Да <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC адключаны"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC уключаны"</string>
@@ -447,6 +451,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Разблакіруйце, каб выкарыстоўваць NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Гэта прылада належыць вашай арганізацыі"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Гэта прылада належыць арганізацыі \"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>\""</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Тэлефон: правядзіце пальцам ад значка"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Галасавая дапамога: правядзіце пальцам ад значка"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Камера: правядзіце пальцам ад значка"</string>
@@ -467,9 +473,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Паказаць профіль"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Дадаць карыстальніка"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Новы карыстальнік"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Завяршыць гасцявы сеанс?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Завяршыць гасцявы сеанс"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Выдаліць госця?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Усе праграмы і даныя гэтага сеанса будуць выдалены."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Завяршыць сеанс"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Выдаліць"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"З вяртаннем, госць!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Хочаце працягнуць сеанс?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Пачаць зноў"</string>
@@ -546,6 +553,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Ваша арганізацыя ўсталявала ў вашым працоўным профілі цэнтр сертыфікацыі. Ваш абаронены сеткавы трафік могуць праглядваць ці змяняць."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"На гэтай прыладзе ўсталяваны цэнтр сертыфікацыі. Ваш абаронены сеткавы трафік могуць праглядваць ці змяняць."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Ваш адміністратар уключыў вядзенне журнала сеткі, з дапамогай якога адсочваецца трафік на вашай прыладзе."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Ваш адміністратар уключыў вядзенне журнала сеткі, з дапамогай якога адсочваецца трафік у вашым працоўным профілі. Трафік вашага асабістага профілю застаецца недаступным."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Вы падключаны да праграмы <xliff:g id="VPN_APP">%1$s</xliff:g>, якая можа сачыць за вашай сеткавай дзейнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Вы падключаны да праграм <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="368812367182387320">"Ваш працоўны профіль падключаны да праграмы <xliff:g id="VPN_APP">%1$s</xliff:g>, якая можа сачыць за вашай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string>
@@ -626,6 +634,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Дакраніцеся, каб адключыць гук. Можа быць адключаны гук службаў спецыяльных магчымасцей."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Дакраніцеся, каб уключыць вібрацыю."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Дакраніцеся, каб адключыць гук"</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"выключыць гук"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"уключыць гук"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"вібрыраваць"</string>
@@ -739,7 +749,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Гэта апавяшчэнне аўтаматычна пераведзена сістэмай у &lt;b&gt;рэжым \"Без гуку\"&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Гэта апавяшчэнне аўтаматычна ацэнена як &lt;b&gt;важнае&lt;/b&gt; для вас."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Гэта апавяшчэнне аўтаматычна ацэнена як &lt;b&gt;няважнае&lt;/b&gt; для вас."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Усё правільна?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Напішыце распрацоўшчыку водгук. Усё правільна?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Дзякуй за водгук!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ОК"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Кіраванне апавяшчэннямі для <xliff:g id="APP_NAME">%1$s</xliff:g> адкрыта"</string>
@@ -890,6 +900,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Перамясціць на пазіцыю <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Дадаць на пазіцыю <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Пазіцыя <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Плітка дададзена"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Плітка выдалена"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Рэдактар хуткіх налад."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Апавяшчэнне <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Адкрыць налады."</string>
@@ -980,7 +992,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Праграма \"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>\" выкарыстоўвае праграму \"<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>\""</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Праграма \"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>\" нядаўна выкарыстоўвала праграму \"<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>\""</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(прадпрыемства)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Тэлефонны выклік"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Тэлефонны выклік"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(праз праграму \"<xliff:g id="ATTRIBUTION">%s</xliff:g>\")"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"камера"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"геалакацыя"</string>
@@ -988,7 +1000,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Датчыкі выкл."</string>
     <string name="device_services" msgid="1549944177856658705">"Сэрвісы прылады"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Без назвы"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Націсніце, каб перазапусціць гэту праграму і перайсці ў поўнаэкранны рэжым."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Перамясціць"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Навігацыя ў сістэме абноўлена. Каб унесці змяненні, перайдзіце ў Налады."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Перайдзіце ў Налады, каб абнавіць параметры навігацыі ў сістэме"</string>
@@ -1044,6 +1055,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Дадаць"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Прапанавана праграмай \"<xliff:g id="APP">%s</xliff:g>\""</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Элементы кіравання абноўлены"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Прылада блакіравана"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-код складаецца з літар або знакаў"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Спраўдзіце прыладу \"<xliff:g id="DEVICE">%s</xliff:g>\""</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Няправільны PIN-код"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index adf852b..6716e15 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Екранна снимка с превъртане"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Отхвърляне на екранната снимка"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Визуализация на екранната снимка"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Горна граница"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Долна граница"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Запис на екрана"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Записът на екрана се обработва"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Текущо известие за сесия за записване на екрана"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До изгрев"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ще се включи в <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"До <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"КБП е деактивирана"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"КБП е активирана"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Отключете, за да използвате NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Това устройство принадлежи на организацията ви"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Това устройство принадлежи на <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Плъзнете с пръст от иконата, за да използвате телефона"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Прекарайте пръст от иконата, за да получите гласова помощ"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Плъзнете с пръст от иконата, за да включите камерата"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Показване на потребителския профил"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Добавяне на потребител"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Нов потребител"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Да се прекрати ли сесията като гост?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Прекратяване на сесията като гост"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Да се премахне ли гостът?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Всички приложения и данни в тази сесия ще бъдат изтрити."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Прекратяване на сесията"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Премахване"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Добре дошли отново в сесията като гост!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Искате ли да продължите сесията си?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Започване отначало"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Организацията ви е инсталирала сертифициращ орган в служебния ви потребителски профил. Трафикът в защитената ви мрежа може да бъде наблюдаван или променян."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"На това устройство е инсталиран сертифициращ орган. Трафикът в защитената ви мрежа може да бъде наблюдаван или променян."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Администраторът ви е включил функцията за регистриране на мрежовата активност, която следи трафика на устройството ви."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Администраторът ви е включил функцията за регистриране на мрежовата активност, която следи трафика в служебния ви потребителски профил, но не и в личния."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Установена е връзка с приложението <xliff:g id="VPN_APP">%1$s</xliff:g>, което може да наблюдава активността ви в мрежата, включително имейли, приложения и уебсайтове."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Установена е връзка с приложенията <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="368812367182387320">"Служебният ви потребителски профил е свързан с приложението <xliff:g id="VPN_APP">%1$s</xliff:g>, което може да наблюдава активността ви в мрежата, включително имейли, приложения и уебсайтове."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Докоснете, за да заглушите звука. Възможно е звукът на услугите за достъпност да бъде заглушен."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Докоснете, за да зададете вибриране."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Докоснете, за да заглушите звука."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"спиране"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"пускане"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"вибриране"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Това известие автоматично бе &lt;b&gt;понижено до беззвучно&lt;/b&gt; от системата."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Това известие автоматично бе &lt;b&gt;класирано по-високо&lt;/b&gt; в панела ви."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Това известие автоматично бе &lt;b&gt;класирано по-ниско&lt;/b&gt; в панела ви."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Правилно ли е това?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Изпратете отзивите си на програмиста. Правилно ли е това?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Благодарим ви за отзивите!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ОК"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Контролите за известията за <xliff:g id="APP_NAME">%1$s</xliff:g> са оттворени"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Преместване към позиция <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Добавяне към позиция <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Позиция <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Панелът е добавен"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Панелът е премахнат"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Редактор за бързи настройки."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Известие от <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Отваряне на настройките."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> използва <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> наскоро използва <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(корпоративна версия)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Телефонно обаждане"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Телефонно обаждане"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(чрез <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"камерата"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"местополож."</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Сензорите са изключени"</string>
     <string name="device_services" msgid="1549944177856658705">"Услуги за устройството"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Няма заглавие"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Докоснете, за да рестартирате това приложение в режим на цял екран."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Преместване"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Режимът за навигиране в системата е актуализиран. За да извършите промени, отворете настройките."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Отворете настройките, за да актуализирате режима за навигиране в системата"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Добавяне"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Предложено от <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Контролите са актуализирани"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"У-вото е заключено"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"ПИН кодът съдържа букви или символи"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Потвърждаване на <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Грешен ПИН код"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 437abb8..ee639d6 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"স্ক্রিনশট স্ক্রল করুন"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"স্ক্রিনশট বাতিল করুন"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"স্ক্রিনশটের প্রিভিউ"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"স্ক্রিনশটের একদম উপরের দিকে"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"স্ক্রিনশটের একদম নিচের দিকে"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"স্ক্রিন রেকর্ডার"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"স্ক্রিন রেকর্ডিং প্রসেস হচ্ছে"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রিন রেকর্ডিং সেশন চলার বিজ্ঞপ্তি"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"সূর্যোদয় পর্যন্ত"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>-এ চালু হবে"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> পর্যন্ত"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC অক্ষম করা আছে"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC সক্ষম করা আছে"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ব্যবহার করতে আনলক করুন"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"এই ডিভাইসটি আপনার প্রতিষ্ঠানের"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"এই ডিভাইসটি <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>-এর"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"ফোনের জন্য আইকন থেকে সোয়াইপ করুন"</string>
     <string name="voice_hint" msgid="7476017460191291417">"ভয়েস সহায়তার জন্য আইকন থেকে সোয়াইপ করুন"</string>
     <string name="camera_hint" msgid="4519495795000658637">"ক্যামেরার জন্য আইকন থেকে সোয়াইপ করুন"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"প্রোফাইল দেখান"</string>
     <string name="user_add_user" msgid="4336657383006913022">"ব্যবহারকারী জুড়ুন"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"নতুন ব্যবহারকারী"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"গেস্ট সেশন শেষ করতে চান?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"গেস্ট সেশন শেষ করুন"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"অতিথি সরাবেন?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"এই সেশনের সব অ্যাপ্লিকেশান ও ডেটা মুছে ফেলা হবে।"</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"সেশন শেষ করুন"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"সরান"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"অতিথি, আপনি ফিরে আসায় আপনাকে স্বাগত!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"আপনি কি আপনার সেশনটি অবিরত রাখতে চান?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"আবার শুরু করুন"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"আপনার প্রতিষ্ঠান আপনার অফিস প্রোফাইলে একটি সার্টিফিকেট কর্তৃপক্ষ ইনস্টল করেছে। আপনার নিরাপদ নেটওয়ার্ক ট্রাফিকে নজর রাখা হতে পারে বা তাতে পরিবর্তন করা হতে পারে।"</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"এই ডিভাইসে একটি সার্টিফিকেট কর্তৃপক্ষ ইনস্টল করা আছে। আপনার নিরাপদ নেটওয়ার্ক ট্রাফিকে নজর রাখা হতে পারে বা তাতে পরিবর্তন করা হতে পারে।"</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"আপনার প্রশাসক নেটওয়ার্ক লগিং চালু করেছেন, যা আপনার ডিভাইসের ট্রাফিকের উপরে নজর রাখে।"</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"আপনার অ্যাডমিন নেটওয়ার্ক লগ করা চালু করেছেন যা আপনার অফিস প্রোফাইলে ট্রাফিক মনিটর করে তবে ব্যক্তিগত প্রোফাইলে করে না।"</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"আপনি <xliff:g id="VPN_APP">%1$s</xliff:g> এ সংযুক্ত রয়েছেন, যা আপনার ইমেল, অ্যাপ, এবং ওয়েবসাইট সহ আপনার নেটওয়ার্ক অ্যাক্টিভিটির উপর নজর রাখতে পারে।"</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"আপনি <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="368812367182387320">"আপনার কর্মস্থলের প্রোফাইল <xliff:g id="VPN_APP">%1$s</xliff:g> এর সাথে সংযুক্ত রয়েছে, যেটি ইমেল, অ্যাপ, এবং ওয়েবসাইট সহ আপনার নেটওয়ার্ক কার্যকলাপে নজর রাখতে পারে।"</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s। মিউট করতে আলতো চাপুন। অ্যাক্সেসযোগ্যতার পরিষেবাগুলিকে মিউট করা হতে পারে।"</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s। ভাইব্রেট করতে ট্যাপ করুন।"</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s। মিউট করতে ট্যাপ করুন।"</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"মিউট করুন"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"আনমিউট করুন"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"ভাইব্রেট করান"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"সিস্টেম অটোমেটিক এই বিজ্ঞপ্তির &lt;b&gt;লেভেল কমিয়ে সাইলেন্ট&lt;/b&gt; করে দিয়েছে।"</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"আপনার শেডে অটোমেটিক এই বিজ্ঞপ্তির &lt;b&gt;র‍্যাঙ্ক বাড়িয়ে&lt;/b&gt; দেওয়া হয়েছে।"</string>
     <string name="feedback_demoted" msgid="951884763467110604">"আপনার শেডে অটোমেটিক এই বিজ্ঞপ্তির &lt;b&gt;র‍্যাঙ্ক কমিয়ে&lt;/b&gt; দেওয়া হয়েছে।"</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"এটি কি সঠিক ছিল?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"ডেভেলপারকে আপনার মতামত জানান। এতে কোনও ভুল দেখতে পেলেন?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"মতামতের জন্য ধন্যবাদ!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"বুঝেছি"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> খোলা থাকলে বিজ্ঞপ্তি নিয়ন্ত্রণ"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g>-এ সরান"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"অবস্থান <xliff:g id="POSITION">%1$d</xliff:g>-এ যোগ করুন"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"অবস্থান <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"টাইল যোগ করা হয়েছে"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"টাইল সরানো হয়েছে"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"দ্রুত সেটিংস সম্পাদক৷"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> বিজ্ঞপ্তি: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"সেটিংস খুলুন।"</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> এখন <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ব্যবহার করছে"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> সম্প্রতি <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ব্যবহার করেছে"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"এন্টারপ্রাইজ"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"ফোনকল"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"ফোন কল"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g>-এর মাধ্যমে)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"ক্যামেরা"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"লোকেশন"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"সেন্সর বন্ধ"</string>
     <string name="device_services" msgid="1549944177856658705">"ডিভাইস সংক্রান্ত পরিষেবা"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"কোনও শীর্ষক নেই"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"এই অ্যাপ রিস্টার্ট করতে ট্যাপ করুন ও ফুল-স্ক্রিন ব্যবহার করুন।"</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"সরান"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"সিস্টেম নেভিগেশন আপডেট হয়েছে। পরিবর্তন করার জন্য সেটিংসে যান।"</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"সিস্টেম নেভিগেশন আপডেট করতে সেটিংসে যান"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"যোগ করুন"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> সাজেস্ট করেছে"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"কন্ট্রোল আপডেট করা হয়েছে"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"ডিভাইস লক করা আছে"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"পিন-এ অক্ষর বা চিহ্ন রয়েছে"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> যাচাই করুন"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"ভুল পিন"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index f2b3edc..01a55d3 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Pokretni snimak ekrana"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Odbacite snimak ekrana"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Pregled snimka ekrana"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Gornja granica"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Donja granica"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Snimač ekrana"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrađivanje snimka ekrana"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Obavještenje za sesiju snimanja ekrana je u toku"</string>
@@ -412,6 +414,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do svitanja"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Uključuje se u <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je onemogućen"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je omogućen"</string>
@@ -445,6 +449,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Otključajte da koristite NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada vašoj organizaciji"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Prevucite preko ikone da otvorite telefon"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Prevucite preko ikone za glasovnu pomoć"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Prevucite od ikone da otvorite kameru"</string>
@@ -465,9 +471,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Pokaži profil"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Dodaj korisnika"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Novi korisnik"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Završiti sesiju gosta?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Završi sesiju gosta"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Želite li ukloniti gosta?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Sve aplikacije i svi podaci iz ove sesije bit će izbrisani."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Završi sesiju"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Ukloni"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Zdravo! Lijepo je opet vidjeti goste."</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Želite li nastaviti sesiju?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Počni ispočetka"</string>
@@ -543,6 +550,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Vaša organizacija je instalirala CA certifikat na vašem radnom profilu. Vaš saobraćaj preko sigurne mreže može se pratiti."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"CA certifikat je instaliran na ovom uređaju. Vaš saobraćaj preko sigurne mreže može se pratiti."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Vaš administrator je uključio zapisivanje na mreži, čime se prati saobraćaj na vašem uređaju."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Administrator je uključio zapisivanje na mreži, čime se nadzire saobraćaj na vašem radnom profilu, ali ne i na ličnom profilu."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Povezani ste s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g> koja može pratiti vašu aktivnost na mreži, uključujući e-poštu i web lokacije."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Povezani ste s aplikacijama <xliff:g id="VPN_APP_0">%1$s</xliff:g> i <xliff:g id="VPN_APP_1">%2$s</xliff:g> koje mogu pratiti vašu aktivnost na mreži, uključujući e-poštu, aplikacije i web lokacije."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Vaš radni profil je povezan s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>, koja može pratiti vašu aktivnost na mreži, uključujući e-poruke i web lokacije."</string>
@@ -623,6 +631,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Dodirnite da isključite zvuk. Zvukovi usluga pristupačnosti mogu biti isključeni."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Dodirnite da postavite vibraciju."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Dodirnite da isključite zvuk."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"isključite zvuk"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"uključite zvuk"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibriranje"</string>
@@ -736,7 +746,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Sistem je ovo obavještenje automatski &lt;b&gt;unazadio u Nečujno&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Ovo obavještenje je automatski &lt;b&gt;rangirano više&lt;/b&gt; u pozadini."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Ovo obavještenje je automatski &lt;b&gt;rangirano niže&lt;/b&gt; u pozadini."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Je li ovo bilo tačno?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Pošaljite programeru svoje povratne informacije. Je li ovo bilo tačno?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Hvala na povratnim informacijama!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"UREDU"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Otvorene su kontrole obavještenja za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -885,6 +895,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Pomjeranje u položaj <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Dodavanje u položaj <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Položaj <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Kartica je dodana"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Kartica je uklonjena"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Uređivanje brzih postavki"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> obavještenje: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Otvori postavke."</string>
@@ -975,7 +987,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Aplikacija <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> koristi aplikaciju <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Aplikacija <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> je nedavno koristila aplikaciju <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(preduzeće)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonski poziv"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefonski poziv"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(putem aplikacije <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"kameru"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"lokaciju"</string>
@@ -983,7 +995,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Senzori su isključeni"</string>
     <string name="device_services" msgid="1549944177856658705">"Usluge uređaja"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Bez naslova"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Dodirnite da ponovo pokrenete ovu aplikaciju i aktivirate prikaz preko cijelog ekrana."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Pomjeri"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigiranje sistemom je ažurirano. Da izvršite promjene, idite u Postavke."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Idite u Postavke da ažurirate navigiranje sistemom"</string>
@@ -1038,6 +1049,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Dodaj"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Predlaže <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Kontrole su ažurirane"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Uređaj je zaključan"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN sadrži slova ili simbole"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Potvrdite uređaj <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Pogrešan PIN"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index bdcde31..5d8ccbc 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Captura de pantalla lliscant"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ignora la captura de pantalla"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Previsualització de la captura de pantalla"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Marge superior"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Marge inferior"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Gravació de pantalla"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processant gravació de pantalla"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificació en curs d\'una sessió de gravació de la pantalla"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Fins a l\'alba"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Activat a les <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Fins a les <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"L\'NFC està desactivada"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"L\'NFC està activada"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloqueja per utilitzar l\'NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Aquest dispositiu pertany a la teva organització"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Aquest dispositiu pertany a <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Llisca des de la icona per obrir el telèfon"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Llisca des de la icona per obrir l\'assistent de veu"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Llisca des de la icona per obrir la càmera"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Mostra el perfil"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Afegeix un usuari"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Usuari nou"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Vols finalitzar la sessió de convidat?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Finalitza la sessió de convidat"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Vols suprimir el convidat?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Totes les aplicacions i les dades d\'aquesta sessió se suprimiran."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Finalitza la sessió"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Suprimeix"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Benvingut de nou, convidat."</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Vols continuar amb la sessió?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Torna a començar"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"La teva organització ha instal·lat una autoritat de certificació al teu perfil de treball. És possible que el trànsit de xarxa segura se supervisi o es modifiqui."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"S\'ha instal·lat una autoritat de certificació en aquest dispositiu. És possible que el trànsit de xarxa segura se supervisi o es modifiqui."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"L\'administrador ha activat el registre de xarxa, que supervisa el trànsit del teu dispositiu."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"L\'administrador ha activat el registre de xarxa, que monitora el trànsit al teu perfil de treball, però no al personal."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Estàs connectat a <xliff:g id="VPN_APP">%1$s</xliff:g>, que pot supervisar la teva activitat a la xarxa, com ara els correus electrònics, les aplicacions i els llocs web."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Estàs connectat a <xliff:g id="VPN_APP_0">%1$s</xliff:g> i <xliff:g id="VPN_APP_1">%2$s</xliff:g>, que poden supervisar la teva activitat a la xarxa, com ara els correus electrònics, les aplicacions i els llocs web."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"El teu perfil de treball està connectat a <xliff:g id="VPN_APP">%1$s</xliff:g>, que pot supervisar la teva activitat a la xarxa, com ara els correus electrònics, les aplicacions i els llocs web."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Toca per silenciar el so. Pot ser que els serveis d\'accessibilitat se silenciïn."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Toca per activar la vibració."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Toca per silenciar."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"silenciar"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"deixar de silenciar"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrar"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"El sistema &lt;b&gt;ha disminuït a Silenci&lt;/b&gt; el nivell d\'aquesta notificació."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Aquesta notificació s\'ha classificat automàticament amb un &lt;b&gt;nivell superior&lt;/b&gt; a l\'àrea de notificacions."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Aquesta notificació s\'ha classificat automàticament amb un &lt;b&gt;nivell inferior&lt;/b&gt; a l\'àrea de notificacions."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"La informació ha estat correcta?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Fes saber els teus suggeriments al desenvolupador. La informació ha estat correcta?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Gràcies pels suggeriments."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"D\'acord"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"S\'han obert els controls de notificació per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mou a la posició <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Afegeix a la posició <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posició <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"El mosaic s\'ha afegit"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"El mosaic s\'ha suprimit"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de configuració ràpida."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificació de <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Obre la configuració."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> està utilitzant: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Recentment <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ha utilitzat: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(empresa)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Trucada"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Trucada"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(a través de: <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"càmera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"ubicació"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensors desactivats"</string>
     <string name="device_services" msgid="1549944177856658705">"Serveis per a dispositius"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Sense títol"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Toca per reiniciar l\'aplicació i passar a pantalla completa."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Mou"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"S\'ha actualitzat el sistema de navegació. Per fer canvis, ves a Configuració."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Ves a Configuració per actualitzar el sistema de navegació"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Afegeix"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Suggerit per <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"S\'han actualitzat els controls"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Dispositiu bloquejat"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"El PIN conté lletres o símbols"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Verifica <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN incorrecte"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index aa5a1dd..024b836 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Posunout snímek obrazovky"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Zavřít snímek obrazovky"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Náhled snímku obrazovky"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Horní hranice"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Dolní hranice"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Rekordér obrazovky"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Záznam obrazovky se zpracovává"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Trvalé oznámení o relaci nahrávání"</string>
@@ -414,6 +416,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do svítání"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Zapnout v <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je vypnuto"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je zapnuto"</string>
@@ -447,6 +451,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC vyžaduje odemknutou obrazovku"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Toto zařízení patří vaší organizaci"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Toto zařízení patří organizaci <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Telefon otevřete přejetím prstem od ikony"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Hlasovou asistenci otevřete přejetím prstem od ikony"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Fotoaparát otevřete přejetím prstem od ikony"</string>
@@ -467,9 +473,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Zobrazit profil"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Přidat uživatele"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Nový uživatel"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Ukončit relaci hosta?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Ukončení relace hosta"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Odstranit hosta?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Veškeré aplikace a data v této relaci budou vymazána."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Ukončit relaci"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Odstranit"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Vítejte zpět v relaci hosta!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Chcete v relaci pokračovat?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Začít znovu"</string>
@@ -546,6 +553,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Organizace do vašeho pracovního profilu nainstalovala certifikační autoritu. Zabezpečený síťový provoz může být sledován nebo upravován."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"V zařízení je nainstalována certifikační autorita. Zabezpečený síťový provoz může být sledován nebo upravován."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Administrátor zapnul protokolování sítě, které monitoruje síťový provoz v zařízení."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Administrátor zapnul protokolování sítě, které monitoruje síťový provoz ve vašem pracovním profilu (ale ne v osobním)."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Jste připojeni k aplikaci <xliff:g id="VPN_APP">%1$s</xliff:g>, která může sledovat vaši aktivitu v síti, včetně e-mailů, aplikací a webů."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Jste připojeni k aplikacím <xliff:g id="VPN_APP_0">%1$s</xliff:g> a <xliff:g id="VPN_APP_1">%2$s</xliff:g>, které mohou sledovat vaši aktivitu v síti, včetně e-mailů, aplikací a webů."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Váš pracovní profil je připojen k aplikaci <xliff:g id="VPN_APP">%1$s</xliff:g>, která může sledovat vaši aktivitu v síti, včetně e-mailů, aplikací a webů."</string>
@@ -626,6 +634,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Klepnutím vypnete zvuk. Služby přístupnosti mohou být ztlumeny."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Klepnutím nastavíte vibrace."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Klepnutím vypnete zvuk."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"vypnout zvuk"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"zapnout zvuk"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrovat"</string>
@@ -739,7 +749,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"U tohoto oznámení systém automaticky &lt;b&gt;snížil prioritu na Tiché&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Toto oznámení bylo na panelu automaticky &lt;b&gt;zařazeno výše&lt;/b&gt;."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Toto oznámení bylo na panelu automaticky &lt;b&gt;zařazeno níže&lt;/b&gt;."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Udělal to správně?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Sdělte vývojáři svůj názor. Udělal to správně?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Děkujeme za zpětnou vazbu."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Ovládací prvky oznámení aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> byly otevřeny"</string>
@@ -890,6 +900,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Přesunout na pozici <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Přidat dlaždici na pozici <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Pozice <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Karta byla přidána"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Karta byla odstraněna"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor rychlého nastavení"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Oznámení aplikace <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Otevřít nastavení."</string>
@@ -980,7 +992,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Aplikace <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> používá aplikaci <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Aplikace <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> nedávno použila aplikaci <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(podniková verze)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonní hovor"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefonní hovor"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(prostřednictvím aplikace <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"fotoaparát"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"poloha"</string>
@@ -988,7 +1000,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Senzory jsou vypnuty"</string>
     <string name="device_services" msgid="1549944177856658705">"Služby zařízení"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Bez názvu"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Klepnutím aplikaci restartujete a přejdete na režim celé obrazovky"</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Přesunout"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Systémová navigace byla aktualizována. Chcete-li provést změny, přejděte do Nastavení."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Přejděte do Nastavení a aktualizujte systémovou navigaci"</string>
@@ -1044,6 +1055,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Přidat"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Návrh z aplikace <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Ovládací prvky aktualizovány"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Zařízení uzamčeno"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Kód PIN obsahuje písmena nebo symboly"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Ověření zařízení <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Chybný PIN"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 5630293..b1a7a5a 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Rul screenshot"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Luk screenshot"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Forhåndsvisning af screenshot"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Øverste kant"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Nederste kant"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Skærmoptagelse"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandler skærmoptagelse"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Konstant notifikation om skærmoptagelse"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Indtil solopgang"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Tænd kl. <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Indtil kl. <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC er deaktiveret"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC er aktiveret"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Lås op for at bruge NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Denne enhed tilhører din organisation"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Denne enhed tilhører <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Stryg fra telefonikonet"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Stryg fra mikrofonikonet"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Stryg fra kameraikonet"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Vis profil"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Tilføj bruger"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Ny bruger"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Vil du afslutte gæstesessionen?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Afslut gæstesessionen"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Vil du fjerne gæsten?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apps og data i denne session slettes."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Afslut sessionen"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Fjern"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Velkommen tilbage, gæst!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Vil du fortsætte din session?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start forfra"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Din organisation har installeret et nøglecenter på din arbejdsprofil. Din sikre netværkstrafik kan overvåges eller ændres."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Der er installeret et nøglecenter på denne enhed. Din sikre netværkstrafik kan overvåges eller ændres."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Din administrator har aktiveret netværksregistrering, som overvåger trafik på din enhed."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Din administrator har aktiveret netværkslogging, som overvåger trafik på din arbejdsprofil, men ikke på din personlige profil."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Du har forbindelse til <xliff:g id="VPN_APP">%1$s</xliff:g>, som kan overvåge din netværksaktivitet, bl.a. mails, apps og websites."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Du har forbindelse til <xliff:g id="VPN_APP_0">%1$s</xliff:g> og <xliff:g id="VPN_APP_1">%2$s</xliff:g>, som kan overvåge din netværksaktivitet, bl.a. mails, apps og websites."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Din arbejdsprofil har forbindelse til <xliff:g id="VPN_APP">%1$s</xliff:g>, som kan overvåge din netværksaktivitet, bl.a. mails, apps og websites."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Tryk for at slå lyden fra. Lyden i tilgængelighedstjenester kan blive slået fra."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Tryk for at aktivere vibration."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Tryk for at slå lyden fra."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"slå lyden fra"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"slå lyden til"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrer"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Denne notifikation blev automatisk &lt;b&gt;angivet som Lydløs&lt;/b&gt; af systemet."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Denne notifikation blev automatisk &lt;b&gt;rangeret højere&lt;/b&gt; i din skygge."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Denne notifikation blev automatisk &lt;b&gt;rangeret lavere&lt;/b&gt; i din skygge."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Var dette korrekt?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Giv udvikleren feedback. Var dette korrekt?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Tak for din feedback"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Styring af notifikationer for <xliff:g id="APP_NAME">%1$s</xliff:g> blev åbnet"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Flyt til <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Føj til placering <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Placering <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Kortet blev tilføjet"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Kortet blev fjernet"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Redigeringsværktøj til Kvikmenu."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>-notifikation: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Åbn Indstillinger."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> anvender <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> anvendte <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> for nylig"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(til virksomhedsbrug)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonopkald"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefonopkald"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(via <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"placering"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Deaktiver sensorer"</string>
     <string name="device_services" msgid="1549944177856658705">"Enhedstjenester"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Ingen titel"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Tryk for at genstarte denne app, og gå til fuld skærm."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Flyt"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Systemnavigationen blev opdateret. Gå til Indstillinger for at foretage ændringer."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Gå til Indstillinger for at opdatere systemnavigationen"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Tilføj"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Foreslået af <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Betjeningselementerne er opdateret"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Enheden er låst"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Pinkoden indeholder bogstaver eller symboler"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Bekræft <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Forkert pinkode"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index e2468bf..88dd62d 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Screenshot scrollen"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Screenshot schließen"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Screenshotvorschau"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Oberer Rand"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Unterer Rand"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Bildschirmaufzeichnung"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Bildschirmaufzeichnung…"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Fortlaufende Benachrichtigung für eine Bildschirmaufzeichnung"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Bis Sonnenaufgang"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"An um <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Bis <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ist deaktiviert"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ist aktiviert"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Zur Verwendung von NFC entsperren"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Dieses Gerät gehört deiner Organisation"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Dieses Gerät gehört <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Zum Öffnen des Telefons vom Symbol wegwischen"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Zum Öffnen des Sprachassistenten vom Symbol wegwischen"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Zum Öffnen der Kamera vom Symbol wegwischen"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Profil öffnen"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Nutzer hinzufügen"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Neuer Nutzer"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Gastsitzung beenden?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Gastsitzung beenden"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Gast entfernen?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle Apps und Daten in dieser Sitzung werden gelöscht."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Sitzung beenden"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Entfernen"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Willkommen zurück im Gastmodus"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Möchtest du deine Sitzung fortsetzen?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Neu starten"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Deine Organisation hat ein Zertifikat einer Zertifizierungsstelle in deinem Arbeitsprofil installiert. Eventuell wird dein sicherer Netzwerkverkehr überwacht oder bearbeitet."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Auf dem Gerät ist das Zertifikat einer Zertifizierungsstelle installiert. Eventuell wird dein sicherer Netzwerkverkehr überwacht oder bearbeitet."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Dein Administrator hat die Netzwerkprotokollierung aktiviert. Damit wird der Netzwerkverkehr auf deinem Gerät überwacht."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Dein Administrator hat die Netzwerkprotokollierung aktiviert. Damit werden die Zugriffe in deinem Arbeitsprofil erfasst, jedoch nicht in deinem privaten Profil."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Du bist mit <xliff:g id="VPN_APP">%1$s</xliff:g> verbunden. Die App kann deine Netzwerkaktivitäten (E-Mails, Apps und Websites) erfassen."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Du bist mit <xliff:g id="VPN_APP_0">%1$s</xliff:g> und <xliff:g id="VPN_APP_1">%2$s</xliff:g> verbunden. Die Apps können deine Netzwerkaktivitäten (E-Mails, Apps und Websites) erfassen."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Dein Arbeitsprofil ist mit <xliff:g id="VPN_APP">%1$s</xliff:g> verbunden, die deine Netzwerkaktivitäten wie E-Mails, Apps und Websites überwachen kann."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Zum Stummschalten tippen. Bedienungshilfen werden unter Umständen stummgeschaltet."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Zum Aktivieren der Vibration tippen."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Zum Stummschalten tippen."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"stummschalten"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"Stummschaltung aufheben"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrieren"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Diese Benachrichtigung wurde durch das System automatisch &lt;b&gt;auf „Lautlos“ herabgestuft&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Diese Benachrichtigung wurde in deiner Leiste automatisch &lt;b&gt;höher eingestuft&lt;/b&gt;."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Diese Benachrichtigung wurde in deiner Leiste automatisch &lt;b&gt;niedriger eingestuft&lt;/b&gt;."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"War das richtig?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Teile dem Entwickler dein Feedback mit. War das richtig?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Vielen Dank für dein Feedback."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Benachrichtigungseinstellungen für <xliff:g id="APP_NAME">%1$s</xliff:g> geöffnet"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Auf Position <xliff:g id="POSITION">%1$d</xliff:g> verschieben"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Zur Position <xliff:g id="POSITION">%1$d</xliff:g> hinzufügen"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Ansicht hinzugefügt"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Ansicht entfernt"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor für Schnelleinstellungen."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Benachrichtigung von <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Einstellungen öffnen."</string>
@@ -967,23 +979,17 @@
     <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Apps verwenden gerade Folgendes: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
     <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
     <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" und "</string>
-    <!-- no translation found for ongoing_privacy_dialog_using_op (4125175620929701569) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_recent_op (4255923947334262404) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_enterprise (4082735415905550729) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_phonecall (3526223335298089311) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_attribution_text (9186683306719924646) -->
-    <skip />
+    <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> verwendet gerade die <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>-App"</string>
+    <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> verwendete kürzlich die <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>-App"</string>
+    <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(Unternehmen)"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefonanruf"</string>
+    <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(über <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"Kamera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"Standort"</string>
     <string name="privacy_type_microphone" msgid="9136763906797732428">"Mikrofon"</string>
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensoren aus"</string>
     <string name="device_services" msgid="1549944177856658705">"Gerätedienste"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Kein Titel"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Tippe, um die App im Vollbildmodus neu zu starten."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Verschieben"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Systemsteuerungseinstellungen wurden angepasst. Änderungen kannst du in den Einstellungen vornehmen."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Gehe zu den Einstellungen, um die Systemsteuerung anzupassen"</string>
@@ -1037,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Hinzufügen"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Vorgeschlagen von <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Gerätekarten aktualisiert"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Gerät gesperrt"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Die PIN enthält Buchstaben oder Symbole"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> bestätigen"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Falsche PIN"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index aa747f2..2133025 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Στιγμιότυπο κύλισης"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Παράβλεψη στιγμιότυπου οθόνης"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Προεπισκόπηση στιγμιότυπου οθόνης"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Ανώτατο όριο"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Κατώτατο όριο"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Εγγραφή οθόνης"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Επεξεργασία εγγραφής οθόνης"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ειδοποίηση σε εξέλιξη για μια περίοδο λειτουργίας εγγραφής οθόνης"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Μέχρι την ανατολή"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ενεργοποίηση στις <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Έως <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Το NFC είναι απενεργοποιημένο"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Το NFC είναι ενεργοποιημένο"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ξεκλείδωμα για χρήση του NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Αυτή η συσκευή ανήκει στον οργανισμό σας."</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Αυτή η συσκευή ανήκει στον οργανισμό <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Σύρετε προς τα έξω για τηλέφωνο"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Σύρετε προς τα έξω για voice assist"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Σύρετε προς τα έξω για κάμερα"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Εμφάνιση προφίλ"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Προσθήκη χρήστη"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Νέος χρήστης"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Λήξη περιόδου σύνδεσης επισκέπτη;"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Λήξη περιόδου σύνδεσης επισκέπτη"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Κατάργηση επισκέπτη;"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Όλες οι εφαρμογές και τα δεδομένα αυτής της περιόδου σύνδεσης θα διαγραφούν."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Λήξη περιόδου σύνδεσης"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Κατάργηση"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Επισκέπτη , καλώς όρισες ξανά!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Θέλετε να συνεχίσετε την περίοδο σύνδεσής σας;"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Έναρξη από την αρχή"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Ο οργανισμός σας εγκατέστησε μια αρχή έκδοσης πιστοποιητικών στο προφίλ εργασίας σας. Η ασφαλής επισκεψιμότητα δικτύου σας μπορεί να παρακολουθείται ή να τροποποιείται."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Μια αρχή έκδοσης πιστοποιητικών έχει εγκατασταθεί σε αυτήν τη συσκευή. Η ασφαλής επισκεψιμότητα δικτύου σας μπορεί να παρακολουθείται ή να τροποποιείται."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Ο διαχειριστής σας ενεργοποίησε την καταγραφή δικτύου, η οποία παρακολουθεί την επισκεψιμότητα στη συσκευή σας."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Ο διαχειριστής σας έχει ενεργοποιήσει την καταγραφή δικτύου, η οποία παρακολουθεί την επισκεψιμότητα στο προφίλ εργασίας σας, αλλά όχι στο προσωπικό προφίλ σας."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Έχετε συνδεθεί στην εφαρμογή <xliff:g id="VPN_APP">%1$s</xliff:g>, η οποία μπορεί να παρακολουθεί τη δραστηριότητα δικτύου σας, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστοτόπων."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Έχετε συνδεθεί στις εφαρμογές <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="368812367182387320">"Το προφίλ εργασίας σας είναι συνδεδεμένο στο <xliff:g id="VPN_APP">%1$s</xliff:g>, το οποίο μπορεί να παρακολουθεί τη δραστηριότητα δικτύου σας, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστοτόπων."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Πατήστε για σίγαση. Οι υπηρεσίες προσβασιμότητας ενδέχεται να τεθούν σε σίγαση."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Πατήστε για να ενεργοποιήσετε τη δόνηση."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Πατήστε για σίγαση."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"σίγαση"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"κατάργηση σίγασης"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"δόνηση"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Αυτή η ειδοποίηση &lt;b&gt;υποβιβάστηκε σε Αθόρυβη&lt;/b&gt; αυτόματα από το σύστημα."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Αυτή η ειδοποίηση &lt;b&gt;κατατάχθηκε υψηλότερα&lt;/b&gt; στο πλαίσιο σκίασης με αυτόματο τρόπο."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Αυτή η ειδοποίηση &lt;b&gt;κατατάχθηκε χαμηλότερα&lt;/b&gt; στο πλαίσιο σκίασης με αυτόματο τρόπο."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Ήταν σωστό αυτό;"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Μοιραστείτε τα σχόλιά σας με τον προγραμματιστή. Ήταν σωστό αυτό;"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Σας ευχαριστούμε για τα σχόλιά σας!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ΟΚ"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Τα στοιχεία ελέγχου ειδοποιήσεων για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> άνοιξαν"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Μετακίνηση στη θέση <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Προσθήκη στη θέση <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Θέση <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Το πλακίδιο προστέθηκε"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Το πλακίδιο καταργήθηκε"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Επεξεργασία γρήγορων ρυθμίσεων."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Ειδοποίηση <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Άνοιγμα ρυθμίσεων."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Χρήση <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> από την εφαρμογή <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Πρόσφατη χρήση <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> από την εφαρμογή <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(για επιχειρήσεις)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Τηλεφωνική κλήση"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Τηλεφωνική κλήση"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(μέσω <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"κάμερα"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"τοποθεσία"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Αισθητήρες ανενεργοί"</string>
     <string name="device_services" msgid="1549944177856658705">"Υπηρεσίες συσκευής"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Χωρίς τίτλο"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Πατήστε για επανεκκίνηση αυτής της εφαρμογής και ενεργοποίηση πλήρους οθόνης."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Μετακίνηση"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Η πλοήγηση συστήματος ενημερώθηκε. Για να κάνετε αλλαγές, μεταβείτε στις Ρυθμίσεις."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Μεταβείτε στις Ρυθμίσεις για να ενημερώσετε την πλοήγηση συστήματος"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Προσθήκη"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Προτείνεται από <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Ενημέρωση στοιχείων ελέγχου"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Η συσκευή κλειδώθηκε"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Το PIN περιέχει γράμματα ή σύμβολα"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Επαλήθευση <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Λάθος PIN"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 88a40c3..0a0f8f7 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Scroll screenshot"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Dismiss screenshot"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Screenshot preview"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Top boundary"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Bottom boundary"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Screen Recorder"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -410,6 +412,7 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Until sunrise"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Reduce brightness"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
@@ -443,6 +446,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organisation"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Swipe from icon for phone"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Swipe from icon for voice assist"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Swipe from icon for camera"</string>
@@ -463,9 +468,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Show profile"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Add user"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"New user"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"End Guest session?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"End Guest session"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Remove guest?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"End session"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Remove"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Welcome back, guest!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Do you want to continue your session?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start again"</string>
@@ -540,6 +546,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Your organisation installed a certificate authority in your work profile. Your secure network traffic may be monitored or modified."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"A certificate authority is installed on this device. Your secure network traffic may be monitored or modified."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Your admin has turned on network logging, which monitors traffic on your device."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Your admin has turned on network logging, which monitors traffic in your work profile but not in your personal profile."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"You\'re connected to <xliff:g id="VPN_APP">%1$s</xliff:g>, which can monitor your network activity, including emails, apps and websites."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"You\'re connected to <xliff:g id="VPN_APP_0">%1$s</xliff:g> and <xliff:g id="VPN_APP_1">%2$s</xliff:g>, which can monitor your network activity, including emails, apps and websites."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Your work profile is connected to <xliff:g id="VPN_APP">%1$s</xliff:g>, which can monitor your network activity, including emails, apps and websites."</string>
@@ -620,6 +627,7 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Tap to mute. Accessibility services may be muted."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Tap to set to vibrate."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Tap to mute."</string>
+    <string name="volume_ringer_change" msgid="3574969197796055532">"Tap to change ringer mode"</string>
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"mute"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"unmute"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrate"</string>
@@ -733,7 +741,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"This notification was automatically &lt;b&gt;demoted to silent&lt;/b&gt; by the system."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"This notification was automatically &lt;b&gt;ranked higher&lt;/b&gt; in your shade."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"This notification was automatically &lt;b&gt;ranked lower&lt;/b&gt; in your shade."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Was this correct?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Let the developer know your feedback. Was this correct?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Thanks for your feedback!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Notification controls for <xliff:g id="APP_NAME">%1$s</xliff:g> opened"</string>
@@ -880,6 +888,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Move to <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Add to position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Tile added"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Tile removed"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Quick settings editor."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> notification: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Open settings."</string>
@@ -970,7 +980,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> is using the <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> used the <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> recently"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(enterprise)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Phonecall"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Phone call"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(through <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"location"</string>
@@ -978,7 +988,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensors off"</string>
     <string name="device_services" msgid="1549944177856658705">"Device Services"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"No title"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Tap to restart this app and go full screen."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Move"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"System navigation updated. To make changes, go to Settings."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Go to Settings to update system navigation"</string>
@@ -1032,6 +1041,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Add"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Suggested by <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Controls updated"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Device locked"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN contains letters or symbols"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Verify <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Wrong PIN"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index bf7883a..403fdee 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Scroll screenshot"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Dismiss screenshot"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Screenshot preview"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Top boundary"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Bottom boundary"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Screen Recorder"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -410,6 +412,7 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Until sunrise"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Reduce brightness"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
@@ -443,6 +446,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organisation"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Swipe from icon for phone"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Swipe from icon for voice assist"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Swipe from icon for camera"</string>
@@ -463,9 +468,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Show profile"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Add user"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"New user"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"End Guest session?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"End Guest session"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Remove guest?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"End session"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Remove"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Welcome back, guest!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Do you want to continue your session?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start again"</string>
@@ -540,6 +546,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Your organisation installed a certificate authority in your work profile. Your secure network traffic may be monitored or modified."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"A certificate authority is installed on this device. Your secure network traffic may be monitored or modified."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Your admin has turned on network logging, which monitors traffic on your device."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Your admin has turned on network logging, which monitors traffic in your work profile but not in your personal profile."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"You\'re connected to <xliff:g id="VPN_APP">%1$s</xliff:g>, which can monitor your network activity, including emails, apps and websites."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"You\'re connected to <xliff:g id="VPN_APP_0">%1$s</xliff:g> and <xliff:g id="VPN_APP_1">%2$s</xliff:g>, which can monitor your network activity, including emails, apps and websites."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Your work profile is connected to <xliff:g id="VPN_APP">%1$s</xliff:g>, which can monitor your network activity, including emails, apps and websites."</string>
@@ -620,6 +627,7 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Tap to mute. Accessibility services may be muted."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Tap to set to vibrate."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Tap to mute."</string>
+    <string name="volume_ringer_change" msgid="3574969197796055532">"Tap to change ringer mode"</string>
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"mute"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"unmute"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrate"</string>
@@ -733,7 +741,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"This notification was automatically &lt;b&gt;demoted to silent&lt;/b&gt; by the system."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"This notification was automatically &lt;b&gt;ranked higher&lt;/b&gt; in your shade."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"This notification was automatically &lt;b&gt;ranked lower&lt;/b&gt; in your shade."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Was this correct?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Let the developer know your feedback. Was this correct?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Thanks for your feedback!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Notification controls for <xliff:g id="APP_NAME">%1$s</xliff:g> opened"</string>
@@ -880,6 +888,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Move to <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Add to position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Tile added"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Tile removed"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Quick settings editor."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> notification: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Open settings."</string>
@@ -970,7 +980,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> is using the <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> used the <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> recently"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(enterprise)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Phonecall"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Phone call"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(through <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"location"</string>
@@ -978,7 +988,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensors off"</string>
     <string name="device_services" msgid="1549944177856658705">"Device Services"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"No title"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Tap to restart this app and go full screen."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Move"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"System navigation updated. To make changes, go to Settings."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Go to Settings to update system navigation"</string>
@@ -1032,6 +1041,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Add"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Suggested by <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Controls updated"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Device locked"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN contains letters or symbols"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Verify <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Wrong PIN"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 88a40c3..0a0f8f7 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Scroll screenshot"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Dismiss screenshot"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Screenshot preview"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Top boundary"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Bottom boundary"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Screen Recorder"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -410,6 +412,7 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Until sunrise"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Reduce brightness"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
@@ -443,6 +446,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organisation"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Swipe from icon for phone"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Swipe from icon for voice assist"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Swipe from icon for camera"</string>
@@ -463,9 +468,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Show profile"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Add user"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"New user"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"End Guest session?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"End Guest session"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Remove guest?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"End session"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Remove"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Welcome back, guest!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Do you want to continue your session?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start again"</string>
@@ -540,6 +546,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Your organisation installed a certificate authority in your work profile. Your secure network traffic may be monitored or modified."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"A certificate authority is installed on this device. Your secure network traffic may be monitored or modified."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Your admin has turned on network logging, which monitors traffic on your device."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Your admin has turned on network logging, which monitors traffic in your work profile but not in your personal profile."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"You\'re connected to <xliff:g id="VPN_APP">%1$s</xliff:g>, which can monitor your network activity, including emails, apps and websites."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"You\'re connected to <xliff:g id="VPN_APP_0">%1$s</xliff:g> and <xliff:g id="VPN_APP_1">%2$s</xliff:g>, which can monitor your network activity, including emails, apps and websites."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Your work profile is connected to <xliff:g id="VPN_APP">%1$s</xliff:g>, which can monitor your network activity, including emails, apps and websites."</string>
@@ -620,6 +627,7 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Tap to mute. Accessibility services may be muted."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Tap to set to vibrate."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Tap to mute."</string>
+    <string name="volume_ringer_change" msgid="3574969197796055532">"Tap to change ringer mode"</string>
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"mute"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"unmute"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrate"</string>
@@ -733,7 +741,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"This notification was automatically &lt;b&gt;demoted to silent&lt;/b&gt; by the system."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"This notification was automatically &lt;b&gt;ranked higher&lt;/b&gt; in your shade."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"This notification was automatically &lt;b&gt;ranked lower&lt;/b&gt; in your shade."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Was this correct?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Let the developer know your feedback. Was this correct?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Thanks for your feedback!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Notification controls for <xliff:g id="APP_NAME">%1$s</xliff:g> opened"</string>
@@ -880,6 +888,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Move to <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Add to position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Tile added"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Tile removed"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Quick settings editor."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> notification: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Open settings."</string>
@@ -970,7 +980,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> is using the <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> used the <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> recently"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(enterprise)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Phonecall"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Phone call"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(through <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"location"</string>
@@ -978,7 +988,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensors off"</string>
     <string name="device_services" msgid="1549944177856658705">"Device Services"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"No title"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Tap to restart this app and go full screen."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Move"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"System navigation updated. To make changes, go to Settings."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Go to Settings to update system navigation"</string>
@@ -1032,6 +1041,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Add"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Suggested by <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Controls updated"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Device locked"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN contains letters or symbols"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Verify <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Wrong PIN"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 88a40c3..0a0f8f7 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Scroll screenshot"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Dismiss screenshot"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Screenshot preview"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Top boundary"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Bottom boundary"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Screen Recorder"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -410,6 +412,7 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Until sunrise"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Reduce brightness"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
@@ -443,6 +446,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organisation"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Swipe from icon for phone"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Swipe from icon for voice assist"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Swipe from icon for camera"</string>
@@ -463,9 +468,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Show profile"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Add user"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"New user"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"End Guest session?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"End Guest session"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Remove guest?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"End session"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Remove"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Welcome back, guest!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Do you want to continue your session?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start again"</string>
@@ -540,6 +546,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Your organisation installed a certificate authority in your work profile. Your secure network traffic may be monitored or modified."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"A certificate authority is installed on this device. Your secure network traffic may be monitored or modified."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Your admin has turned on network logging, which monitors traffic on your device."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Your admin has turned on network logging, which monitors traffic in your work profile but not in your personal profile."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"You\'re connected to <xliff:g id="VPN_APP">%1$s</xliff:g>, which can monitor your network activity, including emails, apps and websites."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"You\'re connected to <xliff:g id="VPN_APP_0">%1$s</xliff:g> and <xliff:g id="VPN_APP_1">%2$s</xliff:g>, which can monitor your network activity, including emails, apps and websites."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Your work profile is connected to <xliff:g id="VPN_APP">%1$s</xliff:g>, which can monitor your network activity, including emails, apps and websites."</string>
@@ -620,6 +627,7 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Tap to mute. Accessibility services may be muted."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Tap to set to vibrate."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Tap to mute."</string>
+    <string name="volume_ringer_change" msgid="3574969197796055532">"Tap to change ringer mode"</string>
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"mute"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"unmute"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrate"</string>
@@ -733,7 +741,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"This notification was automatically &lt;b&gt;demoted to silent&lt;/b&gt; by the system."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"This notification was automatically &lt;b&gt;ranked higher&lt;/b&gt; in your shade."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"This notification was automatically &lt;b&gt;ranked lower&lt;/b&gt; in your shade."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Was this correct?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Let the developer know your feedback. Was this correct?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Thanks for your feedback!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Notification controls for <xliff:g id="APP_NAME">%1$s</xliff:g> opened"</string>
@@ -880,6 +888,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Move to <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Add to position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Tile added"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Tile removed"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Quick settings editor."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> notification: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Open settings."</string>
@@ -970,7 +980,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> is using the <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> used the <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> recently"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(enterprise)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Phonecall"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Phone call"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(through <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"location"</string>
@@ -978,7 +988,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensors off"</string>
     <string name="device_services" msgid="1549944177856658705">"Device Services"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"No title"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Tap to restart this app and go full screen."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Move"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"System navigation updated. To make changes, go to Settings."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Go to Settings to update system navigation"</string>
@@ -1032,6 +1041,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Add"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Suggested by <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Controls updated"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Device locked"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN contains letters or symbols"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Verify <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Wrong PIN"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index a14566a..a665fb1 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‏‎‏‎‏‎‏‎‎‎‎‏‎‏‏‎‏‎‏‏‏‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‎‏‏‎‎‏‏‎‏‏‏‏‎Scroll screenshot‎‏‎‎‏‎"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‏‎‎‎‎‏‎‎‏‎‎‏‏‏‎‎‏‎‏‏‏‏‎‏‏‎‏‎‎‎‎‎‏‎‎‎‎‎‏‏‎‎‎‎‏‏‎‎‏‎‎Dismiss screenshot‎‏‎‎‏‎"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎‏‎‏‎‏‏‎‎‎‎‎‎‎‏‎‏‏‎‏‎‏‎‏‏‎‏‎‏‏‎‎‎‏‏‎‏‏‎‏‎‎Screenshot preview‎‏‎‎‏‎"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‏‎‎‏‏‎‎‎‏‎‏‏‏‏‎‏‎‎‏‏‎‎‎‏‎‏‏‎‎‎‏‏‎‎‏‎‎‎‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎Top boundary‎‏‎‎‏‎"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‎‎‎‏‎‏‎‎‏‎‎‎‎‎‎‏‏‎‎‏‎‏‎‏‏‏‏‎‏‎‎‎‏‏‏‏‎‎‏‎‎‏‎‎‎‏‎‎‎‏‏‏‏‎Bottom boundary‎‏‎‎‏‎"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‎‎‏‎‎‎‎‏‎‎‎‏‎‏‎‎‏‎‏‎‎‎‎‎‏‎‎‎‏‎‏‎‎‏‎‎‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‎‎‎Screen Recorder‎‏‎‎‏‎"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‎‎‏‏‎‏‏‏‏‎‎‎‏‏‏‏‎‎‎‏‏‎‎‏‎‎Processing screen recording‎‏‎‎‏‎"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‎‏‏‎‏‎‏‏‎‎‎‎‎‏‎‏‎‏‏‎‏‎‎‎‏‏‎‏‏‏‎‎‏‎‎‎‎‎‎‏‏‎‎‎‏‏‏‏‎‏‏‏‏‎Ongoing notification for a screen record session‎‏‎‎‏‎"</string>
@@ -410,6 +412,7 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‏‎‎‎‎‏‎‏‎‎‏‎‏‏‏‎‏‎‎‎‏‎‎‎‏‎‎‏‎‎‏‎‏‎‎‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‎‎‎‎Until sunrise‎‏‎‎‏‎"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‏‎‏‏‎‏‎‎‎‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‏‏‎‎‎‎‎‏‏‏‎‏‎‏‏‏‏‏‏‎On at ‎‏‎‎‏‏‎<xliff:g id="TIME">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‎‏‎‎‏‏‏‏‎‎‏‏‏‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎‏‏‎‏‏‎‏‏‎‎‏‎‏‎‏‎Until ‎‏‎‎‏‏‎<xliff:g id="TIME">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎‏‎‎‎‎‎‏‏‎‏‏‏‎‎‏‎‎‎‎‏‎‏‏‏‎‎‏‏‎‎‎‏‏‎‎‏‏‎‏‏‏‏‎‏‏‎‎‏‏‏‎Reduce brightness‎‏‎‎‏‎"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‎‎‏‏‎‏‏‎‎‎‎‎‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‏‎‏‏‏‏‎‏‏‎‏‎‎‎‏‏‏‎‏‎‏‎‏‎NFC‎‏‎‎‏‎"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‏‎‏‏‎‎‎‏‎‎‏‏‏‎‎‏‏‎‎‎‏‏‏‏‎‎‎‏‎‏‎‎‎‎‏‎‏‎‎‎‎‎‏‎‏‏‎‎‏‎‏‏‏‎NFC is disabled‎‏‎‎‏‎"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‏‏‏‏‎‎‏‎‎‏‏‎‎‏‎‎‏‏‏‎‎‏‏‏‎‎‏‏‏‏‏‎‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‎‏‏‎‎NFC is enabled‎‏‎‎‏‎"</string>
@@ -443,6 +446,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‏‎‏‎‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‏‏‏‎‎‎‎‏‏‏‏‏‎‎‎‎‏‎‏‎‎‏‏‏‏‎Unlock to use NFC‎‏‎‎‏‎"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‏‎‏‎‎‏‎‏‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‎‏‎‏‏‎‎‏‎‏‏‏‏‎‏‏‏‏‏‎This device belongs to your organization‎‏‎‎‏‎"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‎‎‏‏‏‎‎‎‎‎‎‎‎‏‏‎‏‎‏‎‎‎‏‎‏‏‏‏‏‎‎‎‏‎‎‏‎‏‎‎‏‎‎‏‎‎‎‏‏‏‎‏‏‎This device belongs to ‎‏‎‎‏‏‎<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‏‏‏‎‏‏‏‎‏‎‏‏‎‏‏‎‎‏‎‏‏‏‏‎‎‎‎‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‏‏‎‏‏‎‏‏‎‏‎‏‎Swipe from icon for phone‎‏‎‎‏‎"</string>
     <string name="voice_hint" msgid="7476017460191291417">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‎‎‎‎‎‎‏‎‎‏‏‎‎‏‎‎‎‏‎‏‎‎‏‏‏‎‎‏‎‏‎‏‎‎‎‏‏‏‏‎‏‎‎‎‎‎‎‏‏‎‎‏‎Swipe from icon for voice assist‎‏‎‎‏‎"</string>
     <string name="camera_hint" msgid="4519495795000658637">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‏‏‏‎‎‏‎‏‏‏‏‎‏‎‏‏‏‏‎‎‎‎‏‏‏‎‎‎‏‎‏‏‎‎‏‎‏‎‏‏‎‎‏‏‎‏‎Swipe from icon for camera‎‏‎‎‏‎"</string>
@@ -463,9 +468,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‎‏‏‎‎‏‏‏‎‏‎‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‎‎‎‏‎‏‎‏‎‎‏‏‎‏‎‎‎‏‎‎‎‎‎Show profile‎‏‎‎‏‎"</string>
     <string name="user_add_user" msgid="4336657383006913022">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‎‏‏‏‎‏‏‏‎‎‏‏‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‏‎‏‎‏‏‎‎‏‏‏‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‎Add user‎‏‎‎‏‎"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎‎‎‎‎‏‎‏‏‎‎‎‎‏‎‏‎‎‎‎‏‎‎‏‎‎‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‎‏‎‎‎‎‏‏‎‎‏‏‎‏‎New user‎‏‎‎‏‎"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‏‏‎‎‏‏‏‎‏‏‎‏‏‏‏‎‏‎‎‎‏‎‎‎‏‏‏‏‏‎‏‎‏‎‏‎End guest session?‎‏‎‎‏‎"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‎‏‎‏‏‏‏‎‎‏‏‎‎‏‎‎‏‏‏‎‎‏‏‎‏‎‎‏‎‎‎‏‏‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‎End guest session‎‏‎‎‏‎"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‎‏‏‎‏‏‎‏‎‏‎‏‏‎‎‏‎‏‏‎‏‏‏‎‏‎‎‎‏‎‏‏‎‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‎‎‏‏‏‎‎Remove guest?‎‏‎‎‏‎"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‎‎‎‎‎‏‎‎‏‎‏‏‎‎‏‏‎‏‎‎‏‏‏‎‏‏‏‏‎‏‎‏‏‏‎‏‎All apps and data in this session will be deleted.‎‏‎‎‏‎"</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‏‎‏‎‎‎‏‏‎‏‎‏‏‎‏‎‏‏‏‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‎End session‎‏‎‎‏‎"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‏‎‏‎‎‎‎‎‎‏‎‏‎‏‎‏‎‏‎‎‏‏‏‎‏‎‏‎‏‏‏‎‎‏‏‎‎‏‎‎‎‎‏‏‏‎‎‎‏‏‎‏‎Remove‎‏‎‎‏‎"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‏‎‎‏‎‏‎‏‎‏‏‎‏‎‎‎‎‏‎‎‏‎‏‏‏‎‎‏‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‎‎Welcome back, guest!‎‏‎‎‏‎"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‏‏‎‎‏‎‏‎‎‏‎‎‎‏‎‎‏‎‏‏‏‏‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‎‎‏‎‏‏‏‏‏‎‎‎‏‎Do you want to continue your session?‎‏‎‎‏‎"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‏‏‏‏‏‎‏‎‎‎‏‎‎‎‏‎‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‎‎‏‏‏‎‏‎Start over‎‏‎‎‏‎"</string>
@@ -540,6 +546,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‎‎‏‏‏‎‎‏‏‎‎‎‏‎‎‎‏‎‎‏‎‏‏‏‏‎‎‎‎‏‎‎‏‏‎‏‏‎‏‎‏‏‏‎‎‏‏‏‏‏‏‎Your organization installed a certificate authority in your work profile. Your secure network traffic may be monitored or modified.‎‏‎‎‏‎"</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‏‏‏‎‏‎‏‏‏‎‎‏‎‏‎‎‏‎‎‏‎‎‎‏‎‏‎‎‏‏‎‏‏‏‏‏‎‏‎‏‏‎‏‎‏‏‏‎‎‏‏‎‎‏‎A certificate authority is installed on this device. Your secure network traffic may be monitored or modified.‎‏‎‎‏‎"</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‎‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‏‎‏‎‎‏‏‎Your admin has turned on network logging, which monitors traffic on your device.‎‏‎‎‏‎"</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‎‏‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‎‎‏‎‏‎‏‏‎‏‏‏‏‏‎‏‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎Your admin has turned on network logging, which monitors traffic in your work profile but not in your personal profile.‎‏‎‎‏‎"</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‎‎‏‎‏‏‏‏‎‏‏‏‎‏‏‎‎‎‏‎‎‏‎‎‏‏‎‏‎‎‏‏‎‎‎‎‏‏‎‎‏‏‎‏‏‏‎‎‏‎‎‎‏‏‎You\'re connected to ‎‏‎‎‏‏‎<xliff:g id="VPN_APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎, which can monitor your network activity, including emails, apps, and websites.‎‏‎‎‏‎"</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‏‏‎‎‏‎‎‏‎‏‎‏‏‏‏‎‎‎‎‎‏‏‏‎‏‏‏‏‎‎‎‏‏‎‎‎‏‎‏‏‎‏‎‏‎‎‏‎‏‏‏‎You\'re connected to ‎‏‎‎‏‏‎<xliff:g id="VPN_APP_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎ and ‎‏‎‎‏‏‎<xliff:g id="VPN_APP_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎, which can monitor your network activity, including emails, apps, and websites.‎‏‎‎‏‎"</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‎‎‎‏‏‏‏‎‎‏‎‎‏‎‎‎‏‏‏‎‎‏‎‎‏‏‎‏‎‏‏‎‏‎‏‎‏‏‎‏‎‏‎‏‏‎‎‎‎‏‏‏‏‎‎‎‎Your work profile is connected to ‎‏‎‎‏‏‎<xliff:g id="VPN_APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎, which can monitor your network activity, including emails, apps, and websites.‎‏‎‎‏‎"</string>
@@ -620,6 +627,7 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‏‎‏‏‏‎‏‎‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‎‏‏‎‏‎‎‏‏‏‎‏‏‎‏‎‏‏‏‎‎‏‏‎‏‏‎‎‎‎%1$s. Tap to mute. Accessibility services may be muted.‎‏‎‎‏‎"</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‎‎‏‏‏‎‏‎‏‏‎‏‏‎‏‎‏‎‎‏‏‏‎‏‎‏‏‎‎‎‏‎‏‏‎‏‏‏‎‎‎‏‎‎‏‏‎‏‎‏‏‏‏‏‎%1$s. Tap to set to vibrate.‎‏‎‎‏‎"</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‏‎‏‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‎‎‏‎‏‎‏‏‎‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‏‏‎‎‎%1$s. Tap to mute.‎‏‎‎‏‎"</string>
+    <string name="volume_ringer_change" msgid="3574969197796055532">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‎‏‏‏‎‎‏‏‎‏‎‏‏‏‏‎‎‎‏‎‏‏‎‏‎‏‏‏‎‏‏‎‎‏‏‎‎‎‏‏‎‏‏‎‎‏‏‏‏‎‏‏‎‎‎Tap to change ringer mode‎‏‎‎‏‎"</string>
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‎‎‏‎‏‏‎‎‎‎‏‎‎‎‏‎‏‏‎‎‏‏‎‏‏‎‏‏‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎‏‏‎‎mute‎‏‎‎‏‎"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‎‏‏‎‏‎‏‏‏‎‏‎‎‎‏‏‎‏‏‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‏‎‏‎‎‏‏‎‏‏‎‎‏‎‎‎‎‎unmute‎‏‎‎‏‎"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‎‏‎‎‎‎‎‏‎‎‎‏‏‎‎‎‎‏‎‎‏‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‏‏‎‎‏‎‎‏‎‏‎vibrate‎‏‎‎‏‎"</string>
@@ -733,7 +741,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‎‏‏‏‎‏‎‏‎‎‎‏‏‏‏‎‎‎‎‎‎‎‏‏‎‎‎‏‏‎‎‎‎‏‏‎‏‎‎‎‎‏‏‏‏‎‎‏‎This notification was automatically &lt;b&gt;demoted to Silent&lt;/b&gt; by the system.‎‏‎‎‏‎"</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‎‎‏‏‎‎‎‎‎‎‎‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‎‎‏‏‏‏‎‎‎‏‏‏‎This notification was automatically &lt;b&gt;ranked higher&lt;/b&gt; in your shade.‎‏‎‎‏‎"</string>
     <string name="feedback_demoted" msgid="951884763467110604">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‏‏‎‏‎‏‏‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎‎‎‏‎‏‎‎‏‏‎‎‏‎‎‎‎‎‏‎‏‏‎‎‎‏‏‎‎‏‏‎‎‎This notification was automatically &lt;b&gt;ranked lower&lt;/b&gt; in your shade.‎‏‎‎‏‎"</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‏‎‏‎‎‏‏‎‎‎‎‎‏‎‎‎‎‏‏‏‏‎‎‎‎‎‎‏‎‏‏‏‎‎‏‏‎‏‎‎‏‎‏‏‎‎‏‎Was this correct?‎‏‎‎‏‎"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‏‎‎‏‏‎‎‎‎‎‏‏‏‎‏‏‎Let the developer know your feedback. Was this correct?‎‏‎‎‏‎"</string>
     <string name="feedback_response" msgid="4671729244976641339">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‏‎Thanks for your feedback!‎‏‎‎‏‎"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‎‎‏‎‏‎‏‎‎‏‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‏‎‎‎‎‎‏‎‏‏‏‎‏‏‏‏‏‎‎‏‎‏‏‏‎‎‎‎OK‎‏‎‎‏‎"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‎‎‎‏‏‎‎‎‏‎‎‏‏‏‎‏‏‏‎‎‏‏‎‎‏‏‏‎‏‏‎‏‎‏‎‏‎‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎‎Notification controls for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ opened‎‏‎‎‏‎"</string>
@@ -880,6 +888,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‏‎‎‎‏‏‏‎‎‏‎‏‎‎‎‏‏‎‎‎‏‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‎‎‎‎‏‏‏‏‎‎‎Move to ‎‏‎‎‏‏‎<xliff:g id="POSITION">%1$d</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‏‎‎‎‎‏‎‎‏‎‎‏‎‎‎‎‎‎‎‎‏‎‎Add to position ‎‏‎‎‏‏‎<xliff:g id="POSITION">%1$d</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‎‎‎‏‏‎‏‏‎‏‏‏‎‎‎‏‎‏‎‏‏‎‎Position ‎‏‎‎‏‏‎<xliff:g id="POSITION">%1$d</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‎‏‏‏‏‏‎‎‏‎‏‎‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‏‏‎‏‏‏‎‎Tile added‎‏‎‎‏‎"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‏‎‎‎‏‏‎‏‏‏‎‏‎‎‎‏‎‎‎‎‏‏‏‏‎‎‎‏‏‏‎‏‎‏‎‎‏‎‎‏‎‏‎‏‏‏‏‎‎‎‏‎‎‎Tile removed‎‏‎‎‏‎"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‏‏‏‎‎‏‏‎‏‏‏‎‎‎‎‎‎‎‏‏‏‏‏‎‏‎‎‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‎‎‏‎Quick settings editor.‎‏‎‎‏‎"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‏‏‏‎‏‏‏‏‎‎‎‏‏‏‎‎‎‏‏‏‎‎‎‎‎‎‏‏‏‏‏‎‎‎‎‏‏‏‏‏‏‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="ID_1">%1$s</xliff:g>‎‏‎‎‏‏‏‎ notification: ‎‏‎‎‏‏‎<xliff:g id="ID_2">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‎‎‏‎‏‏‏‎‎‏‏‎‏‎‏‎‏‏‎‎‏‎‎‏‏‏‎‎‎‎‎‎‎‏‏‏‏‏‎‏‎‎‏‎‎‏‏‎‏‎‎‏‎Open settings.‎‏‎‎‏‎"</string>
@@ -970,7 +980,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‏‎‏‏‏‏‏‎‎‎‎‎‎‎‏‏‎‎‏‏‏‎‏‏‏‎‎‎‏‏‎‏‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is using the ‎‏‎‎‏‏‎<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‎‎‎‏‎‎‎‎‎‎‎‏‎‏‎‎‎‏‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‎‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ used the ‎‏‎‎‏‏‎<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ recently‎‏‎‎‏‎"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‏‎‏‎‎‎‏‏‎‎‏‎‏‎‎‎‏‏‏‎‏‎‏‏‎‎‎‎‎‎‏‏‏‏‎‏‎‏‎‎‎‎‎‎‎‏‏‎‎‎‏‎‎‏‎(enterprise)‎‏‎‎‏‎"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‏‎‎‏‎‏‏‏‎‎‎‎‏‏‎‏‎‎‏‏‎‎‏‎‎‎‏‎‏‏‎‎‎‎‎‏‎‏‎‏‏‏‏‏‎Phonecall‎‏‎‎‏‎"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‎‎‎‏‏‎‎‏‎‏‎‏‏‏‏‏‎‎‎‎‎‎‎‏‏‎‎‏‏‎‏‎‏‏‎‏‏‎‎‏‎‎‏‏‏‏‏‏‎‎‎‎‏‎‎Phone call‎‏‎‎‏‎"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‏‎‎‏‏‏‏‏‎‎‏‎‏‏‎‏‎‏‏‎‎‏‎‎‎‎‏‏‎‏‎‏‎‏‎‎‎‏‏‎‏‎‎‏‏‎‎(through ‎‏‎‎‏‏‎<xliff:g id="ATTRIBUTION">%s</xliff:g>‎‏‎‎‏‏‏‎)‎‏‎‎‏‎"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‎‎‏‏‎‎‎‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‎‎‎‎‎‎‎‎‏‎‏‏‎‏‏‏‏‎‎‎camera‎‏‎‎‏‎"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‏‏‏‎‏‏‏‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‏‏‏‎‎‏‎‏‏‏‎‎‎‏‏‏‏‎location‎‏‎‎‏‎"</string>
@@ -978,7 +988,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‏‎‎‏‎‎‏‏‏‎‏‎‎‎‏‎‏‎‎‏‏‎‎‎‏‏‎‏‎‏‎‏‏‎‏‎‏‏‏‎‎‎‏‏‏‎‎‎Sensors off‎‏‎‎‏‎"</string>
     <string name="device_services" msgid="1549944177856658705">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‎‎‎‏‎‏‎‎‎‎‎‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‏‏‎‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‏‎‎‎‏‎‎‎‏‎Device Services‎‏‎‎‏‎"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‏‎‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‎‎‏‎‎‏‏‎‎‎‏‏‏‎‎‏‏‎‏‏‏‎‎‏‏‏‏‎‏‎‎No title‎‏‎‎‏‎"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‎‎‎‎‎‏‎‎‎‎‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‏‏‎‎‎‎‎‎Tap to restart this app and go full screen.‎‏‎‎‏‎"</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‎‎‏‏‎‎‏‏‏‎‏‎‏‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‏‏‏‎‎‏‏‎‎‏‎‎‏‏‎‏‎‏‎‏‏‎‏‎‏‎‏‎‎Move‎‏‎‎‏‎"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‏‏‏‎‎‎‎‏‎‏‏‏‏‏‎‎‎‏‏‎‎‏‏‏‏‎‏‏‏‎‏‏‎‎‎‎‎‏‎‎‎‎‏‏‎‏‎‎‎‎‎‎‎‎‎System navigation updated. To make changes, go to Settings.‎‏‎‎‏‎"</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‎‏‏‏‏‏‎‎‎‏‎‏‏‏‎‎‏‎‏‎‎‎‏‏‏‏‏‎‎‎‏‎‏‏‎‎‎‎‎Go to Settings to update system navigation‎‏‎‎‏‎"</string>
@@ -1032,6 +1041,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‏‎‎‎‏‏‏‎‏‎‏‎‏‏‎‎‎‎‏‎‎‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‏‎‎‎‏‎‏‎‎‏‏‎‏‏‏‏‎‎Add‎‏‎‎‏‎"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‎‎‏‎‎‎Suggested by ‎‏‎‎‏‏‎<xliff:g id="APP">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‎‏‎‎‎‏‏‏‎‏‏‏‎‏‎‎‏‏‎‎‎‎‏‎‎‎‏‏‏‎‎‎‎‏‏‎‏‏‏‎‎‎‏‏‎‎‏‎‎‎‏‎‏‏‏‎Controls updated‎‏‎‎‏‎"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‎‏‎‎‏‏‎‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎‏‏‏‎‏‎‏‏‎‎‎‏‎‎‎‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‎Device locked‎‏‎‎‏‎"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‎‎‏‎‎‏‏‏‎‏‎‎‏‎‎‏‎‎‏‏‎‎‎‏‎‎‏‏‏‏‏‎‎‏‎‎‏‎‎‎‎‏‎‏‏‎‏‏‏‏‎‎PIN contains letters or symbols‎‏‎‎‏‎"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‏‎‏‏‏‎‎‏‎‎‎‎‎‏‎‏‎‏‎‏‏‎‎‏‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‏‎‎Verify ‎‏‎‎‏‏‎<xliff:g id="DEVICE">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‎‏‏‎‎‏‎‎‏‎‎‏‏‎‎‏‎‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‏‏‎‏‏‏‏‎‏‏‏‏‏‏‏‏‎‎‏‏‎Wrong PIN‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 4b482b9..c97194f 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Desplazar captura de pantalla"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Descartar captura de pantalla"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Vista previa de la captura de pantalla"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Límite superior"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Límite inferior"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Grabadora de pantalla"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando grabación pantalla"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación constante para una sesión de grabación de pantalla"</string>
@@ -115,7 +117,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Compartir"</string>
     <string name="screenrecord_cancel_success" msgid="1775448688137393901">"Se canceló la grabación de pantalla"</string>
     <string name="screenrecord_save_message" msgid="490522052388998226">"Se guardó la grabación de pantalla; presiona para verla"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Error al borrar la grabación de pantalla"</string>
+    <string name="screenrecord_delete_error" msgid="2870506119743013588">"No se pudo borrar la grabación de pantalla"</string>
     <string name="screenrecord_permission_error" msgid="7856841237023137686">"Error al obtener permisos"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Error al iniciar la grabación de pantalla"</string>
     <string name="usb_preference_title" msgid="1439924437558480718">"Opciones de transferencia de archivos por USB"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hasta el amanecer"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"A la(s) <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Hasta la(s) <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"La tecnología NFC está inhabilitada"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"La tecnología NFC está habilitada"</string>
@@ -440,9 +444,11 @@
     <string name="notification_tap_again" msgid="4477318164947497249">"Presiona de nuevo para abrir"</string>
     <string name="keyguard_unlock" msgid="8031975796351361601">"Desliza el dedo hacia arriba para abrir"</string>
     <string name="keyguard_retry" msgid="886802522584053523">"Desliza el dedo hacia arriba para volver a intentarlo"</string>
-    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquee el dispositivo para usar NFC"</string>
+    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquea el dispositivo para usar NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertenece a tu organización"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Este dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Desliza el dedo para desbloquear el teléfono."</string>
     <string name="voice_hint" msgid="7476017460191291417">"Desliza el dedo desde el ícono para abrir asistente de voz."</string>
     <string name="camera_hint" msgid="4519495795000658637">"Desliza el dedo para acceder a la cámara."</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Mostrar perfil"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Agregar usuario"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Usuario nuevo"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"¿Quieres finalizar la sesión de invitado?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Finalizar sesión de invitado"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"¿Eliminar invitado?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Se eliminarán las aplicaciones y los datos de esta sesión."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Finalizar sesión"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Eliminar"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Bienvenido nuevamente, invitado."</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"¿Quieres retomar la sesión?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Volver a empezar"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Tu organización instaló una autoridad de certificación en tu perfil de trabajo. Es posible que se controle o modifique el tráfico de tu red segura."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Hay una autoridad de certificación instalada en este dispositivo. Es posible que se controle o modifique el tráfico de tu red segura."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Tu administrador activó el registro de red, que supervisa el tráfico en tu dispositivo."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"El administrador activó el registro de red, que supervisa el tráfico de tu perfil de trabajo, pero no el de tu perfil personal."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Estás conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>, que puede controlar la actividad de tu red, incluidos los correos electrónicos, las apps y los sitios web."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Estás conectado a <xliff:g id="VPN_APP_0">%1$s</xliff:g> y <xliff:g id="VPN_APP_1">%2$s</xliff:g>, que pueden controlar tu actividad de red, incluidos los correos electrónicos, las apps y los sitios web."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Tu perfil de trabajo está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>, que puede controlar tu actividad de red, incluidos los correos electrónicos, las apps y los sitios web."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Presiona para silenciar. Es posible que los servicios de accesibilidad estén silenciados."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Presiona para establecer el modo vibración."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Presiona para silenciar."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"silenciar"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"dejar de silenciar"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrar"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"El sistema &lt;b&gt;descendió esta notificación a Silenciada&lt;/b&gt; de forma automática."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Se clasificó esta notificación &lt;b&gt;en una posición superior&lt;/b&gt; de forma automática en el panel."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Se clasificó esta notificación &lt;b&gt;en una posición inferior&lt;/b&gt; de forma automática en el panel."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"¿Te parece bien?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Envía tus comentarios al desarrollador. ¿Te parece bien?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Gracias por tus comentarios."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Aceptar"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Se abrieron los controles de notificaciones de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mover a <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Agregar a la posición <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posición <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Se agregó la tarjeta"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Se quitó la tarjeta"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de Configuración rápida"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificación de <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Abrir Configuración"</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> está usando <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> usó <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> recientemente"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(empresarial)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Teléfono"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Llamada telefónica"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(a través de <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"cámara"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"ubicación"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Se desactivaron los sensores"</string>
     <string name="device_services" msgid="1549944177856658705">"Servicios del dispositivo"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Sin título"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Presiona para reiniciar esta app y acceder al modo de pantalla completa."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Mover"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Se actualizó el sistema de navegación. Para hacer cambios, ve a Configuración."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Ve a Configuración para actualizar la navegación del sistema"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Agregar"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Sugerido por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Controles actualizados"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Dispos. bloqueado"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"El PIN contiene letras o símbolos"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Verificar <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN incorrecto"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 36fee3f..4c5ef0b 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Hacer captura de pantalla continua"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Cerrar captura de pantalla"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Vista previa de captura de pantalla"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Margen superior"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Margen inferior"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Grabación de pantalla"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando grabación de pantalla"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación continua de una sesión de grabación de la pantalla"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hasta el amanecer"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"A las <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Hasta las <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"El NFC está desactivado"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"El NFC está activado"</string>
@@ -440,9 +444,11 @@
     <string name="notification_tap_again" msgid="4477318164947497249">"Toca de nuevo para abrir"</string>
     <string name="keyguard_unlock" msgid="8031975796351361601">"Desliza el dedo hacia arriba para abrir"</string>
     <string name="keyguard_retry" msgid="886802522584053523">"Desliza el dedo hacia arriba para volverlo a intentar"</string>
-    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquear para usar NFC"</string>
+    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquea para usar el NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertenece a tu organización"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Este dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Desliza desde el icono para abrir el teléfono"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Desliza desde el icono para abrir asistente de voz"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Desliza desde el icono para abrir la cámara"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Mostrar perfil"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Añadir usuario"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Nuevo usuario"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"¿Finalizar sesión de invitado?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Finalizar sesión de invitado"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"¿Quitar invitado?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Se eliminarán todas las aplicaciones y datos de esta sesión."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Finalizar sesión"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Quitar"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Hola de nuevo, invitado"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"¿Quieres continuar con la sesión?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Volver a empezar"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Tu organización ha instalado una entidad de certificación en tu perfil de trabajo. Es posible que se supervise o se modifique tu tráfico de red seguro."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Se ha instalado una entidad de certificación en este dispositivo. Es posible que se supervise o se modifique tu tráfico de red seguro."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"El administrador ha activado el registro de la red para supervisar el tráfico en tu dispositivo."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Tu administrador ha activado el registro de la red, por lo que se monitorizará el tráfico de tu perfil de trabajo, aunque no el de tu perfil personal."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Te has conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>, que puede supervisar tu actividad de red, como los correos electrónicos, las aplicaciones y los sitios web."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Te has conectado a <xliff:g id="VPN_APP_0">%1$s</xliff:g> y <xliff:g id="VPN_APP_1">%2$s</xliff:g>, que pueden supervisar tu actividad de red, como los correos electrónicos, las aplicaciones y los sitios web."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Tu perfil de trabajo está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>, que puede supervisar tu actividad de red, como los correos electrónicos, las aplicaciones y los sitios web."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Toca para silenciar. Los servicios de accesibilidad pueden silenciarse."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Toca para activar la vibración."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Toca para silenciar."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"silenciar"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"dejar de silenciar"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrar"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"El sistema ha &lt;b&gt;disminuido automáticamente a Silencio&lt;/b&gt; la importancia de esta notificación."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Esta notificación se ha colocado automáticamente en una &lt;b&gt;posición más alta&lt;/b&gt; en tu pantalla de notificaciones."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Esta notificación se ha colocado automáticamente en una &lt;b&gt;posición más baja&lt;/b&gt; en tu pantalla de notificaciones."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"¿Estuvo bien?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Envía tus comentarios al desarrollador. ¿Ha estado bien?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Gracias por tus comentarios."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Aceptar"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Se han abierto los controles de las notificaciones de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mover a <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Añadir a la posición <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posición <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Tarjeta añadida"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Tarjeta quitada"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de ajustes rápidos."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificación de <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Abrir ajustes."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> está usando este elemento: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ha usado recientemente este elemento: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(empresa)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Llamada telefónica"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Llamada telefónica"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(a través de <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"cámara"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"ubicación"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensores desactivados"</string>
     <string name="device_services" msgid="1549944177856658705">"Servicios del dispositivo"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Sin título"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Toca para reiniciar esta aplicación e ir a la pantalla completa."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Mover"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Se ha actualizado la navegación del sistema. Para hacer cambios, ve a Ajustes."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Ve a Ajustes para actualizar la navegación del sistema"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Añadir"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Sugerido por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Controles actualizados"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Dispositivo bloqueado"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"El PIN contiene letras o símbolos"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Verifica <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN incorrecto"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index ff043e0..65c5930 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Ekraanipildi kerimine"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ekraanipildist loobumine"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Ekraanipildi eelvaade"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Ülempiir"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Alampiir"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Ekraanisalvesti"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekraanisalvestuse töötlemine"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pooleli märguanne ekraanikuva salvestamise seansi puhul"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Kuni päikesetõusuni"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Sisse kell <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Kuni <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC on keelatud"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC on lubatud"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC kasutamiseks avage."</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"See seade kuulub teie organisatsioonile"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Selle seadme omanik on <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Telefoni kasutamiseks pühkige ikoonilt eemale"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Häälabi kasutamiseks pühkige ikoonilt eemale"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Kaamera kasutamiseks pühkige ikoonilt eemale"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Kuva profiil"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Lisa kasutaja"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Uus kasutaja"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Kas lõpetada külastajaseanss?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Lõpeta külastajaseanss"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Kas eemaldada külaline?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Seansi kõik rakendused ja andmed kustutatakse."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Lõpeta seanss"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Eemalda"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Tere tulemast tagasi, külaline!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Kas soovite seansiga jätkata?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Alusta uuesti"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Teie organisatsioon installis teie tööprofiilile sertifikaadi volituse. Teie turvalist võrguliiklust võidakse jälgida ja muuta."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Sertifikaadi volitus on sellesse seadmesse installitud. Teie turvalist võrguliiklust võidakse jälgida ja muuta."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Teie administraator lülitas sisse võrgu logimise funktsiooni, mis jälgib teie seadmes liiklust."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Teie administraator on sisse lülitanud võrgu logimise funktsiooni, mis jälgib liiklust teie võrguprofiilil, kuid mitte teie isiklikul profiilil."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Teil on ühendus rakendusega <xliff:g id="VPN_APP">%1$s</xliff:g>, mis saab jälgida teie võrgutegevusi, sh meile, rakendusi ja veebisaite."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Teil on ühendus rakendustega <xliff:g id="VPN_APP_0">%1$s</xliff:g> ja <xliff:g id="VPN_APP_1">%2$s</xliff:g>, mis saavad jälgida teie võrgutegevusi, sh meile, rakendusi ja veebisaite."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Teie tööprofiil on ühendatud rakendusega <xliff:g id="VPN_APP">%1$s</xliff:g>, mis saab jälgida teie võrgutegevusi, sh meile, rakendusi ja veebisaite."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Puudutage vaigistamiseks. Juurdepääsetavuse teenused võidakse vaigistada."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Puudutage vibreerimise määramiseks."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Puudutage vaigistamiseks."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"vaigistamine"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"vaigistuse tühistamine"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibreerimine"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Süsteem määras sellele märguandele automaatselt prioriteedi &lt;b&gt;Vaikne&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Sellele märguandele määrati teie märguandealas automaatselt &lt;b&gt;kõrgem prioriteet&lt;/b&gt;."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Sellele märguandele määrati teie märguandealas automaatselt &lt;b&gt;madalam prioriteet&lt;/b&gt;."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Kas see oli õige?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Andke arendajale tagasisidet. Kas see oli õige?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Täname tagasiside eest!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> märguannete juhtelemendid on avatud"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Teisaldamine asendisse <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Lisamine asendisse <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Asend <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Paan on lisatud"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Paan on eemaldatud"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Kiirseadete redigeerija."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Teenuse <xliff:g id="ID_1">%1$s</xliff:g> märguanne: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Ava seaded."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> kasutab järgmist: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> kasutas hiljuti järgmist: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(ettevõte)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonikõne"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefonikõne"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(üksuse <xliff:g id="ATTRIBUTION">%s</xliff:g> kaudu)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"kaamera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"asukoht"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Andurid on välja lülitatud"</string>
     <string name="device_services" msgid="1549944177856658705">"Seadme teenused"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Pealkiri puudub"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Puudutage rakenduse taaskäivitamiseks ja täisekraanrežiimi aktiveerimiseks."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Teisalda"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Süsteemis navigeerimine on värskendatud. Muutmiseks avage jaotis Seaded."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Süsteemi navigeerimise värskendamiseks avage jaotis Seaded"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Lisa"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Soovitas <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Juhtelemente värskendati"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Seade on lukustatud"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-kood sisaldab tähti või sümboleid"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Kinnitage <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Vale PIN-kood"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 7517f17..9cebde1 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Pantaila-argazki etengabea"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Baztertu pantaila-argazkia"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Pantaila-argazkiaren aurrebista"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Goiko ertza"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Beheko ertza"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Pantaila-grabagailua"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Pantaila-grabaketa prozesatzen"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pantailaren grabaketa-saioaren jakinarazpen jarraitua"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Egunsentira arte"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aktibatze-ordua: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Desaktibatze-ordua: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Desgaituta dago NFC"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Gaituta dago NFC"</string>
@@ -440,9 +444,11 @@
     <string name="notification_tap_again" msgid="4477318164947497249">"Irekitzeko, ukitu berriro"</string>
     <string name="keyguard_unlock" msgid="8031975796351361601">"Pasatu hatza gora irekitzeko"</string>
     <string name="keyguard_retry" msgid="886802522584053523">"Berriro saiatzeko, pasatu hatza gora"</string>
-    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desblokeatu NFC erabiltzeko"</string>
+    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desblokea ezazu NFC erabiltzeko"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Gailu hau zure erakundearena da"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Gailu hau <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> erakundearena da"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Pasatu hatza ikonotik, telefonoa irekitzeko"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Pasatu hatza ikonotik, ahots-laguntza irekitzeko"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Pasatu hatza ikonotik, kamera irekitzeko"</string>
@@ -458,14 +464,15 @@
     <string name="keyguard_indication_charging_time_fast" msgid="7895986003578341126">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Bizkor kargatzen (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatu arte)"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="245442950133408398">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mantso kargatzen (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatu arte)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Aldatu erabiltzailea"</string>
-    <string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Aldatu erabiltzailez. <xliff:g id="CURRENT_USER_NAME">%s</xliff:g> da saioa hasita duena."</string>
-    <string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Uneko erabiltzailea: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
+    <string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Aldatu erabiltzailea. <xliff:g id="CURRENT_USER_NAME">%s</xliff:g> da saioa hasita daukana."</string>
+    <string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Erabiltzailea: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Erakutsi profila"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Gehitu erabiltzailea"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Erabiltzaile berria"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Gonbidatuentzako saioa amaitu nahi duzu?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Amaitu gonbidatuentzako saioa"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Gonbidatua kendu nahi duzu?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Saioko aplikazio eta datu guztiak ezabatuko dira."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Amaitu saioa"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Kendu"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Ongi etorri berriro, gonbidatu hori!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Saioarekin jarraitu nahi duzu?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Hasi berriro"</string>
@@ -474,7 +481,7 @@
     <string name="guest_notification_text" msgid="4202692942089571351">"Aplikazioak eta datuak ezabatzeko, kendu gonbidatua"</string>
     <string name="guest_notification_remove_action" msgid="4153019027696868099">"KENDU GONBIDATUA"</string>
     <string name="user_logout_notification_title" msgid="3644848998053832589">"Amaitu erabiltzailearen saioa"</string>
-    <string name="user_logout_notification_text" msgid="7441286737342997991">"Amaitu uneko erabiltzailearen saioa"</string>
+    <string name="user_logout_notification_text" msgid="7441286737342997991">"Amaitu erabiltzailearen saioa"</string>
     <string name="user_logout_notification_action" msgid="7974458760719361881">"AMAITU ERABILTZAILEAREN SAIOA"</string>
     <string name="user_add_user_title" msgid="4172327541504825032">"Beste erabiltzaile bat gehitu?"</string>
     <string name="user_add_user_message_short" msgid="2599370307878014791">"Erabiltzaile bat gehitzen duzunean, horrek bere eremua konfiguratu beharko du.\n\nEdozein erabiltzailek egunera ditzake beste erabiltzaile guztien aplikazioak."</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Erakundeak ziurtagiri-emaile bat instalatu dizu laneko profilean. Baliteke sareko trafiko segurua gainbegiratzea edo aldatzea."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Ziurtagiri-emaile bat dago instalatuta gailuan. Baliteke sareko trafiko segurua gainbegiratzea edo aldatzea."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Administratzaileak sare-erregistroak aktibatu ditu; horrela, zure gailuko trafikoa gainbegira dezake."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Administratzaileak sarearen erregistroak aktibatu ditu; horrela, zure laneko profileko trafikoa gainbegira dezake, baina ez zure profil pertsonalekoa."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"<xliff:g id="VPN_APP">%1$s</xliff:g> aplikaziora konektatuta zaude eta hark sareko jarduerak gainbegira ditzake, mezu elektronikoak, aplikazioak eta webguneak barne."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> eta <xliff:g id="VPN_APP_1">%2$s</xliff:g> aplikazioetara konektatuta zaude, eta haiek sareko jarduerak gainbegira ditzakete, mezu elektronikoak, aplikazioak eta webguneak barne."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"<xliff:g id="VPN_APP">%1$s</xliff:g> aplikaziora dago konektatuta laneko profila, eta aplikazio horrek sareko jarduerak gainbegira ditzake, mezu elektronikoak, aplikazioak eta webguneak barne."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Sakatu audioa desaktibatzeko. Baliteke erabilerraztasun-eginbideen audioa desaktibatzea."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Sakatu hau dardara ezartzeko."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Sakatu hau audioa desaktibatzeko."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"desaktibatu audioa"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"aktibatu audioa"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"dardara"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Jakinarazpen hau automatikoki &lt;b&gt;aldatu da soinurik gabeko modura&lt;/b&gt; du sistemak."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Jakinarazpen hau automatikoki &lt;b&gt;igo da mailaz&lt;/b&gt;."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Jakinarazpen hau automatikoki &lt;b&gt;jaitsi da mailaz&lt;/b&gt;."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Zuzena al da hau?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Jakinarazi oharrak garatzaileari. Zuzena al da?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Mila esker iritzia emateagatik!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Ados"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Ireki dira <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioaren jakinarazpenak kontrolatzeko aukerak"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Eraman <xliff:g id="POSITION">%1$d</xliff:g>garren lekura"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Gehitu <xliff:g id="POSITION">%1$d</xliff:g>garren lekuan"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g>garren lekua"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Gehitu da lauza"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Kendu da lauza"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Ezarpen bizkorren editorea."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> zerbitzuaren jakinarazpena: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Ireki ezarpenak."</string>
@@ -947,7 +959,7 @@
     <string name="running_foreground_services_msg" msgid="3009459259222695385">"Sakatu bateria eta datuen erabilerari buruzko xehetasunak ikusteko"</string>
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Datu-konexioa desaktibatu nahi duzu?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"<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="6496033312431658238">"Uneko operadorea"</string>
+    <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"Zure operadorea"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Aplikazio bat baimen-eskaera oztopatzen ari denez, ezarpenek ezin dute egiaztatu erantzuna."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<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="6675965177075443714">"- <xliff:g id="APP">%1$s</xliff:g> aplikazioaren informazioa irakur dezake."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> aplikazioa <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> erabiltzen ari da"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> aplikazioak <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> erabili du duela gutxi"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(enpresa)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefono-deia"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefono-deia"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> aplikazioaren bidez)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"kokapena"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sentsoreak desaktibatuta daude"</string>
     <string name="device_services" msgid="1549944177856658705">"Gailuetarako zerbitzuak"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Ez du izenik"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Berrabiarazi aplikazio hau eta ezarri pantaila osoko modua."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Eraman"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Eguneratu da sistemaren nabigazioa. Aldaketak egiteko, joan Ezarpenak atalera."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Sistemaren nabigazioa eguneratzeko, joan Ezarpenak atalera"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Gehitu"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> aplikazioak iradoki du"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Eguneratu dira kontrolatzeko aukerak"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Gailua blokeatuta"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN kodeak hizkiak edo ikurrak ditu"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Egiaztatu <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN okerra"</string>
@@ -1043,8 +1055,8 @@
     <string name="controls_structure_tooltip" msgid="4355922222944447867">"Pasatu hatza aukera gehiago ikusteko"</string>
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Gomendioak kargatzen"</string>
     <string name="controls_media_title" msgid="1746947284862928133">"Multimedia-edukia"</string>
-    <string name="controls_media_close_session" msgid="3957093425905475065">"Ezkutatu uneko saioa."</string>
-    <string name="controls_media_active_session" msgid="1984383994625845642">"Ezin da ezkutatu uneko saioa."</string>
+    <string name="controls_media_close_session" msgid="3957093425905475065">"Ezkutatu saioa."</string>
+    <string name="controls_media_active_session" msgid="1984383994625845642">"Ezin da ezkutatu saioa."</string>
     <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Baztertu"</string>
     <string name="controls_media_resume" msgid="1933520684481586053">"Berrekin"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Ezarpenak"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 231eb45..04b14f1 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"نماگرفت پیمایشی"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"رد کردن نماگرفت"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"پیش‌نمایش نماگرفت"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"مرز بالایی"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"مرز پایینی"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"ضبط‌کننده صفحه‌نمایش"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"درحال پردازش ضبط صفحه‌نمایش"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"اعلان درحال انجام برای جلسه ضبط صفحه‌نمایش"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"تا طلوع آفتاب"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"ساعت <xliff:g id="TIME">%s</xliff:g> روشن می‌شود"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"تا<xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"‏ارتباط میدان نزدیک (NFC)"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"‏«ارتباط میدان نزدیک» (NFC) غیرفعال است"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"‏«ارتباط میدان نزدیک» (NFC) فعال است"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"‏برای استفاده از NFC، قفل را باز کنید"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"این دستگاه به سازمان شما تعلق دارد"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"این دستگاه به <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> تعلق دارد"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"انگشتتان را از نماد تلفن تند بکشید"</string>
     <string name="voice_hint" msgid="7476017460191291417">"برای «دستیار صوتی»، تند بکشید"</string>
     <string name="camera_hint" msgid="4519495795000658637">"انگشتتان را از نماد دوربین تند بکشید"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"نمایش نمایه"</string>
     <string name="user_add_user" msgid="4336657383006913022">"افزودن کاربر"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"کاربر جدید"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"جلسه مهمان تمام شود؟"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"پایان دادن به جلسه مهمان"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"مهمان حذف شود؟"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"همه برنامه‌ها و داده‌های این جلسه حذف خواهد شد."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"پایان جلسه"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"حذف"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"مهمان گرامی، بازگشتتان را خوش آمد می‌گوییم!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"آیا می‌خواهید جلسه‌تان را ادامه دهید؟"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"شروع مجدد"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"سازمان شما مرجع گواهینامه‌ای در نمایه کاری شما نصب کرده است. ممکن است ترافیک امن شبکه شما پایش یا تغییر داده شود."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"مرجع گواهینامه‌ای در این دستگاه نصب شده است. ممکن است ترافیک امن شبکه شما پایش یا تغییر داده شود."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"سرپرست سیستم شما گزارش‌گیری از شبکه را (که ترافیک دستگاه شما را پایش می‌کند) روشن کرده است."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"سرپرست شما گزارش‌گیری شبکه را که بر ترافیک نمایه کاری‌تان نظارت می‌کند، اما بر ترافیک نمایه شخصی‌تان نظارت نمی‌کند روشن کرده است."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"به <xliff:g id="VPN_APP">%1$s</xliff:g> متصل شده‌اید، که می‌تواند فعالیت شبکه شما را (ازجمله ایمیل‌ها، برنامه‌‌ها و وب‌سایت‌ها) پایش کند."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"به <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="368812367182387320">"نمایه کاری شما به <xliff:g id="VPN_APP">%1$s</xliff:g> متصل است، که می‌تواند فعالیت شما در شبکه (ازجمله ایمیل‌ها، برنامه‌ها و وب‌سایت‌ها) را پایش کند."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"‏%1$s. برای صامت کردن ضربه بزنید. ممکن است سرویس‌های دسترس‌پذیری صامت شود."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"‏%1$s. برای تنظیم روی لرزش، ضربه بزنید."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"‏%1$s. برای صامت کردن ضربه بزنید."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"صامت کردن"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"باصدا کردن"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"لرزش"</string>
@@ -709,9 +719,9 @@
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"سیستم را تنظیم کنید که تشخیص دهد اعلان صدا و لرزش داشته باشد یا نه"</string>
     <string name="notification_channel_summary_automatic_alerted" msgid="954166812246932240">"‏&lt;b&gt;وضعیت:&lt;/b&gt; به «پیش‌فرض» ارتقا یافت"</string>
     <string name="notification_channel_summary_automatic_silenced" msgid="7403004439649872047">"‏&lt;b&gt;وضعیت:&lt;/b&gt; به «بی‌صدا» تنزل یافت"</string>
-    <string name="notification_channel_summary_automatic_promoted" msgid="1301710305149590426">"‏&lt;b&gt;وضعیت:&lt;/b&gt; در رتبه‌بندی بالاتری قرار گرفت"</string>
-    <string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"‏&lt;b&gt;وضعیت:&lt;/b&gt; در رتبه‌بندی پایین‌تری قرار گرفت"</string>
-    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"در بالای بخش مکالمه به‌صورت حبابک شناور نشان داده می‌شود و تصویر نمایه را در صفحه قفل نمایش می‌دهد"</string>
+    <string name="notification_channel_summary_automatic_promoted" msgid="1301710305149590426">"‏&lt;b&gt;وضعیت:&lt;/b&gt; در رده‌بندی بالاتری قرار گرفت"</string>
+    <string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"‏&lt;b&gt;وضعیت:&lt;/b&gt; در رده‌بندی پایین‌تری قرار گرفت"</string>
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"در بالای بخش مکالمه به‌صورت حبابک شناور نشان داده می‌شود و عکس نمایه را در صفحه قفل نمایش می‌دهد"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"تنظیمات"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"اولویت"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> از ویژگی‌های مکالمه پشتیبانی نمی‌کند"</string>
@@ -731,9 +741,9 @@
     <string name="notification_appops_ok" msgid="2177609375872784124">"تأیید"</string>
     <string name="feedback_alerted" msgid="5192459808484271208">"‏سیستم این اعلان را به‌طور خودکار &lt;b&gt;به «پیش‌فرض» ارتقا داد&lt;/b&gt;."</string>
     <string name="feedback_silenced" msgid="9116540317466126457">"‏سیستم این اعلان را به‌طور خودکار &lt;b&gt;به «بی‌صدا» تنزل داد&lt;/b&gt;."</string>
-    <string name="feedback_promoted" msgid="2125562787759780807">"‏این اعلان به‌طور خودکار در کشوی اعلانات &lt;b&gt;در رتبه‌بندی بالاتری قرار گرفت&lt;/b&gt;."</string>
-    <string name="feedback_demoted" msgid="951884763467110604">"‏این اعلان به‌طور خودکار در کشوی اعلانات &lt;b&gt;در رتبه‌بندی پایین‌تری قرار گرفت&lt;/b&gt;."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"این مورد درست بود؟"</string>
+    <string name="feedback_promoted" msgid="2125562787759780807">"‏این اعلان به‌طور خودکار در کشوی اعلانات &lt;b&gt;در رده‌بندی بالاتری قرار گرفت&lt;/b&gt;."</string>
+    <string name="feedback_demoted" msgid="951884763467110604">"‏این اعلان به‌طور خودکار در کشوی اعلانات &lt;b&gt;در رده‌بندی پایین‌تری قرار گرفت&lt;/b&gt;."</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"بازخوردتان را به اطلاع توسعه‌دهنده برسانید. این مورد درست بود؟"</string>
     <string name="feedback_response" msgid="4671729244976641339">"از بازخوردتان سپاس‌گزاریم!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"تأیید"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"کنترل‌های اعلان برای <xliff:g id="APP_NAME">%1$s</xliff:g> باز شد"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"انتقال به <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"افزودن به موقعیت <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"موقعیت <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"کاشی اضافه شد"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"کاشی حذف شد"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ویرایشگر تنظیمات سریع."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"اعلان <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"باز کردن تنظیمات."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> درحال استفاده از <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> است"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> اخیراً از <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> استفاده کرده است"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(شرکتی)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Phonecall"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"تماس تلفنی"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(ازطریق <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"دوربین"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"مکان"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"حسگرها خاموش است"</string>
     <string name="device_services" msgid="1549944177856658705">"سرویس‌های دستگاه"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"بدون عنوان"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"برای بازراه‌اندازی این برنامه و تغییر به حالت تمام‌صفحه، ضربه بزنید."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"انتقال"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"پیمایش سیستم به‌روزرسانی شد. برای انجام تغییرات به «تنظیمات» بروید."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"برای به‌روزرسانی پیمایش سیستم، به «تنظیمات» بروید"</string>
@@ -986,7 +997,7 @@
     <string name="priority_onboarding_title" msgid="2893070698479227616">"مکالمه روی اولویت تنظیم شده است"</string>
     <string name="priority_onboarding_behavior" msgid="5342816047020432929">"مکالمه‌های اولویت‌دار:"</string>
     <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"نمایش در بالای بخش مکالمه"</string>
-    <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"تصویر نمایه را در صفحه قفل نمایش می‌دهد"</string>
+    <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"عکس نمایه را در صفحه قفل نمایش می‌دهد"</string>
     <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"به‌شکل حبابک شناور روی برنامه‌ها ظاهر می‌شود"</string>
     <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"وقفه در «مزاحم نشوید»"</string>
     <string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"متوجه‌ام"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"افزودن"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"پیشنهاد <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"کنترل‌ها به‌روزرسانی شد"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"دستگاه قفل است"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"پین شامل حروف یا نماد است"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"تأیید <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"پین اشتباه است"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index a6c43d9..d08bfb5 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Vieritä kuvakaappausta"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Hylkää kuvakaappaus"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Kuvakaappauksen esikatselu"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Yläraja"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Alaraja"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Näytön tallentaja"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Näytön tallennusta käsitellään"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pysyvä ilmoitus näytön tallentamisesta"</string>
@@ -123,7 +125,7 @@
     <string name="use_ptp_button_title" msgid="7676427598943446826">"Käytä kamerana (PTP)"</string>
     <string name="installer_cd_button_title" msgid="5499998592841984743">"Asenna Android File Transfer -sovellus Macille"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Takaisin"</string>
-    <string name="accessibility_home" msgid="5430449841237966217">"Aloituspainike"</string>
+    <string name="accessibility_home" msgid="5430449841237966217">"Aloitus"</string>
     <string name="accessibility_menu" msgid="2701163794470513040">"Valikko"</string>
     <string name="accessibility_accessibility_button" msgid="4089042473497107709">"Esteettömyys"</string>
     <string name="accessibility_rotate_button" msgid="1238584767612362586">"Näytön kääntäminen"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Auringonnousuun"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Päälle klo <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> asti"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC on poistettu käytöstä"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC on käytössä"</string>
@@ -440,9 +444,11 @@
     <string name="notification_tap_again" msgid="4477318164947497249">"Avaa napauttamalla uudelleen"</string>
     <string name="keyguard_unlock" msgid="8031975796351361601">"Avaa pyyhkäisemällä ylös"</string>
     <string name="keyguard_retry" msgid="886802522584053523">"Yritä uudelleen pyyhkäisemällä ylös"</string>
-    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Avaa lukitus käyttääksesi NFC:tä"</string>
+    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Avaa lukitus, jotta voit käyttää NFC:tä"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Organisaatiosi omistaa tämän laitteen"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> omistaa tämän laitteen"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Avaa puhelu pyyhkäisemällä."</string>
     <string name="voice_hint" msgid="7476017460191291417">"Avaa ääniapuri pyyhkäisemällä kuvakkeesta."</string>
     <string name="camera_hint" msgid="4519495795000658637">"Avaa kamera pyyhkäisemällä."</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Näytä profiili"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Lisää käyttäjä"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Uusi käyttäjä"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Lopetetaanko Vierailija-käyttökerta?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Lopeta Vierailija-käyttökerta"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Poistetaaanko vieras?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Kaikki sovellukset ja tämän istunnon tiedot poistetaan."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Lopeta käyttökerta"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Poista"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Tervetuloa takaisin!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Haluatko jatkaa istuntoa?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Aloita alusta"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Organisaatiosi lisäsi työprofiiliin varmenteen myöntäjän. Suojattua verkkoliikennettäsi voidaan valvoa tai muuttaa."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Laitteeseen on asennettu varmenteen myöntäjä. Suojattua verkkoliikennettäsi voidaan valvoa tai muuttaa."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Järjestelmänvalvoja on ottanut käyttöön verkkolokitietojen tallentamisen, joka valvoo laitteellasi tapahtuvaa liikennettä."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Järjestelmänvalvoja on ottanut käyttöön verkkolokitietojen tallentamisen. Sen avulla seurataan liikennettä työprofiilissasi mutta ei henkilökohtaisessa profiilissasi."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Olet yhteydessä sovellukseen <xliff:g id="VPN_APP">%1$s</xliff:g>, joka voi valvoa verkkotoimintaasi, esimerkiksi sähköposteja, sovelluksia ja verkkosivustoja."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Olet yhteydessä sovelluksiin <xliff:g id="VPN_APP_0">%1$s</xliff:g> ja <xliff:g id="VPN_APP_1">%2$s</xliff:g>, jotka voivat valvoa verkkotoimintaasi, esimerkiksi sähköposteja, sovelluksia ja verkkosivustoja."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Työprofiilisi on yhteydessä sovellukseen <xliff:g id="VPN_APP">%1$s</xliff:g>, joka voi valvoa toimintaasi verkossa, esimerkiksi sähköposteja, sovelluksia ja verkkosivustoja."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Mykistä koskettamalla. Myös esteettömyyspalvelut saattavat mykistyä."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Siirry värinätilaan napauttamalla."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Mykistä napauttamalla."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"mykistä"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"poista mykistys"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"värinä"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Järjestelmä &lt;b&gt;hiljensi&lt;/b&gt; tämän ilmoituksen automaattisesti."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Tämä ilmoitus valittiin automaattisesti &lt;b&gt;tärkeämmäksi&lt;/b&gt; ilmoitusalueella."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Tämä ilmoitus valittiin automaattisesti &lt;b&gt;vähemmän tärkeäksi&lt;/b&gt; ilmoitusalueella."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Oliko tämä oikein?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Anna kehittäjälle palautetta. Oliko tämä oikein?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Kiitos palautteesta!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Sovelluksen <xliff:g id="APP_NAME">%1$s</xliff:g> ilmoitusten hallinta on avattu."</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Siirrä paikkaan <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Lisää paikkaan <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Paikka <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Kiekko lisätty"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Kiekko poistettu"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Pika-asetusten muokkausnäkymä"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Ilmoitus kohteesta <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Avaa asetukset."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> käyttää kohdetta <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> käytti kohdetta <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> äskettäin"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(yritys)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Puhelu"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Puhelu"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(kautta: <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"sijainti"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Anturit pois päältä"</string>
     <string name="device_services" msgid="1549944177856658705">"Laitepalvelut"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Ei nimeä"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Napauta, niin sovellus käynnistyy uudelleen ja siirtyy koko näytön tilaan."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Siirrä"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Järjestelmän navigointitapa vaihdettu. Voit muuttaa sitä asetuksista."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Vaihda järjestelmän navigointitapaa asetuksista"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Lisää"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Ehdottaja: <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Säätimet päivitetty"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Laite lukittu"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-koodi sisältää kirjaimia tai symboleja"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Vahvista <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Väärä PIN-koodi"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 07f8af5..3d1ab93 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Faire défiler la capture d\'écran"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Fermer la capture d\'écran"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Aperçu de la capture d\'écran"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Limite supérieure"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Limite inférieure"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Enregistreur d\'écran"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Trait. de l\'enregist. d\'écran…"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notification en cours pour une session d\'enregistrement d\'écran"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Jusqu\'à l\'aube"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Actif à <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Jusqu\'à <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC désactivée"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC activée"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Déverrouillez l\'écran pour utiliser la NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Cet appareil appartient à votre organisation"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Cet appareil appartient à <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Balayez à partir de l\'icône pour accéder au téléphone"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Balayez à partir de l\'icône pour accéder à l\'assist. vocale"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Balayez à partir de l\'icône pour accéder à l\'appareil photo"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Afficher le profil"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Ajouter un utilisateur"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Nouvel utilisateur"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Mettre fin à la session d\'invité?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Mettre fin à la session d\'invité"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Supprimer l\'invité?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Toutes les applications et les données de cette session seront supprimées."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Fermer la session"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Supprimer"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Bienvenue à nouveau dans la session Invité"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Voulez-vous poursuivre la session?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Recommencer"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Votre entreprise a installé une autorité de certification dans votre profil professionnel. Votre trafic sur le réseau sécurisé peut être contrôlé ou modifié."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Une autorité de certification est installée sur cet appareil. Votre trafic sur le réseau sécurisé peut être contrôlé ou modifié."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Votre administrateur a activé la journalisation réseau, qui surveille le trafic sur votre appareil."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Votre administrateur a activé la journalisation réseau, qui surveille le trafic dans votre profil professionnel, mais pas dans votre profil personnel."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Vous êtes connecté à <xliff:g id="VPN_APP">%1$s</xliff:g>, qui peut contrôler votre activité réseau, y compris les courriels, les applications et les sites Web."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Vous êtes connecté à <xliff:g id="VPN_APP_0">%1$s</xliff:g> et à <xliff:g id="VPN_APP_1">%2$s</xliff:g>, qui peuvent contrôler votre activité sur le réseau, y compris l\'activité relative aux courriels, aux applications et aux sites Web."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Votre profil professionnel est connecté à <xliff:g id="VPN_APP">%1$s</xliff:g>, qui peut contrôler votre activité réseau, y compris les courriels, les applications et les sites Web."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Touchez pour couper le son. Il est possible de couper le son des services d\'accessibilité."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Touchez pour activer les vibrations."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Touchez pour couper le son."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"désactiver le son"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"réactiver le son"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibration"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"La notification a été automatiquement &lt;b&gt;abaissée à la catégorie Silencieux&lt;/b&gt; par le système."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"La notification a été automatiquement &lt;b&gt;élevée d\'un niveau&lt;/b&gt; dans votre volet."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"La notification a été automatiquement &lt;b&gt;abaissée d\'un niveau&lt;/b&gt; dans votre volet."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Était-ce correct?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Faites part de vos commentaires au concepteur. Était-ce correct?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Merci de vos commentaires!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Les paramètres des notifications pour <xliff:g id="APP_NAME">%1$s</xliff:g> sont ouverts"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Déplacer vers <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Ajouter à la position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Tuile ajoutée"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Tuile retirée"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Éditeur de paramètres rapides."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notification <xliff:g id="ID_1">%1$s</xliff:g> : <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Ouvrir les paramètres."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> utilise cet élément : <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> a récemment utilisé cet élément : <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(entreprise)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Appel téléphonique"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Appel téléphonique"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(par l\'intermédiaire de <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"appareil photo"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"position"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Capteurs désactivés"</string>
     <string name="device_services" msgid="1549944177856658705">"Services de l\'appareil"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Sans titre"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Touchez pour redémarrer cette application et passer en plein écran."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Déplacer"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"La navigation système a été mise à jour. Pour apporter des modifications, accédez au menu Paramètres."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Accédez au menu Paramètres pour mettre à jour la navigation système"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Ajouter"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Suggestion de <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Commandes mises à jour"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Appareil verrouillé"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Le NIP contient des lettres ou des symboles"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Vérifier <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"NIP incorrect"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 7bbbff6..c6d0674 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Faire défiler la capture d\'écran"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Fermer la capture d\'écran"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Aperçu de la capture d\'écran"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Limite supérieure"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Limite inférieure"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Enregistreur d\'écran"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Enregistrement de l\'écran…"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notification en cours pour une session d\'enregistrement de l\'écran"</string>
@@ -236,7 +238,7 @@
     <skip />
     <string name="accessibility_notification_dismissed" msgid="4411652015138892952">"Notification masquée"</string>
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Volet des notifications"</string>
-    <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Paramètres rapides"</string>
+    <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Réglages rapides"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Écran de verrouillage"</string>
     <string name="accessibility_desc_settings" msgid="6728577365389151969">"Paramètres"</string>
     <string name="accessibility_desc_recent_apps" msgid="1748675199348914194">"Aperçu"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Jusqu\'à l\'aube"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"À partir de <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Jusqu\'à <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC désactivée"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"La technologie NFC est activée"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Déverrouillez l\'écran pour pouvoir utiliser NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Cet appareil appartient à votre organisation"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Cet appareil appartient à <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Balayer pour téléphoner"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Balayer l\'écran depuis l\'icône pour l\'assistance vocale"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Balayer pour prendre une photo"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Afficher le profil"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Ajouter un utilisateur"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Nouvel utilisateur"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Fermer la session Invité ?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Fermer la session Invité"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Supprimer l\'invité ?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Toutes les applications et les données de cette session seront supprimées."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Fermer la session"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Supprimer"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Bienvenue à nouveau dans la session Invité"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Voulez-vous poursuivre la dernière session ?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Non, nouvelle session"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Votre entreprise a installé une autorité de certification dans votre profil professionnel. Votre trafic sur le réseau sécurisé peut être contrôlé ou modifié."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Une autorité de certification est installée sur cet appareil. Votre trafic sur le réseau sécurisé peut être contrôlé ou modifié."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Votre administrateur a activé la journalisation du réseau, pour contrôler le trafic sur votre appareil."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Votre administrateur a activé la journalisation réseau, qui surveille le trafic de votre profil professionnel, mais pas celui de votre profil personnel."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Vous êtes connecté à <xliff:g id="VPN_APP">%1$s</xliff:g>, qui peut contrôler votre activité sur le réseau, y compris l\'activité relative aux e-mails, aux applications et aux sites Web."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Vous êtes connecté à <xliff:g id="VPN_APP_0">%1$s</xliff:g> et à <xliff:g id="VPN_APP_1">%2$s</xliff:g>, qui peuvent contrôler votre activité sur le réseau, y compris l\'activité relative aux e-mails, aux applications et aux sites Web."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Votre profil professionnel est connecté à <xliff:g id="VPN_APP">%1$s</xliff:g>, qui peut contrôler votre activité sur le réseau, y compris l\'activité relative aux e-mails, aux applications et aux sites Web."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Appuyez pour ignorer. Vous pouvez ignorer les services d\'accessibilité."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Appuyez pour mettre en mode vibreur."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Appuyez pour ignorer."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"couper le son"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"réactiver le son"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"activer le vibreur"</string>
@@ -635,7 +645,7 @@
     <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
     <string name="show_battery_percentage" msgid="6235377891802910455">"Afficher le pourcentage intégré de la batterie"</string>
     <string name="show_battery_percentage_summary" msgid="9053024758304102915">"Affichez le pourcentage correspondant au niveau de la batterie dans l\'icône de la barre d\'état lorsque l\'appareil n\'est pas en charge."</string>
-    <string name="quick_settings" msgid="6211774484997470203">"Configuration rapide"</string>
+    <string name="quick_settings" msgid="6211774484997470203">"Réglages rapides"</string>
     <string name="status_bar" msgid="4357390266055077437">"Barre d\'état"</string>
     <string name="overview" msgid="3522318590458536816">"Aperçu"</string>
     <string name="demo_mode" msgid="263484519766901593">"Mode de démonstration de l\'interface du système"</string>
@@ -645,13 +655,13 @@
     <string name="status_bar_alarm" msgid="87160847643623352">"Alarme"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Profil professionnel"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Mode Avion"</string>
-    <string name="add_tile" msgid="6239678623873086686">"Ajouter une tuile"</string>
-    <string name="broadcast_tile" msgid="5224010633596487481">"Tuile de diffusion"</string>
+    <string name="add_tile" msgid="6239678623873086686">"Ajouter un bloc"</string>
+    <string name="broadcast_tile" msgid="5224010633596487481">"Bloc de diffusion"</string>
     <string name="zen_alarm_warning_indef" msgid="5252866591716504287">"Vous n\'entendrez pas votre prochaine alarme <xliff:g id="WHEN">%1$s</xliff:g>, sauf si vous désactivez cette option avant."</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Vous n\'entendrez pas votre prochaine alarme <xliff:g id="WHEN">%1$s</xliff:g>."</string>
     <string name="alarm_template" msgid="2234991538018805736">"à <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="alarm_template_far" msgid="3561752195856839456">"le <xliff:g id="WHEN">%1$s</xliff:g>"</string>
-    <string name="accessibility_quick_settings_detail" msgid="544463655956179791">"Configuration rapide – <xliff:g id="TITLE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_detail" msgid="544463655956179791">"Réglages rapides – <xliff:g id="TITLE">%s</xliff:g>"</string>
     <string name="accessibility_status_bar_hotspot" msgid="2888479317489131669">"Point d\'accès"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil professionnel"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Divertissant pour certains, mais pas pour tous"</string>
@@ -664,8 +674,8 @@
     <string name="activity_not_found" msgid="8711661533828200293">"L\'application n\'est pas installée sur votre appareil."</string>
     <string name="clock_seconds" msgid="8709189470828542071">"Afficher les secondes sur l\'horloge"</string>
     <string name="clock_seconds_desc" msgid="2415312788902144817">"Afficher les secondes dans la barre d\'état. Cela risque de réduire l\'autonomie de la batterie."</string>
-    <string name="qs_rearrange" msgid="484816665478662911">"Réorganiser la fenêtre de configuration rapide"</string>
-    <string name="show_brightness" msgid="6700267491672470007">"Afficher la luminosité dans fenêtre de configuration rapide"</string>
+    <string name="qs_rearrange" msgid="484816665478662911">"Réorganiser les Réglages rapides"</string>
+    <string name="show_brightness" msgid="6700267491672470007">"Afficher la luminosité dans les Réglages rapides"</string>
     <string name="experimental" msgid="3549865454812314826">"Paramètres expérimentaux"</string>
     <string name="enable_bluetooth_title" msgid="866883307336662596">"Activer le Bluetooth ?"</string>
     <string name="enable_bluetooth_message" msgid="6740938333772779717">"Pour connecter un clavier à votre tablette, vous devez avoir activé le Bluetooth."</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"La notification a été automatiquement &lt;b&gt;abaissée à la catégorie \"Silencieux\"&lt;/b&gt; par le système."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"La notification a été automatiquement &lt;b&gt;élevée d\'un niveau&lt;/b&gt; dans votre volet."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"La notification a été automatiquement &lt;b&gt;abaissée d\'un niveau&lt;/b&gt; dans votre volet."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Est-ce que c\'était correct ?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Faites part de vos commentaires au développeur. Est-ce que c\'était correct ?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Merci de nous avoir envoyé vos commentaires."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Les commandes de notification sont disponibles pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -873,18 +883,20 @@
   </string-array>
     <string name="tuner_low_priority" msgid="8412666814123009820">"Afficher les icônes de notification à faible priorité"</string>
     <string name="other" msgid="429768510980739978">"Autre"</string>
-    <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"supprimer la carte"</string>
-    <string name="accessibility_qs_edit_tile_add_action" msgid="5051211910345301833">"ajouter la carte à la fin"</string>
-    <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Déplacer la carte"</string>
-    <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Ajouter une carte"</string>
+    <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"supprimer le bloc"</string>
+    <string name="accessibility_qs_edit_tile_add_action" msgid="5051211910345301833">"ajouter le bloc à la fin"</string>
+    <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Déplacer le bloc"</string>
+    <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Ajouter un bloc"</string>
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Déplacer vers <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Ajouter à la position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
-    <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Éditeur de configuration rapide."</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Bloc ajouté"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Bloc supprimé"</string>
+    <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Éditeur Réglages rapides"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notification <xliff:g id="ID_1">%1$s</xliff:g> : <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Ouvrir les paramètres."</string>
-    <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Ouvrir la fenêtre de configuration rapide."</string>
-    <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Fermer la fenêtre de configuration rapide."</string>
+    <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Ouvrir les Réglages rapides."</string>
+    <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Fermer les Réglages rapides."</string>
     <string name="accessibility_quick_settings_alarm_set" msgid="7237918261045099853">"Alarme définie."</string>
     <string name="accessibility_quick_settings_user" msgid="505821942882668619">"Connecté en tant que <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="data_connection_no_internet" msgid="691058178914184544">"Aucun accès à Internet"</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> utilise <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> a utilisé <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> récemment"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(Enterprise)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Appel téléphonique"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Appel téléphonique"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(via <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"appareil photo"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"position"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Capteurs désactivés"</string>
     <string name="device_services" msgid="1549944177856658705">"Services pour l\'appareil"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Sans titre"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Appuyez pour redémarrer cette application et activer le mode plein écran."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Déplacer"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigation système mise à jour. Pour apporter des modifications, accédez aux paramètres."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Accédez aux paramètres pour mettre à jour la navigation système"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Ajouter"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Suggérée par <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Commandes mises à jour"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Appareil verrouillé"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Le code contient des lettres ou des symboles"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Valider <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Code incorrect"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 0ac8261..08841a2 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Realizar unha captura de pantalla continua"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ignorar a captura de pantalla"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Vista previa da captura de pantalla"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Bordo superior"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Bordo inferior"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Gravadora da pantalla"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando gravación pantalla"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación en curso sobre unha sesión de gravación de pantalla"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Ata o amencer"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Activarase ás: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Utilizarase ata as: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"A opción NFC está desactivada"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"A opción NFC está activada"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquea o dispositivo para utilizar a NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence á túa organización"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Este dispositivo pertence a <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Pasa o dedo desde a icona para acceder ao teléfono"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Pasa o dedo desde a icona para acceder ao asistente de voz"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Pasa o dedo desde a icona para acceder á cámara"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Mostrar perfil"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Engadir usuario"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Novo usuario"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Queres finalizar a sesión de invitado?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Finalizar sesión de invitado"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Queres eliminar o invitado?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Eliminaranse todas as aplicacións e datos desta sesión."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Finalizar sesión"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Eliminar"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Benvido de novo, convidado."</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Queres continuar coa túa sesión?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Comezar de novo"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"A túa organización instalou unha autoridade de certificación no teu perfil de traballo. É posible que se controle ou se modifique o teu tráfico de rede segura."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Este dispositivo ten unha autoridade de certificación instalada. É posible que se controle ou se modifique o teu tráfico de rede segura."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"O administrador activou o rexistro na rede, que controla o tráfico do teu dispositivo."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"O administrador activou o rexistro na rede, que supervisa o tráfico do teu perfil de traballo, pero non o do perfil persoal."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Estás conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode controlar a túa actividade na rede, mesmo os correos electrónicos, as aplicacións e os sitios web."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Estás conectado a <xliff:g id="VPN_APP_0">%1$s</xliff:g> e a <xliff:g id="VPN_APP_1">%2$s</xliff:g>, que poden controlar a túa actividade na rede, mesmo os correos electrónicos, as aplicacións e os sitios web."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"O teu perfil de traballo está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode controlar a túa actividade na rede, mesmo os correos electrónicos, as aplicacións e os sitios web."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Toca para silenciar. Pódense silenciar os servizos de accesibilidade."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Toca para establecer a vibración."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Toca para silenciar."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"silenciar"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"activar o son"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrar"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"O sistema &lt;b&gt;diminuíu a Silencioso&lt;/b&gt; o nivel desta notificación de forma automática."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Esta notificación &lt;b&gt;clasificouse nun nivel superior&lt;/b&gt; de forma automática no teu ton."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Esta notificación &lt;b&gt;clasificouse nun nivel inferior&lt;/b&gt; de forma automática no teu ton."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"A información era correcta?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Faille saber a túa opinión ao programador. A información era correcta?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Grazas polo teu comentario"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Aceptar"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Abríronse os controis de notificacións da aplicación <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mover a <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Engadir á posición <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posición <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Engadiuse a tarxeta"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Quitouse a tarxeta"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de configuración rápida."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificación de <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Abrir configuración."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> está utilizando a aplicación <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> utilizou recentemente a aplicación <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(versión empresarial)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Chamada de teléfono"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Chamada de teléfono"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(mediante <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"a cámara"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"a localiz."</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Desactivar sensores"</string>
     <string name="device_services" msgid="1549944177856658705">"Servizos do dispositivo"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Sen título"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Toca o botón para reiniciar esta aplicación e abrila en pantalla completa."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Mover"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Actualizouse a navegación do sistema. Para facer cambios, vai a Configuración."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Para actualizar a navegación do sistema, vai a Configuración"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Engadir"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Control suxerido por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Actualizáronse os controis"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Disposit. bloqueado"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"O PIN contén letras ou símbolos"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Verificar <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"O PIN é incorrecto"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index f4e1333..867bc2f 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"સ્ક્રીનશૉટ પર સ્ક્રોલ કરો"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"સ્ક્રીનશૉટ છોડી દો"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"સ્ક્રીનશૉટનો પ્રીવ્યૂ"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"સ્ક્રીનશૉટની સૌથી ઉપરની બાજુની સીમા"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"સ્ક્રીનશૉટની સૌથી નીચેની બાજુની સીમા"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"સ્ક્રીન રેકૉર્ડર"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"સ્ક્રીન રેકૉર્ડિંગ ચાલુ છે"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"સ્ક્રીન રેકોર્ડિંગ સત્ર માટે ચાલુ નોટિફિકેશન"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"સૂર્યોદય સુધી"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> વાગ્યે ચાલુ"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> વાગ્યા સુધી"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC અક્ષમ કરેલ છે"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC સક્ષમ કરેલ છે"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCનો ઉપયોગ કરવા માટે અનલૉક કરો"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"આ ડિવાઇસ તમારી સંસ્થાની માલિકીનું છે"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"આ ડિવાઇસ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>ની માલિકીનું છે"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"ફોન માટે આયકનમાંથી સ્વાઇપ કરો"</string>
     <string name="voice_hint" msgid="7476017460191291417">"વૉઇસ સહાય માટે આયકનમાંથી સ્વાઇપ કરો"</string>
     <string name="camera_hint" msgid="4519495795000658637">"કૅમેરા માટે આયકનમાંથી સ્વાઇપ કરો"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"પ્રોફાઇલ બતાવો"</string>
     <string name="user_add_user" msgid="4336657383006913022">"વપરાશકર્તા ઉમેરો"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"નવો વપરાશકર્તા"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"શું અતિથિ સત્ર સમાપ્ત કરીએ?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"અતિથિ સત્ર સમાપ્ત કરો"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"અતિથિ દૂર કરીએ?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"આ સત્રમાંની તમામ ઍપ્લિકેશનો અને ડેટા કાઢી નાખવામાં આવશે."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"સત્ર સમાપ્ત કરો"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"દૂર કરો"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"ફરી સ્વાગત છે, અતિથિ!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"શું તમે તમારું સત્ર ચાલુ કરવા માંગો છો?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"શરૂ કરો"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"તમારી સંસ્થાએ તમારી કાર્ય પ્રોફાઇલમાં પ્રમાણપત્ર સત્તાધિકારી ઇન્સ્ટૉલ કર્યું છે. તમારા સુરક્ષિત નેટવર્ક ટ્રાફિકનું નિયમન થઈ શકે છે અથવા તેમાં ફેરફાર કરવામાં આવી શકે છે."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"આ ઉપકરણ પર પ્રમાણપત્ર સત્તાધિકારી ઇન્સ્ટૉલ કરેલ છે. તમારા સુરક્ષિત નેટવર્ક ટ્રાફિકનું નિયમન થઈ શકે છે અથવા તેમાં ફેરફાર કરવામાં આવી શકે છે."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"તમારા વ્યવસ્થાપકે નેટવર્ક લૉગિંગ ચાલુ કર્યું છે, જે તમારા ઉપકરણ પર નેટવર્ક ટ્રાફિકનું નિયમન કરે છે."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"તમારા વ્યવસ્થાપકે નેટવર્ક લૉગ ઇન ચાલુ કર્યુ છે, જે તમારી વ્યક્તિગત પ્રોફાઇલમાં નહીં, પરંતુ ઑફિસની પ્રોફાઇલમાં ટ્રાફિકનું નિરીક્ષણ કરે છે."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"તમે <xliff:g id="VPN_APP">%1$s</xliff:g> સાથે કનેક્ટ થયાં છો, જે ઇમેઇલ, ઍપ્લિકેશનો અને વેબસાઇટ સહિત તમારી નેટવર્ક પ્રવૃત્તિનું નિરીક્ષણ કરી શકે છે."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"તમે <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="368812367182387320">"તમારી કાર્યાલયની પ્રોફાઇલ <xliff:g id="VPN_APP">%1$s</xliff:g> સાથે કનેક્ટ કરેલ છે, જે ઇમેઇલ, ઍપ્લિકેશનો અને વેબસાઇટો સહિતની તમારી નેટવર્ક પ્રવૃત્તિનું નિયમન કરી શકે છે."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. મ્યૂટ કરવા માટે ટૅપ કરો. ઍક્સેસિબિલિટી સેવાઓ મ્યૂટ કરવામાં આવી શકે છે."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. કંપન પર સેટ કરવા માટે ટૅપ કરો."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. મ્યૂટ કરવા માટે ટૅપ કરો."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"મ્યૂટ કરો"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"અનમ્યૂટ કરો"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"વાઇબ્રેટ"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"સિસ્ટમ દ્વારા આ નોટિફિકેશનને ઑટોમૅટિક રીતે &lt;b&gt;સાઇલન્ટ પર અવનત&lt;/b&gt; કરવામાં આવ્યું."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"તમારા શેડમાં આ નોટિફિકેશનને ઑટોમૅટિક રીતે &lt;b&gt;ઉપલી રેંક&lt;/b&gt; આપવામાં આવી."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"તમારા શેડમાં આ નોટિફિકેશનને ઑટોમૅટિક રીતે &lt;b&gt;નીચલી રેંક&lt;/b&gt; આપવામાં આવી."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"શું આ યોગ્ય હતું?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"ડેવલપરને તમારા પ્રતિસાદ વિશે જાણવા દો. શું આ યોગ્ય હતું?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"તમારા પ્રતિસાદ બદલ આભાર!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ઓકે"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે સૂચના નિયંત્રણો ચાલુ છે"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> પર ખસેડો"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"જગ્યા પર <xliff:g id="POSITION">%1$d</xliff:g> ઉમેરો"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"જગ્યા <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"ટાઇલ ઉમેરી"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"ટાઇલ કાઢી નાખી"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ઝડપી સેટિંગ્સ સંપાદક."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> નોટિફિકેશન: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"સેટિંગ્સ ખોલો."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>, <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>નો ઉપયોગ કરી રહી છે"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>એ તાજેતરમાં જ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>નો ઉપયોગ કર્યો છે"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(એન્ટરપ્રાઇઝ)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"ફોન કૉલ"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"ફોન કૉલ"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> મારફતે)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"કૅમેરા"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"સ્થાન"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"સેન્સર બંધ છે"</string>
     <string name="device_services" msgid="1549944177856658705">"ડિવાઇસ સેવાઓ"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"કોઈ શીર્ષક નથી"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"આ ઍપ ફરીથી ચાલુ કરવા માટે ટૅપ કરીને પૂર્ણ સ્ક્રીન કરો."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"ખસેડો"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"સિસ્ટમ નૅવિગેશન અપડેટ કર્યું. ફેરફારો કરવા માટે, સેટિંગ પર જાઓ."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"સિસ્ટમ નૅવિગેશનને અપડેટ કરવા માટે સેટિંગ પર જાઓ"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"ઉમેરો"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> દ્વારા સૂચન કરેલા"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"નિયંત્રણ અપડેટ કર્યા"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"ડિવાઇસ લૉક કરેલું છે"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"પિનમાં અક્ષરો અથવા પ્રતીકોનો સમાવેશ થાય છે"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g>ને ચકાસો"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"ખોટો પિન"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 50b078f..a357ad2 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"स्क्रीनशॉट को स्क्रोल करें"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"स्क्रीनशॉट को खारिज करें"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"स्क्रीनशॉट की झलक"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"स्क्रीनशॉट को ऊपर से काटने की सीमा"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"स्क्रीनशॉट को नीचे से काटने की सीमा"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"स्क्रीन रिकॉर्डर"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"स्क्रीन रिकॉर्डिंग को प्रोसेस किया जा रहा है"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"स्क्रीन रिकॉर्ड सेशन के लिए जारी सूचना"</string>
@@ -412,6 +414,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"सुबह तक चालू रहेगी"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> पर चालू हाेगी"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> तक चालू रहेगी"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"एनएफ़सी"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC बंद है"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC चालू है"</string>
@@ -442,9 +446,11 @@
     <string name="notification_tap_again" msgid="4477318164947497249">"खोलने के लिए फिर से टैप करें"</string>
     <string name="keyguard_unlock" msgid="8031975796351361601">"खोलने के लिए ऊपर स्वाइप करें"</string>
     <string name="keyguard_retry" msgid="886802522584053523">"फिर से कोशिश करने के लिए ऊपर की ओर स्वाइप करें"</string>
-    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"एनएफ़सी इस्तेमाल करने के लिए, स्क्रीन को अनलॉक करें"</string>
+    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"एनएफ़सी इस्तेमाल करने के लिए स्क्रीन को अनलॉक करें"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"इस डिवाइस का मालिकाना हक आपके संगठन के पास है"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"इस डिवाइस का मालिकाना हक <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> के पास है"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"फ़ोन के लिए आइकॉन से स्वाइप करें"</string>
     <string name="voice_hint" msgid="7476017460191291417">"\'आवाज़ से डिवाइस का इस्तेमाल\' आइकॉन से स्वाइप करें"</string>
     <string name="camera_hint" msgid="4519495795000658637">"कैमरे के लिए आइकॉन से स्वाइप करें"</string>
@@ -465,9 +471,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"प्रोफ़ाइल दिखाएं"</string>
     <string name="user_add_user" msgid="4336657383006913022">"उपयोगकर्ता जोड़ें"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"नया उपयोगकर्ता"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"मेहमान के तौर पर ब्राउज़ करने का सेशन खत्म करना चाहते हैं?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"मेहमान के तौर पर ब्राउज़ करने का सेशन खत्म करें"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"अतिथि को निकालें?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"इस सत्र के सभी ऐप्स और डेटा को हटा दिया जाएगा."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"सेशन खत्म करें"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"निकालें"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"अतिथि, आपका फिर से स्वागत है!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"क्‍या आप अपना सत्र जारी रखना चाहते हैं?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"फिर से शुरू करें"</string>
@@ -542,6 +549,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"आपके संगठन ने आपकी वर्क प्रोफ़ाइल में एक प्रमाणपत्र अनुमति इंस्टॉल की है. आपके सुरक्षित नेटवर्क ट्रैफ़िक की निगरानी या उसमें बदलाव किया जा सकता है."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"इस डिवाइस पर एक प्रमाणपत्र अनुमति इंस्टॉल की है. आपके सुरक्षित नेटवर्क ट्रैफ़िक की निगरानी या उसमें बदलाव किया जा सकता है."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"आपके व्यवस्थापक ने नेटवर्क लॉगिंग चालू किया है, जो आपके डिवाइस पर ट्रैफ़िक की निगरानी करता है."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"आपके एडमिन ने नेटवर्क लॉगिंग की सुविधा चालू कर दी है. इससे आपकी वर्क प्रोफ़ाइल पर आने वाले ट्रैफ़िक की निगरानी की जाती है. हालांकि, इससे आपकी निजी प्रोफ़ाइल की निगरानी नहीं की जाती."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"आप <xliff:g id="VPN_APP">%1$s</xliff:g> से कनेक्‍ट हैं, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकते हैं."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"आप <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="368812367182387320">"आपकी वर्क प्रोफ़ाइल <xliff:g id="VPN_APP">%1$s</xliff:g> से कनेक्ट है, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है."</string>
@@ -622,6 +630,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. म्यूट करने के लिए टैप करें. सुलभता सेवाएं म्यूट हो सकती हैं."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. कंपन (वाइब्रेशन) पर सेट करने के लिए छूएं."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. म्यूट करने के लिए टैप करें."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"म्यूट करें"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"अनम्यूट करें"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"वाइब्रेशन की सुविधा चालू करें"</string>
@@ -735,7 +745,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"सिस्टम ने अपने-आप &lt;b&gt;इस सूचना का लेवल घटाकर, इसे साइलेंट&lt;/b&gt; पर सेट किया था."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"आपकी शेड में, इस सूचना को अपने-आप &lt;b&gt;रैंकिंग में ऊपर&lt;/b&gt; किया गया था."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"आपकी शेड में, इस सूचना को अपने-आप &lt;b&gt;रैंकिंग में नीचे&lt;/b&gt; किया गया था."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"आपको यह सुविधा कैसी लगी?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"डेवलपर को अपना सुझाव/राय दें. आपको यह सुविधा कैसी लगी?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"सुझाव या शिकायत के लिए धन्यवाद!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ठीक है"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए सूचना नियंत्रण चालू हैं"</string>
@@ -882,6 +892,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"टाइल को <xliff:g id="POSITION">%1$d</xliff:g> पोज़िशन पर ले जाएं"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"टाइल को <xliff:g id="POSITION">%1$d</xliff:g> पोज़िशन पर जोड़ें"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"टाइल की पोज़िशन <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"टाइल जोड़ी गई"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"टाइल हटाई गई"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"त्वरित सेटिंग संपादक."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> सूचना: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"सेटिंग खोलें."</string>
@@ -955,8 +967,8 @@
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- यह <xliff:g id="APP">%1$s</xliff:g> से सूचना पढ़ सकता है"</string>
     <string name="slice_permission_text_2" msgid="6758906940360746983">"- यह <xliff:g id="APP">%1$s</xliff:g> में कार्रवाई कर सकता है"</string>
     <string name="slice_permission_checkbox" msgid="4242888137592298523">"<xliff:g id="APP">%1$s</xliff:g> को किसी भी ऐप्लिकेशन के हिस्से (स्लाइस) दिखाने की मंज़ूरी दें"</string>
-    <string name="slice_permission_allow" msgid="6340449521277951123">"मंज़ूरी दें"</string>
-    <string name="slice_permission_deny" msgid="6870256451658176895">"नामंज़ूर करें"</string>
+    <string name="slice_permission_allow" msgid="6340449521277951123">"अनुमति दें"</string>
+    <string name="slice_permission_deny" msgid="6870256451658176895">"अनुमति न दें"</string>
     <string name="auto_saver_title" msgid="6873691178754086596">"बैटरी सेवर शेड्यूल करने के लिए टैप करें"</string>
     <string name="auto_saver_text" msgid="3214960308353838764">"जब बैटरी खत्म होने वाली हो तब \'बैटरी सेवर\' चालू करें"</string>
     <string name="no_auto_saver_action" msgid="7467924389609773835">"जी नहीं, शुक्रिया"</string>
@@ -971,16 +983,15 @@
     <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" और "</string>
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>, <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> का इस्तेमाल कर रहा है"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ने हाल ही में <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> का इस्तेमाल किया"</string>
-    <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"एंटरप्राइज़ वर्शन"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Phonecall"</string>
-    <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"<xliff:g id="ATTRIBUTION">%s</xliff:g> के ज़रिए"</string>
+    <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(एंटरप्राइज़ वर्शन)"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"फ़ोन कॉल"</string>
+    <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> के ज़रिए)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"कैमरा"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"जगह"</string>
     <string name="privacy_type_microphone" msgid="9136763906797732428">"माइक्रोफ़ोन"</string>
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"सेंसर बंद हैं"</string>
     <string name="device_services" msgid="1549944177856658705">"डिवाइस सेवाएं"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"कोई शीर्षक नहीं"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"इस ऐप्लिकेशन को रीस्टार्ट करने और फ़ुल स्क्रीन चालू करने के लिए टैप करें."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"ले जाएं"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"सिस्टम नेविगेशन अपडेट हो गया. बदलाव करने के लिए \'सेटिंग\' पर जाएं."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"सिस्टम नेविगेशन अपडेट करने के लिए \'सेटिंग\' में जाएं"</string>
@@ -1034,6 +1045,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"जोड़ें"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> से मिला सुझाव"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"कंट्रोल अपडेट किए गए"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"डिवाइस लॉक है"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"पिन में अक्षर या चिह्न शामिल होते हैं"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> की पुष्टि करें"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"गलत पिन"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index c80f262..d8064ab 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Pomicanje snimke zaslona"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Odbacivanje snimke zaslona"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Pregled snimke zaslona"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Gornja granica"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Donja granica"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Snimač zaslona"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrada snimanja zaslona"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Tekuća obavijest za sesiju snimanja zaslona"</string>
@@ -412,6 +414,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do izlaska sunca"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Uključuje se u <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je onemogućen"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je omogućen"</string>
@@ -445,6 +449,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Otključajte da biste upotrijebili NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada vašoj organizaciji"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Prijeđite prstom od ikone za telefon"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Prijeđite prstom od ikone za glasovnu pomoć"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Prijeđite prstom od ikone za fotoaparat"</string>
@@ -465,9 +471,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Prikaz profila"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Dodavanje korisnika"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Novi korisnik"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Završiti gostujuću sesiju?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Završi gostujuću sesiju"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Ukloniti gosta?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Sve aplikacije i podaci u ovoj sesiji bit će izbrisani."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Završi sesiju"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Ukloni"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Dobro došli natrag, gostu!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Želite li nastaviti sesiju?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Počni ispočetka"</string>
@@ -543,6 +550,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Vaša je organizacija instalirala izdavač certifikata na vašem radnom profilu. Vaš sigurni mrežni promet možda se nadzire ili modificira."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Na ovom je uređaju instaliran izdavač certifikata. Vaš sigurni mrežni promet možda se nadzire ili modificira."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Administrator je uključio mrežni zapisnik koji nadzire promet na vašem uređaju."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Administrator je uključio mrežni zapisnik koji prati promet na vašem poslovnom profilu, ali ne i na osobnom profilu."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Povezani ste s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g> koja može nadzirati vašu aktivnost na mreži, uključujući e-poštu, aplikacije i web-lokacije."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Povezani ste s aplikacijama <xliff:g id="VPN_APP_0">%1$s</xliff:g> i <xliff:g id="VPN_APP_1">%2$s</xliff:g> koje mogu nadzirati vašu aktivnost na mreži, uključujući e-poruke, aplikacije i web-lokacije."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Vaš je radni profil povezan s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g> koja može nadzirati vašu aktivnost na mreži, uključujući e-poruke, aplikacije i web-lokacije."</string>
@@ -623,6 +631,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Dodirnite da biste isključili zvuk. Usluge pristupačnosti možda neće imati zvuk."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Dodirnite da biste postavili na vibraciju."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Dodirnite da biste isključili zvuk."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"isključivanje zvuka"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"uključivanje zvuka"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibriranje"</string>
@@ -736,7 +746,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Sustav je ovu obavijest automatski &lt;b&gt;prebacio u bešumnu&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Ova obavijest automatski je &lt;b&gt;rangirana više&lt;/b&gt; na vašem zaslonu."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Ova obavijest automatski je &lt;b&gt;rangirana niže&lt;/b&gt; na vašem zaslonu."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Je li to bilo točno?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Recite razvojnom programeru što mislite. Je li to bilo točno?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Zahvaljujemo na povratnim informacijama!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"U redu"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Otvorene su kontrole obavijesti za <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -885,6 +895,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Premještanje u prostoriju <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Dodavanje na položaj <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Položaj <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Kartica je dodana"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Kartica je uklonjena"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Uređivač brzih postavki."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> obavijest: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Otvaranje postavki."</string>
@@ -975,7 +987,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Aplikacija <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> koristi sljedeće: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Aplikacija <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> nedavno je koristila sljedeće: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(za poslovne korisnike)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonski poziv"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefonski poziv"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(putem aplikacije <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"fotoaparat"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"lokaciju"</string>
@@ -983,7 +995,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Senzori su isključeni"</string>
     <string name="device_services" msgid="1549944177856658705">"Usluge uređaja"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Bez naslova"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Dodirnite da biste ponovo pokrenuli tu aplikaciju i prikazali je na cijelom zaslonu."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Premjesti"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Ažurirana je navigacija sustavom. Možete je promijeniti u Postavkama."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Navigaciju sustavom možete ažurirati u Postavkama"</string>
@@ -1038,6 +1049,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Dodaj"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Preporuka s kanala <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Kontrole su ažurirane"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Uređaj je zaključan"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN sadrži slova ili simbole"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Potvrdite uređaj <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Pogrešan PIN"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 868b2e7..a736f88 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Görgethető képernyőkép"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Képernyőkép elvetése"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Képernyőkép előnézete"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Felső határ"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Alsó határ"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Képernyőrögzítő"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Képernyőrögzítés feldolgozása"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Folyamatban lévő értesítés képernyőrögzítési munkamenethez"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Napfelkeltéig"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Be: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Eddig: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Az NFC ki van kapcsolva"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Az NFC be van kapcsolva"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Az NFC használatához oldja fel a képernyőzárat"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Ez az eszköz az Ön szervezetének tulajdonában van"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Ez az eszköz a(z) <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> tulajdonában van"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"A telefonhoz csúsztasson az ikonról"</string>
     <string name="voice_hint" msgid="7476017460191291417">"A hangsegéd eléréséhez csúsztassa ujját az ikonról"</string>
     <string name="camera_hint" msgid="4519495795000658637">"A fényképezőhöz csúsztasson az ikonról"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Profil megjelenítése"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Felhasználó hozzáadása"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Új felhasználó"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Befejezi a vendég munkamenetet?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"A vendég munkamenet befejezése"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Eltávolítja a vendég munkamenetet?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"A munkamenetben található összes alkalmazás és adat törlődni fog."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Munkamenet befejezése"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Eltávolítás"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Örülünk, hogy visszatért, vendég!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Folytatja a munkamenetet?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Újrakezdés"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Szervezete tanúsítványkibocsátót telepített a munkaprofilba. Ezáltal figyelhetik és befolyásolhatják az Ön biztonságos hálózati forgalmát."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Az eszközre tanúsítványkibocsátó van telepítve. Ezáltal figyelhetik és befolyásolhatják az Ön biztonságos hálózati forgalmát."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"A rendszergazda bekapcsolta az eszköz forgalmát figyelő hálózati naplózást."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"A rendszergazda bekapcsolta a hálózati naplózást, amely a munkaprofilban figyeli a forgalmat, a személyes profilban azonban nem."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Ön kapcsolódik a(z) <xliff:g id="VPN_APP">%1$s</xliff:g> alkalmazáshoz, amely figyelheti hálózati tevékenységét, beleértve a levelezést, valamint az alkalmazás- és webhelyhasználatot."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Ön csatlakozik a(z) <xliff:g id="VPN_APP_0">%1$s</xliff:g> és a(z) <xliff:g id="VPN_APP_1">%2$s</xliff:g> alkalmazásokhoz, amelyek figyelhetik hálózati tevékenységét, beleértve a levelezést, valamint az alkalmazás- és webhelyhasználatot."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Munkaprofilja csatlakozik a(z) <xliff:g id="VPN_APP">%1$s</xliff:g> alkalmazáshoz, amely figyelheti hálózati tevékenységét, beleértve a levelezést, az alkalmazásokat és a webhelyeket."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Koppintson a némításhoz. Előfordulhat, hogy a kisegítő lehetőségek szolgáltatásai le vannak némítva."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Koppintson a rezgés beállításához."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Koppintson a némításhoz."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"némítás"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"némítás feloldása"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"rezgés"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Ezt az értesítést automatikusan &lt;b&gt;némára állította&lt;/b&gt; a rendszer."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Ezt az értesítést automatikusan &lt;b&gt;előrébb sorolta&lt;/b&gt; a rendszer az értesítési felületen."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Ezt az értesítést automatikusan &lt;b&gt;hátrébb sorolta&lt;/b&gt; a rendszer az értesítési felületen."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Megfelelő ez így?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Ossza meg a fejlesztővel a visszajelzését. Megfelelő ez így?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Köszönjük a visszajelzést!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> értesítésvezérlői megnyitva"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Áthelyezés ide: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Hozzáadás a következő pozícióhoz: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g>. hely"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Kártya hozzáadva"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Kártya eltávolítva"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Gyorsbeállítások szerkesztője"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>-értesítések: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Beállítások megnyitása."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"A(z) <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> használja a következőt: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"A(z) <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> nemrég használta a következőt: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(vállalati)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonhívás"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefonhívás"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(a következőn keresztül: <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"helyadatok"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Érzékelők kikapcsolva"</string>
     <string name="device_services" msgid="1549944177856658705">"Eszközszolgáltatások"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Nincs cím"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Koppintson az alkalmazás újraindításához és a teljes képernyős mód elindításához."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Áthelyezés"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"A rendszer-navigáció módja megváltozott. Módosításához nyissa meg a Beállításokat."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"A rendszer-navigációs lehetőségeket a Beállításokban módosíthatja"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Hozzáadás"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> javasolta"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Vezérlők frissítve"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Az eszköz zárolva van"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"A PIN-kód betűket vagy szimbólumokat tartalmaz"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> ellenőrzése"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Helytelen PIN-kód"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 3c08874..40ddf54 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Ոլորել սքրինշոթը"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Փակել սքրինշոթը"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Սքրինշոթի նախադիտում"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Վերևի սահմանագիծ"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Ներքևի սահմանագիծ"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Էկրանի տեսագրիչ"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Էկրանի տեսագրության մշակում"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Էկրանի տեսագրման աշխատաշրջանի ընթացիկ ծանուցում"</string>
@@ -410,6 +412,7 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Մինչև լուսաբաց"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Կմիանա՝ <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Մինչև <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Պայծառության նվազեցում"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC-ն անջատված է"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC-ն միացված է"</string>
@@ -443,6 +446,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ապակողպեք՝ NFC-ն օգտագործելու համար"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Այս սարքը պատկանում է ձեր կազմակերպությանը"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Այս սարքը պատկանում է «<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>» կազմակերպությանը"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Սահահարվածեք հեռախոսի պատկերակից"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Սահահարվածեք ձայնային հուշման պատկերակից"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Սահահարվածեք խցիկի պատկերակից"</string>
@@ -463,9 +468,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Ցույց տալ դիտարկումը"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Ավելացնել օգտատեր"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Նոր օգտատեր"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Ավարտե՞լ հյուրի աշխատաշրջանը"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Ավարտել հյուրի աշխատաշրջանը"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Հեռացնե՞լ հյուրին:"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Այս աշխատաշրջանի բոլոր ծրագրերն ու տվյալները կջնջվեն:"</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Ավարտել աշխատաշրջանը"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Հեռացնել"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Բարի վերադարձ, հյուր:"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Դուք ցանկանու՞մ եք շարունակել ձեր գործողությունը:"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Սկսել"</string>
@@ -540,6 +546,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Ձեր կազմակերպությունը ձեր աշխատանքային պրոֆիլում տեղադրել է վկայագրման կենտրոն։ Ձեր ցանցի ապահով թրաֆիկը կարող է վերահսկվել կամ փոփոխվել։"</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Այս սարքում տեղադրված է վկայագրման կենտրոն։ Ձեր ցանցի ապահով թրաֆիկը կարող է վերահսկվել կամ փոփոխվել։"</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Ձեր ադմինիստրատորը միացրել է ցանցային իրադարձությունների գրանցումը, որը վերահսկում է ձեր սարքի թրաֆիկը։"</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Ձեր ադմինիստրատորը միացրել է ցանցային իրադարձությունների գրանցումը, որը վերահսկում է ձեր աշխատանքային պրոֆիլի թրաֆիկը (այլ ոչ անձնական պրոֆիլը)։"</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Դուք կապակցված եք <xliff:g id="VPN_APP">%1$s</xliff:g> հավելվածին, որը կարող է վերահսկել ձեր ցանցային գործողությունը, այդ թվում նաև էլփոստը, հավելվածները և կայքերը:"</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Դուք կապակցված եք <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="368812367182387320">"Ձեր աշխատանքային պրոֆիլը կապակցված է <xliff:g id="VPN_APP">%1$s</xliff:g> հավելվածին, որը կարող է վերահսկել ձեր ցանցային գործունեությունը, այդ թվում նաև էլփոստը, հավելվածները և կայքերը:"</string>
@@ -620,6 +627,7 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s: Հպեք՝ ձայնն անջատելու համար: Մատչելիության ծառայությունների ձայնը կարող է անջատվել:"</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s։ Հպեք՝ թրթռոցը միացնելու համար։"</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s։ Հպեք՝ ձայնը անջատելու համար։"</string>
+    <string name="volume_ringer_change" msgid="3574969197796055532">"Հպեք՝ զանգակի ռեժիմը փոխելու համար"</string>
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"անջատել ձայնը"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"միացնել ձայնը"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"միացնել թրթռոցը"</string>
@@ -733,7 +741,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Այս ծանուցման կարևորության մակարդակը ավտոմատ &lt;b&gt;իջեցվել է և դարձել անձայն&lt;/b&gt;։"</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Ծանուցումների վահանակում այս ծանուցուման կարևորության մակարդակն ավտոմատ &lt;b&gt;բարձրացվել է&lt;/b&gt;։"</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Ծանուցումների վահանակում այս ծանուցուման կարևորության մակարդակն ավտոմատ &lt;b&gt;իջեցվել է&lt;/b&gt;։"</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Սա ճի՞շտ էր"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Ուղարկեք ձեր կարծիքը մշակողին։ Սա ճի՞շտ էր։"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Շնորհակալություն արձագանքելու համար"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Եղավ"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի ծանուցումների կառավարումը բաց է"</string>
@@ -880,6 +888,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Տեղափոխել դիրք <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Ավելացնել դիրք <xliff:g id="POSITION">%1$d</xliff:g>-ում"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Դիրք <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Սալիկն ավելացվեց"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Սալիկը հեռացվեց"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Արագ կարգավորումների խմբագրիչ:"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> ծանուցում՝ <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Բացել կարգավորումները:"</string>
@@ -970,7 +980,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> հավելվածն օգտագործում է «<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>» գործառույթը"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> հավելվածը վերջերս օգտագործել է «<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>» գործառույթը"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(կորպորատիվ տարբերակ)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Հեռախոսազանգ"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Հեռախոսազանգ"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g>-ի միջոցով)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"տեսախցիկը"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"վայրը"</string>
@@ -978,7 +988,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Տվիչներն անջատած են"</string>
     <string name="device_services" msgid="1549944177856658705">"Սարքի ծառայություններ"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Անանուն"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Հպեք՝ հավելվածը վերագործարկելու և լիաէկրան ռեժիմին անցնելու համար։"</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Տեղափոխել"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Համակարգի նավիգացիան թարմացվեց: Փոփոխություններ անելու համար անցեք կարգավորումներ:"</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Թարմացրեք համակարգի նավիգացիան կարգավորումներում"</string>
@@ -1032,6 +1041,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Ավելացնել"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Առաջարկվել է <xliff:g id="APP">%s</xliff:g> հավելվածի կողմից"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Կառավարման տարրերը թարմացվեցին"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Սարքը կողպված է"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN կոդը տառեր և նշաններ է պարունակում"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Ստուգել <xliff:g id="DEVICE">%s</xliff:g> սարքը"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN կոդը սխալ է"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index a5d8a27..e20dd51 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Men-scroll screenshot"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Menutup screenshot"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Pratinjau screenshot"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Batas atas"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Batas bawah"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Perekam Layar"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Memproses perekaman layar"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notifikasi yang sedang berjalan untuk sesi rekaman layar"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Sampai pagi"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aktif pada <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Sampai <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC dinonaktifkan"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC diaktifkan"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Buka kunci untuk menggunakan NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Perangkat ini milik organisasi Anda"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Perangkat ini milik <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Geser dari ikon untuk telepon"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Geser dari ikon untuk bantuan suara"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Geser dari ikon untuk kamera"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Tampilkan profil"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Tambahkan pengguna"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Pengguna baru"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Akhiri sesi tamu?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Akhiri sesi tamu"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Hapus tamu?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Semua aplikasi dan data di sesi ini akan dihapus."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Akhiri sesi"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Hapus"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Selamat datang kembali, tamu!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Lanjutkan sesi Anda?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Mulai ulang"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Organisasi Anda menginstal otoritas sertifikat di profil kerja. Traffic jaringan aman Anda mungkin dipantau atau diubah."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Otoritas sertifikat diinstal di perangkat. Traffic jaringan aman Anda mungkin dipantau atau diubah."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Admin telah mengaktifkan pencatatan jaringan, yang memantau traffic di perangkat."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Admin telah mengaktifkan logging jaringan, yang memantau traffic di profil kerja, tetapi tidak di profil pribadi."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Anda tersambung ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Anda tersambung ke <xliff:g id="VPN_APP_0">%1$s</xliff:g> dan <xliff:g id="VPN_APP_1">%2$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Profil kerja Anda tersambung ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Ketuk untuk membisukan. Layanan aksesibilitas mungkin dibisukan."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Ketuk untuk menyetel agar bergetar."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Ketuk untuk menonaktifkan."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"Tanpa suara"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"aktifkan"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"getar"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Notifikasi ini otomatis &lt;b&gt;didemosikan menjadi Senyap&lt;/b&gt; oleh sistem."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Notifikasi ini otomatis &lt;b&gt;diberi peringkat lebih tinggi&lt;/b&gt; di shade Anda."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Notifikasi ini otomatis &lt;b&gt;diberi peringkat lebih rendah&lt;/b&gt; di shade Anda."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Sudah benar?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Berikan masukan kepada developer. Sudah benar?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Terima kasih atas masukan Anda"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Oke"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Kontrol notifikasi untuk <xliff:g id="APP_NAME">%1$s</xliff:g> dibuka"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Pindahkan ke <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Tambahkan ke posisi <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posisi <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Kartu ditambahkan"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Kartu dihapus"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor setelan cepat."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notifikasi <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Buka setelan."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> sedang menggunakan <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> menggunakan <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> baru-baru ini"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(perusahaan)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Panggilan telepon"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Panggilan telepon"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(melalui <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"lokasi"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensor nonaktif"</string>
     <string name="device_services" msgid="1549944177856658705">"Layanan Perangkat"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Tanpa judul"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Ketuk untuk memulai ulang aplikasi ini dan membuka layar penuh."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Pindahkan"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigasi sistem diupdate. Untuk melakukan perubahan, buka Setelan."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Buka Setelan untuk mengupdate navigasi sistem"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Tambahkan"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Disarankan oleh <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Kontrol diperbarui"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Perangkat terkunci"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN berisi huruf atau simbol"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Verifikasi <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN salah"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 5f794e7..0c99420 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Flettiskjáskot"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Loka skjámynd"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Forskoðun skjámyndar"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Efri mörk"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Neðri mörk"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Skjáupptaka"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Vinnur úr skjáupptöku"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Áframhaldandi tilkynning fyrir skjáupptökulotu"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Til sólarupprásar"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Virkt kl. <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Til <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Slökkt á NFC"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Kveikt á NFC"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Taktu úr lás til að nota NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Þetta tæki tilheyrir fyrirtækinu þínu"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Þetta tæki tilheyrir <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Strjúktu frá tákninu fyrir síma"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Strjúktu frá tákninu fyrir raddaðstoð"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Strjúktu frá tákninu fyrir myndavél"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Sýna snið"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Bæta notanda við"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Nýr notandi"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Ljúka gestalotu?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Ljúka gestalotu"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Fjarlægja gest?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Öllum forritum og gögnum í þessari lotu verður eytt."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Ljúka lotu"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Fjarlægja"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Velkominn aftur, gestur!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Viltu halda áfram með lotuna?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Byrja upp á nýtt"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Fyrirtækið þitt setti upp CA-vottorð á vinnusniðinu þínu. Eftirlit kann að vera haft með öruggri netnotkun þinni eða henni kann að vera breytt."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"CA-vottorð er uppsett á þessu tæki. Eftirlit kann að vera haft með öruggri netnotkun þinni eða henni kann að vera breytt."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Kerfisstjóri hefur kveikt á eftirliti netkerfa, sem fylgist með netumferð á tækinu þínu."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Stjórnandinn kveikti á eftirliti netkerfa sem fylgist með netumferð á vinnusniðinu þínu en ekki á eigin sniði."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Þú ert með tengingu við <xliff:g id="VPN_APP">%1$s</xliff:g>, sem getur fylgst með netnotkun þinni, þ. á m. tölvupósti, forritum og vefsvæðum."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Þú ert með tengingu við <xliff:g id="VPN_APP_0">%1$s</xliff:g> og <xliff:g id="VPN_APP_1">%2$s</xliff:g>, sem geta fylgst með netnotkun þinni, þar á meðal tölvupósti, forritum og vefsvæðum."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Vinnusniðið þitt er tengt <xliff:g id="VPN_APP">%1$s</xliff:g>, sem getur fylgst með netnotkun þinni, þ. á m. tölvupósti, forritum og vefsvæðum."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Ýttu til að þagga. Hugsanlega verður slökkt á hljóði aðgengisþjónustu."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Ýttu til að stilla á titring."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Ýttu til að þagga."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"þagga"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"hætta að þagga"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"titringur"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Stig þessarar tilkynningar var sjálfkrafa &lt;b&gt;lækkað í þögult&lt;/b&gt; af kerfinu."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Stig þessarar tilkynningar var sjálfkrafa &lt;b&gt;hækkað&lt;/b&gt; í tilkynningaglugganum þínum."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Stig þessarar tilkynningar var sjálfkrafa &lt;b&gt;lækkað&lt;/b&gt; í tilkynningaglugganum þínum."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Var þetta rétt?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Sendu framleiðandanum ábendingu. Var þetta rétt?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Takk fyrir að segja þína skoðun!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Í lagi"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Opnað fyrir tilkynningastýringar <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Færa í <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Bæta við í stöðu <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Staða <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Reit bætt við"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Reitur fjarlægður"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Flýtistillingaritill."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> tilkynning: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Opna stillingar."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> er að nota <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> notaði <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> nýlega"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(fyrirtæki)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Símtal"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Símtal"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(í gegnum <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"myndavél"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"staðsetning"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Slökkt á skynjurum"</string>
     <string name="device_services" msgid="1549944177856658705">"Tækjaþjónusta"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Enginn titill"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Ýttu til að endurræsa forritið og sýna það á öllum skjánum."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Færa"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Kerfisstjórnun uppfærð. Þú getur breytt þessu í stillingunum."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Farðu í stillingar til að uppfæra kerfisstjórnun"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Bæta við"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Tillaga frá <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Stýringar uppfærðar"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Tækið er læst"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN inniheldur bókstafi eða tákn"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Staðfesta <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Rangt PIN-númer"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index cfd0797..527a695 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Scorri screenshot"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ignora screenshot"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Anteprima screenshot"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Limite superiore"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Limite inferiore"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Registrazione dello schermo"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Elaboraz. registraz. schermo"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notifica costante per una sessione di registrazione dello schermo"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Fino all\'alba"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Attivazione alle <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Fino alle <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC non attiva"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC attiva"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Sblocca per usare NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Questo dispositivo appartiene alla tua organizzazione"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Questo dispositivo appartiene a <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Scorri per accedere al telefono"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Scorri dall\'icona per accedere a Voice Assist"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Scorri dall\'icona per accedere alla fotocamera"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Mostra profilo"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Aggiungi utente"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Nuovo utente"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Vuoi terminare la sessione Ospite?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Termina sessione Ospite"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Rimuovere l\'ospite?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tutte le app e i dati di questa sessione verranno eliminati."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Termina sessione"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Rimuovi"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Bentornato, ospite."</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Vuoi continuare la sessione?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Ricomincia"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"La tua organizzazione ha installato un\'autorità di certificazione nel tuo profilo di lavoro. Il tuo traffico di rete protetto potrebbe essere monitorato o modificato."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Sul dispositivo è installata un\'autorità di certificazione. Il tuo traffico di rete protetto potrebbe essere monitorato o modificato."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"L\'amministratore ha attivato i log di rete, che consentono di monitorare il traffico sul dispositivo."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"L\'amministratore ha attivato i log di rete, che consentono di monitorare il traffico nel profilo di lavoro, ma non nel profilo personale."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Sei connesso a <xliff:g id="VPN_APP">%1$s</xliff:g>, che consente di monitorare le attività di rete, inclusi siti web, email e app."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Sei connesso a <xliff:g id="VPN_APP_0">%1$s</xliff:g> e <xliff:g id="VPN_APP_1">%2$s</xliff:g>, che consentono di monitorare le attività di rete, inclusi siti web, email e app."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Il tuo profilo di lavoro è collegato a <xliff:g id="VPN_APP">%1$s</xliff:g>, da cui è possibile monitorare la tua attività di rete, inclusi siti web, email e app."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Tocca per disattivare l\'audio. L\'audio dei servizi di accessibilità può essere disattivato."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Tocca per attivare la vibrazione."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Tocca per disattivare l\'audio."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"disattiva l\'audio"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"riattiva l\'audio"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrazione"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Questa notifica è stata &lt;b&gt;retrocessa automaticamente a Silenziosa&lt;/b&gt; dal sistema."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Questa notifica è stata &lt;b&gt;posizionata automaticamente più in alto&lt;/b&gt; nell\'area notifiche."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Questa notifica è stata &lt;b&gt;posizionata automaticamente più in basso&lt;/b&gt; nell\'area notifiche."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Era corretto?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Fai conoscere la tua opinione allo sviluppatore. La classificazione era corretta?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Grazie per il feedback."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Controlli di gestione delle notifiche per <xliff:g id="APP_NAME">%1$s</xliff:g> aperti"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Sposta nella posizione <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Aggiungi alla posizione <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posizione <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Riquadro aggiunto"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Riquadro rimosso"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor di impostazioni rapide."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notifica di <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Apri le impostazioni."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> sta usando: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ha usato di recente: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(enterprise)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Phonecall"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefonata"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(tramite <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"Fotocamera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"luogo"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensori disattivati"</string>
     <string name="device_services" msgid="1549944177856658705">"Servizi del dispositivo"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Senza titolo"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Tocca per riavviare l\'app e passare a schermo intero."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Sposta"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigazione del sistema aggiornata. Per apportare modifiche, usa le Impostazioni."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Usa le Impostazioni per aggiornare la navigazione del sistema"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Aggiungi"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Suggerito da <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Controlli aggiornati"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Dispositivo bloccato"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Il PIN contiene lettere o simboli"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Verifica <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN errato"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index c4d088d..9fc8b23 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"צילום מסך נגלל"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"סגירת צילום מסך"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"תצוגה מקדימה של צילום מסך"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"הקצה העליון"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"הקצה התחתון"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"מקליט המסך"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"מתבצע עיבוד של הקלטת מסך"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"התראה מתמשכת לסשן הקלטת מסך"</string>
@@ -414,6 +416,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"עד הזריחה"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"יתחיל בשעה <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"עד <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"‏NFC מושבת"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"‏NFC מופעל"</string>
@@ -444,9 +448,11 @@
     <string name="notification_tap_again" msgid="4477318164947497249">"הקש שוב כדי לפתוח"</string>
     <string name="keyguard_unlock" msgid="8031975796351361601">"צריך להחליק כדי לפתוח"</string>
     <string name="keyguard_retry" msgid="886802522584053523">"יש להחליק למעלה כדי לנסות שוב"</string>
-    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"‏יש לבטל נעילה כדי להשתמש ב-NFC"</string>
+    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"‏יש לבטל את הנעילה כדי להשתמש ב-NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"המכשיר הזה שייך לארגון שלך"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"המכשיר הזה שייך לארגון <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"החלק מהסמל כדי להפעיל את הטלפון"</string>
     <string name="voice_hint" msgid="7476017460191291417">"החלק מהסמל כדי להפעיל את המסייע הקולי"</string>
     <string name="camera_hint" msgid="4519495795000658637">"החלק מהסמל כדי להפעיל את המצלמה"</string>
@@ -467,9 +473,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"הצג פרופיל"</string>
     <string name="user_add_user" msgid="4336657383006913022">"הוספת משתמש"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"משתמש חדש"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"להפסיק את הגלישה כאורח?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"הפסקת הגלישה כאורח"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"להסיר אורח?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"כל האפליקציות והנתונים בפעילות זו באתר יימחקו."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"הפסקת הגלישה"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"הסר"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"שמחים לראותך שוב!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"האם ברצונך להמשיך בפעילות באתר?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ברצוני להתחיל מחדש"</string>
@@ -546,6 +553,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"הארגון שלך התקין רשות אישורים בפרופיל העבודה. ניתן לעקוב אחר התנועה ברשת המאובטחת או לשנות אותה."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"במכשיר זה מותקנת רשות אישורים. ניתן לעקוב אחר התנועה ברשת המאובטחת או לשנות אותה."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"מנהל המערכת הפעיל את התכונה \'רישום התנועה ברשת\', שמנטרת את תנועת הנתונים במכשיר."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"מנהל המערכת הפעיל את תכונת רישום התנועה ברשת, שמנטרת את תנועת הנתונים בפרופיל העבודה, אבל לא בפרופיל האישי."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"אתה מחובר לאפליקציה <xliff:g id="VPN_APP">%1$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת, כולל הודעות אימייל, אפליקציות ואתרים."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"אתה מחובר לאפליקציות <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="368812367182387320">"פרופיל העבודה שלך מחובר לאפליקציה <xliff:g id="VPN_APP">%1$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת, כולל הודעות אימייל, אפליקציות ואתרים."</string>
@@ -626,6 +634,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"‏%1$s. הקש כדי להשתיק. ייתכן ששירותי הנגישות מושתקים."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"‏%1$s. הקש כדי להעביר למצב רטט."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"‏%1$s. הקש כדי להשתיק."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"השתקה"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"ביטול ההשתקה"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"רטט"</string>
@@ -739,7 +749,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"‏ההתראה הזו &lt;b&gt;הורדה בדרגה ל\'שקט\'&lt;/b&gt; באופן אוטומטי על-ידי המערכת."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"‏ההתראה הזו &lt;b&gt;דורגה גבוה יותר&lt;/b&gt; באופן אוטומטי בהתראות שלך."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"‏ההתראה הזו &lt;b&gt;דורגה נמוך יותר&lt;/b&amp;gt באופן אוטומטי בהתראות שלך."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"האם פעולה זו הייתה נכונה?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"אפשר לשלוח למפתח את המשוב שלך. האם פעולה זו הייתה נכונה?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"תודה על המשוב!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"אישור"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"פקדי ההודעות של <xliff:g id="APP_NAME">%1$s</xliff:g> נפתחו"</string>
@@ -890,6 +900,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"העברה למיקום <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"הוספה למיקום <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"מיקום <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"האריח נוסף"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"האריח הוסר"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"עורך הגדרות מהירות."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"התראות <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"פתיחת הגדרות."</string>
@@ -977,23 +989,17 @@
     <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"אפליקציות משתמשות ב<xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
     <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
     <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" וגם "</string>
-    <!-- no translation found for ongoing_privacy_dialog_using_op (4125175620929701569) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_recent_op (4255923947334262404) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_enterprise (4082735415905550729) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_phonecall (3526223335298089311) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_attribution_text (9186683306719924646) -->
-    <skip />
+    <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"האפליקציה <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> משתמשת ב<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"האפליקציה <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> השתמשה לאחרונה ב<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(גרסה ארגונית)"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"שיחת טלפון"</string>
+    <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(באמצעות <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"מצלמה"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"מיקום"</string>
     <string name="privacy_type_microphone" msgid="9136763906797732428">"מיקרופון"</string>
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"החיישנים כבויים"</string>
     <string name="device_services" msgid="1549944177856658705">"שירותים למכשיר"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"ללא שם"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"צריך להקיש כדי להפעיל מחדש את האפליקציה הזו ולעבור למסך מלא."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"העברה"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"הניווט במערכת עודכן. אפשר לערוך שינויים דרך ההגדרות."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"יש לעבור להגדרות כדי לעדכן את הניווט במערכת"</string>
@@ -1049,6 +1055,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"הוספה"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"הוצע על-ידי <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"הפקדים עודכנו"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"המכשיר נעול"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"קוד האימות מכיל אותיות או סמלים"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"אימות <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"קוד גישה שגוי"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 3fcc713..1b18b5c 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"スクリーンショットをスクロールします"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"スクリーンショットを閉じます"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"スクリーンショットのプレビュー"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"上部境界"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"下部境界"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"スクリーン レコーダー"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"画面の録画を処理しています"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"画面の録画セッション中の通知"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"日の出まで"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>にオン"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g>まで"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC は無効です"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC は有効です"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC を使用するには、ロックを解除してください"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"これは組織が所有するデバイスです"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"これは <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> が所有するデバイスです"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"右にスワイプして通話"</string>
     <string name="voice_hint" msgid="7476017460191291417">"アイコンからスワイプして音声アシストを起動"</string>
     <string name="camera_hint" msgid="4519495795000658637">"左にスワイプしてカメラを起動"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"プロファイルを表示"</string>
     <string name="user_add_user" msgid="4336657383006913022">"ユーザーを追加"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"新しいユーザー"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"ゲスト セッションを終了しますか?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"ゲスト セッションを終了する"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"ゲストを削除しますか?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"このセッションでのアプリとデータはすべて削除されます。"</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"セッションを終了"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"削除"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"おかえりなさい、ゲストさん"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"セッションを続行しますか?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"最初から開始"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"組織によって、あなたの仕事用プロファイルに認証局がインストールされました。保護されたネットワーク トラフィックが監視、変更される場合があります。"</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"このデバイスには認証局がインストールされています。保護されたネットワーク トラフィックが監視、変更される可能性があります。"</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"管理者がネットワーク ログを有効にしているため、このデバイスのトラフィックが監視されています。"</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"管理者がネットワーク ログを有効にしているため、仕事用プロファイルのトラフィックは監視されています(個人用プロファイルは対象外)。"</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"<xliff:g id="VPN_APP">%1$s</xliff:g> に接続しています。このアプリはあなたのネットワーク アクティビティ(メール、アプリ、ウェブサイトなど)を監視できます。"</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"<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="368812367182387320">"この仕事用プロファイルは <xliff:g id="VPN_APP">%1$s</xliff:g> に接続しています。このアプリはあなたのネットワーク アクティビティ(メール、アプリ、ウェブサイトなど)を監視できます。"</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s。タップしてミュートします。ユーザー補助機能サービスがミュートされる場合があります。"</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s。タップしてバイブレーションに設定します。"</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s。タップしてミュートします。"</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"ミュート"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"ミュートを解除"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"バイブレーション"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"この通知は、システムによって自動的に&lt;b&gt;ランクがサイレントに下がり&lt;/b&gt;ました。"</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"この通知は、自動的にシェード内の&lt;b&gt;ランクが上がり&lt;/b&gt;ました。"</string>
     <string name="feedback_demoted" msgid="951884763467110604">"この通知は、自動的にシェード内の&lt;b&gt;ランクが下がり&lt;/b&gt;ました。"</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"間違いありませんか?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"皆様のご意見がデベロッパーに届きます。これで間違いありませんか?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"フィードバックをお寄せいただきありがとうございます。"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> の通知管理は開いています"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> に移動"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"ポジション <xliff:g id="POSITION">%1$d</xliff:g> に追加"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"位置: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"タイルを追加しました"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"タイルを削除しました"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"クイック設定エディタ"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> の通知: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"設定を開きます。"</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> は <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> を使用しています"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> は最近 <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> を使用しました"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(エンタープライズ版)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"電話"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"通話"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> 経由)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"カメラ"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"現在地情報"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"センサー OFF"</string>
     <string name="device_services" msgid="1549944177856658705">"デバイス サービス"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"タイトルなし"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"タップしてこのアプリを再起動すると、全画面表示になります。"</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"移動"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"システム ナビゲーションを更新しました。変更するには [設定] に移動してください。"</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"システム ナビゲーションを更新するには [設定] に移動してください"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"追加"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> によるおすすめ"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"コントロールを更新しました"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"デバイス: ロック状態"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN に英字や記号を含める"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g>の確認"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN が間違っています"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 5c11fa4..e2b9fac 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"ეკრანის ანაბეჭდში გადაადგილება"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ეკრანის ანაბეჭდის დახურვა"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ეკრანის ანაბეჭდის გადახედვა"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"ზედა საზღვარი"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"ქვედა საზღვარი"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"ეკრანის ჩამწერი"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ეკრანის ჩანაწერი მუშავდება"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"უწყვეტი შეტყობინება ეკრანის ჩაწერის სესიისთვის"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"მზის ამოსვლამდე"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"ჩაირთოს <xliff:g id="TIME">%s</xliff:g>-ზე"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g>-მდე"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC გათიშულია"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ჩართულია"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"განბლოკეთ NFC-ის გამოსაყენებლად"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"ამ მოწყობილობას ფლობს თქვენი ორგანიზაცია"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"ამ მოწყობილობას ფლობს <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"ტელეფონისთვის გადაფურცლეთ ხატულადან"</string>
     <string name="voice_hint" msgid="7476017460191291417">"ხმოვანი დახმარებისთვის გადაფურცლეთ ხატულადან"</string>
     <string name="camera_hint" msgid="4519495795000658637">"კამერისთვის გადაფურცლეთ ხატულადან"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"პროფილის ჩვენება"</string>
     <string name="user_add_user" msgid="4336657383006913022">"მომხმარებლის დამატება"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"ახალი მომხმარებელი"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"დასრულდეს სტუმრის სესია?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"სტუმრის სესიის დასრულება"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"სტუმრის ამოშლა?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ამ სესიის ყველა აპი და მონაცემი წაიშლება."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"სესიის დასრულება"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"ამოშლა"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"სტუმარო, გვიხარია, რომ დაბრუნდით!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"გსურთ, თქვენი სესიის გაგრძელება?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ხელახლა დაწყება"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"თქვენმა ორგანიზაციამ სამსახურის პროფილში სერტიფიცირების ორგანო დააინსტალირა. თქვენი ქსელის დაცული ტრაფიკი შეიძლება შეიცვალოს, ან მასზე მონიტორინგი განხორციელდეს."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"ამ მოწყობილობაზე დაინსტალირებულია სერტიფიცირების ორგანო. თქვენი ქსელის დაცული ტრაფიკი შეიძლება შეიცვალოს, ან მასზე მონიტორინგი განხორციელდეს."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"თქვენმა ადმინისტრატორმა ჩართო ქსელის ჟურნალირება, რომელიც თქვენი მოწყობილობის ტრაფიკის მონიტორინგს ახორციელებს."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"თქვენმა ადმინისტრატორმა ქსელის ჟურნალირება ჩართო, რომელიც ახორციელებს თქვენი სამსახურის პროფილის, მაგრამ არა პირადი პროფილის, ტრაფიკის მონიტორინგს."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"თქვენ დაკავშირებული ხართ <xliff:g id="VPN_APP">%1$s</xliff:g>-თან, რომელსაც შეუძლია თქვენი ქსელის აქტივობის (მათ შორის, ელფოსტის, აპებისა და ვებსაიტების) მონიტორინგი."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"თქვენ დაკავშირებული ხართ <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="368812367182387320">"თქვენი სამსახურის პროფილი დაკავშირებულია <xliff:g id="VPN_APP">%1$s</xliff:g>-თან, რომელსაც შეუძლია თქვენი ქსელის აქტივობის (მათ შორის, ელფოსტის, აპებისა და ვებსაიტების) მონიტორინგი."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. შეეხეთ დასადუმებლად. შეიძლება დადუმდეს მარტივი წვდომის სერვისებიც."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. შეეხეთ ვიბრაციაზე დასაყენებლად."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. შეეხეთ დასადუმებლად."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"დადუმება"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"დადუმების მოხსნა"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"ვიბრაცია"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"ეს შეტყობინება ავტომატურად &lt;b&gt;გადავიდა „უხმო“ სტატუსზე&lt;/b&gt; სისტემის მიერ."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"ეს შეტყობინება ავტომატურად &lt;b&gt;ჩაითვალა უფრო&lt;/b&gt; პრიორიტეტულად."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"ეს შეტყობინება ავტომატურად &lt;b&gt;ჩაითვალა ნაკლებად&lt;/b&gt; პრიორიტეტულად."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"სწორია ეს?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"მიაწოდეთ დეველოპერს თქვენი გამოხმაურება. სწორია ეს?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"გმადლობთ გამოხმაურებისთვის!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"კარგი"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"შეტყობინებების მართვა „<xliff:g id="APP_NAME">%1$s</xliff:g>“-ისთვის გახსნილია"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"გადატანა <xliff:g id="POSITION">%1$d</xliff:g>-ზე"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"დამატება პოზიციაზე <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"პოზიცია <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"მოზაიკის ფილა დაემატა"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"მოზაიკის ფილა ამოიშალა"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"სწრაფი პარამეტრების რედაქტორი."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> შეტყობინება: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"პარამეტრების გახსნა."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> იყენებს აპს <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"აპმა <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ახლახან გამოიყენა <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(კორპორაციული)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"სატელეფონო ზარი"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"სატელეფონო ზარი"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(აპის <xliff:g id="ATTRIBUTION">%s</xliff:g> მეშვეობით)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"კამერა"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"მდებარეობა"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"სენსორების გამორთვა"</string>
     <string name="device_services" msgid="1549944177856658705">"მოწყობილობის სერვისები"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"უსათაურო"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"შეეხეთ ამ აპის გადასატვირთად და გადადით სრულ ეკრანზე."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"გადატანა"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"სისტემური ნავიგაცია განახლდა. ცვლილებების შესატანად გადადით პარამეტრებზე."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"სისტემური ნავიგაციის გასაახლებლად გადადით პარამეტრებზე"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"დამატება"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"შემოთავაზებულია <xliff:g id="APP">%s</xliff:g>-ის მიერ"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"მართვის საშუალებები განახლდა"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"მოწყობილ. ჩაკეტილია"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-კოდი შეიცავს ასოებს ან სიმბოლოებს"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"დაადასტურეთ <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN-კოდი არასწორია"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 89f905733f..1fbb8a5 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Скриншотты айналдыру"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Скриншотты жабу"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Скриншотты алдын ала қарау"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Жоғарғы шектік сызық"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Төменгі шектік сызық"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Экран жазғыш"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Экран жазғыш бейнесін өңдеу"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Экранды бейнеге жазудың ағымдағы хабарландыруы"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Күн шыққанға дейін"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Қосылу уақыты: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> дейін"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC өшірулі"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC қосулы"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC пайдалану үшін құлыпты ашыңыз."</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Бұл құрылғы ұйымыңызға тиесілі."</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Бұл құрылғы <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ұйымына тиесілі."</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Телефонды ашу үшін белгішеден әрі қарай сырғытыңыз"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Дауыс көмекшісін ашу үшін белгішеден әрі қарай сырғытыңыз"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Камераны ашу үшін белгішеден әрі қарай сырғытыңыз"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Профильді көрсету"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Пайдаланушы қосу"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Жаңа пайдаланушы"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Қонақ сеансы аяқталсын ба?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Қонақ сеансын аяқтау"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Қонақты жою керек пе?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Осы сеанстағы барлық қолданбалар мен деректер жойылады."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Сеансты аяқтау"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Алып тастау"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Қош келдіңіз, қонақ"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Сеансты жалғастыру керек пе?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Қайта бастау"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Ұйымыңыз жұмыс профиліңізде сертификат орнатқан. Қорғалған желі трафигіңіз бақылануы немесе өзгертілуі мүмкін."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Осы құрылғыда сертификат орнатылған. Қорғалған желі трафигіңіз бақылануы немесе өзгертілуі мүмкін."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Әкімші құрылғыңыздағы трафикті бақылайтын желі журналын жүргізуді қосқан."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Әкімші жеке профильдегі емес, жұмыс профиліндегі трафикті қадағалау үшін желі журналын жүргізуді қосып қойған."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Желідегі әрекеттеріңізді, соның ішінде электрондық хабарларды, қолданбаларды және вебсайттарды бақылай алатын <xliff:g id="VPN_APP">%1$s</xliff:g> желісіне қосылдыңыз."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Желідегі әрекеттеріңізді, соның ішінде электрондық хабарларды, қолданбаларды және вебсайттарды бақылай алатын <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="368812367182387320">"Жұмыс профиліңіз желідегі белсенділігіңізді, соның ішінде электрондық хабарларды, қолданбаларды және веб-сайттарды бақылай алатын <xliff:g id="VPN_APP">%1$s</xliff:g> қолданбасына қосылған."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Дыбысын өшіру үшін түртіңіз. Арнайы мүмкіндік қызметтерінің дыбысы өшуі мүмкін."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Діріл режимін орнату үшін түртіңіз."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Дыбысын өшіру үшін түртіңіз."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"дыбысын өшіру"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"дыбысын қосу"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"дірілдету"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Жүйе бұл хабарландырудың деңгейін автоматты түрде &lt;b&gt;\"Үнсіз\" санатына төмендетті&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Жүйе бұл хабарландырудың маңыздылық деңгейін автоматты түрде &lt;b&gt;көтерді&lt;/b&gt;."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Жүйе бұл хабарландырудың маңыздылық деңгейін автоматты түрде &lt;b&gt;төмендетті&lt;/b&gt;."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Барлығы дұрыс па?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Әзірлеушіге пікіріңізді білдіріңіз. Барлығы дұрыс па?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Пікіріңіз үшін рақмет!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Жарайды"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> хабарландыруларын басқару элементтері ашылды"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> орнына жылжыту"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> орнына қосу"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g> орны"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Бөлшек қосылды."</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Бөлшек өшірілді."</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Жылдам параметрлер өңдегіші."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> хабарландыруы: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Параметрлерді ашу."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> қолданбасы қазір <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> пайдаланады"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> қолданбасы жақында <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> пайдаланды"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(корпоративтік)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Телефон қоңырауы"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Телефон қоңырауы"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> арқылы)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"камера"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"геодерек"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Датчиктер өшірулі"</string>
     <string name="device_services" msgid="1549944177856658705">"Құрылғы қызметтері"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Атауы жоқ"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Бұл қолданбаны қайта қосып, толық экранға өту үшін түртіңіз."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Жылжыту"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Жүйе навигациясы жаңартылды. Өзгерту енгізу үшін \"Параметрлер\" бөліміне өтіңіз."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Жүйе навигациясын жаңарту үшін \"Параметрлер\" бөліміне өтіңіз."</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Енгізу"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ұсынған"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Басқару элементтері жаңартылды"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Құрылғы құлыпталды."</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN коды әріптерден не таңбалардан құралады."</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> растау"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN коды қате"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 8555707..e6f9668 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"មុខងារ​ថតរូបថត​អេក្រង់​រំកិល"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ច្រានចោល​រូបថត​អេក្រង់"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ការមើល​រូបថត​អេក្រង់​សាកល្បង"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"បន្ទាត់បែងចែក​ខាងលើ"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"បន្ទាត់បែងចែក​ខាងក្រោម"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"មុខងារថត​អេក្រង់"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"កំពុង​ដំណើរការ​ការថតអេក្រង់"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ការជូនដំណឹង​ដែល​កំពុង​ដំណើរការ​សម្រាប់​រយៈពេលប្រើ​ការថត​សកម្មភាព​អេក្រង់"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"រហូត​ដល់​ពេល​ថ្ងៃរះ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"បើកនៅម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"រហូតដល់ម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"បាន​បិទ NFC"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"បាន​បើក NFC"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"ដោះសោ ដើម្បីប្រើ NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"ឧបករណ៍​នេះគឺជា​កម្មសិទ្ធិរបស់​ស្ថាប័ន​អ្នក"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"ឧបករណ៍នេះ​គឺជា​កម្មសិទ្ធិ​របស់ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"អូសចេញពីរូបតំណាងដើម្បីប្រើទូរស័ព្ទ"</string>
     <string name="voice_hint" msgid="7476017460191291417">"អូសចេញពីរូបតំណាងដើម្បីប្រើជំនួយសំឡេង"</string>
     <string name="camera_hint" msgid="4519495795000658637">"អូសចេញពីរូបតំណាងដើម្បីប្រើកាមេរ៉ា"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"បង្ហាញ​ប្រវត្តិរូប"</string>
     <string name="user_add_user" msgid="4336657383006913022">"បន្ថែម​អ្នកប្រើ"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"អ្នកប្រើ​ថ្មី"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"បញ្ចប់វគ្គភ្ញៀវឬ?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"បញ្ចប់វគ្គភ្ញៀវ"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"លុប​ភ្ញៀវ​?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ទិន្នន័យ និង​កម្មវិធី​ទាំងអស់​ក្នុង​សម័យ​នេះ​នឹង​ត្រូវ​បាន​លុប។"</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"បញ្ចប់វគ្គ"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"លុបចេញ"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"សូម​ស្វាគមន៍​ការ​ត្រឡប់​មកវិញ, ភ្ញៀវ!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"តើ​អ្នក​ចង់​បន្ត​សម័យ​របស់​អ្នក​?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ចាប់ផ្ដើម"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"ស្ថាប័នរបស់អ្នក​បានដំឡើង​អាជ្ញាធរវិញ្ញាបនបត្រ​នៅក្នុង​កម្រងព័ត៌មាន​ការងារ។ ចរាចរណ៍​បណ្តាញដែលមាន​សុវត្ថិភាព​របស់អ្នក​អាច​ត្រូវបាន​តាមដាន ឬ​កែសម្រួល។"</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"បាន​ដំឡើង​អាជ្ញាធរវិញ្ញាបនបត្រ​នៅលើ​ឧបករណ៍​នេះ។ ចរាចរណ៍​បណ្តាញដែលមានសុវត្ថិភាព​របស់អ្នក​អាច​ត្រូវបាន​តាមដាន ឬ​កែសម្រួល។"</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"អ្នក​គ្រប់គ្រង​របស់អ្នក​បាន​បើក​ការ​ធ្វើ​កំណត់ហេតុ​បណ្តាញ​ ដែល​នឹង​តាមដាន​ចរាចរណ៍​នៅលើ​ឧបករណ៍​របស់អ្នក។"</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"អ្នកគ្រប់គ្រង​របស់អ្នក​បានបើក​ការធ្វើ​កំណត់ហេតុ​បណ្តាញ ដែល​តាមដាន​ចរាចរណ៍​នៅក្នុងកម្រងព័ត៌មាន​ការងាររបស់អ្នក ប៉ុន្តែមិនតាមដាន​នៅក្នុងកម្រងព័ត៌មានផ្ទាល់ខ្លួន​របស់អ្នកឡើយ។"</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"អ្នកបានភ្ជាប់ទៅ <xliff:g id="VPN_APP">%1$s</xliff:g> ដែលអាចតាមដានសកម្មភាពក្នុងបណ្តាញរបស់អ្នក រួមទាំងអ៊ីមែល កម្មវិធី និងគេហទំព័រផងដែរ។"</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"អ្នកបាន​ភ្ជាប់ទៅ <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="368812367182387320">"កម្រងព័ត៌មាន​ការងារ​របស់អ្នក​ត្រូវបាន​ភ្ជាប់​ទៅ <xliff:g id="VPN_APP">%1$s</xliff:g> ដែលអាច​តាមដាន​សកម្មភាព​បណ្តាញ​របស់អ្នក រួមទាំងអ៊ីមែល កម្មវិធី និង​គេហទំព័រ​ផងដែរ។"</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s។ ប៉ះដើម្បីបិទសំឡេង។ សេវាកម្មលទ្ធភាពប្រើប្រាស់អាចនឹងត្រូវបានបិទសំឡេង។"</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s ។ ចុច​ដើម្បី​កំណត់​ឲ្យ​ញ័រ។"</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s ។ ចុច​ដើម្បី​បិទ​សំឡេង។"</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"បិទ​សំឡេង"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"បើក​សំឡេង"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"ញ័រ"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"ការជូនដំណឹងនេះ​ត្រូវបាន&lt;b&gt;បញ្ចុះ​ទៅស្ងាត់&lt;/b&gt;ដោយប្រព័ន្ធដោយស្វ័យប្រវត្តិ។"</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"ការជូនដំណឹងនេះ​ត្រូវបាន&lt;b&gt;ចាត់ថ្នាក់ខ្ពស់ជាងមុន&lt;/b&gt;ដោយស្វ័យប្រវត្តិ នៅក្នុង​ផ្ទាំងជូនដំណឹង​របស់អ្នក។"</string>
     <string name="feedback_demoted" msgid="951884763467110604">"ការជូនដំណឹងនេះ​ត្រូវបាន&lt;b&gt;ចាត់ថ្នាក់​ទាបជាងមុន&lt;/b&gt;ដោយស្វ័យប្រវត្តិ នៅក្នុង​ផ្ទាំងជូនដំណឹង​របស់អ្នក។"</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"តើវា​ត្រឹមត្រូវទេ?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"ប្រាប់ឱ្យអ្នក​អភិវឌ្ឍន៍ដឹងអំពីមតិកែលម្អរបស់អ្នក។ តើវា​ត្រឹមត្រូវដែរទេ?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"សូមអរគុណចំពោះ​មតិកែលម្អ​របស់អ្នក!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"យល់ព្រម"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"ការគ្រប់គ្រងការជូនដំណឹងសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g> បានបើក"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"ផ្លាស់​ទីទៅ <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"បញ្ចូលទៅ​ទីតាំងទី <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"ទីតាំងទី <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"បានបញ្ចូលប្រអប់"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"បាន​ផ្លាស់ទី​ប្រអប់"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"កម្មវិធីកែការកំណត់រហ័ស"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> ការជូនដំណឹង៖ <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"បើកការកំណត់"</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> កំពុងប្រើ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> បានប្រើ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ថ្មីៗនេះ"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(សហគ្រាស)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"ការហៅទូរសព្ទ"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"ការហៅ​ទូរសព្ទ"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(តាមរយៈ <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"កាមេរ៉ា"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"ទីតាំង"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"បិទឧបករណ៍​ចាប់សញ្ញា"</string>
     <string name="device_services" msgid="1549944177856658705">"សេវាកម្មឧបករណ៍"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"គ្មាន​ចំណងជើង"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"ចុចដើម្បី​ចាប់ផ្ដើម​កម្មវិធី​នេះឡើងវិញ រួចចូលប្រើ​ពេញអេក្រង់។"</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"ផ្លាស់ទី"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"បានធ្វើ​បច្ចុប្បន្នភាព​ការរុករកក្នុង​ប្រព័ន្ធ។ ដើម្បីធ្វើការផ្លាស់ប្ដូរ សូមចូលទៅ​កាន់ការកំណត់។"</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"ចូល​ទៅកាន់​ការកំណត់ ដើម្បី​ធ្វើបច្ចុប្បន្នភាព​ការរុករក​ក្នុង​ប្រព័ន្ធ"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"បញ្ចូល"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"បាន​ណែនាំដោយ <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"បានធ្វើបច្ចុប្បន្នភាពការគ្រប់គ្រង"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"បានចាក់សោ​ឧបករណ៍"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"កូដ PIN មាន​អក្សរ ឬនិមិត្តសញ្ញា"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"ផ្ទៀងផ្ទាត់ <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"កូដ PIN មិន​ត្រឹមត្រូវ​"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index c920cc2..15abcaa 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಸ್ಕ್ರಾಲ್ ಮಾಡಿ"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಅನ್ನು ವಜಾಗೊಳಿಸಿ"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ಸ್ಕ್ರೀನ್‍ಶಾಟ್‍ನ ಪೂರ್ವವೀಕ್ಷಣೆ"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"ಮೇಲಿನ ಗಡಿರೇಖೆ"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"ಕೆಳಗಿನ ಗಡಿರೇಖೆ"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡರ್"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಆಗುತ್ತಿದೆ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಸೆಶನ್‌ಗಾಗಿ ಚಾಲ್ತಿಯಲ್ಲಿರುವ ಅಧಿಸೂಚನೆ"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ಸೂರ್ಯೋದಯದವರೆಗೆ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> ಸಮಯದಲ್ಲಿ"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> ವರೆಗೂ"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ಸಕ್ರಿಯಗೊಂಡಿದೆ"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ಬಳಸಲು ಅನ್‌ಲಾಕ್ ಮಾಡಿ"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"ಈ ಸಾಧನವು ನಿಮ್ಮ ಸಂಸ್ಥೆಗೆ ಸೇರಿದೆ"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"ಈ ಸಾಧನವು <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ಗೆ ಸೇರಿದೆ"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"ಫೋನ್‌ಗಾಗಿ ಐಕಾನ್‌ನಿಂದ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
     <string name="voice_hint" msgid="7476017460191291417">"ಧ್ವನಿ ಸಹಾಯಕ್ಕಾಗಿ ಐಕಾನ್‌ನಿಂದ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
     <string name="camera_hint" msgid="4519495795000658637">"ಕ್ಯಾಮರಾಗಾಗಿ ಐಕಾನ್‌ನಿಂದ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"ಪ್ರೊಫೈಲ್‌ ತೋರಿಸು"</string>
     <string name="user_add_user" msgid="4336657383006913022">"ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಿ"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"ಹೊಸ ಬಳಕೆದಾರರು"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"ಅತಿಥಿ ಸೆಷನ್ ಅಂತ್ಯಗೊಳಿಸುವುದೇ?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"ಅತಿಥಿ ಸೆಷನ್ ಕೊನೆಗೊಳಿಸಿ"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"ಅತಿಥಿಯನ್ನು ತೆಗೆದುಹಾಕುವುದೇ?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ಈ ಸೆಷನ್‌ನಲ್ಲಿನ ಎಲ್ಲ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"ಸೆಷನ್ ಅಂತ್ಯಗೊಳಿಸಿ"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"ತೆಗೆದುಹಾಕಿ"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"ಮತ್ತೆ ಸುಸ್ವಾಗತ, ಅತಿಥಿ!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"ನಿಮ್ಮ ಸೆಷನ್‌ ಮುಂದುವರಿಸಲು ಇಚ್ಚಿಸುವಿರಾ?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ಪ್ರಾರಂಭಿಸಿ"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ನಿಮ್ಮ ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ನಲ್ಲಿ ಪ್ರಮಾಣಪತ್ರ ಅಂಗೀಕಾರವನ್ನು ಸ್ಥಾಪಿಸಿದೆ. ನಿಮ್ಮ ಸುರಕ್ಷಿತ ನೆಟ್‌ವರ್ಕ್ ಟ್ರಾಫಿಕ್ ಅನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು ಅಥವಾ ಮಾರ್ಪಡಿಸಬಹುದು."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"ಈ ಸಾಧನದಲ್ಲಿ ಪ್ರಮಾಣಪತ್ರ ಅಂಗೀಕಾರವನ್ನು ಸ್ಥಾಪಿಸಲಾಗಿದೆ. ನಿಮ್ಮ ಸುರಕ್ಷಿತ ನೆಟ್‌ವರ್ಕ್ ಟ್ರಾಫಿಕ್ ಅನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು ಅಥವಾ ಮಾರ್ಪಡಿಸಬಹುದು."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನೆಟ್‌ವರ್ಕ್ ಲಾಗಿಂಗ್ ಆನ್ ಮಾಡಿದ್ದಾರೆ. ಇದು ನಿಮ್ಮ ಸಾಧನದ ಟ್ರಾಫಿಕ್ ಅನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡುತ್ತದೆ."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನೆಟ್‌ವರ್ಕ್‌ ಲಾಗಿಂಗ್ ಆನ್ ಮಾಡಿದ್ದಾರೆ, ಅದು ನಿಮ್ಮ ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ ನಲ್ಲಿ ಇರುವ ಟ್ರಾಫಿಕ್ ಮೇಲೆ ನಿಗಾ ಇರಿಸುತ್ತದೆ ಆದರೆ ನಿಮ್ಮ ವೈಯಕ್ತಿಕ ಪ್ರೊಫೈಲ್‌ನಲ್ಲಿ ಇರುವ ಟ್ರಾಫಿಕ್ ಮೇಲೆ ಅಲ್ಲ."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"ನೀವು <xliff:g id="VPN_APP">%1$s</xliff:g> ಗೆ ಸಂಪರ್ಕಗೊಂಡಿದ್ದೀರಿ. ಇದು ನಿಮ್ಮ ಇಮೇಲ್‌ಗಳು, ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ವೆಬ್‌ಸೈಟ್‌ಗಳೂ ಸೇರಿದಂತೆ ನಿಮ್ಮ ನೆಟ್‌ವರ್ಕ್ ಚಟುವಟಿಕೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"ನೀವು <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="368812367182387320">"ನಿಮ್ಮ ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ <xliff:g id="VPN_APP">%1$s</xliff:g> ಗೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ. ಇದು ನಿಮ್ಮ ಇಮೇಲ್‌ಗಳು, ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ವೆಬ್‌ಸೈಟ್‌ಗಳೂ ಸೇರಿದಂತೆ ನೆಟ್‌ವರ್ಕ್ ಚಟುವಟಿಕೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. ಮ್ಯೂಟ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ. ಪ್ರವೇಶಿಸುವಿಕೆ ಸೇವೆಗಳನ್ನು ಮ್ಯೂಟ್‌ ಮಾಡಬಹುದು."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. ವೈಬ್ರೇಟ್ ಮಾಡಲು ಹೊಂದಿಸುವುದಕ್ಕಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. ಮ್ಯೂಟ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"ಮ್ಯೂಟ್ ಮಾಡಿ"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"ಅನ್‌ಮ್ಯೂಟ್ ಮಾಡಿ"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"ವೈಬ್ರೇಟ್‌"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"ಈ ಅಧಿಸೂಚನೆಯು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸಿಸ್ಟಂನಿಂದ &lt;b&gt;ಸೈಲೆಂಟ್‌ಗೆ ಹಿಂಬಡ್ತಿ ಹೊಂದಿದೆ&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"ಈ ಅಧಿಸೂಚನೆಯು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ನಿಮ್ಮ ಶೇಡ್‌ನಲ್ಲಿ &lt;b&gt;ಉನ್ನತ ಸ್ಥಾನವನ್ನು ಹೊಂದಿದೆ&lt;/b&gt;."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"ಈ ಅಧಿಸೂಚನೆಯು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ನಿಮ್ಮ ಶೇಡ್‌ನಲ್ಲಿ &lt;b&gt;ಕಡಿಮೆ ಸ್ಥಾನವನ್ನು ಹೊಂದಿದೆ&lt;/b&gt;."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"ಇದು ಸರಿಯಾಗಿತ್ತೇ?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"ನಿಮ್ಮ ಪ್ರತಿಕ್ರಿಯೆಯನ್ನು ಡೆವಲಪರ್‌ಗೆ ತಿಳಿಸಿ. ಇದು ಸರಿಯಾಗಿತ್ತೇ?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"ನಿಮ್ಮ ಪ್ರತಿಕ್ರಿಯೆಗೆ ಧನ್ಯವಾದಗಳು!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ಸರಿ"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> ನ ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳನ್ನು ತೆರೆಯಲಾಗಿದೆ"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"ಇಲ್ಲಿಗೆ ಸರಿಸಿ <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> ಸ್ಥಾನಕ್ಕೆ ಸೇರಿಸಿ"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"ಸ್ಥಾನ <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"ಟೈಲ್ ಸೇರಿಸಲಾಗಿದೆ"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"ಟೈಲ್ ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‍ಗಳ ಎಡಿಟರ್."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> ಅಧಿಸೂಚನೆ: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ತೆರೆಯಿರಿ."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>, <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ಅನ್ನು ಬಳಸುತ್ತಿದೆ"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ಇತ್ತೀಚೆಗೆ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ಅನ್ನು ಬಳಸಿದೆ"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(ಎಂಟರ್‌ಪ್ರೈಸ್)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"ಫೋನ್ ಕರೆ"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"ಫೋನ್ ಕರೆ"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> ಮೂಲಕ)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"ಕ್ಯಾಮರಾ"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"ಸ್ಥಳ"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"ಸೆನ್ಸರ್‌ಗಳು ಆಫ್"</string>
     <string name="device_services" msgid="1549944177856658705">"ಸಾಧನ ಸೇವೆಗಳು"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"ಯಾವುದೇ ಶೀರ್ಷಿಕೆಯಿಲ್ಲ"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"ಈ ಆ್ಯಪ್ ಅನ್ನು ಮರುಪ್ರಾರಂಭಿಸಲು ಮತ್ತು ಪೂರ್ಣ ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿ ನೋಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"ಸರಿಸಿ"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"ಸಿಸ್ಟಂ ನ್ಯಾವಿಗೇಷನ ಅಪ್‌ಡೇಟ್ ಮಾಡಲಾಗಿದೆ ಬದಲಾವಣೆಗಳನ್ನು ಮಾಡಲು, ಸೆಟ್ಟಿಂಗ್‌ಗಳಿಗೆ ಹೋಗಿ."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"ಸಿಸ್ಟಂ ನ್ಯಾವಿಗೇಷನ್ ಅಪ್‌ಡೇಟ್ ಮಾಡಲು ಸೆಟ್ಟಿಂಗ್‌ಗಳಿಗೆ ಹೋಗಿ"</string>
@@ -1032,6 +1043,8 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"ಸೇರಿಸಿ"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ಆ್ಯಪ್ ಸೂಚಿಸಿದೆ"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"ನಿಯಂತ್ರಣಗಳನ್ನು ನವೀಕರಿಸಲಾಗಿದೆ"</string>
+    <!-- no translation found for controls_tile_locked (731547768182831938) -->
+    <skip />
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"ಪಿನ್ ಅಕ್ಷರಗಳು ಅಥವಾ ಸಂಕೇತಗಳನ್ನು ಒಳಗೊಂಡಿದೆ"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> ಅನ್ನು ಪರಿಶೀಲಿಸಿ"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"ತಪ್ಪಾದ ಪಿನ್‌"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 362c0bc..78c2958 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"스크롤 스크린샷"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"스크린샷 닫기"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"스크린샷 미리보기"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"상단 경계"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"하단 경계"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"화면 녹화"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"화면 녹화 처리 중"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"화면 녹화 세션에 관한 지속적인 알림"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"일출까지"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>에 켜짐"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g>까지"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC 사용 중지됨"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC 사용 설정됨"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"잠금 해제하여 NFC 사용"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"내 조직에 속한 기기입니다."</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>에 속한 기기입니다."</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"전화 기능을 사용하려면 아이콘에서 스와이프하세요."</string>
     <string name="voice_hint" msgid="7476017460191291417">"음성 지원을 사용하려면 아이콘에서 스와이프하세요."</string>
     <string name="camera_hint" msgid="4519495795000658637">"카메라를 사용하려면 아이콘에서 스와이프하세요."</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"프로필 표시"</string>
     <string name="user_add_user" msgid="4336657383006913022">"사용자 추가"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"신규 사용자"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"게스트 세션을 종료하시겠습니까?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"게스트 세션 종료"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"게스트를 삭제하시겠습니까?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"이 세션에 있는 모든 앱과 데이터가 삭제됩니다."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"세션 종료"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"삭제"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"게스트 세션 다시 시작"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"세션을 계속 진행하시겠습니까?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"다시 시작"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"조직에서 직장 프로필에 인증기관을 설치했습니다. 보안 네트워크 트래픽을 모니터링 또는 수정할 수 있습니다."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"이 기기에는 인증기관이 설치되어 있습니다. 보안 네트워크 트래픽을 모니터링 또는 수정할 수 있습니다."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"관리자가 기기에서 발생하는 트래픽을 모니터링하는 네트워크 로깅을 사용 설정했습니다."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"관리자가 직장 프로필에서 발생하는 트래픽을 모니터링하는 네트워크 로깅을 사용 설정했습니다. 하지만 개인 프로필은 모니터링되지 않습니다."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"<xliff:g id="VPN_APP">%1$s</xliff:g>에 연결되었습니다. 이 앱은 이메일, 앱, 웹사이트와 같은 내 네트워크 활동을 모니터링할 수 있습니다."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"<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="368812367182387320">"직장 프로필이 <xliff:g id="VPN_APP">%1$s</xliff:g>에 연결되었습니다. 이 앱은 이메일, 앱, 웹사이트와 같은 내 네트워크 활동을 모니터링할 수 있습니다."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. 탭하여 음소거로 설정하세요. 접근성 서비스가 음소거될 수 있습니다."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. 탭하여 진동으로 설정하세요."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. 탭하여 음소거로 설정하세요."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"음소거"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"음소거 해제"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"진동"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"시스템에서 자동으로 이 알림의 순위를 &lt;b&gt;무음으로 낮췄&lt;/b&gt;습니다."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"알림 창에서 자동으로 이 알림의 순위를 &lt;b&gt;높였&lt;/b&gt;습니다."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"알림 창에서 자동으로 이 알림의 순위를 &lt;b&gt;낮췄&lt;/b&gt;습니다."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"맞나요?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"개발자에게 의견을 알려주세요. 정보가 정확했나요?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"의견을 보내 주셔서 감사합니다."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"확인"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> 알림 컨트롤을 열었습니다."</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> 위치로 이동"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> 위치에 추가"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g> 위치"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"타일 추가됨"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"타일 삭제됨"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"빠른 설정 편집기"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> 알림: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"설정 열기"</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>에서 <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> 사용 중"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>에서 최근에 <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>을(를) 사용함"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(기업용)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"전화 통화"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"전화 통화"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> 사용)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"카메라"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"위치"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"센서 사용 안함"</string>
     <string name="device_services" msgid="1549944177856658705">"기기 서비스"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"제목 없음"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"탭하여 이 앱을 다시 시작하고 전체 화면으로 이동합니다."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"이동"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"시스템 탐색이 업데이트되었습니다. 변경하려면 설정으로 이동하세요."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"설정으로 이동하여 시스템 탐색을 업데이트하세요."</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"추가"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g>에서 제안"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"컨트롤 업데이트됨"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"기기 잠김"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN에 문자나 기호가 포함됨"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> 확인"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"잘못된 PIN"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index fe69443..7a4d7d2 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -93,11 +93,13 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Скриншотту сыдырып кароо"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Скриншотту четке кагуу"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Скриншотту алдын ала көрүү"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Жогорку чеги"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Төмөнкү чеги"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"экрандан видео жаздырып алуу"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Экрандан жаздырылып алынган видео иштетилүүдө"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Экранды жаздыруу сеансы боюнча учурдагы билдирме"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Жаздырып баштайсызбы?"</string>
-    <string name="screenrecord_description" msgid="1123231719680353736">"Жаздыруу учурунда Android тутуму экраныңызда көрүнүп турган жана түзмөктө ойноп жаткан бардык купуя маалыматты жаздырып алат. Буга сырсөздөр, төлөм маалыматы, сүрөттөр, билдирүүлөр жана аудио файлдар кирет."</string>
+    <string name="screenrecord_description" msgid="1123231719680353736">"Жаздыруу учурунда Android системасы экраныңызда көрүнүп турган жана түзмөктө ойноп жаткан бардык купуя маалыматты жаздырып алат. Буга сырсөздөр, төлөм маалыматы, сүрөттөр, билдирүүлөр жана аудио файлдар кирет."</string>
     <string name="screenrecord_audio_label" msgid="6183558856175159629">"Аудио жаздыруу"</string>
     <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Түзмөктүн аудиосу"</string>
     <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Музыка, чалуулар жана шыңгырлар сыяктуу түзмөгүңүздөгү добуштар"</string>
@@ -412,6 +414,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Күн чыкканга чейин"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Саат <xliff:g id="TIME">%s</xliff:g> күйөт"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> чейин"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC өчүрүлгөн"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC иштетилген"</string>
@@ -421,7 +425,7 @@
     <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Улантуу үчүн &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; колдонмосуна түзмөгүңүздүн микрофонун пайдаланууга уруксат беришиңиз керек."</string>
     <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Улантуу үчүн &lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; колдонмосуна түзмөгүңүздүн камерасын пайдаланууга уруксат беришиңиз керек."</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Түзмөк"</string>
-    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Башка колдонмого которулуу үчүн,, өйдө сүрүңүз"</string>
+    <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Башка колдонмого которулуу үчүн өйдө сүрүңүз"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Колдонмолорду тез которуштуруу үчүн, оңго сүйрөңүз"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Сереп салууну өчүрүү/күйгүзүү"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Кубатталды"</string>
@@ -442,12 +446,14 @@
     <string name="notification_tap_again" msgid="4477318164947497249">"Ачуу үчүн кайра таптап коюңуз"</string>
     <string name="keyguard_unlock" msgid="8031975796351361601">"Ачуу үчүн өйдө сүрүңүз"</string>
     <string name="keyguard_retry" msgid="886802522584053523">"Кайталоо үчүн экранды өйдө сүрүңүз"</string>
-    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC технологиясын колдонуу үчүн кулпуcун ачыңыз"</string>
+    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC колдонуу үчүн түзмөктүн кулпусун ачыңыз"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Бул түзмөк уюмуңузга таандык"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Бул түзмөк төмөнкүгө таандык: <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
-    <string name="phone_hint" msgid="6682125338461375925">"Сүрөтчөнү серпип телефонго өтүңүз"</string>
-    <string name="voice_hint" msgid="7476017460191291417">"Сүрөтчөнү серпип үн жардамчысына өтүңүз"</string>
-    <string name="camera_hint" msgid="4519495795000658637">"Сүрөтчөнү серпип камерага өтүңүз"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
+    <string name="phone_hint" msgid="6682125338461375925">"Сүрөтчөнү сүрүп телефонго өтүңүз"</string>
+    <string name="voice_hint" msgid="7476017460191291417">"Сүрөтчөнү сүрүп үн жардамчысына өтүңүз"</string>
+    <string name="camera_hint" msgid="4519495795000658637">"Сүрөтчөнү сүрүп камерага өтүңүз"</string>
     <string name="interruption_level_none_with_warning" msgid="8394434073508145437">"Толук жымжырттык талап кылынат. Бул экрандагыны окугучтарды да тынчтандырат."</string>
     <string name="interruption_level_none" msgid="219484038314193379">"Тымтырс"</string>
     <string name="interruption_level_priority" msgid="661294280016622209">"Шашылыш билдирүүлөр гана"</string>
@@ -465,9 +471,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Профилди көрсөтүү"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Колдонуучу кошуу"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Жаңы колдонуучу"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Конок сеансы бүтүрүлсүнбү?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Конок сеансын бүтүрүү"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Конокту алып саласызбы?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Бул сеанстагы бардык колдонмолор жана дайындар өчүрүлөт."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Сеансты бүтүрүү"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Алып салуу"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Кайтып келишиңиз менен, конок!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Сеансыңызды улантасызбы?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Кайра баштоо"</string>
@@ -542,6 +549,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Ишканаңыз жумуш профилиңизге тастыктоочу борборду орнотту. Коопсуз тармагыңыздын трафиги көзөмөлдөнүп же өзгөртүлүшү мүмкүн."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Бул түзмөктө тастыктоочу борбор орнотулган. Коопсуз тармагыңыздын трафиги көзөмөлдөнүп же өзгөртүлүшү мүмкүн."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Администраторуңуз түзмөгүңүздөгү трафикти көзөмөлдөөчү тармактын таржымалын каттоо функциясын иштетти."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Администраторуңуз жумуш профилиндеги трафикти көзөмөлдөгөн тармакка кирүүнү күйгүздү. Буга жеке профилиңиз кирбейт."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Электрондук почта, колдонмолор жана вебсайттар сыяктуу тармактагы аракеттериңизди тескей турган <xliff:g id="VPN_APP">%1$s</xliff:g> колдонмосуна туташып турасыз."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Электрондук почта, колдонмолор жана вебсайттар сыяктуу тармактагы аракеттериңизди көзөмөлдөй турган <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="368812367182387320">"Жумуш профилиңиз электрондук почта, колдонмолор жана вебсайттар сыяктуу тармактык аракеттериңизди көзөмөлдөй турган <xliff:g id="VPN_APP">%1$s</xliff:g> колдонмосуна туташып турат."</string>
@@ -622,6 +630,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Үнүн өчүрүү үчүн таптап коюңуз. Атайын мүмкүнчүлүктөр кызматынын үнүн өчүрүп койсо болот."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Дирилдөөгө коюу үчүн басыңыз."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Үнүн өчүрүү үчүн басыңыз."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"үнсүз"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"үнүн чыгаруу"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"дирилдөө"</string>
@@ -735,7 +745,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Бул билдирмени тутум автоматтык түрдө &lt;b&gt;Үнсүз абалга төмөндөттү&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Бул билдирменин панелиңиздеги абалы автоматтык түрдө &lt;b&gt;жогорулады&lt;/b&gt;."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Бул билдирменин панелиңиздеги абалы автоматтык түрдө &lt;b&gt;төмөндөдү&lt;/b&gt;."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Бул туурабы?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Иштеп чыгуучуга пикириңизди билдириңиз. Бул туурабы?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Пикириңиз үчүн рахмат!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Жарайт"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу үчүн эскертмени көзөмөлдөө функциялары ачылды"</string>
@@ -882,6 +892,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Төмөнкүгө жылдыруу: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g>-позицияга кошуу"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g>-позиция"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Карта кошулду"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Карта өчүрүлдү"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Ыкчам жөндөөлөр түзөткүчү."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> эскертмеси: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Жөндөөлөрдү ачуу."</string>
@@ -972,7 +984,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> колдонуп жатат"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Жакында <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> колдонулду"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(корпоративдик)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Телефон чалуу"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Телефон чалуу"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> аркылуу)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"камера"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"жайгашкан жер"</string>
@@ -980,7 +992,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Сенсорлорду өчүрүү"</string>
     <string name="device_services" msgid="1549944177856658705">"Түзмөк кызматтары"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Аталышы жок"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Бул колдонмону өчүрүп күйгүзүп, толук экранга өтүү үчүн, таптап коюңуз."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Жылдыруу"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Тутум чабыттоосу жаңырды. Өзгөртүү үчүн, Жөндөөлөргө өтүңүз."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Тутум чабыттоосун жаңыртуу үчүн Жөндөөлөргө өтүңүз"</string>
@@ -1034,6 +1045,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Кошуу"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> сунуштайт"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Башкаруу элементтери жаңырды"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Түзмөк кулпуланды"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN код тамгалардан же символдордон турат"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> түзмөгүн ырастаңыз"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN код туура эмес"</string>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index 24c7655..51d7b8e 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -52,6 +52,4 @@
     <!-- (footer_height -48dp)/2 -->
     <dimen name="controls_management_footer_top_margin">4dp</dimen>
     <dimen name="controls_management_favorites_top_margin">8dp</dimen>
-
-    <dimen name="toast_y_offset">24dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index e5e89e44..7070fa1 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"ເລື່ອນຮູບໜ້າຈໍ"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ປິດຮູບໜ້າຈໍ"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ຕົວຢ່າງຮູບໜ້າຈໍ"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"ຂອບເຂດທາງເທິງ"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"ຂອບເຂດທາງລຸ່ມ"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"ໂປຣແກຣມບັນທຶກໜ້າຈໍ"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ກຳລັງປະມວນຜົນການບັນທຶກໜ້າຈໍ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ການແຈ້ງເຕືອນສຳລັບເຊດຊັນການບັນທຶກໜ້າຈໍໃດໜຶ່ງ"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ຈົນກວ່າຕາເວັນຂຶ້ນ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"ເປີດເວລາ <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"ຈົນຮອດ <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"ປົດລັອກເພື່ອໃຊ້ NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"ອຸປະກອນນີ້ເປັນຂອງອົງການທ່ານ"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"ອຸ​ປະ​ກອນ​ນີ້​ເປັນ​ຂອງ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"ປັດ​ຈາກ​ໄອ​ຄອນ​ສຳ​ລັບ​ໂທ​ລະ​ສັບ"</string>
     <string name="voice_hint" msgid="7476017460191291417">"ປັດ​ຈາກ​ໄອ​ຄອນ​ສຳ​ລັບ​ການ​ຊ່ວຍ​ທາງ​ສຽງ"</string>
     <string name="camera_hint" msgid="4519495795000658637">"ປັດ​ຈາກ​ໄອ​ຄອນ​ສຳ​ລັບ​ກ້ອງ​ຖ່າຍ​ຮູບ"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"​ສະ​ແດງ​ໂປຣ​ໄຟລ໌"</string>
     <string name="user_add_user" msgid="4336657383006913022">"ເພີ່ມຜູ້ໃຊ້"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"ຜູ່ໃຊ້ໃໝ່"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"ສິ້ນສຸດເຊດຊັນແຂກບໍ?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"ສິ້ນສຸດເຊດຊັນແຂກ"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"ລຶບ​ແຂກ​ບໍ?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ແອັບຯ​ແລະ​ຂໍ້​ມູນ​ທັງ​ໝົດ​ໃນ​ເຊດ​ຊັນ​ນີ້​ຈະ​ຖືກ​ລຶບ​ອອກ."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"ສິ້ນສຸດເຊດຊັນ"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"ລຶບ​"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"ຍິນ​ດີ​ຕ້ອນ​ຮັບ​ກັບ​ມາ, ຜູ່​ຢ້ຽມ​ຢາມ!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"ທ່ານ​ຕ້ອງ​ການ​ສືບ​ຕໍ່​ເຊດ​ຊັນ​ຂອງ​ທ່ານບໍ່?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ເລີ່ມຕົ້ນໃຫມ່"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"ອົງກອນຂອງທ່ານຕິດຕັ້ງອຳນາດໃບຮັບຮອງໄວ້ໃນໂປຣໄຟລ໌ບ່ອນເຮັດວຽກນີ້. ທຣາບຟິກເຄືອຂ່າຍທີ່ເຂົ້າລະຫັດໄວ້ຂອງທ່ານອາດຖືກຕິດຕາມ ຫຼື ແກ້ໄຂໄດ້."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"ມີອຳນາດໃບຮັບຮອງຕິດຕັ້ງຢູ່ໃນອຸປະກອນນີ້. ທຣາບຟິກເຄືອຂ່າຍທີ່ເຂົ້າລະຫັດໄວ້ຂອງທ່ານອາດຖືກຕິດຕາມ ຫຼື ແກ້ໄຂໄດ້."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"ຜູ້ເບິ່ງແຍງຂອງທ່ານໄດ້ເປີດໃຊ້ການບັນທຶກເຄືອຂ່າຍໄວ້, ເຊິ່ງຈະຕິດຕາມທຣາບຟິກໃນອຸປະກອນຂອງທ່ານ."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"ຜູ້ເບິ່ງແຍງຂອງທ່ານໄດ້ເປີດໃຊ້ການບັນທຶກເຄືອຂ່າຍໄວ້, ເຊິ່ງຈະຕິດຕາມທຣາບຟິກໃນໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຂອງທ່ານ ແຕ່ຈະບໍ່ຕິດຕາມໃນໂປຣໄຟລ໌ສ່ວນຕົວຂອງທ່ານ."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"ທ່ານເຊື່ອມຕໍ່ກັບ <xliff:g id="VPN_APP">%1$s</xliff:g> ແລ້ວ, ເຊິ່ງຈະສາມາດຕິດຕາມການເຄື່ອນໄຫວເຄືອຂ່າຍ, ຮວມທັງອີເມວ, ແອັບ ແລະ ເວັບໄຊຕ່າງໆຂອງທ່ານໄດ້."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"ທ່ານເຊື່ອມຕໍ່ກັບ <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="368812367182387320">"ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຂອງທ່ານເຊື່ອມຕໍ່ຫາ <xliff:g id="VPN_APP">%1$s</xliff:g>, ເຊິ່ງສາມາດຕິດຕາມການເຄື່ອນໄຫວເຄືອຂ່າຍຂອງທ່ານ, ຮວມເຖິງອີເມວ, ແອັບ ແລະ ເວັບໄຊ."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. ແຕະເພື່ອປິດສຽງ. ບໍລິການຊ່ວຍເຂົ້າເຖິງອາດຖືກປິດສຽງໄວ້."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. ແຕະເພື່ອຕັ້ງເປັນສັ່ນເຕືອນ."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. ແຕະເພື່ອປິດສຽງ."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"ປິດສຽງ"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"ເຊົາປິດສຽງ"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"ສັ່ນເຕືອນ"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"ການແຈ້ງເຕືອນນີ້ &lt;b&gt;ຖືກຫຼຸດລະດັບເປັນປິດສຽງອັດຕະໂນມັດແລ້ວ&lt;/b&gt; ໂດຍລະບົບ."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"ການແຈ້ງເຕືອນນີ້ &lt;b&gt;ມີອັນດັບສູງຂຶ້ນໂດຍອັດຕະໂນມັດແລ້ວ&lt;/b&gt; ໃນໜ້າການແຈ້ງເຕືອນຂອງທ່ານ."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"ການແຈ້ງເຕືອນນີ້ &lt;b&gt;ມີອັນດັບຕ່ຳລົງໂດຍອັດຕະໂນມັດແລ້ວ&lt;/b&gt; ໃນໜ້າການແຈ້ງເຕືອນຂອງທ່ານ."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"ສິ່ງນີ້ບໍ່ຖືກຕ້ອງບໍ?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"ສົ່ງຄຳຕິຊົມຂອງທ່ານໃຫ້ນັກພັດທະນາ. ສິ່ງນີ້ບໍ່ຖືກຕ້ອງບໍ?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"ຂອບໃຈສຳລັບຄຳເຫັນຂອງທ່ານ!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ຕົກລົງ"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"ເປີດຕົວຄວບຄຸມການແຈ້ງເຕືອນສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g> ແລ້ວ"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"ຍ້າຍໄປ <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"ເພີ່ມໃສ່ຕຳແໜ່ງ <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"ຕຳແໜ່ງ <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"ເພີ່ມແຜ່ນແລ້ວ"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"ລຶບແຜ່ນແລ້ວ"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ຕົວແກ້ໄຂການຕັ້ງຄ່າດ່ວນ"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"ການແຈ້ງເຕືອນ <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ເປີດການຕັ້ງຄ່າ."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ກຳລັງໃຊ້ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ຢູ່"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ໃຊ້ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ເມື່ອບໍ່ດົນມານີ້"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(ອົງກອນ)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"ໂທລະສັບ"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"ໂທລະສັບ"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(ຜ່ານ <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"ກ້ອງຖ່າຍຮູບ"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"ສະຖານທີ່"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"ປິດການຮັບຮູ້ຢູ່"</string>
     <string name="device_services" msgid="1549944177856658705">"ບໍລິການອຸປະກອນ"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"ບໍ່ມີຊື່"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"ແຕະເພື່ອຣີສະຕາດແອັບນີ້ ແລະ ໃຊ້ແບບເຕັມຈໍ."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"ຍ້າຍ"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"ອັບເດດການນຳທາງລະບົບແລ້ວ. ເພື່ອປ່ຽນແປງ, ກະລຸນາໄປທີ່ການຕັ້ງຄ່າ."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"ໄປທີ່ການຕັ້ງຄ່າເພື່ອອັບເດດການນຳທາງລະບົບ"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"ເພີ່ມ"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"ແນະນຳໂດຍ <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"ອັບເດດການຄວບຄຸມແລ້ວ"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"ອຸປະກອນຖືກລັອກໄວ້"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN ປະກອບມີຕົວອັກສອນ ຫຼື ສັນຍາລັກ"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"ຢັ້ງຢືນ <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN ບໍ່ຖືກຕ້ອງ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index a5de095..ff69e05 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Viso puslapio ekrano kopija"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Praleisti ekrano kopiją"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Ekrano kopijos peržiūra"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Viršutinė riba"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Apatinė riba"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Ekrano vaizdo įrašytuvas"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Apdorojam. ekrano vaizdo įraš."</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Šiuo metu rodomas ekrano įrašymo sesijos pranešimas"</string>
@@ -414,6 +416,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Iki saulėtekio"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Iki <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"ALR"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"ALR išjungtas"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"ALR įjungtas"</string>
@@ -447,6 +451,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Norėdami naudoti NFC, atrakinkite"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Šis įrenginys priklauso jūsų organizacijai"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Šis įrenginys priklauso „<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>“"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Perbraukite iš telefono piktogramos"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Perbraukite iš „Voice Assist“ piktogramos"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Perbraukite iš fotoaparato piktogramos"</string>
@@ -467,9 +473,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Rodyti profilį"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Pridėti naudotoją"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Naujas naudotojas"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Baigti svečio sesiją?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Baigti svečio sesiją"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Pašalinti svečią?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bus ištrintos visos šios sesijos programos ir duomenys."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Baigti sesiją"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Pašalinti"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Sveiki sugrįžę, svety!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Ar norite tęsti sesiją?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Pradėti iš naujo"</string>
@@ -546,6 +553,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Jūsų organizacija įdiegė darbo profilyje sertifikato įgaliojimą. Jūsų saugaus tinklo srautas gali būti stebimas arba keičiamas."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Šiame įrenginyje įdiegtas sertifikato įgaliojimas. Jūsų saugaus tinklo srautas gali būti stebimas arba keičiamas."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Administratorius įjungė tinklo duomenų įrašymą į žurnalą. Įjungus šią funkciją stebimas srautas jūsų įrenginyje."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Administratorius įjungė tinklo duomenų įrašymą į žurnalą. Įjungus šią funkciją stebimas srautas jūsų darbo, bet ne asmeniniame profilyje."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Esate prisijungę prie programos „<xliff:g id="VPN_APP">%1$s</xliff:g>“, kuri gali stebėti tinklo veiklą, įskaitant el. laiškus, programas ir svetaines."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Esate prisijungę prie programų „<xliff:g id="VPN_APP_0">%1$s</xliff:g>“ ir „<xliff:g id="VPN_APP_1">%2$s</xliff:g>“, kurios gali stebėti tinklo veiklą, įskaitant el. laiškus, programas ir svetaines."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Darbo profilis susietas su programa „<xliff:g id="VPN_APP">%1$s</xliff:g>“, kuri gali stebėti tinklo veiklą, įskaitant el. laiškus, programas ir svetaines."</string>
@@ -626,6 +634,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Palieskite, kad nutildytumėte. Gali būti nutildytos pritaikymo neįgaliesiems paslaugos."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Palieskite, kad nustatytumėte vibravimą."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Palieskite, kad nutildytumėte."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"nutildyti"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"įjungti garsą"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibruoti"</string>
@@ -739,7 +749,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Šio pranešimo svarbą sistema automatiškai &lt;b&gt;sumažino iki begarsio lygio&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Šio pranešimo reitingas pranešimų skydelyje automatiškai &lt;b&gt;padidintas&lt;/b&gt;."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Šio pranešimo reitingas pranešimų skydelyje automatiškai &lt;b&gt;sumažintas&lt;/b&gt;."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Ar tai teisinga?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Pateikite savo atsiliepimą kūrėjui. Ar tai teisinga?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Dėkojame už atsiliepimą!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Gerai"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ pranešimų valdikliai atidaryti"</string>
@@ -890,6 +900,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Perkelkite į <xliff:g id="POSITION">%1$d</xliff:g> poziciją"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Pridėkite <xliff:g id="POSITION">%1$d</xliff:g> pozicijoje"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g> pozicija"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Išklotinė pridėta"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Išklotinė pašalinta"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Sparčiųjų nustatymų redagavimo priemonė."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"„<xliff:g id="ID_1">%1$s</xliff:g>“ pranešimas: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Atidaryti nustatymus."</string>
@@ -980,7 +992,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Programa „<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>“ naudoja: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Programa „<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>“ neseniai naudojo: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(įmonės versija)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefono skambutis"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefono skambutis"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(naud. <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"fotoaparatą"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"vietovę"</string>
@@ -988,7 +1000,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Jutikliai išjungti"</string>
     <string name="device_services" msgid="1549944177856658705">"Įrenginio paslaugos"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Nėra pavadinimo"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Palieskite, kad paleistumėte iš naujo šią programą arba įjungtumėte viso ekrano režimą."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Perkelti"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Sistemos naršymo funkcijos atnaujintos. Jei norite pakeisti, eikite į skiltį „Nustatymai“."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Eikite į skiltį „Nustatymai“, kad atnaujintumėte sistemos naršymo funkcijas"</string>
@@ -1044,6 +1055,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Pridėti"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Siūlo „<xliff:g id="APP">%s</xliff:g>“"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Valdikliai atnaujinti"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Įrenginys užrakintas"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN kodą sudaro raidės arba simboliai"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> patvirtinimas"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Netinkamas PIN kodas"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 019810f..18816ad 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Ritināt ekrānuzņēmumu"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Nerādīt ekrānuzņēmumu"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Ekrānuzņēmuma priekšskatījums"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Augšējā robeža"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Apakšējā robeža"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Ekrāna ierakstītājs"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekrāna ieraksta apstrāde"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Aktīvs paziņojums par ekrāna ierakstīšanas sesiju"</string>
@@ -412,6 +414,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Līdz saullēktam"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Plkst. <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Līdz plkst. <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ir atspējoti"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ir iespējoti"</string>
@@ -445,6 +449,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Atbloķējiet ierīci, lai izmantotu NFC."</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Šī ierīce pieder jūsu organizācijai."</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Šī ierīce pieder organizācijai <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>."</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Lai lietotu tālruni, velciet no ikonas"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Lai lietotu balss palīgu, velciet no ikonas"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Lai lietotu kameru, velciet no ikonas"</string>
@@ -465,9 +471,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Parādīt profilu"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Lietotāja pievienošana"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Jauns lietotājs"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Vai beigt viesa sesiju?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Beigt viesa sesiju"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Vai noņemt viesi?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tiks dzēstas visas šīs sesijas lietotnes un dati."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Beigt sesiju"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Noņemt"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Laipni lūdzam atpakaļ, viesi!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Vai vēlaties turpināt savu sesiju?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Sākt no sākuma"</string>
@@ -543,6 +550,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Jūsu organizācija instalēja sertifikātu jūsu darba profilā. Jūsu drošā tīkla datplūsma var tikt uzraudzīta."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Šajā ierīcē ir instalēts sertifikāts. Drošā tīkla datplūsma var tikt uzraudzīta."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Administrators ieslēdza tīkla reģistrēšanu, kuru izmanto, lai pārraudzītu datplūsmu jūsu ierīcē."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Administrators ir ieslēdzis tīkla reģistrēšanu, kuru izmanto, lai pārraudzītu datplūsmu jūsu darba profilā, bet ne personīgajā profilā."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Ir izveidots savienojums ar lietotni <xliff:g id="VPN_APP">%1$s</xliff:g>, kas var pārraudzīt jūsu darbības tīklā, tostarp e-pasta ziņojumus, lietotnes un vietnes."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Ir izveidots savienojums ar lietotnēm <xliff:g id="VPN_APP_0">%1$s</xliff:g> un <xliff:g id="VPN_APP_1">%2$s</xliff:g>, kas var pārraudzīt jūsu darbības tīklā, tostarp e-pasta ziņojumus, lietotnes un vietnes."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Jūsu darba profilam ir izveidots savienojums ar lietotni <xliff:g id="VPN_APP">%1$s</xliff:g>, kas var pārraudzīt jūsu darbības tīklā, tostarp saņemtos un nosūtītos e-pasta ziņojumus, instalētās lietotnes un apmeklētās tīmekļa vietnes."</string>
@@ -623,6 +631,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Pieskarieties, lai izslēgtu skaņu. Var tikt izslēgti pieejamības pakalpojumu signāli."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Pieskarieties, lai iestatītu vibrozvanu."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Pieskarieties, lai izslēgtu skaņu."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"izslēgt skaņu"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"ieslēgt skaņu"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrēt"</string>
@@ -736,7 +746,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Šī paziņojuma svarīgums sistēmā tika automātiski &lt;b&gt;pazemināts, un paziņojums tiks rādīts bez skaņas&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Šī paziņojums rangs paziņojumu panelī tika automātiski &lt;b&gt;paaugstināts&lt;/b&gt;."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Šī paziņojuma rangs paziņojumu panelī tika automātiski &lt;b&gt;pazemināts&lt;/b&gt;."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Vai šī informācija ir pareiza?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Sniedziet atsauksmes izstrādātājam. Vai šī informācija ir pareiza?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Paldies par atsauksmēm!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Labi"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Lietotnes <xliff:g id="APP_NAME">%1$s</xliff:g> paziņojumu vadīklas ir atvērtas"</string>
@@ -885,6 +895,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Pārvietot uz pozīciju numur <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Pievienot elementu pozīcijā numur <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Pozīcija numur <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Elements ir pievienots"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Elements ir noņemts"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Ātro iestatījumu redaktors."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> paziņojums: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Atvērt iestatījumus."</string>
@@ -975,7 +987,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> pašlaik izmanto šādu darbību: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> nesen izmantoja šādu darbību: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(uzņēmumiem)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Tālruņa zvaniem"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Tālruņa zvans"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(izmantojot lietotni <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"atrašanās vieta"</string>
@@ -983,7 +995,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensori izslēgti"</string>
     <string name="device_services" msgid="1549944177856658705">"Ierīces pakalpojumi"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Nav nosaukuma"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Pieskarieties, lai restartētu šo lietotni un pārietu pilnekrāna režīmā."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Pārvietot"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Sistēmas navigācija ir atjaunināta. Lai veiktu izmaiņas, atveriet iestatījumus."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Atveriet iestatījumus, lai atjauninātu sistēmas navigāciju"</string>
@@ -1038,6 +1049,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Pievienot"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Ieteica: <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Vadīklas atjauninātas"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Ierīce ir bloķēta"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN ietver burtus vai simbolus."</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Verifikācija: <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Nepareizs PIN"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index c124eef..59fc2d4 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Континуирана слика од екранот"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Отфрлете ја сликата од екранот"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Преглед на слика од екранот"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Горна граница"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Долна граница"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Снимач на екран"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Се обработува снимка од екран"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Тековно известување за сесија за снимање на екранот"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До изгрејсонце"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Се вклучува во <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"До <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC е оневозможено"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC е овозможено"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Отклучете за да користите NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Уредов е во сопственост на организацијата"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Уредов е во сопственост на <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Повлечете од иконата за телефонот"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Повлечете од иконата за гласовна помош"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Повлечете од иконата за камерата"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Прикажи го профилот"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Додај корисник"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Нов корисник"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Да се заврши гостинската сесија?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Заврши ја гостинската сесија"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Да се отстрани гостинот?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Сите апликации и податоци во сесијата ќе се избришат."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Заврши ја сесијата"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Отстрани"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Добре дојде пак, гостине!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Дали сакате да продолжите со сесијата?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Почни одново"</string>
@@ -501,7 +508,7 @@
     <string name="notification_section_header_gentle" msgid="6804099527336337197">"Безгласно"</string>
     <string name="notification_section_header_alerting" msgid="5581175033680477651">"Известувања"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Разговори"</string>
-    <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Избриши ги сите тивки известувања"</string>
+    <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Избриши ги сите бесчујни известувања"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Известувањата се паузирани од „Не вознемирувај“"</string>
     <string name="media_projection_action_text" msgid="3634906766918186440">"Започни сега"</string>
     <string name="empty_shade_text" msgid="8935967157319717412">"Нема известувања"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Вашата организација инсталираше авторитет за сертификат на вашиот работен профил. Вашиот безбеден мрежен сообраќај можно е да се следи или изменува."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"На уредов е инсталиран авторитет за сертификат. Вашиот безбеден мрежен сообраќај можно е да се следи или изменува."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Вашиот администратор вклучил евиденција на мрежата, што подразбира следење на сообраќајот на вашиот уред."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Вашиот администратор вклучил мрежна евиденција, што подразбира следење на сообраќајот во работниот, но не и во личниот профил."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Поврзани сте на <xliff:g id="VPN_APP">%1$s</xliff:g>, што може да ја следи вашата активност на мрежата, вклучувајќи ги е-пораките, апликациите и веб-сајтовите."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Поврзани сте на <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="368812367182387320">"Вашиот работен профил е поврзан на <xliff:g id="VPN_APP">%1$s</xliff:g>, што може да ја следи вашата активност на мрежата, заедно со е-пораките, апликациите и веб-сајтовите."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Допрете за да исклучите звук. Можеби ќе се исклучи звукот на услугите за достапност."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Допрете за да се постави на вибрации."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Допрете за да се исклучи звукот."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"исклучен звук"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"вклучен звук"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"вибрации"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Известувањево беше автоматски &lt;b&gt;намалено на „Тивко“&lt;/b&gt; од страна на системот."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Известувањево беше автоматски &lt;b&gt;рангирано повисоко&lt;/b&gt; во нијансите за известувања."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Известувањево беше автоматски &lt;b&gt;рангирано пониско&lt;/b&gt; во нијансите за известувања."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Дали ова беше точно?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Дајте му повратни информации на програмерот. Дали ова беше точно?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Фала за повратните информации!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Во ред"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Контролите за известувањата за <xliff:g id="APP_NAME">%1$s</xliff:g> се отворија"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Преместување на <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Додавање на позиција <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Позиција <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Додадена е плочка"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Отстранета е плочка"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Уредник за брзи поставки."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Известување од <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Отворете ги поставките."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> користи <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> користеше <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> неодамна"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(претпријатие)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Телефонски повик"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Телефонски повик"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(преку <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"камера"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"локација"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Сензорите се исклучени"</string>
     <string name="device_services" msgid="1549944177856658705">"Услуги за уредот"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Без наслов"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Допрете за да ја рестартирате апликацијава и да ја отворите на цел екран."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Премести"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Навигацијата на системот е ажурирана. За да извршите промени, одете во „Поставки“."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Одете во „Поставки“ за да ја ажурирате навигацијата на системот"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Додај"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Предложено од <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Контролите се ажурирани"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Уредот е заклучен"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-кодот содржи букви или симболи"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Потврдете го <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Погрешен PIN"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 965f4df..44883d6d 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"സ്ക്രീൻഷോട്ട് സ്ക്രോൾ ചെയ്യുക"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"സ്ക്രീൻഷോട്ട് ഡിസ്‌മിസ് ചെയ്യുക"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"സ്‌ക്രീൻഷോട്ട് പ്രിവ്യു"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"മുകളിലുള്ള അതിർത്തി"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"ചുവടെയുള്ള അതിർത്തി"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"സ്ക്രീൻ റെക്കോർഡർ"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"സ്ക്രീൻ റെക്കോർഡിംഗ് പ്രോസസുചെയ്യുന്നു"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ഒരു സ്ക്രീൻ റെക്കോർഡിംഗ് സെഷനായി നിലവിലുള്ള അറിയിപ്പ്"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"സൂര്യോദയം വരെ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>-ന്"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> വരെ"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC പ്രവർത്തനരഹിതമാക്കി"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC പ്രവർത്തനക്ഷമമാക്കി"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ഉപയോഗിക്കാൻ അൺലോക്ക് ചെയ്യുക"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"ഈ ഉപകരണം നിങ്ങളുടെ സ്ഥാപനത്തിന്റേതാണ്"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"ഈ ഉപകരണം <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> എന്ന സ്ഥാപനത്തിന്റേതാണ്"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"ഫോൺ ഐക്കണിൽ നിന്ന് സ്വൈപ്പുചെയ്യുക"</string>
     <string name="voice_hint" msgid="7476017460191291417">"വോയ്‌സ് അസിസ്റ്റിനായുള്ള ഐക്കണിൽ നിന്ന് സ്വൈപ്പുചെയ്യുക"</string>
     <string name="camera_hint" msgid="4519495795000658637">"ക്യാമറ ഐക്കണിൽ നിന്ന് സ്വൈപ്പുചെയ്യുക"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"പ്രൊഫൈൽ കാണിക്കുക"</string>
     <string name="user_add_user" msgid="4336657383006913022">"ഉപയോക്താവിനെ ചേര്‍ക്കുക"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"പുതിയ ഉപയോക്താവ്"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"അതിഥി സെഷൻ അവസാനിപ്പിക്കണോ?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"അതിഥി സെഷൻ അവസാനിപ്പിക്കുക"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"അതിഥിയെ നീക്കംചെയ്യണോ?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ഈ സെഷനിലെ എല്ലാ അപ്ലിക്കേഷനുകളും ഡാറ്റയും ഇല്ലാതാക്കും."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"സെഷൻ അവസാനിപ്പിക്കുക"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"നീക്കംചെയ്യുക"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"അതിഥിയ്‌ക്ക് വീണ്ടും സ്വാഗതം!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"നിങ്ങളുടെ സെഷൻ തുടരണോ?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"പുനരാംരംഭിക്കുക"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈലിൽ നിങ്ങളുടെ സ്ഥാപനമൊരു സർട്ടിഫിക്കറ്റ് അതോറിറ്റി ഇൻസ്റ്റാൾ ചെയ്തിരിക്കുന്നു. നിങ്ങളുടെ സുരക്ഷിത നെറ്റ്‌വർക്ക് ട്രാഫിക്ക് നിരീക്ഷിക്കപ്പെടുകയോ പരിഷ്കരിക്കപ്പെടുയോ ചെയ്തേക്കാം."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"നിങ്ങളുടെ ഉപകരണത്തിൽ ഒരു സർട്ടിഫിക്കറ്റ് അതോറിറ്റി ഇൻസ്റ്റാൾ ചെയ്തിരിക്കുന്നു. നിങ്ങളുടെ സുരക്ഷിത നെറ്റ്‌വർക്ക് ട്രാഫിക്ക് നിരീക്ഷിക്കപ്പെടുകയോ പരിഷ്കരിക്കപ്പെടുയോ ചെയ്തേക്കാം."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"നിങ്ങളുടെ അഡ്‌മിൻ, നെറ്റ്‌വർക്ക് ലോഗിംഗ് ഓണാക്കിയിട്ടുണ്ട്, ഇതിന് നിങ്ങളുടെ ഉപകരണത്തിലെ ട്രാഫിക്ക് നിരീക്ഷിക്കാൻ കഴിയും."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"നിങ്ങളുടെ അഡ്‌മിൻ നെറ്റ്‌വർക്ക് ലോഗിംഗ് ഓണാക്കി, ഇത് നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈലിലെ ട്രാഫിക് നിരീക്ഷിക്കുന്നു എന്നാൽ വ്യക്തിപരമായ പ്രൊഫൈലിലെ ട്രാഫിക് നിരീക്ഷിക്കുന്നില്ല."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"നിങ്ങൾ <xliff:g id="VPN_APP">%1$s</xliff:g> എന്ന ആപ്പിലേക്ക് കണക്റ്റുചെയ്‌തിരിക്കുന്നു, ഇമെയിലുകൾ, ആപ്പുകൾ, വെബ്‌സൈറ്റുകൾ എന്നിവ ഉൾപ്പെടെ നിങ്ങളുടെ നെറ്റ്‌വർക്ക് ആക്റ്റിവിറ്റി നിരീക്ഷിക്കാൻ ഈ ആപ്പിന് കഴിയും."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"നിങ്ങൾ <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="368812367182387320">"<xliff:g id="VPN_APP">%1$s</xliff:g> ആപ്പിലേക്ക് നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈൽ കണക്റ്റുചെയ്‌തിരിക്കുന്നു, ഇമെയിലുകൾ, ആപ്‌സ്, വെബ്‌സൈറ്റുകൾ എന്നിവ ഉൾപ്പെടെ നിങ്ങളുടെ നെറ്റ്‌വർക്ക് ആക്റ്റിവിറ്റി നിരീക്ഷിക്കാൻ ഈ ആപ്പിന് കഴിയും."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. മ്യൂട്ടുചെയ്യുന്നതിന് ടാപ്പുചെയ്യുക. ഉപയോഗസഹായി സേവനങ്ങൾ മ്യൂട്ടുചെയ്യപ്പെട്ടേക്കാം."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s വൈബ്രേറ്റിലേക്ക് സജ്ജമാക്കുന്നതിന് ടാപ്പുചെയ്യുക."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s മ്യൂട്ടുചെയ്യുന്നതിന് ടാപ്പുചെയ്യുക."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"മ്യൂട്ട് ചെയ്യുക"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"അൺമ്യൂട്ട് ചെയ്യുക"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"വൈബ്രേറ്റ് ചെയ്യുക"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"ഈ അറിയിപ്പ്, സിസ്‌റ്റം സ്വയമേവ &lt;b&gt;നിശബ്‌ദമാക്കി തരം താഴ്ത്തി&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"ഈ അറിയിപ്പിന് നിങ്ങളുടെ ഷെയ്‌ഡിൽ സ്വയമേവ &lt;b&gt;ഉയർന്ന റാങ്കിംഗ് നൽകി&lt;/b&gt;."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"ഈ അറിയിപ്പിന് നിങ്ങളുടെ ഷെയ്‌ഡിൽ സ്വയമേവ &lt;b&gt;താഴ്ന്ന റാങ്കിംഗ് നൽകി&lt;/b&gt;."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"ഇത് ശരിയായിരുന്നോ?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"ഡെവലപ്പറിനെ നിങ്ങളുടെ ഫീഡ്ബാക്ക് അറിയിക്കൂ. ഇത് ശരിയായിരുന്നോ?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"നിങ്ങളുടെ ഫീഡ്‌ബാക്കിന് നന്ദി!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ശരി"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> ആപ്പിന്റെ അറിയിപ്പ് നിയന്ത്രണങ്ങൾ തുറന്നു"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> എന്നതിലേക്ക് നീക്കുക"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> എന്ന സ്ഥാനത്തേക്ക് ചേർക്കുക"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"സ്ഥാനം <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"ടൈൽ ചേർത്തു"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"ടൈൽ നീക്കം ചെയ്‌തു"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ദ്രുത ക്രമീകരണ എഡിറ്റർ."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> അറിയിപ്പ്: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ക്രമീകരണം തുറക്കുക."</string>
@@ -967,23 +979,17 @@
     <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ആപ്പുകൾ നിങ്ങളുടെ <xliff:g id="TYPES_LIST">%s</xliff:g> ഉപയോഗിക്കുന്നു."</string>
     <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
     <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" കൂടാതെ "</string>
-    <!-- no translation found for ongoing_privacy_dialog_using_op (4125175620929701569) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_recent_op (4255923947334262404) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_enterprise (4082735415905550729) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_phonecall (3526223335298089311) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_attribution_text (9186683306719924646) -->
-    <skip />
+    <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ആപ്പ്, <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ഉപയോഗിക്കുന്നു"</string>
+    <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> അടുത്തിടെ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ഉപയോഗിച്ചു"</string>
+    <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(എന്റർപ്രൈസ്)"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"ഫോൺ കോൾ"</string>
+    <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> എന്നതിലൂടെ)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"ക്യാമറ"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"ലൊക്കേഷന്‍"</string>
     <string name="privacy_type_microphone" msgid="9136763906797732428">"മൈക്രോഫോൺ"</string>
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"സെൻസറുകൾ ഓഫാണ്"</string>
     <string name="device_services" msgid="1549944177856658705">"ഉപകരണ സേവനങ്ങള്‍"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"പേരില്ല"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"ഈ ആപ്പ് റീസ്‌റ്റാർട്ട് ചെയ്യാനും പൂർണ്ണ സ്‌ക്രീനാവാനും ടാപ്പ് ചെയ്യുക."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"നീക്കുക"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"സിസ്‌റ്റം നാവിഗേഷൻ അപ്‌ഡേറ്റ് ചെയ്‌തു. മാറ്റങ്ങൾ വരുത്താൻ ക്രമീകരണത്തിലേക്ക് പോവുക."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"സിസ്‌റ്റം നാവിഗേഷൻ അപ്‌ഡേറ്റ് ചെയ്യാൻ ക്രമീകരണത്തിലേക്ക് പോവുക"</string>
@@ -1037,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"ചേർക്കുക"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> നിർദ്ദേശിച്ചത്"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"നിയന്ത്രണങ്ങൾ അപ്ഡേറ്റ് ചെയ്തു"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"ഉപകരണം ലോക്ക് ചെയ്തു"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"പിന്നിൽ അക്ഷരങ്ങളോ ചിഹ്നങ്ങളോ അടങ്ങിയിരിക്കുന്നു"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> പരിശോധിച്ചുറപ്പിക്കുക"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"പിൻ തെറ്റാണ്"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 400352b..efb2711 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Бүхэлд нь багтаасан дэлгэцийн агшин"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Дэлгэцийн агшныг хаах"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Дэлгэцийн агшныг урьдчилан үзэх"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Дээд талын хязгаар"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Доод талын хязгаар"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Дэлгэцийн үйлдэл бичигч"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Дэлгэц бичлэг боловсруулж байна"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Дэлгэц бичих горимын үргэлжилж буй мэдэгдэл"</string>
@@ -410,6 +412,7 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Нар мандах хүртэл"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>-д"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> хүртэл"</string>
+    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Гэрэлтүүлгийг багасгах"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC-г цуцалсан"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC-г идэвхжүүлсэн"</string>
@@ -421,7 +424,7 @@
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Төхөөрөмж"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Апп сэлгэхийн тулд дээш шударна уу"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Аппуудыг хурдан сэлгэхийн тулд баруун тийш чирнэ үү"</string>
-    <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Тоймыг унтраах/асаах"</string>
+    <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Тоймыг асаах/унтраах"</string>
     <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Цэнэглэгдсэн"</string>
     <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Цэнэглэж байна"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="757991461445765011">"дүүргэхэд <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
@@ -443,6 +446,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC-г ашиглахын тулд түгжээг тайлна уу"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Энэ төхөөрөмж танай байгууллагад харьяалагддаг"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Энэ төхөөрөмж <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>-д харьяалагддаг"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Утсыг гаргахын тулд дүрс тэмдгээс шудрах"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Дуут туслахыг нээхийн тулд дүрс тэмдгээс шудрах"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Камер нээхийн тулд дүрс тэмдгийг шудрах"</string>
@@ -463,9 +468,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Профайлыг харуулах"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Хэрэглэгч нэмэх"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Шинэ хэрэглэгч"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Зочны сургалтыг дуусгах уу?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Зочны сургалтыг дуусгах"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Зочныг хасах уу?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Энэ сешний бүх апп болон дата устах болно."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Сургалтыг дуусгах"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Хасах"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Тавтай морилно уу!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Та үргэлжлүүлэхийг хүсэж байна уу?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Дахин эхлүүлэх"</string>
@@ -540,6 +546,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Таны байгууллага таны ажлын профайлд сертификатын зөвшөөрөл суулгасан байна. Таны аюулгүй сүлжээний ачааллыг өөрчлөх эсвэл хянах боломжтой."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Сертификатын зөвшөөрлийг энэ төхөөрөмжид суулгасан байна. Таны аюулгүй сүлжээний ачааллыг өөрчлөх эсвэл хянах боломжтой."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Таны админ төхөөрөмжийн ачааллыг хянадаг сүлжээний логийг асаасан байна."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Таны админ ажлын профайлын тань ачааллыг хянадаг сүлжээний логийг асаасан бөгөөд энэ нь хувийн профайлын ачааллыг хянахгүй."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Та имэйл, апп, веб хуудас зэрэг сүлжээний үйл ажиллагааг хянах боломжтой <xliff:g id="VPN_APP">%1$s</xliff:g>-д холбогдсон байна."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Та имэйл, апп, веб хуудас зэрэг сүлжээний үйл ажиллагааг хянах боломжтой <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="368812367182387320">"Таны ажлын профайл <xliff:g id="VPN_APP">%1$s</xliff:g>-д холбогдсон байна. Энэ нь таны имэйл, апп, веб хуудас зэрэг сүлжээний үйл ажиллагааг хянах боломжтой."</string>
@@ -620,6 +627,7 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Дууг нь хаахын тулд товшино уу. Хүртээмжийн үйлчилгээний дууг хаасан."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Чичиргээнд тохируулахын тулд товшино уу."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Дууг хаахын тулд товшино уу."</string>
+    <string name="volume_ringer_change" msgid="3574969197796055532">"Хонхны горимыг өөрчлөхийн тулд товшино уу"</string>
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"дууг хаах"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"дууг нээх"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"чичрэх"</string>
@@ -733,7 +741,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Энэ мэдэгдлийг систем автоматаар &lt;b&gt;Чимээгүй болгож зэрэглэлийг нь бууруулсан&lt;/b&gt; байна."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Энэ мэдэгдлийг таны хураангуй самбарт автоматаар &lt;b&gt;дээгүүр зэрэглэл хийсэн&lt;/b&gt; байна."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Энэ мэдэгдлийг таны хураангуй самбарт автоматаар &lt;b&gt;доогуур зэрэглэл хийсэн&lt;/b&gt; байна."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Энэ зөв байсан уу?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Хөгжүүлэгчид санал хүсэлтээ мэдэгдээрэй. Энэ зөв байсан уу?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Санал хүсэлтээ илгээсэнд баярлалаа!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ОК"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g>-н мэдэгдлийн хяналтыг нээсэн"</string>
@@ -880,6 +888,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> руу зөөнө үү"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> байрлалд нэмнэ үү"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g> байрлал"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Хавтан нэмсэн"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Хавтанг хассан"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Түргэн тохиргоо засварлагч."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> мэдэгдэл: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Тохиргоог нээнэ үү."</string>
@@ -970,7 +980,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>-г ашиглаж байна"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>-г саяхан ашигласан"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(байгууллага)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Утасны дуудлага"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Утасны дуудлага"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g>-р)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"камер"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"байршил"</string>
@@ -978,7 +988,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Мэдрэгчийг унтраах"</string>
     <string name="device_services" msgid="1549944177856658705">"Төхөөрөмжийн үйлчилгээ"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Гарчиггүй"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Энэ аппыг дахин эхлүүлж, бүтэн дэлгэцэд орохын тулд товшино уу."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Зөөх"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Системийн навигацыг шинэчиллээ. Өөрчлөхийн тулд Тохиргоо руу очно уу."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Системийн навигацыг шинэчлэхийн тулд Тохиргоо руу очно уу"</string>
@@ -1032,6 +1041,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Нэмэх"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g>-н санал болгосон"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Хяналтуудыг шинэчиллээ"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Төхөөрөмжийг түгжсэн"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"ПИН нь үсэг эсвэл дүрс тэмдэгт агуулдаг"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g>-г бататгах"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"ПИН код буруу байна"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index fe1c910..fcff3df 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"स्क्रीनशॉटवर स्क्रोल करा"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"स्क्रीनशॉट डिसमिस करा"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"स्क्रीनशॉटचे पूर्वावलोकन"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"सर्वात वरची सीमा"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"तळाची सीमा"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"स्क्रीन रेकॉर्डर"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"स्क्रीन रेकॉर्डिंग प्रोसेस सुरू"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"स्क्रीन रेकॉर्ड सत्रासाठी सुरू असलेली सूचना"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"सूर्योदयापर्यंत"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> वाजता सुरू होते"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> पर्यंत"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC अक्षम केले आहे"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC सक्षम केले आहे"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC वापरण्यासाठी स्क्रीन अनलॉक करा"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"हे डिव्हाइस तुमच्या संस्थेचे आहे"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"हे डिव्हाइस <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> चे आहे"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"फोनसाठी चिन्हावरून स्वाइप करा"</string>
     <string name="voice_hint" msgid="7476017460191291417">"व्हॉइस सहाय्यासाठी चिन्हावरून स्वाइप करा"</string>
     <string name="camera_hint" msgid="4519495795000658637">"कॅमेर्‍यासाठी चिन्हावरून स्वाइप करा"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"प्रोफाईल दर्शवा"</string>
     <string name="user_add_user" msgid="4336657383006913022">"वापरकर्ता जोडा"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"नवीन वापरकर्ता"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"अतिथी सत्र संपायचे का?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"अतिथी सत्र संपवा"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"अतिथी काढायचे?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"या सत्रातील सर्व अ‍ॅप्स आणि डेटा हटवला जाईल."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"सत्र संपवा"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"काढा"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"अतिथी, तुमचे पुन्‍हा स्‍वागत आहे!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"तुम्ही तुमचे सत्र सुरू ठेवू इच्छिता?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"येथून सुरू करा"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"आपल्या संस्थेने आपल्या कार्य प्रोफाइलवर प्रमाणपत्र अधिकार इंस्टॉल केला आहे. आपल्या सुरक्षित नेटवर्क रहदारीचे परीक्षण केले जाऊ शकते किंवा ती सुधारली जाऊ शकते."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"या डिव्हाइसवर प्रमाणपत्र अधिकार इंस्टॉल केला आहे. आपल्या सुरक्षित नेटवर्क रहदारीचे परीक्षण केले जाऊ शकते किंवा ती सुधारली जाऊ शकते."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"आपल्या प्रशासकाने नेटवर्क लॉगिंग सुरू केले आहे, जे आपल्या डिव्हाइसवरील रहदारीचे परीक्षण करते."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"तुमच्या ॲडमिनने नेटवर्क लॉग इन सुरू केले आहे, जे तुमच्या कार्य प्रोफाइलमधील रहदारीचे निरीक्षण करत असले तरी तुमच्या वैयक्तिक प्रोफाइलमधील रहदारीचे निरीक्षण करत नाही."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"तुम्‍ही <xliff:g id="VPN_APP">%1$s</xliff:g> शी कनेक्‍ट केले आहे, जे ईमेल, अ‍ॅप्स आणि वेबसाइटसहित आपल्‍या नेटवर्क क्रिया मॉनिटर करू शकते."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"तुम्‍ही <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="368812367182387320">"तुमचे कार्य प्रोफाइल <xliff:g id="VPN_APP">%1$s</xliff:g> शी कनेक्‍ट केले आहे, जे ईमेल, अ‍ॅप्स आणि वेबसाइटसह आपल्‍या नेटवर्क क्रियाकलापाचे परीक्षण करू शकते."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. म्यूट करण्यासाठी टॅप करा. प्रवेशक्षमता सेवा म्यूट केल्या जाऊ शकतात."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. व्हायब्रेट सेट करण्यासाठी टॅप करा."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. म्यूट करण्यासाठी टॅप करा."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"म्यूट करा"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"म्यूट काढून टाका"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"व्हायब्रेट करा"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"सिस्टमद्वारे या सूचनेला आपोआप &lt;b&gt;सायलंट म्हणून डीमोट केले&lt;/b&gt; गेले."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"तुमच्या रंगछटेमध्ये या सूचनेला आपोआप &lt;b&gt;थोडी जास्त&lt;/b&gt; म्हणून रँक केले गेले."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"तुमच्या रंगछटेमध्ये या सूचनेला आपोआप &lt;b&gt;थोडी कमी&lt;/b&gt; म्हणून रँक केले गेले."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"हे बरोबर होते का?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"डेव्हलपरला तुमचा फीडबॅक कळवा. हे बरोबर होते का?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"तुमच्‍या फीडबॅकबद्दल धन्यवाद!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ओके"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी सूचना नियंत्रणे खुली आहेत"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> यावर हलवा"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> स्थानावर जोडा"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"स्थान <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"टाइल जोडली"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"टाइल काढून टाकली"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"द्रुत सेटिंग्ज संपादक."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> सूचना: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"सेटिंग्ज उघडा."</string>
@@ -967,23 +979,17 @@
     <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ॲप्लिकेशन्स तुमचे <xliff:g id="TYPES_LIST">%s</xliff:g> वापरत आहे."</string>
     <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
     <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" आणि "</string>
-    <!-- no translation found for ongoing_privacy_dialog_using_op (4125175620929701569) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_recent_op (4255923947334262404) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_enterprise (4082735415905550729) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_phonecall (3526223335298089311) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_attribution_text (9186683306719924646) -->
-    <skip />
+    <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> हे <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> वापरत आहे"</string>
+    <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ने अलीकडे <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> वापरले आहे"</string>
+    <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(एंटरप्राइझ)"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"फोन कॉल"</string>
+    <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> द्वारे)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"कॅमेरा"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"स्थान"</string>
     <string name="privacy_type_microphone" msgid="9136763906797732428">"मायक्रोफोन"</string>
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"सेन्सर बंद आहेत"</string>
     <string name="device_services" msgid="1549944177856658705">"डिव्हाइस सेवा"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"शीर्षक नाही"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"हे अ‍ॅप रीस्टार्ट करण्यासाठी आणि फुल स्क्रीन करण्यासाठी टॅप करा."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"हलवा"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"सिस्टम नेव्हिगेशन अपडेट केले. बदल करण्यासाठी, सेटिंग्जवर जा."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"सिस्टम नेव्हिगेशन अपडेट करण्यासाठी सेटिंग्जवर जा"</string>
@@ -1037,6 +1043,8 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"जोडा"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ने सुचवले आहे"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"नियंत्रणे अपडेट केली आहेत"</string>
+    <!-- no translation found for controls_tile_locked (731547768182831938) -->
+    <skip />
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"पिनमध्ये अक्षरे किंवा चिन्हे आहेत"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> ची पडताळणी करा"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"चुकीचा पिन"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index b1d0b47..e723ec6 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Penatalan tangkapan skrin"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ketepikan tangkapan skrin"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Pratonton tangkapan skrin"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Sempadan atas"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Sempadan bawah"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Perakam Skrin"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Memproses rakaman skrin"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pemberitahuan breterusan untuk sesi rakaman skrin"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hingga matahari trbt"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Dihidupkan pada <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Hingga <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC dilumpuhkan"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC didayakan"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Buka kunci untuk menggunakan NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Peranti ini milik organisasi anda"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Peranti ini milik <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Leret dari ikon untuk telefon"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Leret dari ikon untuk bantuan suara"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Leret dari ikon untuk kamera"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Tunjuk profil"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Tambah pengguna"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Pengguna baharu"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Tamatkan sesi tetamu?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Tamatkan sesi tetamu"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Alih keluar tetamu?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Semua apl dan data dalam sesi ini akan dipadam."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Tamatkan sesi"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Alih keluar"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Selamat kembali, tetamu!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Adakah anda ingin meneruskan sesi anda?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Mulakan semula"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Organisasi anda memasang sijil kuasa dalam profil kerja anda. Trafik rangkaian selamat anda mungkin dipantau atau diubah suai."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Sijil kuasa dipasang pada peranti ini. Trafik rangkaian selamat anda mungkin dipantau atau diubah suai."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Pentadbir anda telah menghidupkan pengelogan rangkaian yang memantau trafik pada peranti anda."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Pentadbir anda telah menghidupkan pengelogan rangkaian yang memantau trafik dalam profil kerja anda tetapi bukan dalam profil peribadi anda."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Anda dihubungkan ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang boleh memantau aktiviti rangkaian anda, termasuk e-mel, apl dan tapak web."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Anda dihubungkan ke <xliff:g id="VPN_APP_0">%1$s</xliff:g> dan <xliff:g id="VPN_APP_1">%2$s</xliff:g>, yang boleh memantau aktiviti rangkaian anda, termasuk e-mel, apl dan tapak web."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Profil kerja anda dihubungkan ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang dapat memantau aktiviti rangkaian anda, termasuk e-mel, apl dan tapak web."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Ketik untuk meredam. Perkhidmatan kebolehaksesan mungkin diredamkan."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Ketik untuk menetapkan pada getar."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Ketik untuk meredam."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"redam"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"nyahredam"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"getar"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Pemberitahuan ini secara automatik &lt;b&amp;gtditurunkan taraf kepada Senyap&lt;/b&gt; oleh sistem."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Pemberitahuan ini secara automatik &lt;b&gt;dinilai lebih tinggi&lt;/b&gt; dalam rona warna anda."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Pemberitahuan ini secara automatik &lt;b&gt;dinilai lebih rendah&lt;/b&gt; dalam rona warna anda."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Adakah ini betul?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Beritahu pembangun tentang maklum balas anda. Adakah ini betul?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Terima kasih atas maklum balas anda!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Kawalan pemberitahuan untuk <xliff:g id="APP_NAME">%1$s</xliff:g> dibuka"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Alih ke <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Tambahkan pada kedudukan <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Kedudukan <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Jubin ditambah"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Jubin dialih keluar"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor tetapan pantas."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Pemberitahuan <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Buka tetapan."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> sedang menggunakan <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> menggunakan <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> baru-baru ini"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(perusahaan)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Panggilan telefon"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Panggilan telefon"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(melalui <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"lokasi"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Penderia dimatikan"</string>
     <string name="device_services" msgid="1549944177856658705">"Perkhidmatan Peranti"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Tiada tajuk"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Ketik untuk memulakan semula apl ini dan menggunakan skrin penuh."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Alih"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigasi sistem dikemas kini. Untuk membuat perubahan, pergi ke Tetapan."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Pergi ke Tetapan untuk mengemas kini navigasi sistem"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Tambah"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Dicadangkan oleh <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Kawalan dikemas kini"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Peranti dikunci"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN mengandungi huruf atau simbol"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Sahkan <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN salah"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 42b5b23..c57a94c 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"ဖန်သားပြင်ဓာတ်ပုံကို လှိမ့်ရန်"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ဖန်သားပြင်ဓာတ်ပုံကို ပယ်သည်"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ဖန်သားပြင်ဓာတ်ပုံ အစမ်းကြည့်ရှုခြင်း"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"ထိပ်ပိုင်းအနားသတ်"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"အောက်ခြေအနားသတ်"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"ဖန်သားပြင် ရိုက်ကူးမှု"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ဖန်သားပြင်ရိုက်ကူးနေသည်"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ဖန်သားပြင် ရိုက်ကူးသည့် စက်ရှင်အတွက် ဆက်တိုက်လာနေသော အကြောင်းကြားချက်"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"နေထွက်ချိန် အထိ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> တွင် ဖွင့်မည်"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> အထိ"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ကို ပိတ်ထားသည်"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ကို ဖွင့်ထားသည်"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ကို အသုံးပြုရန် လော့ခ်ဖွင့်ပါ"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"ဤစက်ကို သင့်အဖွဲ့အစည်းက ပိုင်ဆိုင်သည်"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"ဤစက်ကို <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> က ပိုင်ဆိုင်သည်"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"ဖုန်းအတွက် သင်္ကေတပုံအား ပွတ်ဆွဲပါ"</string>
     <string name="voice_hint" msgid="7476017460191291417">"အသံအကူအညီအတွက် သင်္ကေတပုံအား ပွတ်ဆွဲပါ"</string>
     <string name="camera_hint" msgid="4519495795000658637">"ကင်မရာအတွက် သင်္ကေတပုံအား ပွတ်ဆွဲပါ"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"ပရိုဖိုင်ကို ပြရန်"</string>
     <string name="user_add_user" msgid="4336657383006913022">"အသုံးပြုသူ ထည့်ရန်"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"အသုံးပြုသူ အသစ်"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"ဧည့်သည်စက်ရှင်ကို အဆုံးသတ်မလား။"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"ဧည့်သည်ဆက်ရှင်ကို အဆုံးသတ်ရန်"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"ဧည့်သည်ကို ဖယ်ထုတ်လိုက်ရမလား?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ဒီချိတ်ဆက်မှု ထဲက အက်ပ်များ အားလုံး နှင့် ဒေတာကို ဖျက်ပစ်မည်။"</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"သတ်မှတ်ပေးထားသည့်အချိန် ပြီးဆုံးပြီ"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"ဖယ်ထုတ်ပါ"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"ပြန်လာတာ ကြိုဆိုပါသည်၊ ဧည့်သည်!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"သင်သည် သင်၏ ချိတ်ဆက်မှုကို ဆက်ပြုလုပ် လိုပါသလား?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"အစမှ ပြန်စပါ"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"သင်၏ အဖွဲ့အစည်းသည် သင်၏ အလုပ်ပရိုဖိုင်တွင် စီမံခန့်ခွဲမှုဆိုင်ရာ အသိအမှတ်ပြုလက်မှတ်ကို ထည့်သွင်းထားပါသည်။ လုံခြုံမှုရှိသော ကွန်ရက်ဒေတာစီးဆင်းမှုကို စောင့်ကြည့်ခြင်း သို့မဟုတ် ပြုပြင်ခြင်းများ ပြုလုပ်နိုင်ပါသည်။"</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"ဤစက်ပစ္စည်းတွင် စီမံခန့်ခွဲမှုဆိုင်ရာ အသိအမှတ်ပြုလက်မှတ်ကို ထည့်သွင်းထားပါသည်။ လုံခြုံမှုရှိသော ကွန်ရက်ဒေတာစီးဆင်းမှုကို စောင့်ကြည့်ခြင်း သို့မဟုတ် ပြုပြင်ခြင်းများ ပြုလုပ်နိုင်ပါသည်။"</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"စက်ပစ္စည်းပေါ်ရှိ ဒေတာစီးဆင်းမှုများကို စောင့်ကြည့်နိုင်သည့်  ကွန်ရက်မှတ်တမ်းတင်ခြင်းစနစ်ကို သင်၏ စီမံခန့်ခွဲသူက ဖွင့်ထားပါသည်။"</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"သင်၏စီမံခန့်ခွဲသူက ကွန်ရက်မှတ်တမ်းတင်ခြင်းကို ဖွင့်လိုက်သည်။ ၎င်းသည် သင့်အလုပ်ပရိုဖိုင်ရှိ ဒေတာစီးဆင်းမှုကို စောင့်ကြည့်သော်လည်း ကိုယ်ပိုင်ပရိုဖိုင်တွင် မစောင့်ကြည့်ပါ။"</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"သင်သည် သင်၏ အီးမေးလ်၊ အက်ပ်နှင့် ဝဘ်ဆိုက်များအပါအဝင် ကွန်ရက်လုပ်ဆောင်ချက်ကို စောင့်ကြည့်နိုင်သည့် <xliff:g id="VPN_APP">%1$s</xliff:g> သို့ ချိတ်ဆက်ထားပါသည်။"</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"သင်သည် သင်၏ အီးမေးလ်၊ အက်ပ်နှင့် ဝဘ်ဆိုက်များအပါအဝင် သင်၏ကွန်ရက်လုပ်ဆောင်ချက်ကို စောင့်ကြည့်နိုင်သည့် <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="368812367182387320">"သင်၏အလုပ်ပရိုဖိုင်သည် အီးမေးလ်၊ အက်ပ်နှင့် ဝဘ်ဆိုက်များအပါအဝင် သင်၏ကွန်ရက်လုပ်ဆောင်ချက်ကို စောင့်ကြည့်နိုင်သည့် <xliff:g id="VPN_APP">%1$s</xliff:g> သို့ ချိတ်ဆက်ထားပါသည်။"</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s။ အသံပိတ်ရန် တို့ပါ။ အများသုံးစွဲနိုင်မှု ဝန်ဆောင်မှုများကို အသံပိတ်ထားနိုင်ပါသည်။"</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s။ တုန်ခါခြင်းသို့ သတ်မှတ်ရန်တို့ပါ။"</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s။ အသံတိတ်ရန် တို့ပါ။"</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"အသံတိတ်ရန်"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"အသံဖွင့်ရန်"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"တုန်ခါမှု"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"ဤအကြောင်းကြားချက်ကို စနစ်က အလိုအလျောက် &lt;b&gt;အသံတိတ်ခြင်းသို့ ပြန်ချိန်ညှိထားသည်&lt;/b&gt;။"</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"ဤအကြောင်းကြားချက်ကို သင့်အကြောင်းကြားစာအကွက်တွင် အလိုအလျောက် &lt;b&gt;အဆင့်တိုးထားသည်&lt;/b&gt;။"</string>
     <string name="feedback_demoted" msgid="951884763467110604">"ဤအကြောင်းကြားချက်ကို သင့်အကြောင်းကြားစာအကွက်တွင် အလိုအလျောက် &lt;b&gt;အဆင့်လျှော့ထားသည်&lt;/b&gt;။"</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"ဤအရာက မှန်ပါသလား။"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"သင့်အကြံပြုချက်ကို ဆော့ဖ်ဝဲအင်ဂျင်နီယာအား အသိပေးပါ။ ဤအရာက မှန်ပါသလား။"</string>
     <string name="feedback_response" msgid="4671729244976641339">"အကြံပြုချက်အတွက် ကျေးဇူးတင်ပါသည်"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် အကြောင်းကြားချက်ထိန်းချုပ်မှုများကို ဖွင့်ထားသည်"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> သို့ ရွှေ့ရန်"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> အနေအထားသို့ ပေါင်းထည့်ရန်"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g> အနေအထား"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"အကွက်ငယ်ကို ထည့်ပြီးပါပြီ"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"အကွက်ငယ်ကို ဖယ်ရှားပြီးပါပြီ"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"မြန်ဆန်သည့် ဆက်တင်တည်းဖြတ်စနစ်"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> အကြောင်းကြားချက် − <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ဆက်တင်များကို ဖွင့်ပါ။"</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> က <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ကို အသုံးပြုနေသည်"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> က <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ကို မကြာသေးမီက အသုံးပြုထားသည်"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(လုပ်ငန်းသုံး)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"ဖုန်းခေါ်ဆိုမှု"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"ဖုန်းခေါ်ဆိုမှု"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> မှတစ်ဆင့်)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"ကင်မရာ"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"တည်နေရာ"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"အာရုံခံကိရိယာများ ပိတ်ထားသည်"</string>
     <string name="device_services" msgid="1549944177856658705">"စက်ပစ္စည်းဝန်ဆောင်မှုများ"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"ခေါင်းစဉ် မရှိပါ"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"ဤအက်ပ်ကို ပြန်စတင်ပြီး မျက်နှာပြင်အပြည့်လုပ်ရန် တို့ပါ။"</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"ရွှေ့ရန်"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"စနစ်လမ်းညွှန်ခြင်း အပ်ဒိတ်လုပ်ပြီးပါပြီ။ အပြောင်းအလဲများ ပြုလုပ်ရန် \'ဆက်တင်များ\' သို့သွားပါ။"</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"စနစ်လမ်းညွှန်ခြင်း အပ်ဒိတ်လုပ်ရန် \'ဆက်တင်များ\' သို့သွားပါ"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"ထည့်ရန်"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> က အကြံပြုထားသည်"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"ထိန်းချုပ်မှု အပ်ဒိတ်လုပ်ပြီးပြီ"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"စက်ကိုလော့ခ်ချထားသည်"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"ပင်နံပါတ်တွင် စာလုံး သို့မဟုတ် သင်္ကေတများပါဝင်သည်"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> ကို အတည်ပြုခြင်း"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"ပင်နံပါတ် မှားနေသည်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index ef48f8f..997147d 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Rull skjermdumpen"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Avvis skjermdumpen"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Forhåndsvisning av skjermdump"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Øvre grense"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Nedre grense"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Skjermopptaker"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandler skjermopptaket"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Vedvarende varsel for et skjermopptak"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Til soloppgang"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Slås på klokken <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Til <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC er slått av"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC er slått på"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Lås opp for å bruke NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Denne enheten tilhører organisasjonen din"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Denne enheten tilhører <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Sveip ikonet for å åpne telefon"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Sveip fra ikonet for å åpne talehjelp"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Sveip ikonet for å åpne kamera"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Vis profil"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Legg til brukere"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Ny bruker"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Vil du avslutte gjesteøkten?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Avslutt gjesteøkten"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Vil du fjerne gjesten?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle appene og all informasjon i denne økten slettes."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Avslutt økten"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Fjern"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Velkommen tilbake, gjest!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Vil du fortsette økten?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start på nytt"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Organisasjonen din installerte en sertifiseringsinstans i jobbprofilen din. Den sikre nettverkstrafikken din kan overvåkes eller endres."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"En sertifiseringsinstans er installert på denne enheten. Den sikre nettverkstrafikken din kan overvåkes eller endres."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Administratoren din har slått på loggføring av nettverk, som overvåker trafikken på enheten din."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Administratoren din har slått på loggføring av nettverk, som overvåker trafikken i jobbprofilen din, men ikke i den personlige profilen din."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Du er koblet til <xliff:g id="VPN_APP">%1$s</xliff:g>, som kan overvåke nettverksaktiviteten din, inkludert e-post, apper og nettsteder."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Du er koblet til <xliff:g id="VPN_APP_0">%1$s</xliff:g> og <xliff:g id="VPN_APP_1">%2$s</xliff:g>, som kan overvåke nettverksaktiviteten din, inkludert e-post, apper og nettsteder."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Jobbprofilen din er koblet til <xliff:g id="VPN_APP">%1$s</xliff:g>, som kan overvåke nettverksaktiviteten din, inkludert e-poster, apper og nettsteder."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Trykk for å slå av lyden. Lyden kan bli slått av for tilgjengelighetstjenestene."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Trykk for å angi vibrasjon."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Trykk for å slå av lyden."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"kutt lyden"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"slå på lyden"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrer"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Dette varselet ble automatisk &lt;b&gt;nedgradert til lydløst&lt;/b&gt; av systemet."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Dette varselet ble automatisk &lt;b&gt;rangert høyere&lt;/b&gt; i panelet."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Dette varselet ble automatisk &lt;b&gt;rangert lavere&lt;/b&gt; i panelet."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Var det riktig?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Gi utvikleren tilbakemeldingen din. Var det riktig?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Takk for tilbakemeldingen!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Varselinnstillingene for <xliff:g id="APP_NAME">%1$s</xliff:g> er åpnet"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Flytt til <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Legg til posisjonen <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posisjon <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"En infobrikke er lagt til"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"En infobrikke er fjernet"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Redigeringsvindu for hurtiginnstillinger."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>-varsel: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Åpne innstillingene."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> bruker <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> har brukt <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> nylig"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(enterprise)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonsamtale"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefonsamtale"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(til og med <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"posisjon"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensorer er av"</string>
     <string name="device_services" msgid="1549944177856658705">"Enhetstjenester"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Ingen tittel"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Trykk for å starte denne appen på nytt og vise den i fullskjerm."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Flytt"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Systemnavigeringen er oppdatert. For å gjøre endringer, gå til Innstillinger."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Gå til Innstillinger for å oppdatere systemnavigeringen"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Legg til"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Foreslått av <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Kontrollene er oppdatert"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Enheten er låst"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-koden inneholder bokstaver eller symboler"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Bekreft <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Feil PIN-kode"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 2594e8c..e03ee5b 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"स्क्रिनसट स्क्रोल गर्नुहोस्"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"स्क्रिनसट हटाउनुहोस्"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"स्क्रिनसटको पूर्वावलोकन"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"सिरानको सीमा"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"फेदको सीमा"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"स्क्रिन रेकर्डर"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"स्क्रिन रेकर्डिङको प्रक्रिया अघि बढाइँदै"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"कुनै स्क्रिन रेकर्ड गर्ने सत्रका लागि चलिरहेको सूचना"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"सूर्योदयसम्म"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> मा सक्रिय"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> सम्म"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC लाई असक्षम पारिएको छ"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC लाई सक्षम पारिएको छ"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC प्रयोग गर्न स्क्रिन अनलक गर्नुहोस्"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"यो यन्त्र तपाईंको सङ्गठनको स्वामित्वमा छ"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"यो यन्त्र <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> को स्वामित्वमा छ"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"फोनको लागि आइकनबाट स्वाइप गर्नुहोस्"</string>
     <string name="voice_hint" msgid="7476017460191291417">"आवाज सहायताका लागि आइकनबाट स्वाइप गर्नुहोस्"</string>
     <string name="camera_hint" msgid="4519495795000658637">"क्यामेराको लागि आइकनबाट स्वाइप गर्नुहोस्"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"प्रोफाइल देखाउनुहोस्"</string>
     <string name="user_add_user" msgid="4336657383006913022">"प्रयोगकर्ता थप्नुहोस्"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"नयाँ प्रयोगकर्ता"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"अतिथिको सत्र अन्त्य गर्ने हो?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"अतिथिको सत्र अन्त्य गर्नुहोस्"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"अतिथि हटाउने हो?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"यस सत्रमा सबै एपहरू र डेटा मेटाइनेछ।"</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"सत्र अन्त्य गर्नुहोस्"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"हटाउनुहोस्"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"पुनः स्वागत, अतिथि!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"तपाईं आफ्नो सत्र जारी गर्न चाहनुहुन्छ?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"सुरु गर्नुहोस्"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"तपाईंको संगठनले तपाईंको कार्य प्रोफाइलमा एउटा प्रमाणपत्र सम्बन्धी अख्तियार सुविधा स्थापना गरेको छ। तपाईंको सुरक्षित नेटवर्क ट्राफिकको अनुगमन वा परिमार्जन हुनसक्छ।"</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"यस यन्त्रमा एउटा प्रमाणपत्र सम्बन्धी अख्तियार सुविधा स्थापना गरिएको छ। तपाईंको सुरक्षित नेटवर्कको ट्राफिकको अनुगमन वा परिमार्जन हुनसक्छ।"</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"तपाईंका प्रशासकले तपाईंको यन्त्रमा ट्राफिकको अनुगमन गर्ने नेटवर्क लग गर्ने प्रक्रियालाई सक्रिय गर्नुभएको छ।"</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"तपाईंका एड्मिनले \'नेटवर्क लगिङ\' सुविधा अन गर्नुभएको छ। यो सुविधाले तपाईंको कार्य प्रोफाइलको ट्राफिक अनुगमन गर्छ तर व्यक्तिगत प्रोफाइलको ट्राफिक भने अनुगमन गर्दैन।"</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"तपाईं इमेल, एप र वेबसाइटहरू लगायत तपाईंको नेटवर्कको गतिविधिको अनुगमन गर्नसक्ने <xliff:g id="VPN_APP">%1$s</xliff:g> मा जडान हुनुहुन्छ।"</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"तपाईं इमेल, एप र वेबसाइटहरू लगायत तपाईंको नेटवर्कको गतिविधिको अनुगमन गर्नसक्ने <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="368812367182387320">"तपाईंको कार्य प्रोफाइल तपाईंका इमेल, एप र वेबसाइटहरू लगायत तपाईंको नेटवर्कको गतिविधिको अनुगमन गर्नसक्ने <xliff:g id="VPN_APP">%1$s</xliff:g> मा जडान छ।"</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s। म्यूट गर्नाका लागि ट्याप गर्नुहोस्। पहुँच सम्बन्धी सेवाहरू म्यूट हुन सक्छन्।"</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s। कम्पन मोडमा सेट गर्न ट्याप गर्नुहोस्।"</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s। म्यूट गर्न ट्याप गर्नुहोस्।"</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"म्युट गर्नुहोस्"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"अनम्युट गर्नुहोस्"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"कम्पन गर्नुहोस्"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"सिस्टमले स्वतः यस सूचनालाई &lt;b&gt;कम महत्त्वपूर्ण ठानी साइलेन्ट मोडमा&lt;/b&gt; सेट गरिदियो।"</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"तपाईंको सेडमा यो सूचना स्वतः &lt;b&gt;धेरै महत्त्वपूर्ण सूचनाका रूपमा&lt;/b&gt; सेट गरियो।"</string>
     <string name="feedback_demoted" msgid="951884763467110604">"तपाईंको सेडमा यो सूचना स्वतः &lt;b&gt;कम महत्त्वपूर्ण सूचनाका रूपमा&lt;/b&gt; सेट गरियो।"</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"के यो सही थियो?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"विकासकर्तालाई तपाईंको प्रतिक्रिया थाहा पाउन दिनुहोस्। यो कुरा सही थियो?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"तपाईंको प्रतिक्रियाका लागि धन्यवाद!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ठिक छ"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> का सूचना सम्बन्धी नियन्त्रणहरूलाई खोलियो"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"टाइल सारेर <xliff:g id="POSITION">%1$d</xliff:g> मा लैजानुहोस्"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"टाइल यो अवस्था <xliff:g id="POSITION">%1$d</xliff:g> मा हाल्नुहोस्"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"टाइल हालियो"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"टाइल हटाइयो"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"द्रुत सेटिङ सम्पादक।"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> को सूचना: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"सेटिङहरूलाई खोल्नुहोस्।"</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ले <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> प्रयोग गरिरहेको छ"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ले हालसालै <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> प्रयोग गरेको छ"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(इन्टरप्राइज)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"फोन कल"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"फोन कल"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> मार्फत)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"क्यामेरा"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"स्थान"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"सेन्सरहरू निष्क्रिय छन्"</string>
     <string name="device_services" msgid="1549944177856658705">"यन्त्रका सेवाहरू"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"शीर्षक छैन"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"यो एप पुनः सुरु गर्न ट्याप गर्नुहोस् र फुल स्क्रिन मोडमा जानुहोस्।"</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"सार्नुहोस्"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"प्रणालीको नेभिगेसन अद्यावधिक गरियो। परिवर्तन गर्न सेटिङमा जानुहोस्।"</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"प्रणालीको नेभिगेसन अद्यावधिक गर्न सेटिङमा जानुहोस्"</string>
@@ -1032,6 +1043,8 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"थप्नुहोस्"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ले सिफारिस गरेको"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"नियन्त्रण सुविधाहरू अद्यावधिक गरिए"</string>
+    <!-- no translation found for controls_tile_locked (731547768182831938) -->
+    <skip />
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN मा अक्षर वा चिन्हहरू समाविष्ट हुन्छन्"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> पुष्टि गर्नुहोस्"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN मिलेन"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 0274132..8ffc3f4 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Screenshot scrollen"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Screenshot sluiten"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Voorbeeld van screenshot"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Bovengrens"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Ondergrens"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Schermopname"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Schermopname verwerken"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Doorlopende melding voor een schermopname-sessie"</string>
@@ -345,7 +347,7 @@
     <string name="quick_settings_location_label" msgid="2621868789013389163">"Locatie"</string>
     <string name="quick_settings_location_off_label" msgid="7923929131443915919">"Locatie uit"</string>
     <string name="quick_settings_camera_label" msgid="1367149596242401934">"Camera blokkeren"</string>
-    <string name="quick_settings_mic_label" msgid="8245831073612564953">"Microfoon dempen"</string>
+    <string name="quick_settings_mic_label" msgid="8245831073612564953">"Microfoon uitzetten"</string>
     <string name="quick_settings_media_device_label" msgid="8034019242363789941">"Media-apparaat"</string>
     <string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
     <string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Alleen noodoproepen"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Tot zonsopgang"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aan om <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Tot <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is uitgeschakeld"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is ingeschakeld"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ontgrendel het apparaat om NFC te gebruiken"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Dit apparaat is eigendom van je organisatie"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Dit apparaat is eigendom van <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Swipen voor telefoon"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Swipen vanaf icoon voor spraakassistent"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Vegen voor camera"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Profiel weergeven"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Gebruiker toevoegen"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Nieuwe gebruiker"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Gastsessie beëindigen?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Gastsessie beëindigen"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Gast verwijderen?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apps en gegevens in deze sessie worden verwijderd."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Sessie beëindigen"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Verwijderen"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Welkom terug, gast!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Wil je doorgaan met je sessie?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Opnieuw starten"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Je organisatie heeft een certificeringsinstantie geïnstalleerd in je werkprofiel. Je beveiligde netwerkverkeer kan worden bijgehouden of aangepast."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Er is een certificeringsinstantie geïnstalleerd op dit apparaat. Je beveiligde netwerkverkeer kan worden bijgehouden of aangepast."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Je beheerder heeft netwerkregistratie ingeschakeld, waarmee het verkeer op je apparaat wordt bijgehouden."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Je beheerder heeft logboekregistratie voor het netwerk aangezet. Hiermee wordt verkeer in je werkprofiel bijgehouden, maar niet in je persoonlijke profiel."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Je bent verbonden met <xliff:g id="VPN_APP">%1$s</xliff:g>, waarmee je netwerkactiviteit (waaronder e-mails, apps en websites) kan worden gecontroleerd."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Je bent verbonden met <xliff:g id="VPN_APP_0">%1$s</xliff:g> en <xliff:g id="VPN_APP_1">%2$s</xliff:g>, waarmee je netwerkactiviteit (waaronder e-mails, apps en websites) kan worden bijgehouden."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Je werkprofiel is verbonden met <xliff:g id="VPN_APP">%1$s</xliff:g>, waarmee je netwerkactiviteit (waaronder e-mails, apps en websites) kan worden bijgehouden."</string>
@@ -612,16 +620,18 @@
     <string name="ring_toggle_title" msgid="5973120187287633224">"Gesprekken"</string>
     <string name="volume_ringer_status_normal" msgid="1339039682222461143">"Bellen"</string>
     <string name="volume_ringer_status_vibrate" msgid="6970078708957857825">"Trillen"</string>
-    <string name="volume_ringer_status_silent" msgid="3691324657849880883">"Dempen"</string>
+    <string name="volume_ringer_status_silent" msgid="3691324657849880883">"Geluid staat uit"</string>
     <string name="qs_status_phone_vibrate" msgid="7055409506885541979">"Telefoon op trillen"</string>
-    <string name="qs_status_phone_muted" msgid="3763664791309544103">"Telefoon gedempt"</string>
+    <string name="qs_status_phone_muted" msgid="3763664791309544103">"Telefoongeluid staat uit"</string>
     <string name="volume_stream_content_description_unmute" msgid="7729576371406792977">"%1$s. Tik om dempen op te heffen."</string>
-    <string name="volume_stream_content_description_vibrate" msgid="4858111994183089761">"%1$s. Tik om in te stellen op trillen. Toegankelijkheidsservices kunnen zijn gedempt."</string>
-    <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Tik om te dempen. Toegankelijkheidsservices kunnen zijn gedempt."</string>
+    <string name="volume_stream_content_description_vibrate" msgid="4858111994183089761">"%1$s. Tik om in te stellen op trillen. Het geluid van toegankelijkheidsservices kan hierdoor uitgaan."</string>
+    <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Tik om te dempen. Het geluid van toegankelijkheidsservices kan hierdoor uitgaan."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Tik om in te stellen op trillen."</string>
-    <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Tik om te dempen."</string>
-    <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"dempen"</string>
-    <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"dempen opheffen"</string>
+    <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Tik om geluid uit te zetten."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
+    <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"geluid uit"</string>
+    <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"geluid aanzetten"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"trillen"</string>
     <string name="volume_dialog_title" msgid="6502703403483577940">"%s-volumeknoppen"</string>
     <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Gesprekken en meldingen gaan over (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string>
@@ -716,7 +726,7 @@
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioriteit"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ondersteunt geen gespreksfuncties"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Deze meldingen kunnen niet worden aangepast."</string>
-    <string name="notification_multichannel_desc" msgid="7414593090056236179">"Deze groep meldingen kan hier niet worden geconfigureerd"</string>
+    <string name="notification_multichannel_desc" msgid="7414593090056236179">"Deze groep meldingen kan hier niet worden ingesteld"</string>
     <string name="notification_delegate_header" msgid="1264510071031479920">"Melding via proxy"</string>
     <string name="notification_channel_dialog_title" msgid="6856514143093200019">"Alle meldingen van <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="see_more_title" msgid="7409317011708185729">"Meer weergeven"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Deze melding is automatisch &lt;b&gt;verlaagd naar Stil&lt;/b&gt; door het systeem."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Deze melding is automatisch &lt;b&gt;hoger gerangschikt&lt;/b&gt; in je meldingenpaneel."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Deze melding is automatisch &lt;b&gt;lager gerangschikt&lt;/b&gt; in je meldingenpaneel."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Is dit juist?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Stuur de ontwikkelaar feedback. Was dit goed?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Bedankt voor je feedback."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Beheeropties voor meldingen voor <xliff:g id="APP_NAME">%1$s</xliff:g> geopend"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Verplaatsen naar <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Toevoegen aan positie <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Positie <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Tegel toegevoegd"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Tegel verwijderd"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor voor \'Snelle instellingen\'."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>-melding: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Instellingen openen."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> gebruikt de <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> heeft de <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> recent gebruikt"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(zakelijke versie)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefoongesprek"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefoongesprek"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(via <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"locatie"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensoren uit"</string>
     <string name="device_services" msgid="1549944177856658705">"Apparaatservices"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Geen titel"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Tik om deze app opnieuw te starten en te openen op het volledige scherm."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Verplaatsen"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Systeemnavigatie geüpdatet. Als je wijzigingen wilt aanbrengen, ga je naar Instellingen."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Ga naar Instellingen om de systeemnavigatie te updaten"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Toevoegen"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Voorgesteld door <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Bedieningselementen geüpdated"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Apparaat vergrendeld"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Pincode bevat letters of symbolen"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> verifiëren"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Onjuiste pincode"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 16d8a296..f03c31d 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"ସ୍କ୍ରିନସଟ୍ ସ୍କ୍ରୋଲ୍ କରନ୍ତୁ"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ସ୍କ୍ରିନସଟ୍ ଖାରଜ କରନ୍ତୁ"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ସ୍କ୍ରିନସଟର ପ୍ରିଭ୍ୟୁ"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"ଶୀର୍ଷ ସୀମାରେଖା"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"ନିମ୍ନ ସୀମାରେଖା"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"ସ୍କ୍ରିନ୍ ରେକର୍ଡର୍"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ସ୍କ୍ରିନ ରେକର୍ଡିଂର ପ୍ରକ୍ରିୟାକରଣ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ଏକ ସ୍କ୍ରି‍ନ୍‍ ରେକର୍ଡ୍‍ ସେସନ୍‍ ପାଇଁ ଚାଲୁଥିବା ବିଜ୍ଞପ୍ତି"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ସକାଳ ପର୍ଯ୍ୟନ୍ତ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>ରେ ଚାଲୁ ହେବ"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> ପର୍ଯ୍ୟନ୍ତ"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ଅକ୍ଷମ କରାଯାଇଛି"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ସକ୍ଷମ କରାଯାଇଛି"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ବ୍ୟବହାର କରିବାକୁ ଅନଲକ୍ କରନ୍ତୁ"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"ଏହି ଡିଭାଇସଟି ଆପଣଙ୍କ ସଂସ୍ଥାର ଅଟେ"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"ଏହି ଡିଭାଇସଟି <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>ର ଅଟେ"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"ଫୋନ୍‍ ପାଇଁ ଆଇକନରୁ ସ୍ୱାଇପ୍‍ କରନ୍ତୁ"</string>
     <string name="voice_hint" msgid="7476017460191291417">"ଭଏସ୍‍ ସହାୟକ ପାଇଁ ଆଇକନରୁ ସ୍ୱାଇପ୍‍ କରନ୍ତୁ"</string>
     <string name="camera_hint" msgid="4519495795000658637">"କ୍ୟାମେରା ପାଇଁ ଆଇକନରୁ ସ୍ୱାଇପ୍‍ କରନ୍ତୁ"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"ପ୍ରୋଫାଇଲ୍ ଦେଖାନ୍ତୁ"</string>
     <string name="user_add_user" msgid="4336657383006913022">"ଉପଯୋଗକର୍ତ୍ତାଙ୍କୁ ଯୋଗ କରନ୍ତୁ"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"ନୂଆ ଉପଯୋଗକର୍ତ୍ତା"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"ଅତିଥି ସେସନ୍ ଶେଷ କରିବେ?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"ଅତିଥି ସେସନ୍ ଶେଷ କରନ୍ତୁ"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"ଅତିଥିଙ୍କୁ କାଢ଼ିଦେବେ?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ଏହି ଅବଧିର ସମସ୍ତ ଆପ୍‌ ଓ ଡାଟା ଡିଲିଟ୍‌ ହୋଇଯିବ।"</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"ସେସନ୍ ଶେଷ କରନ୍ତୁ"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"କାଢ଼ିଦିଅନ୍ତୁ"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"ପୁଣି ସ୍ୱାଗତ, ଅତିଥି!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"ଆପଣ ନିଜର ଅବଧି ଜାରି ରଖିବାକୁ ଚାହାନ୍ତି କି?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ଆରମ୍ଭ କରନ୍ତୁ"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"ଆପଣଙ୍କ ୱର୍କ ପ୍ରୋଫାଇଲରେ ଆପଣଙ୍କ ସଂସ୍ଥା ଏକ ସର୍ଟିଫିକେଟ୍‍ ଅଥରିଟି ଇନଷ୍ଟଲ୍‍ କରିଛନ୍ତି। ଆପଣଙ୍କ ସୁରକ୍ଷିତ ନେଟୱର୍କ ଟ୍ରାଫିକ୍‍ ନୀରିକ୍ଷଣ କିମ୍ବା ସଂଶୋଧନ କରାଯାଇ ପାରେ।"</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"ଏହି ଡିଭାଇସରେ ଏକ ସର୍ଟିଫିକେଟ୍‍ ଅଥରିଟି ଇନଷ୍ଟଲ୍‍ କରାଯାଇଛି। ଆପଣଙ୍କ ସୁରକ୍ଷିତ ନେଟୱର୍କ ଟ୍ରାଫିକ୍‍ ନୀରିକ୍ଷଣ କିମ୍ବା ସଂଶୋଧନ କରାଯାଇ ପାରେ।"</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"ଆପଣଙ୍କ ଆଡମିନ୍‍ ନେଟୱର୍କ ଲଗଇନ୍‍ କରିବା ଅନ୍‍ କରିଛନ୍ତି, ଯାହା ଆପଣଙ୍କ ଡିଭାଇସରେ ଟ୍ରାଫିକ୍‍ ନୀରିକ୍ଷଣ କରେ।"</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"ଆପଣଙ୍କ ଆଡମିନ୍ ନେଟୱାର୍କ ଲଗିଂ ଚାଲୁ କରିଛନ୍ତି, ଯାହା ଆପଣଙ୍କ ୱାର୍କ ପ୍ରୋଫାଇଲରେ ଟ୍ରାଫିକ୍ ନିରୀକ୍ଷଣ କରେ କିନ୍ତୁ ଆପଣଙ୍କ ବ୍ୟକ୍ତିଗତ ପ୍ରୋଫାଇଲରେ ନୁହେଁ।"</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"ଆପଣ <xliff:g id="VPN_APP">%1$s</xliff:g>ରେ ସଂଯୁକ୍ତ, ଯାହା ଇମେଲ୍‍, ଆପ୍‌ ଓ ୱେବସାଇଟ୍‍ ସମେତ ଆପଣଙ୍କ ନେଟୱର୍କ ଗତିବିଧିକୁ ନିରୀକ୍ଷଣ କରିପାରେ।"</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"ଆପଣ <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="368812367182387320">"ଆପଣଙ୍କ ୱର୍କ ପ୍ରୋଫାଇଲ୍‍ <xliff:g id="VPN_APP">%1$s</xliff:g>ରେ ସଂଯୁକ୍ତ, ଯାହା ଇମେଲ୍‍, ଆପ୍‌ ଓ ୱେବସାଇଟ୍‍ ସମେତ ଆପଣଙ୍କ ନେଟୱର୍କ ଗତିବିଧିକୁ ନିରୀକ୍ଷଣ କରିପାରେ।"</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s। ମ୍ୟୁଟ୍‍ କରିବାକୁ ଟାପ୍‍ କରନ୍ତୁ। ଆକ୍ସେସିବିଲିଟୀ ସର୍ଭିସ୍‌ ମ୍ୟୁଟ୍‍ କରାଯାଇପାରେ।"</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s। ଭାଇବ୍ରେଟରେ ସେଟ୍‍ କରିବାକୁ ଟାପ୍‍ କରନ୍ତୁ।"</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s। ମ୍ୟୁଟ୍‍ କରିବାକୁ ଟାପ୍‍ କରନ୍ତୁ।"</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"ମ୍ୟୁଟ୍"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"ଅନ୍‍-ମ୍ୟୁଟ୍ କରନ୍ତୁ"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"ଭାଇବ୍ରେଟ୍"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"ସିଷ୍ଟମ୍ ଏହି ବିଜ୍ଞପ୍ତିକୁ ସ୍ୱଚାଳିତ ଭାବେ &lt;b&gt;ନୀରବକୁ ଡିମୋଟ୍ କରିଛି&lt;/b&gt;।"</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"ଆପଣଙ୍କ ସେଡରେ ସ୍ୱଚାଳିତ ଭାବେ ଏହି ବିଜ୍ଞପ୍ତିର &lt;b&gt;ରେଙ୍କ ଉପରକୁ&lt;/b&gt; କରାଯାଇଛି।"</string>
     <string name="feedback_demoted" msgid="951884763467110604">"ଆପଣଙ୍କ ସେଡରେ ସ୍ୱଚାଳିତ ଭାବେ ଏହି ବିଜ୍ଞପ୍ତିର &lt;b&gt;ରେଙ୍କ ତଳକୁ&lt;/b&gt; କରାଯାଇଛି।"</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"ଏହା ଠିକ୍ ଥିଲା କି?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"ଡେଭଲପରଙ୍କୁ ଆପଣଙ୍କ ମତାମତ ଜଣାନ୍ତୁ। ଏହା ଠିକ୍ ଥିଲା କି?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"ଆପଣଙ୍କ ମତାମତ ପାଇଁ ଧନ୍ୟବାଦ!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ଠିକ୍ ଅଛି"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ବିଜ୍ଞପ୍ତି ନିୟନ୍ତ୍ରଣ ଖୋଲା ଯାଇଛି"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g>କୁ ମୁଭ୍ କରନ୍ତୁ"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> ଅବସ୍ଥିତିରେ ଯୋଗ କରନ୍ତୁ"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"ଅବସ୍ଥିତି <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"ଟାଇଲ୍ ଯୋଗ କରାଯାଇଛି"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"ଟାଇଲ୍ କାଢ଼ି ଦିଆଯାଇଛି"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ଦ୍ରୁତ ସେଟିଙ୍ଗ ଏଡିଟର୍।"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> ବିଜ୍ଞପ୍ତି: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ସେଟିଂସ୍ ଖୋଲନ୍ତୁ।"</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ବ୍ୟବହାର କରୁଛି"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ଏବେ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ବ୍ୟବହାର କରିଛି"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(ଏଣ୍ଟରପ୍ରାଇଜ୍)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"ଫୋନକଲ୍"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"ଫୋନ୍ କଲ୍"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> ମାଧ୍ୟମରେ)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"କ୍ୟାମେରା"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"ଲୋକେସନ୍‍"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"ସେନ୍ସର୍‍ଗୁଡ଼ିକ ବନ୍ଦ ଅଛି"</string>
     <string name="device_services" msgid="1549944177856658705">"ଡିଭାଇସ୍‍ ସେବାଗୁଡିକ"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"କୌଣସି ଶୀର୍ଷକ ନାହିଁ"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"ଏହି ଆପ୍‌କୁ ରିଷ୍ଟାର୍ଟ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ ଏବଂ ଫୁଲ୍‌ସ୍କ୍ରିନ୍‌କୁ ଯାଆନ୍ତୁ।"</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"ନିଅନ୍ତୁ"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"ସିଷ୍ଟମ୍ ନାଭିଗେସନ୍ ଅପ୍‌ଡେଟ୍ ହୋଇଛି। ପରିବର୍ତ୍ତନ କରିବା ପାଇଁ, ସେଟିଂସ୍‌କୁ ଯାଆନ୍ତୁ।"</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"ସିଷ୍ଟମ୍ ନାଭିଗେସନ୍ ଅପ୍‌ଡେଟ୍ କରିବା ପାଇଁ ସେଟିଂସ୍‍କୁ ଯାଆନ୍ତୁ"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"ଯୋଗ କରନ୍ତୁ"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ଦ୍ଵାରା ପ୍ରସ୍ତାବିତ"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ଅପଡେଟ୍ କରାଯାଇଛି"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"ଡିଭାଇସ୍ ଲକ୍ ହୋଇଯାଇଛି"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PINରେ ଅକ୍ଷର କିମ୍ୱା ପ୍ରତୀକଗୁଡ଼ିକ ଥାଏ"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> ଯାଞ୍ଚ କରନ୍ତୁ"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"ଭୁଲ PIN"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index d33455d..459b163 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਨੂੰ ਸਕ੍ਰੋਲ ਕਰੋ"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਖਾਰਜ ਕਰੋ"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਪੂਰਵ-ਝਲਕ"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"ਉੱਪਰ ਦੀ ਸੀਮਾ"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"ਹੇਠਾਂ ਦੀ ਸੀਮਾ"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਰ"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ ਜਾਰੀ ਹੈ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ਕਿਸੇ ਸਕ੍ਰੀਨ ਰਿਕਾਰਡ ਸੈਸ਼ਨ ਲਈ ਚੱਲ ਰਹੀ ਸੂਚਨਾ"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ਸੂਰਜ ਚੜ੍ਹਨ ਤੱਕ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> ਵਜੇ ਚਾਲੂ"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> ਵਜੇ ਤੱਕ"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ਨੂੰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ਨੂੰ ਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ਵਰਤਣ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"ਇਹ ਡੀਵਾਈਸ ਤੁਹਾਡੀ ਸੰਸਥਾ ਨਾਲ ਸੰਬੰਧਿਤ ਹੈ"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"ਇਹ ਡੀਵਾਈਸ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ਨਾਲ ਸੰਬੰਧਿਤ ਹੈ"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"ਫ਼ੋਨ ਲਈ ਪ੍ਰਤੀਕ ਤੋਂ ਸਵਾਈਪ ਕਰੋ"</string>
     <string name="voice_hint" msgid="7476017460191291417">"ਅਵਾਜ਼ੀ ਸਹਾਇਕ ਲਈ ਪ੍ਰਤੀਕ ਤੋਂ ਸਵਾਈਪ ਕਰੋ"</string>
     <string name="camera_hint" msgid="4519495795000658637">"ਕੈਮਰੇ ਲਈ ਪ੍ਰਤੀਕ ਤੋਂ ਸਵਾਈਪ ਕਰੋ"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"ਪ੍ਰੋਫਾਈਲ ਦਿਖਾਓ"</string>
     <string name="user_add_user" msgid="4336657383006913022">"ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"ਨਵਾਂ ਵਰਤੋਂਕਾਰ"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"ਕੀ ਮਹਿਮਾਨ ਸੈਸ਼ਨ ਸਮਾਪਤ ਕਰਨਾ ਹੈ?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"ਮਹਿਮਾਨ ਸੈਸ਼ਨ ਸਮਾਪਤ ਕਰੋ"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"ਕੀ ਮਹਿਮਾਨ ਹਟਾਉਣਾ ਹੈ?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ਇਸ ਸੈਸ਼ਨ ਵਿੱਚ ਸਾਰੀਆਂ ਐਪਾਂ ਅਤੇ ਡਾਟਾ ਨੂੰ ਮਿਟਾ ਦਿੱਤਾ ਜਾਏਗਾ।"</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"ਸੈਸ਼ਨ ਸਮਾਪਤ ਕਰੋ"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"ਹਟਾਓ"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"ਮਹਿਮਾਨ, ਫਿਰ ਤੁਹਾਡਾ ਸੁਆਗਤ ਹੈ!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"ਕੀ ਤੁਸੀਂ ਆਪਣਾ ਸੈਸ਼ਨ ਜਾਰੀ ਰੱਖਣਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ਸ਼ੁਰੂ ਕਰੋ"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਤੁਹਾਡੇ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਵਿੱਚ ਇੱਕ ਪ੍ਰਮਾਣ-ਪੱਤਰ ਅਥਾਰਟੀ ਸਥਾਪਤ ਕੀਤੀ ਗਈ ਹੈ। ਤੁਹਾਡੇ ਸੁਰੱਖਿਅਤ ਨੈੱਟਵਰਕ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ ਜਾਂ ਉਸਨੂੰ ਸੋਧਿਆ ਜਾ ਸਕਦਾ ਹੈ।"</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"ਇੱਕ ਪ੍ਰਮਾਣ-ਪੱਤਰ ਅਥਾਰਟੀ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਸਥਾਪਤ ਕੀਤੀ ਜਾਂਦੀ ਹੈ। ਤੁਹਾਡੇ ਸੁਰੱਖਿਅਤ ਨੈੱਟਵਰਕ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ ਜਾਂ ਉਸਨੂੰ ਸੋਧਿਆ ਜਾ ਸਕਦਾ ਹੈ।"</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਨੇ ਨੈੱਟਵਰਕ ਲੌਗਿੰਗ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਹੋਇਆ ਹੈ, ਜੋ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰਦਾ ਹੈ।"</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਨੇ ਨੈੱਟਵਰਕ ਲੌਗ-ਇਨ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਹੋਇਆ ਹੈ, ਜੋ ਤੁਹਾਡੇ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਵਿੱਚ ਟਰੈਫ਼ਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰਦਾ ਹੈ ਪਰ ਤੁਹਾਡੀ ਨਿੱਜੀ ਪ੍ਰੋਫਾਈਲ ਵਿੱਚ ਨਹੀਂ।"</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"ਤੁਸੀਂ <xliff:g id="VPN_APP">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੋ, ਜੋ ਈਮੇਲਾਂ, ਐਪਾਂ, ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।"</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"ਤੁਸੀਂ <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="368812367182387320">"ਤੁਹਾਡੀ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ <xliff:g id="VPN_APP">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੈ, ਜੋ ਈਮੇਲਾਂ, ਐਪਾਂ ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।"</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s। ਮਿਊਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ। ਪਹੁੰਚਯੋਗਤਾ ਸੇਵਾਵਾਂ ਮਿਊਟ ਹੋ ਸਕਦੀਆਂ ਹਨ।"</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s। ਥਰਥਰਾਹਟ \'ਤੇ ਸੈੱਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s। ਮਿਊਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"ਮਿਊਟ ਕਰੋ"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"ਅਣਮਿਊਟ ਕਰੋ"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"ਥਰਥਰਾਹਟ"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"ਸਿਸਟਮ ਨੇ ਇਸ ਸੂਚਨਾ ਦਾ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ &lt;b&gt;ਦਰਜਾ ਘਟਾ ਕੇ ਸ਼ਾਂਤ&lt;/b&gt; \'ਤੇ ਸੈੱਟ ਕਰ ਦਿੱਤਾ ਗਿਆ ਸੀ।"</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"ਤੁਹਾਡੇ ਸ਼ੇਡ ਵਿੱਚ ਇਸ ਸੂਚਨਾ ਦਾ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ &lt;b&gt;ਦਰਜਾ ਉੱਪਰ&lt;/b&gt; ਕਰ ਦਿੱਤਾ ਗਿਆ ਸੀ।"</string>
     <string name="feedback_demoted" msgid="951884763467110604">"ਤੁਹਾਡੇ ਸ਼ੇਡ ਵਿੱਚ ਇਸ ਸੂਚਨਾ ਦਾ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ &lt;b&gt;ਦਰਜਾ ਹੇਠਾਂ&lt;/b&gt; ਕਰ ਦਿੱਤਾ ਗਿਆ ਸੀ।"</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"ਕੀ ਇਹ ਸਹੀ ਸੀ?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"ਵਿਕਾਸਕਾਰ ਨੂੰ ਆਪਣੇ ਵਿਚਾਰ ਦੱਸੋ। ਕੀ ਇਹ ਸਹੀ ਸੀ?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"ਤੁਹਾਡੇ ਵਿਚਾਰ ਲਈ ਧੰਨਵਾਦ!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ਠੀਕ ਹੈ"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਸੂਚਨਾ ਕੰਟਰੋਲਾਂ ਨੂੰ ਖੋਲ੍ਹਿਆ ਗਿਆ"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> \'ਤੇ ਲਿਜਾਓ"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> ਸਥਾਨ \'ਤੇ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"ਸਥਾਨ <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"ਟਾਇਲ ਨੂੰ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"ਟਾਇਲ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਗਿਆ"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਸੰਪਾਦਕ।"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> ਸੂਚਨਾ: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹੋ।"</string>
@@ -967,23 +979,17 @@
     <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ਐਪਲੀਕੇਸ਼ਨਾਂ ਤੁਹਾਡੇ <xliff:g id="TYPES_LIST">%s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀਆਂ ਹਨ।"</string>
     <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
     <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ਅਤੇ "</string>
-    <!-- no translation found for ongoing_privacy_dialog_using_op (4125175620929701569) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_recent_op (4255923947334262404) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_enterprise (4082735415905550729) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_phonecall (3526223335298089311) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_attribution_text (9186683306719924646) -->
-    <skip />
+    <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ਐਪ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀ ਹੈ"</string>
+    <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ਨੇ ਹਾਲ ਹੀ ਵਿੱਚ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕੀਤੀ"</string>
+    <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(ਐਂਟਰਪ੍ਰਾਈਜ਼)"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"ਫ਼ੋਨ ਕਾਲ"</string>
+    <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> ਰਾਹੀਂ)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"ਕੈਮਰਾ"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"ਟਿਕਾਣਾ"</string>
     <string name="privacy_type_microphone" msgid="9136763906797732428">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ"</string>
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"ਸੈਂਸਰ ਬੰਦ ਕਰੋ"</string>
     <string name="device_services" msgid="1549944177856658705">"ਡੀਵਾਈਸ ਸੇਵਾਵਾਂ"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"ਕੋਈ ਸਿਰਲੇਖ ਨਹੀਂ"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"ਇਸ ਐਪ ਨੂੰ ਮੁੜ-ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ ਅਤੇ ਪੂਰੀ-ਸਕ੍ਰੀਨ ਮੋਡ \'ਤੇ ਜਾਓ।"</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"ਲਿਜਾਓ"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"ਸਿਸਟਮ ਨੈਵੀਗੇਸ਼ਨ ਅੱਪਡੇਟ ਹੋ ਗਿਆ। ਤਬਦੀਲੀਆਂ ਕਰਨ ਲਈ, ਸੈਟਿੰਗਾਂ \'ਤੇ ਜਾਓ।"</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"ਸਿਸਟਮ ਨੈਵੀਗੇਸ਼ਨ ਨੂੰ ਅੱਪਡੇਟ ਕਰਨ ਲਈ ਸੈਟਿੰਗਾਂ \'ਤੇ ਜਾਓ"</string>
@@ -1037,6 +1043,8 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ਵੱਲੋਂ ਸੁਝਾਇਆ ਗਿਆ"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"ਕੰਟਰੋਲ ਅੱਪਡੇਟ ਕੀਤੇ ਗਏ"</string>
+    <!-- no translation found for controls_tile_locked (731547768182831938) -->
+    <skip />
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"ਪਿੰਨ ਵਿੱਚ ਅੱਖਰ ਜਾਂ ਚਿੰਨ੍ਹ ਸ਼ਾਮਲ ਹਨ"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"ਗਲਤ ਪਿੰਨ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 6440a65..e16b5ec 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Przewiń zrzut ekranu"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Zamknij zrzut ekranu"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Podgląd zrzutu ekranu"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Górna granica"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Dolna granica"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Nagrywanie ekranu"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Przetwarzam nagrywanie ekranu"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Stałe powiadomienie o sesji rejestrowania zawartości ekranu"</string>
@@ -414,6 +416,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do wschodu słońca"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Włącz o <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"Komunikacja NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Komunikacja NFC jest wyłączona"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Komunikacja NFC jest włączona"</string>
@@ -444,9 +448,11 @@
     <string name="notification_tap_again" msgid="4477318164947497249">"Kliknij ponownie, by otworzyć"</string>
     <string name="keyguard_unlock" msgid="8031975796351361601">"Przesuń w górę, by otworzyć"</string>
     <string name="keyguard_retry" msgid="886802522584053523">"Przesuń w górę, by spróbować ponownie"</string>
-    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Odblokuj, by użyć NFC"</string>
+    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Odblokuj, by użyć komunikacji NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"To urządzenie należy do Twojej organizacji"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Właściciel tego urządzenia: <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Aby włączyć telefon, przesuń palcem od ikony"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Aby uzyskać pomoc głosową, przesuń palcem od ikony"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Przesuń palcem od ikony, by włączyć aparat"</string>
@@ -467,9 +473,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Pokaż profil"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Dodaj użytkownika"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Nowy użytkownik"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Zakończyć sesję gościa?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Zakończ sesję gościa"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Usunąć gościa?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Wszystkie aplikacje i dane w tej sesji zostaną usunięte."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Zakończ sesję"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Usuń"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Witaj ponownie, gościu!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Chcesz kontynuować sesję?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Rozpocznij nową"</string>
@@ -546,6 +553,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Twoja organizacja zainstalowała urząd certyfikacji w Twoim profilu służbowym. Zabezpieczony ruch w sieci może być monitorowany i zmieniany."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Urząd certyfikacji zainstalowany na tym urządzeniu. Twój zabezpieczony ruch w sieci może być monitorowany i zmieniany."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Administrator włączył rejestrowanie sieciowe, które pozwala monitorować ruch na Twoim urządzeniu."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Administrator włączył rejestrowanie sieciowe, które pozwala monitorować ruch na Twoim profilu służbowym, ale nie na profilu osobistym."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Łączysz się z aplikacją <xliff:g id="VPN_APP">%1$s</xliff:g>, która może monitorować Twoją aktywność w sieci, w tym e-maile, aplikacje i strony internetowe."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Łączysz się z aplikacjami <xliff:g id="VPN_APP_0">%1$s</xliff:g> i <xliff:g id="VPN_APP_1">%2$s</xliff:g>, które mogą monitorować Twoją aktywność w sieci, w tym e-maile, aplikacje i strony internetowe."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Twój profil służbowy jest połączony z aplikacją <xliff:g id="VPN_APP">%1$s</xliff:g>, która może monitorować Twoją aktywność w sieci, w tym e-maile, aplikacje i strony internetowe."</string>
@@ -626,6 +634,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Kliknij, by wyciszyć. Ułatwienia dostępu mogą być wyciszone."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Kliknij, by włączyć wibracje."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Kliknij, by wyciszyć."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"wycisz"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"wyłącz wyciszenie"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"włącz wibracje"</string>
@@ -739,7 +749,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"To powiadomienie zostało automatycznie &lt;b&gt;zmienione na Ciche&lt;/b&gt; przez system."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Ważność tego powiadomienia została automatycznie &lt;b&gt;podniesiona&lt;/b&gt; przez system."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Ważność tego powiadomienia została automatycznie &lt;b&gt;obniżona&lt;/b&gt; przez system."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Czy to było prawidłowe?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Daj znać deweloperowi, co o tym sądzisz. Czy to było prawidłowe?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Dziękujemy za opinię"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Sterowanie powiadomieniami aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g> otwarte"</string>
@@ -890,6 +900,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Przenieś do pozycji <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Dodaj w pozycji <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Pozycja <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Dodano kartę"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Usunięto kartę"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Edytor szybkich ustawień."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Powiadomienie z aplikacji <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Otwórz ustawienia."</string>
@@ -980,7 +992,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Aplikacja <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> używa: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Aplikacja <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> używała ostatnio: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(wersja firmowa)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Rozmowa telefoniczna"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Rozmowa telefoniczna"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(przez: <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"aparat"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"lokalizacja"</string>
@@ -988,7 +1000,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Wyłącz czujniki"</string>
     <string name="device_services" msgid="1549944177856658705">"Usługi urządzenia"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Bez tytułu"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Kliknij, by uruchomić tę aplikację ponownie i przejść w tryb pełnoekranowy."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Przenieś"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Nawigacja w systemie została zaktualizowana. Aby wprowadzić zmiany, otwórz Ustawienia."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Otwórz Ustawienia, by zaktualizować nawigację w systemie"</string>
@@ -1044,6 +1055,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Dodaj"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Sugestia: <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Zaktualizowano elementy sterujące"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Urządzenie zablokowane"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Kod PIN zawiera litery lub symbole"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Sprawdź urządzenie <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Nieprawidłowy kod PIN"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 40dc2de..efe0f06 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Captura de tela da página inteira"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Dispensar captura de tela"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Visualização de captura de tela"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Limite superior"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Limite inferior"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Gravador de tela"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processando gravação de tela"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação contínua para uma sessão de gravação de tela"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Até o nascer do sol"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ativar: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Até: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"A NFC está desativada"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"A NFC está ativada"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloqueie para usar a NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence à sua organização"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Este dispositivo pertence à organização <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Deslize a partir do ícone do telefone"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Deslize a partir do ícone de assistência de voz"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Deslize a partir do ícone da câmera"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Mostrar perfil"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Adicionar usuário"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Novo usuário"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Encerrar sessão de visitante?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Encerrar sessão de visitante"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Remover convidado?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todos os apps e dados nesta sessão serão excluídos."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Encerrar sessão"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Remover"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Bem-vindo, convidado."</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Quer continuar a sessão?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Recomeçar"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Sua organização instalou uma autoridade de certificação no seu perfil de trabalho. É possível monitorar ou modificar seu tráfego de rede seguro."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Uma autoridade de certificação foi instalada neste dispositivo. É possível monitorar ou modificar seu tráfego de rede seguro."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Seu administrador ativou o registro de rede, que monitora o tráfego no seu dispositivo."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Seu administrador ativou o registro de rede, que monitora o tráfego no seu perfil de trabalho, mas não no perfil pessoal."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Você está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorar sua atividade na rede, incluindo e-mails, apps e websites."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Você está conectado a <xliff:g id="VPN_APP_0">%1$s</xliff:g> e <xliff:g id="VPN_APP_1">%2$s</xliff:g>, que podem monitorar sua atividade de rede, incluindo e-mails, apps e websites."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Seu perfil de trabalho está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorar sua atividade de rede, incluindo e-mails, apps e websites."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Toque para silenciar. É possível que os serviços de acessibilidade sejam silenciados."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Toque para configurar para vibrar."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Toque para silenciar."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"desativar o som"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"ativar o som"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrar"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Esta notificação foi automaticamente &lt;b&gt;rebaixada para Silenciosa&lt;/b&gt; pelo sistema."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Esta notificação foi automaticamente &lt;b&gt;classificada com maior prioridade&lt;/b&gt;."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Esta notificação foi automaticamente &lt;b&gt;classificada com menor prioridade&lt;/b&gt;."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Isso está correto?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Envie seu feedback ao desenvolvedor. Isso está correto?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Agradecemos seu feedback."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Controles de notificação de <xliff:g id="APP_NAME">%1$s</xliff:g> abertos"</string>
@@ -786,7 +796,7 @@
     <string name="keyboard_key_media_stop" msgid="1509943745250377699">"Parar"</string>
     <string name="keyboard_key_media_next" msgid="8502476691227914952">"Avançar"</string>
     <string name="keyboard_key_media_previous" msgid="5637875709190955351">"Anterior"</string>
-    <string name="keyboard_key_media_rewind" msgid="3450387734224327577">"Retroceder"</string>
+    <string name="keyboard_key_media_rewind" msgid="3450387734224327577">"Voltar"</string>
     <string name="keyboard_key_media_fast_forward" msgid="3572444327046911822">"Avançar rapidamente"</string>
     <string name="keyboard_key_page_up" msgid="173914303254199845">"Page Up"</string>
     <string name="keyboard_key_page_down" msgid="9035902490071829731">"Page Down"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mover para <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Adicionar à posição <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posição <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Bloco adicionado"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Bloco removido"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de configurações rápidas."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificação do <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Abrir configurações."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"O app <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> está usando <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"O app <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> usou <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> recentemente"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(empresarial)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Chamada telefônica"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Chamada telefônica"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(pelo app <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"câmera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"localização"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensores desativados"</string>
     <string name="device_services" msgid="1549944177856658705">"Serviços do dispositivo"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Sem título"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Toque para reiniciar o app e usar tela cheia."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Mover"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navegação no sistema atualizada. Se quiser alterá-la, acesse as configurações."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Acesse as configurações para atualizar a navegação no sistema"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Adicionar"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Sugerido por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Controles atualizados"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Dispositivo bloq."</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"O PIN contém letras ou símbolos"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Verificar <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN incorreto"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 22241f8..3a82feb 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Deslocar captura de ecrã"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ignorar captura de ecrã"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Pré-visualização da captura de ecrã"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Limite superior"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Limite inferior"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Gravador de ecrã"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"A processar a gravação de ecrã"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação persistente de uma sessão de gravação de ecrã"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Até ao amanhecer"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ativado à(s) <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Até à(s) <xliff:g id="TIME">%s</xliff:g>."</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"O NFC está desativado"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"O NFC está ativado"</string>
@@ -440,9 +444,11 @@
     <string name="notification_tap_again" msgid="4477318164947497249">"Toque novamente para abrir"</string>
     <string name="keyguard_unlock" msgid="8031975796351361601">"Deslize rapidamente para cima para abrir"</string>
     <string name="keyguard_retry" msgid="886802522584053523">"Deslize rapidamente para cima para tentar novamente."</string>
-    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloqueie para utilizar o NFC"</string>
+    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquear para utilizar o NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence à sua entidade."</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Este dispositivo pertence à entidade <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>."</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Deslize rapid. a partir do ícone para aceder ao telemóvel"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Deslize rapid. a partir do ícone para aceder ao assist. voz"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Deslize rapidamente a partir do ícone para aceder à câmara"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Mostrar perfil"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Adicionar utilizador"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Novo utilizador"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Pretende terminar a sessão de convidado?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Terminar sessão de convidado"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Remover o convidado?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todas as aplicações e dados desta sessão serão eliminados."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Terminar sessão"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Remover"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Bem-vindo de volta, caro(a) convidado(a)!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Pretende continuar a sessão?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Recomeçar"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"A sua entidade instalou uma autoridade de certificação no seu perfil de trabalho. O tráfego da sua rede segura pode ser monitorizado ou alterado."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Está instalada uma autoridade de certificação neste dispositivo. O tráfego da sua rede segura pode ser monitorizado ou alterado."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"O gestor ativou os registos de rede, que monitorizam o tráfego no seu dispositivo."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"O seu administrador ativou os registos de rede, que monitorizam o tráfego no seu perfil de trabalho, mas não no seu perfil pessoal."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Sites."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Está ligado às redes <xliff:g id="VPN_APP_0">%1$s</xliff:g> e <xliff:g id="VPN_APP_1">%2$s</xliff:g>, que podem monitorizar a sua atividade de rede, incluindo emails, aplicações e Sites."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"O seu perfil de trabalho está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Sites."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Toque para desativar o som. Os serviços de acessibilidade podem ser silenciados."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Toque para ativar a vibração."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Toque para desativar o som."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"desativar som"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"reativar som"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrar"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Esta notificação foi automaticamente &lt;b&gt;despromovida para Silenciosa&lt;/b&gt; pelo sistema."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Esta notificação passou automaticamente para uma &lt;b&gt;classificação superior&lt;/b&gt; no seu painel."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Esta notificação passou automaticamente para uma &lt;b&gt;classificação inferior&lt;/b&gt; no seu painel."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Estava correto?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Partilhe o seu feedback com o programador. Estava correto?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Obrigado pelo seu feedback!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Controlos de notificações da app <xliff:g id="APP_NAME">%1$s</xliff:g> abertos"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mova para <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Adicione à posição <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posição <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Cartão adicionado"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Cartão removido"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de definições rápidas."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificação do <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Abrir as definições."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"A app <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> está a utilizar a app <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>."</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Recentemente, a app <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> utilizou a app <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>."</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(empresarial)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Chamada telefónica"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Chamada"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(através de <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"câmara"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"localização"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensores desativados"</string>
     <string name="device_services" msgid="1549944177856658705">"Serviços do dispositivo"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Sem título"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Toque para reiniciar esta app e ficar em ecrã inteiro."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Mover"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"A navegação no sistema foi atualizada. Para efetuar alterações, aceda às Definições."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Aceda às Definições para atualizar a navegação no sistema."</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Adicionar"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Sugerido por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Controlos atualizados"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Dispositivo bloq."</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"O PIN contém letras ou símbolos."</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Validar <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN incorreto"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 40dc2de..efe0f06 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Captura de tela da página inteira"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Dispensar captura de tela"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Visualização de captura de tela"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Limite superior"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Limite inferior"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Gravador de tela"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processando gravação de tela"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação contínua para uma sessão de gravação de tela"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Até o nascer do sol"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ativar: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Até: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"A NFC está desativada"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"A NFC está ativada"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloqueie para usar a NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence à sua organização"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Este dispositivo pertence à organização <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Deslize a partir do ícone do telefone"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Deslize a partir do ícone de assistência de voz"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Deslize a partir do ícone da câmera"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Mostrar perfil"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Adicionar usuário"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Novo usuário"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Encerrar sessão de visitante?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Encerrar sessão de visitante"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Remover convidado?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todos os apps e dados nesta sessão serão excluídos."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Encerrar sessão"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Remover"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Bem-vindo, convidado."</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Quer continuar a sessão?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Recomeçar"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Sua organização instalou uma autoridade de certificação no seu perfil de trabalho. É possível monitorar ou modificar seu tráfego de rede seguro."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Uma autoridade de certificação foi instalada neste dispositivo. É possível monitorar ou modificar seu tráfego de rede seguro."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Seu administrador ativou o registro de rede, que monitora o tráfego no seu dispositivo."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Seu administrador ativou o registro de rede, que monitora o tráfego no seu perfil de trabalho, mas não no perfil pessoal."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Você está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorar sua atividade na rede, incluindo e-mails, apps e websites."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Você está conectado a <xliff:g id="VPN_APP_0">%1$s</xliff:g> e <xliff:g id="VPN_APP_1">%2$s</xliff:g>, que podem monitorar sua atividade de rede, incluindo e-mails, apps e websites."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Seu perfil de trabalho está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorar sua atividade de rede, incluindo e-mails, apps e websites."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Toque para silenciar. É possível que os serviços de acessibilidade sejam silenciados."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Toque para configurar para vibrar."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Toque para silenciar."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"desativar o som"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"ativar o som"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrar"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Esta notificação foi automaticamente &lt;b&gt;rebaixada para Silenciosa&lt;/b&gt; pelo sistema."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Esta notificação foi automaticamente &lt;b&gt;classificada com maior prioridade&lt;/b&gt;."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Esta notificação foi automaticamente &lt;b&gt;classificada com menor prioridade&lt;/b&gt;."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Isso está correto?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Envie seu feedback ao desenvolvedor. Isso está correto?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Agradecemos seu feedback."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Controles de notificação de <xliff:g id="APP_NAME">%1$s</xliff:g> abertos"</string>
@@ -786,7 +796,7 @@
     <string name="keyboard_key_media_stop" msgid="1509943745250377699">"Parar"</string>
     <string name="keyboard_key_media_next" msgid="8502476691227914952">"Avançar"</string>
     <string name="keyboard_key_media_previous" msgid="5637875709190955351">"Anterior"</string>
-    <string name="keyboard_key_media_rewind" msgid="3450387734224327577">"Retroceder"</string>
+    <string name="keyboard_key_media_rewind" msgid="3450387734224327577">"Voltar"</string>
     <string name="keyboard_key_media_fast_forward" msgid="3572444327046911822">"Avançar rapidamente"</string>
     <string name="keyboard_key_page_up" msgid="173914303254199845">"Page Up"</string>
     <string name="keyboard_key_page_down" msgid="9035902490071829731">"Page Down"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mover para <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Adicionar à posição <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posição <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Bloco adicionado"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Bloco removido"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de configurações rápidas."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificação do <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Abrir configurações."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"O app <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> está usando <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"O app <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> usou <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> recentemente"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(empresarial)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Chamada telefônica"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Chamada telefônica"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(pelo app <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"câmera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"localização"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensores desativados"</string>
     <string name="device_services" msgid="1549944177856658705">"Serviços do dispositivo"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Sem título"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Toque para reiniciar o app e usar tela cheia."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Mover"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navegação no sistema atualizada. Se quiser alterá-la, acesse as configurações."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Acesse as configurações para atualizar a navegação no sistema"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Adicionar"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Sugerido por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Controles atualizados"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Dispositivo bloq."</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"O PIN contém letras ou símbolos"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Verificar <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN incorreto"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index f32453b9..18093b4 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Derulați captura de ecran"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Închideți captura de ecran"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Previzualizare a capturii de ecran"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Marginea superioară"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Marginea inferioară"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Recorder pentru ecran"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Se procesează înregistrarea"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificare în curs pentru o sesiune de înregistrare a ecranului"</string>
@@ -412,6 +414,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Până la răsărit"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Activată la <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Până la <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Serviciul NFC este dezactivat"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Serviciul NFC este activat"</string>
@@ -445,6 +449,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Deblocați pentru a folosi NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Dispozitivul aparține organizației dvs."</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Acest dispozitiv aparține organizației <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Glisați dinspre telefon"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Glisați dinspre pictogramă pentru asistentul vocal"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Glisați pentru a fotografia"</string>
@@ -465,9 +471,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Afișați profilul"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Adăugați un utilizator"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Utilizator nou"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Încheiați sesiunea pentru invitați?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Încheiați sesiunea pentru invitați"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Ștergeți invitatul?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Toate aplicațiile și datele din această sesiune vor fi șterse."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Încheiați sesiunea"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Ștergeți"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Bine ați revenit în sesiunea pentru invitați!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Vreți să continuați sesiunea?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Începeți din nou"</string>
@@ -543,6 +550,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Organizația dvs. a instalat un certificat CA în profilul dvs. de serviciu. Traficul dvs. sigur de rețea poate fi monitorizat sau modificat."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Pe acest dispozitiv este instalat un certificat CA. Traficul dvs. sigur de rețea poate fi monitorizat sau modificat."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Administratorul dvs. a activat înregistrarea în jurnal pentru rețea, funcție ce monitorizează traficul de pe dispozitivul dvs."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Administratorul a activat înregistrarea în jurnal pentru rețea, funcție ce monitorizează traficul în profilul dvs. de serviciu, dar nu și în profilul personal."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"V-ați conectat la aplicația <xliff:g id="VPN_APP">%1$s</xliff:g>, care vă poate monitoriza activitatea în rețea, inclusiv e-mailurile, aplicațiile și site-urile accesate."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"V-ați conectat la <xliff:g id="VPN_APP_0">%1$s</xliff:g> și la <xliff:g id="VPN_APP_1">%2$s</xliff:g>, care vă pot monitoriza activitatea în rețea, inclusiv e-mailurile, aplicațiile și site-urile accesate."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Profilul dvs. de serviciu este conectat la <xliff:g id="VPN_APP">%1$s</xliff:g>, care vă poate monitoriza activitatea în rețea, inclusiv e-mailurile, aplicațiile și site-urile accesate."</string>
@@ -623,6 +631,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Atingeți pentru a dezactiva sunetul. Sunetul se poate dezactiva pentru serviciile de accesibilitate."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Atingeți pentru a seta pe vibrații."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Atingeți pentru a dezactiva sunetul."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"dezactivați sunetul"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"activați sunetul"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrații"</string>
@@ -736,7 +746,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Notificarea a fost &lt;b&gt;setată automat ca Silențioasă&lt;/b&gt; de sistem."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Notificarea a fost &lt;b&gt;clasificată automat mai sus&lt;/b&gt; în umbră."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Notificarea a fost &lt;b&gt;clasificată automat mai jos&lt;/b&gt; în umbră."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Este corect?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Trimiteți feedback dezvoltatorului. Este corect?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Mulțumim pentru feedback!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Opțiunile privind notificările pentru <xliff:g id="APP_NAME">%1$s</xliff:g> sunt afișate"</string>
@@ -885,6 +895,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mutați pe poziția <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Adăugați pe poziția <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Poziția <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Cardul a fost adăugat"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Cardul a fost eliminat"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editorul pentru setări rapide."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificare <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Deschideți setările."</string>
@@ -975,7 +987,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> folosește <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> a folosit recent <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(enterprise)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Phonecall"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Apel telefonic"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(prin <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"cameră foto"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"locație"</string>
@@ -983,7 +995,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Senzori dezactivați"</string>
     <string name="device_services" msgid="1549944177856658705">"Servicii pentru dispozitiv"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Fără titlu"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Atingeți ca să reporniți aplicația și să treceți în modul ecran complet."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Mutați"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigarea în sistem a fost actualizată. Pentru a face modificări, accesați Setările."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Accesați Setările pentru a actualiza navigarea în sistem"</string>
@@ -1038,6 +1049,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Adăugați"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Sugerat de <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"S-au actualizat comenzile"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Dispozitiv blocat"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Codul PIN conține litere sau simboluri"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Verificați <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Cod PIN greșit"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 40fb258..a9f7c02 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Прокрутить скриншот"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Закрыть скриншот"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Предварительный просмотр скриншота"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Верхняя граница"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Нижняя граница"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Запись видео с экрана"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обработка записи с экрана…"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Текущее уведомление для записи видео с экрана"</string>
@@ -414,6 +416,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До рассвета"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Включить в <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"До <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"Модуль NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Модуль NFC отключен"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Модуль NFC включен"</string>
@@ -447,6 +451,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Чтобы использовать NFC, разблокируйте устройство."</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Это устройство принадлежит вашей организации"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Этим устройством владеет организация \"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>\""</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Телефон: проведите от значка"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Аудиоподсказки: проведите от значка"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Камера: проведите от значка"</string>
@@ -467,9 +473,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Показать профиль."</string>
     <string name="user_add_user" msgid="4336657383006913022">"Добавить пользователя"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Новый пользователь"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Завершить гостевой сеанс?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Завершить гостевой сеанс"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Удалить аккаунт гостя?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Все приложения и данные этого профиля будут удалены."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Завершить сеанс"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Удалить"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Рады видеть вас снова!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Продолжить сеанс?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Начать заново"</string>
@@ -546,6 +553,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Ваша организация установила сертификат ЦС в рабочем профиле. Она может отслеживать и изменять защищенный сетевой трафик."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"На устройстве установлен сертификат ЦС. Ваш защищенный сетевой трафик могут отслеживать и изменять."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Администратор включил ведение сетевого журнала, чтобы отслеживать трафик на вашем устройстве."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Администратор включил ведение сетевого журнала, чтобы отслеживать трафик в вашем рабочем профиле (информация из личного профиля не собирается)."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Запущено приложение \"<xliff:g id="VPN_APP">%1$s</xliff:g>\". Оно может отслеживать ваши действия в сети, включая работу с электронной почтой, приложениями и сайтами."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Запущены приложения \"<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="368812367182387320">"В рабочем профиле запущено приложение \"<xliff:g id="VPN_APP">%1$s</xliff:g>\", которое может отслеживать ваши действия в сети, включая работу с электронной почтой, приложениями и веб-сайтами."</string>
@@ -626,6 +634,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Нажмите, чтобы выключить звук. Специальные возможности могут прекратить работу."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Нажмите, чтобы включить вибрацию."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Нажмите, чтобы выключить звук."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"отключить звук"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"включить звук"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"включить вибрацию"</string>
@@ -739,7 +749,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Уровень важности этого уведомления был автоматически &lt;/b&gt;понижен до \"Без звука\"&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Уровень важности этого уведомления на панели был автоматически &lt;b&gt;повышен&lt;/b&gt;."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Уровень важности этого уведомления на панели был автоматически &lt;b&gt;понижен&lt;/b&gt;."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Все верно?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Все верно? Поделитесь своим мнением с разработчиком."</string>
     <string name="feedback_response" msgid="4671729244976641339">"Спасибо!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ОК"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Настройки уведомлений для приложения <xliff:g id="APP_NAME">%1$s</xliff:g> открыты"</string>
@@ -890,6 +900,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Переместить на позицию <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Добавить на позицию <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Позиция <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Панель добавлена"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Панель удалена"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Редактор быстрых настроек."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Уведомление <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Открыть настройки."</string>
@@ -980,7 +992,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Приложение \"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>\" использует другое (<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>)."</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Приложение \"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>\" недавно использовало другое (<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>)."</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(корпоративная версия)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Приложение для звонков"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Телефонный звонок"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(через приложение \"<xliff:g id="ATTRIBUTION">%s</xliff:g>\")"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"камера"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"местоположение"</string>
@@ -988,7 +1000,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Датчики отключены"</string>
     <string name="device_services" msgid="1549944177856658705">"Сервисы устройства"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Без названия"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Нажмите, чтобы перезапустить приложение и перейти в полноэкранный режим."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Перенести"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Параметры навигации в системе обновлены. Чтобы изменить их, перейдите в настройки."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Чтобы обновить параметры навигации в системе, перейдите в настройки."</string>
@@ -1044,6 +1055,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Добавить"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Предложено приложением \"<xliff:g id="APP">%s</xliff:g>\""</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Элементы управления обновлены."</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Устройство заблокировано"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-код содержит буквы или символы"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Подтвердите устройство \"<xliff:g id="DEVICE">%s</xliff:g>\""</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Неверный PIN-код"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index f3d0409..5134e04 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"තිර රුව අනුචලනය කරන්න"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"තිර රුව ඉවත ලන්න"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"තිර රූ පෙර දසුන"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"ඉහළම මායිම"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"පහළම මායිම"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"තිර රෙකෝඩරය"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"තිර පටිගත කිරීම සකසමින්"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"තිර පටිගත කිරීමේ සැසියක් සඳහා කෙරෙන දැනුම් දීම"</string>
@@ -410,6 +412,7 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"හිරු නගින තෙක්"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>ට ක්‍රියාත්මකයි"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> තෙක්"</string>
+    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"දීප්තිය අඩු කරන්න"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC අබලයි"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC සබලයි"</string>
@@ -443,6 +446,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC භාවිත කිරීමට අගුලු හරින්න"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"මෙම උපාංගය ඔබේ සංවිධානයට අයිතිය"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"මෙම උපාංගය <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> සංවිධානයට අයිතිය"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"දුරකථනය සඳහා නිරූපකය වෙතින් ස්වයිප් කරන්න"</string>
     <string name="voice_hint" msgid="7476017460191291417">"හඬ සහාය සඳහා නිරූපකය වෙතින් ස්වයිප් කරන්න"</string>
     <string name="camera_hint" msgid="4519495795000658637">"කැමරාව සඳහා නිරූපකය වෙතින් ස්වයිප් කරන්න"</string>
@@ -463,9 +468,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"පැතිකඩ පෙන්වන්න"</string>
     <string name="user_add_user" msgid="4336657383006913022">"පරිශීලකයෙක් එක් කරන්න"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"නව පරිශීලකයා"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"ආරාධිත සැසිය අවසන් කරන්නද?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"ආරාධිත සැසිය අවසන් කරන්න"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"අමුත්තාන් ඉවත් කරන්නද?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"මෙම සැසියේ සියළුම යෙදුම් සහ දත්ත මකාවී."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"සැසිය අවසන් කරන්න"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"ඉවත් කරන්න"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"නැවත සාදරයෙන් පිළිගනිමු, අමුත්තා!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"ඔබගේ සැසිය දිගටම කරගෙන යෑමට ඔබට අවශ්‍යද?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"යළි මුල සිට අරඹන්න"</string>
@@ -540,6 +546,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"ඔබගේ සංවිධානය ඔබගේ කාර්යාල පැතිකඩ තුළ සහතික අධිකාරියක් ස්ථාපනය කර තිබේ. ඔබගේ ආරක්ෂක ජාල තදබදය නිරීක්ෂණය හෝ වෙනස් කිරීමට පුළුවනි."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"මෙම උපාංගය තුළ සහතික අධිකාරියක් ස්ථාපනය කර තිබේ. ඔබගේ ආරක්ෂක ජාල තදබදය නිරීක්ෂණය හෝ වෙනස් කිරීමට පුළුවනි."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"ඔබගේ පරිපාලක ඔබගේ උපාංගය මත තදබදය නිරීක්ෂණය කරන ජාල ලොග් කිරීම ක්‍රියාත්මක කර ඇත."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"ඔබගේ පරිපාලක ඔබගේ පුද්ගලික පැතිකඩෙහි නොව කාර්යාල පැතිකඩෙහි තදබදය නිරීක්ෂණය කරන, ජාල පිරීම ක්‍රියාත්මක කර ඇත."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"ඊ-තැපැල්, යෙදුම් සහ වෙබ් අඩවි ඇතුළු ඔබේ ජාල ක්‍රියාකාරකම් නිරීක්ෂණය කළ හැකි <xliff:g id="VPN_APP">%1$s</xliff:g>, වෙත ඔබ සම්බන්ධ වී ඇත."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"ඊ-තැපැල්, යෙදුම් සහ වෙබ් අඩවි ඇතුළු ඔබේ ජාල ක්‍රියාකාරකම් නිරීක්ෂණය කළ හැකි <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="368812367182387320">"ඊ-තැපැල්, යෙදුම් සහ වෙබ් අඩවි ඇතුළු ඔබේ ජාල ක්‍රියාකාරකම් නිරීක්ෂණය කළ හැකි <xliff:g id="VPN_APP">%1$s</xliff:g>, වෙත ඔබේ කාර්යාල පැතිකඩ සම්බන්ධ වී ඇත."</string>
@@ -620,6 +627,7 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. නිහඬ කිරීමට තට්ටු කරන්න. ප්‍රවේශ්‍යතා සේවා නිහඬ කළ හැකිය."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. කම්පනය කිරීමට සකස් කිරීමට තට්ටු කරන්න."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. නිහඬ කිරීමට තට්ටු කරන්න."</string>
+    <string name="volume_ringer_change" msgid="3574969197796055532">"නාදකය වෙනස් කිරීමට තට්ටු කරන්න"</string>
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"නිහඬ කරන්න"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"නිශ්ශබ්දතාවය ඉවත් කරන්න"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"කම්පනය"</string>
@@ -733,7 +741,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"පද්ධතිය මගින් මෙම දැනුම්දීම ස්වයංක්‍රියව &lt;b&gt;නිශ්ශබ්ද වෙත පහත දමන ලදි&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"ඔබගේ වැස්ම තුළ මෙම දැනුම්දීම ස්වයංක්‍රියව &lt;b&gt;ඉහළට ශ්‍රේණිගත කරන ලදි&lt;/b&gt;."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"ඔබගේ වැස්ම තුළ මෙම දැනුම්දීම ස්වයංක්‍රියව &lt;b&gt;පහළට ශ්‍රේණිගත කරන ලදි&lt;/b&gt;."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"මෙය නිවැරදි වුයේද?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"ඔබගේ ප්‍රතිපෝෂණය සංවර්ධකට දන්වන්න. මෙය නිවැරදි වුයේද?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"ඔබේ ප්‍රතිපෝෂණයට ස්තූතියි!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"හරි"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා දැනුම්දීම් පාලන විවෘත කරන ලදී"</string>
@@ -880,6 +888,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> වෙත ගෙන යන්න"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> ස්ථානයට එක් කරන්න"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"ස්ථානය <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"ටයිල් එක එක් කරන ලදි"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"ටයිල් ඉවත් කරන ලදි"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ඉක්මන් සැකසුම් සංස්කාරකය."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> දැනුම්දීම: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"සැකසීම් විවෘත කරන්න."</string>
@@ -970,7 +980,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> භාවිත කරමින් ඇත"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> මෑතකදී <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> භාවිත කළේය"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(ව්‍යවසාය)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"දුරකථන ඇමතුම"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"දුරකථන ඇමතුම"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> හරහා)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"කැමරාව"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"ස්ථානය"</string>
@@ -978,7 +988,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"සංවේදක ක්‍රියාවිරහිතයි"</string>
     <string name="device_services" msgid="1549944177856658705">"උපාංග සේවා"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"මාතෘකාවක් නැත"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"මෙම යෙදුම යළි ඇරඹීමට සහ පූර්ණ තිරයට යාමට තට්ටු කරන්න"</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"ගෙන යන්න"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"පද්ධති සංචලනය යාවත්කාලීන කළා. වෙනස්කම් සිදු කිරීමට, සැකසීම් වෙත යන්න."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"පද්ධති සංචලනය යාවත්කාලීන කිරීමට සැකසීම් වෙත යන්න"</string>
@@ -1032,6 +1041,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"එක් කරන්න"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"යෝජනා කළේ <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"පාලන යාවත්කාලීනයි"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"උපාංගය අගුලු දමා ඇත"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN හි අකුරු හෝ සංකේත අඩංගු වේ"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> සත්‍යාපනය කරන්න"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"වැරදි PIN එකකි"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 7e3f3c0..d514b66 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Posúvať snímku obrazovky"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Zavrieť snímku obrazovky"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Ukážka snímky obrazovky"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Horná hranica"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Dolná hranica"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Rekordér obrazovky"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Spracúva sa záznam obrazovky"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Zobrazuje sa upozornenie týkajúce sa relácie záznamu obrazovky"</string>
@@ -414,6 +416,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do východu slnka"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Zapne sa o <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je deaktivované"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je aktivované"</string>
@@ -447,6 +451,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ak chcete použiť NFC, odomknite"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Toto zariadenie patrí vašej organizácii"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Toto zariadení patrí organizácii <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Telefón otvoríte prejdením prstom od ikony"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Hlasového asistenta otvoríte prejdením prstom od ikony"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Fotoaparát otvoríte prejdením prstom od ikony"</string>
@@ -467,9 +473,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Zobraziť profil"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Pridať používateľa"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Nový používateľ"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Chcete ukončiť reláciu hosťa?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Ukončiť reláciu hosťa"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Odstrániť hosťa?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Všetky aplikácie a údaje v tejto relácii budú odstránené."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Ukončiť reláciu"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Odstrániť"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Hosť, vitajte späť!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Chcete v relácii pokračovať?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Začať odznova"</string>
@@ -546,6 +553,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Organizácia nainštalovala pre váš pracovný profil certifikačnú autoritu. Zabezpečená sieťová premávka môže byť sledovaná či upravená."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"V tomto zariadení je nainštalovaná certifikačná autorita. Zabezpečená sieťová premávka môže byť sledovaná či upravená."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Správca aktivoval zapisovanie do denníka siete, ktoré sleduje premávku na vašom zariadení."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Správca aktivoval zapisovanie do denníka siete, ktoré sleduje premávku vo vašom pracovnom profile, ale nie osobnom."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Pripojili ste sa k aplikácii <xliff:g id="VPN_APP">%1$s</xliff:g>, ktorá môže sledovať vašu aktivitu v sieti, vrátane správ, aplikácií a webových stránok."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Pripojili ste sa k aplikáciám <xliff:g id="VPN_APP_0">%1$s</xliff:g> a <xliff:g id="VPN_APP_1">%2$s</xliff:g>, ktoré môžu sledovať vašu aktivitu v sieti, vrátane správ, aplikácií a webových stránok."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Váš pracovný profil je pripojený k aplikácii <xliff:g id="VPN_APP">%1$s</xliff:g>, ktorá môže sledovať vašu aktivitu v sieti vrátane správ, aplikácií a webových stránok."</string>
@@ -626,6 +634,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Klepnutím vypnite zvuk. Služby dostupnosti je možné stlmiť."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Klepnutím nastavíte vibrovanie."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Klepnutím vypnete zvuk."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"vypnite zvuk"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"zapnite zvuk"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"zapnite vibrovanie"</string>
@@ -739,7 +749,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Systém toto upozornenie automaticky &lt;b&gt;preradil nižšie do kategórie Tiché&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Toto upozornenie bolo na vašom paneli automaticky &lt;b&gt;preradené vyššie&lt;/b&gt;."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Toto upozornenie bolo na vašom paneli automaticky &lt;b&gt;preradené nižšie&lt;/b&gt;."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Bolo toto správne?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Pošlite vývojárovi svoju spätnú väzbu. Bolo toto správne?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Ďakujeme za váš názor."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Ovládanie upozornení pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g> je otvorené"</string>
@@ -890,6 +900,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Presunúť na <xliff:g id="POSITION">%1$d</xliff:g>. pozíciu"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Pridať na <xliff:g id="POSITION">%1$d</xliff:g>. pozíciu"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g>. pozícia"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Karta bola pridaná"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Karta bola odstránená"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor rýchlych nastavení"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Upozornenie <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Otvoriť nastavenia"</string>
@@ -980,7 +992,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> používa aplikáciu <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Aplikácia <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> použila nedávno aplikáciu <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(podniková verzia)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonický hovor"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefonický hovor"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(prostredníctvom aplikácie <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"fotoaparát"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"poloha"</string>
@@ -988,7 +1000,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Senzory sú vypnuté"</string>
     <string name="device_services" msgid="1549944177856658705">"Služby zariadenia"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Bez názvu"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Klepnutím reštartujete túto aplikáciu a prejdete do režimu celej obrazovky."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Presunúť"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigácia v systéme bola aktualizovaná. Ak chcete vykonať zmeny, prejdite do Nastavení."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Prejdite do Nastavení a aktualizujte navigáciu v systéme"</string>
@@ -1044,6 +1055,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Pridať"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Navrhuje <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Ovládanie bolo aktualizované"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Uzamknuté zariadenie"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN obsahuje písmená či symboly"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g>, overenie"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Nesprávny PIN"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index b7ebea9..b7b2dd0 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Drseče pomikanje po posnetku zaslona"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Opusti posnetek zaslona"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Predogled posnetka zaslona"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Zgornji rob"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Spodnji rob"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Snemalnik zaslona"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obdelava videoposnetka zaslona"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Nenehno obveščanje o seji snemanja zaslona"</string>
@@ -414,6 +416,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do sončnega vzhoda"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Vklop ob <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Tehnologija NFC je onemogočena"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Tehnologija NFC je omogočena"</string>
@@ -444,9 +448,11 @@
     <string name="notification_tap_again" msgid="4477318164947497249">"Znova se dotaknite, da odprete"</string>
     <string name="keyguard_unlock" msgid="8031975796351361601">"Povlecite navzgor, da odprete"</string>
     <string name="keyguard_retry" msgid="886802522584053523">"Povlecite navzgor za vnovičen poskus"</string>
-    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Odklenite napravo, če želite uporabljati vmesnik NFC."</string>
+    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Odklenite napravo, če želite uporabljati NFC."</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Ta naprava pripada vaši organizaciji"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Ta naprava pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Povlecite z ikone za telefon"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Povlecite z ikone za glasovnega pomočnika"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Povlecite z ikone za fotoaparat"</string>
@@ -467,9 +473,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Prikaz profila"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Dodajanje uporabnika"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Nov uporabnik"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Želite končati sejo gosta?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Končaj sejo gosta"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Želite odstraniti gosta?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Vse aplikacije in podatki v tej seji bodo izbrisani."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Končaj sejo"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Odstrani"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Znova pozdravljeni, gost!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Želite nadaljevati sejo?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Začni znova"</string>
@@ -546,6 +553,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Vaša organizacija je v vaš delovni profil namestila overitelja potrdil. Varni omrežni promet se lahko nadzira ali spreminja."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"V tej napravi je nameščen overitelj potrdil. Varni omrežni promet se lahko nadzira ali spreminja."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Skrbnik je vklopil beleženje omrežnega prometa, ki nadzira promet v napravi."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Skrbnik je vklopil beleženje omrežnega prometa, ki nadzoruje samo promet v delovnem profilu, tistega v osebnem profilu pa ne."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Povezani ste z aplikacijo <xliff:g id="VPN_APP">%1$s</xliff:g>, ki lahko nadzira omrežno dejavnost, vključno z e-pošto, aplikacijami in spletnimi mesti."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Povezani ste z aplikacijama <xliff:g id="VPN_APP_0">%1$s</xliff:g> in <xliff:g id="VPN_APP_1">%2$s</xliff:g>, ki lahko nadzirata omrežno dejavnost, vključno z e-pošto, aplikacijami in spletnimi mesti."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Delovni profil je povezan z aplikacijo <xliff:g id="VPN_APP">%1$s</xliff:g>, ki lahko nadzira omrežno dejavnost, vključno z e-pošto, aplikacijami in spletnimi mesti."</string>
@@ -626,6 +634,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Dotaknite se, če želite izklopiti zvok. V storitvah za ljudi s posebnimi potrebami bo morda izklopljen zvok."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Dotaknite se, če želite nastaviti vibriranje."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Dotaknite se, če želite izklopiti zvok."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"izklop zvoka"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"vklop zvoka"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibriranje"</string>
@@ -739,7 +749,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Sistem je to obvestilo samodejno &lt;b&gt;uvrstil nižje – med obvestila brez zvoka&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"To obvestilo je bilo samodejno &lt;b&gt;uvrščeno višje&lt;/b&gt; na zaslonu z obvestili."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"To obvestilo je bilo samodejno &lt;b&gt;uvrščeno nižje&lt;/b&gt; na zaslonu z obvestili."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Je bilo to prav?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Posredujte povratne informacije razvijalcu. Je bilo to prav?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Hvala za povratne informacije."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"V redu"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Kontrolniki obvestil za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g> so odprti"</string>
@@ -890,6 +900,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Premik na položaj <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Dodajanje na položaj <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Položaj <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Ploščica je bila dodana"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Ploščica je bila odstranjena"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Urejevalnik hitrih nastavitev."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Obvestilo za <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Odpri nastavitve."</string>
@@ -980,7 +992,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Aplikacija <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> uporablja: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Aplikacija <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> je nedavno uporabila: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(za podjetja)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonski klici"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefonski klic"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(prek aplikacije <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"fotoaparat"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"lokacijo"</string>
@@ -988,7 +1000,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Izklop za tipala"</string>
     <string name="device_services" msgid="1549944177856658705">"Storitve naprave"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Brez naslova"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Dotaknite se za vnovični zagon te aplikacije in preklop v celozaslonski način."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Premakni"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Krmarjenje po sistemu je posodobljeno. Če želite opraviti spremembe, odprite nastavitve."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Če želite posodobiti krmarjenje po sistemu, odprite nastavitve"</string>
@@ -1044,6 +1055,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Dodaj"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Predlagala aplikacija <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Kontrolniki so posodobljeni"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Naprava je zaklenjena"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Koda PIN vsebuje črke ali simbole"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Preverjanje naprave <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Napačna koda PIN"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index fede55c..9f4c1e1 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Lëviz në pamjen e ekranit"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Hiq pamjen e ekranit"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Pamja paraprake e imazhit"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Kufiri i sipërm"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Kufiri i poshtëm"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Regjistruesi i ekranit"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Regjistrimi i ekranit po përpunohet"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Njoftim i vazhdueshëm për një seancë regjistrimi të ekranit"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Deri në lindje të diellit"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aktiv në <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Deri në <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC është çaktivizuar"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC është aktivizuar"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Shkyçe për të përdorur NFC-në"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Kjo pajisje i përket organizatës sate"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Kjo pajisje i përket <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Rrëshqit për të hapur telefonin"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Rrëshqit për të hapur ndihmën zanore"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Rrëshqit për të hapur kamerën"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Shfaq profilin"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Shto përdorues"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Përdorues i ri"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Dëshiron t\'i japësh fund sesionit të vizitorit?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Jepi fund sesionit të vizitorit"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Të hiqet i ftuari?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Të gjitha aplikacionet dhe të dhënat në këtë sesion do të fshihen."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Jepi fund sesionit"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Hiq"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Mirë se erdhe, i ftuar!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Dëshiron ta vazhdosh sesionin tënd?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Fillo nga e para"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Organizata jote instaloi një autoritet certifikate në profilin tënd të punës. Trafiku i rrjetit tënd të sigurt mund të monitorohet ose modifikohet."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Në këtë pajisje është instaluar një autoritet certifikate. Trafiku i rrjetit tënd të sigurt mund të monitorohet ose modifikohet."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Administratori ka aktivizuar regjistrimin e rrjetit, i cili monitoron trafikun në pajisjen tënde."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Administratori yt ka aktivizuar regjistrimin e rrjetit, i cili monitoron trafikun në profilin tënd të punës, por jo në profilin tënd personal."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Je lidhur me aplikacionin <xliff:g id="VPN_APP">%1$s</xliff:g>, i cili mund të monitorojë aktivitetin tënd në rrjet, duke përfshirë mail-et, aplikacionet dhe sajtet e uebit."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Je lidhur me aplikacionet <xliff:g id="VPN_APP_0">%1$s</xliff:g> dhe <xliff:g id="VPN_APP_1">%2$s</xliff:g>, të cilat mund të monitorojnë aktivitetin tënd në rrjet, duke përfshirë mail-et, aplikacionet dhe sajtet e uebit."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Profili yt i punës është i lidhur me <xliff:g id="VPN_APP">%1$s</xliff:g>, i cili mund të monitorojë aktivitetin tënd në rrjet, duke përfshirë mail-et, aplikacionet dhe sajtet e uebit."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Trokit për të çaktivizuar. Shërbimet e qasshmërisë mund të çaktivizohen."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Trokit për ta vendosur në dridhje."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Trokit për ta çaktivizuar."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"çaktivizo audion"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"aktivizo audion"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"lësho dridhje"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Ky njoftim është &lt;b&gt;ulur automatikisht në nivel si në heshtje&lt;/b&gt; nga sistemi."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Ky njoftim është &lt;b&gt;renditur automatikisht më lart&lt;/b&gt; në strehën e njoftimeve."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Ky njoftim është &lt;b&gt;renditur automatikisht më poshtë&lt;/b&gt; në strehën e njoftimeve."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"A ishte e saktë kjo?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Tregoji zhvilluesit komentet e tua. A ishte e saktë kjo?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Faleminderit për komentin!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Në rregull"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Kontrollet e njoftimeve për <xliff:g id="APP_NAME">%1$s</xliff:g> janë hapur"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Zhvendos te <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Shto te pozicioni <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Pozicioni <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Pllakëza u shtua"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Pllakëza u hoq"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Redaktori i cilësimeve të shpejta."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Njoftim nga <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Hap cilësimet."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> po përdor <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ka përdorur <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> së fundi"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(ndërmarrje)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Phonecall"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefonata"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(nëpërmjet <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"kamerën"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"vendndodhjen"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensorët joaktivë"</string>
     <string name="device_services" msgid="1549944177856658705">"Shërbimet e pajisjes"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Pa titull"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Trokit për ta rinisur këtë aplikacion dhe për të kaluar në ekranin e plotë."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Zhvendos"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigimi i sistemit u përditësua. Për të bërë ndryshime, shko te \"Cilësimet\"."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Shko te \"Cilësimet\" për të përditësuar navigimin e sistemit"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Shto"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Sugjeruar nga <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Kontrollet u përditësuan"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Pajisja është e kyçur"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Kodi PIN përmban shkronja ose simbole"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Verifiko <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Kod PIN i gabuar"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 0d82246..5c2fbac 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Померајте снимак екрана"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Одбаците снимак екрана"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Преглед снимка екрана"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Горња граница"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Доња граница"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Снимач екрана"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обрађујемо видео снимка екрана"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Обавештење о сесији снимања екрана је активно"</string>
@@ -412,6 +414,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До изласка сунца"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Укључује се у <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"До <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC је онемогућен"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC је омогућен"</string>
@@ -445,6 +449,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Откључајте да бисте користили NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Овај уређај припада организацији"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Овај уређај припада организацији <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Превуците од иконе за телефон"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Превуците од иконе за гласовну помоћ"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Превуците од иконе за камеру"</string>
@@ -465,9 +471,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Прикажи профил"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Додај корисника"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Нови корисник"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Желите да завршите сесију госта?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Заврши сесију госта"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Желите ли да уклоните госта?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Све апликације и подаци у овој сесији ће бити избрисани."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Заврши сесију"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Уклони"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Добро дошли назад, госте!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Желите ли да наставите сесију?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Почни из почетка"</string>
@@ -543,6 +550,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Организација је на пословном профилу инсталирала ауторитет за издавање сертификата. Безбедни мрежни саобраћај може да се прати или мења."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"На овом уређају је инсталиран ауторитет за издавање сертификата. Безбедни мрежни саобраћај може да се прати или мења."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Администратор је укључио евидентирање мреже, које прати саобраћај на уређају."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Администратор је укључио евидентирање мреже, које прати саобраћај на пословном профилу, али не и на личном профилу."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Повезани сте са апликацијом <xliff:g id="VPN_APP">%1$s</xliff:g>, која може да надгледа активности на мрежи, укључујући имејлове, апликације и веб-сајтове."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Повезани сте са апликацијама <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="368812367182387320">"Пословни профил је повезан са апликацијом <xliff:g id="VPN_APP">%1$s</xliff:g>, која може да надгледа активности на мрежи, укључујући имејлове, апликације и веб-сајтове."</string>
@@ -623,6 +631,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Додирните да бисте искључили звук. Звук услуга приступачности ће можда бити искључен."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Додирните да бисте подесили на вибрацију."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Додирните да бисте искључили звук."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"искључите звук"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"укључите звук"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"вибрација"</string>
@@ -736,7 +746,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Систем је ово обавештење аутоматски &lt;b&gt;деградирао у Нечујно&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Ово обавештење је аутоматски &lt;b&gt;рангирано више&lt;/b&gt; на траци са обавештењима."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Ово обавештење је аутоматски &lt;b&gt;рангирано ниже&lt;/b&gt; на траци са обавештењима."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Да ли је то тачно?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Пошаљите програмеру повратне информације. Да ли је то тачно?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Хвала вам на повратним информацијама!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Потврди"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Контроле обавештења за отварање апликације <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -885,6 +895,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Преместите на <xliff:g id="POSITION">%1$d</xliff:g>. позицију"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Додајте на <xliff:g id="POSITION">%1$d</xliff:g>. позицију"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g>. позиција"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Плочица је додата"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Плочица је уклоњена"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Уређивач за Брза подешавања."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Обавештења за <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Отвори Подешавања."</string>
@@ -975,7 +987,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Апликација <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> користи: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Апликација <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> је недавно користила: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(за предузећа)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Телефонски позив"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Телефонски позив"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(преко: <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"камеру"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"локацију"</string>
@@ -983,7 +995,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Сензори су искључени"</string>
     <string name="device_services" msgid="1549944177856658705">"Услуге за уређаје"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Без наслова"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Додирните да бисте рестартовали апликацију и прешли у режим целог екрана."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Премести"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Навигација система је ажурирана. Да бисте унели измене, идите у Подешавања."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Идите у Подешавања да бисте ажурирали навигацију система"</string>
@@ -1038,6 +1049,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Додај"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Предлаже <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Контроле су ажуриране"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Уређај је закључан"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN садржи слова или симболе"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Верификујте: <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Погрешан PIN"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 969bdcd..5ca41ed 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Rullande skärmbild"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Stäng skärmbild"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Förhandsgranskning av skärmbild"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Övre gräns"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Nedre gräns"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Skärminspelare"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandlar skärminspelning"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Avisering om att skärminspelning pågår"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Till soluppgången"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aktivera kl. <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Till <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC är inaktiverat"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC är aktiverat"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Lås upp om du vill använda NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Den här enheten tillhör organisationen"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Den här enheten tillhör <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Svep från ikonen och öppna telefonen"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Svep från ikonen och öppna röstassistenten"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Svep från ikonen och öppna kameran"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Visa profil"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Lägg till användare"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Ny användare"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Vill du avsluta gästsessionen?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Avsluta gästsession"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Vill du ta bort gästen?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alla appar och data i denna session kommer att raderas."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Avsluta session"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Ta bort"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Välkommen tillbaka gäst!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Vill du fortsätta sessionen?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Börja om"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Organisationen har installerat en certifikatutfärdare i jobbprofilen. Din säkra nätverkstrafik kan övervakas och ändras."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"En certifikatutfärdare är installerad på enheten. Din säkra nätverkstrafik kan övervakas och ändras."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Administratören har aktiverat nätverksloggning som övervakar trafik på enheten."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Administratören har aktiverat nätverksloggning som övervakar trafik i jobbprofilen men inte den privata profilen."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Du är ansluten till <xliff:g id="VPN_APP">%1$s</xliff:g> som kan övervaka din nätverksaktivitet, inklusive e-postmeddelanden, appar och webbplatser."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Du är ansluten till <xliff:g id="VPN_APP_0">%1$s</xliff:g> och <xliff:g id="VPN_APP_1">%2$s</xliff:g> som kan övervaka din nätverksaktivitet, inklusive e-postmeddelanden, appar och webbplatser."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Jobbprofilen är ansluten till <xliff:g id="VPN_APP">%1$s</xliff:g> som kan övervaka din nätverksaktivitet, exempelvis e-post, appar och webbplatser."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Tryck här om du vill stänga av ljudet. Tillgänglighetstjänsterna kanske inaktiveras."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Tryck här om du vill aktivera vibrationsläget."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Tryck här om du vill stänga av ljudet."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"stänga av ljudet"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"slå på ljudet"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibration"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Aviseringens relevans &lt;b&gt;ändrades till Tyst&lt;/b&gt; automatiskt av systemet."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Aviseringens relevans i meddelandepanelen &lt;b&gt;höjdes&lt;/b&gt; automatiskt."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Aviseringens relevans i meddelandepanelen &lt;b&gt;sänktes&lt;/b&gt; automatiskt."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Stämmer detta?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Ge utvecklaren din feedback. Stämmer detta?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Tack för din feedback!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Aviseringsinställningarna för <xliff:g id="APP_NAME">%1$s</xliff:g> är öppna"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Flytta till <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Lägg till på position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Kortet har lagts till"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Kortet har tagits bort"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Redigerare för snabbinställningar."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>-avisering: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Öppna inställningarna."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> använder <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> använde <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> nyligen"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(företag)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonsamtal"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefonsamtal"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(genom <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"plats"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensorer har inaktiverats"</string>
     <string name="device_services" msgid="1549944177856658705">"Enhetstjänster"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Ingen titel"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Tryck för att starta om appen i helskärmsläge."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Flytta"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Systemnavigeringen har uppdaterats. Öppna inställningarna om du vill ändra något."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Öppna inställningarna och uppdatera systemnavigeringen"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Lägg till"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Förslag från <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Snabbkontroller uppdaterade"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Enheten är låst"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Pinkoden innehåller bokstäver eller symboler"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Verifiera <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Fel pinkod"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 4055e8d..768e10c 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Fanya picha ya skrini iwe ndefu"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ondoa picha ya skrini"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Onyesho la kukagua picha ya skrini"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Mpaka wa sehemu ya juu"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Mpaka wa sehemu ya chini"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Kinasa Skrini"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Inachakata rekodi ya skrini"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Arifa inayoendelea ya kipindi cha kurekodi skrini"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hadi macheo"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Itawashwa saa <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Hadi saa <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC imezimwa"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC imewashwa"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Fungua ili utumie NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Kifaa hiki kinamilikiwa na shirika lako"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Kifaa hiki kinamilikiwa na <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Telezesha kidole kutoka kwa aikoni ili ufikie simu"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Telezesha kidole kutoka aikoni ili upate mapendekezo ya sauti"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Telezesha kidole kutoka aikoni ili ufikie kamera"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Onyesha wasifu"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Ongeza mtumiaji"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Mtumiaji mpya"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Ungependa kumaliza kipindi cha mgeni?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Maliza kipindi cha mgeni"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Ungependa kumwondoa mgeni?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Data na programu zote katika kipindi hiki zitafutwa."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Maliza kipindi"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Ondoa"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Karibu tena, mwalikwa!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Je, unataka kuendelea na kipindi chako?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Anza tena"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Shirika lako limesakinisha mamlaka ya cheti katika wasifu wako wa kazini. Huenda shughuli kwenye mtandao wako salama zikafuatiliwa au kubadilishwa."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Mamlaka ya cheti imesakinishwa kwenye kifaa hiki. Huenda shughuli kwenye mtandao wako salama zikafuatiliwa au kubadilishwa."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Msimamizi wako amewasha kumbukumbu ya kuingia mtandaoni, ambayo hufuatilia shughuli kwenye kifaa chako."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Msimamizi wako amewasha kumbukumbu ya kuingia mtandaoni ambayo hufuatilia shughuli kwenye wasifu wako wa kazini ila si kwenye wasifu wako wa binafsi."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Umeunganishwa kwenye <xliff:g id="VPN_APP">%1$s</xliff:g>, ambayo inaweza kufuatilia shughuli za mtandao wako, ikiwa ni pamoja na barua pepe, programu na tovuti."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Umeunganishwa kwenye <xliff:g id="VPN_APP_0">%1$s</xliff:g> na <xliff:g id="VPN_APP_1">%2$s</xliff:g>, ambazo zinaweza kufuatilia shughuli za mtandao wako, ikiwa ni pamoja na barua pepe, programu na tovuti."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Wasifu wako wa kazini umeunganishwa kwenye <xliff:g id="VPN_APP">%1$s</xliff:g>, ambayo inaweza kufuatilia shughuli za mtandao wako, ikiwa ni pamoja na barua pepe, programu na tovuti."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Gusa ili ukomeshe. Huenda ikakomesha huduma za zana za walio na matatizo ya kuona au kusikia."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Gusa ili uweke mtetemo."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Gusa ili usitishe."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"zima sauti"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"washa sauti"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"tetema"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Arifa hii &lt;b&gt;imeshushwa hadhi kiotomatiki na mfumo kuwa Kimya&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Arifa hii &lt;b&gt;imeorodheshwa kiotomatiki katika nafasi ya juu&lt;/b&gt; katika kiwango chako."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Arifa hii &lt;b&gt;imeorodheshwa kiotomatiki katika nafasi ya chini&lt;/b&gt; katika kiwango chako."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Je, hatua hii ilikuwa sahihi?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Mpe msanidi programu maoni yako. Je, hatua hii ilikuwa sahihi?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Asante kwa maoni yako!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Sawa"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Vidhibiti vya arifa <xliff:g id="APP_NAME">%1$s</xliff:g> vimefunguliwa"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Hamishia kwenye <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Ongeza kwenye nafasi ya <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Nafasi ya <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Kigae kimewekwa"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Kigae kimeondolewa"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Kihariri cha Mipangilio ya haraka."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Arifa kutoka <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Fungua mipangilio."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> inatumia <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ilitumia <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> hivi majuzi"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(biashara)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Simu"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Simu"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(kupitia <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"mahali"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Umezima vitambuzi"</string>
     <string name="device_services" msgid="1549944177856658705">"Huduma za Kifaa"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Wimbo hauna jina"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Gusa ili uzime na uwashe upya programu hii kisha nenda kwenye skrini nzima."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Sogeza"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Umesasisha usogezaji kwenye mfumo. Ili ubadilishe, nenda kwenye Mipangilio."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Nenda kwenye mipangilio ili usasishe usogezaji kwenye mfumo"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Weka"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Kimependekezwa na <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Umesasisha vidhibiti"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Kifaa kimefungwa"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN ina herufi au alama"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Thibitisha <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Nambari ya PIN si sahihi"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index cbac87e..2ea5a6a 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"ஸ்கிரீன்ஷாட்டைப் பெரிதாக்கும்"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ஸ்கிரீன்ஷாட்டை நிராகரிக்கும்"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ஸ்கிரீன்ஷாட்டின் மாதிரிக்காட்சி"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"மேற்புற எல்லை"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"கீழ்ப்புற எல்லை"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"ஸ்கிரீன் ரெக்கார்டர்"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ஸ்க்ரீன் ரெக்கார்டிங் செயலாக்கப்படுகிறது"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"திரை ரெக்கார்டிங் அமர்விற்கான தொடர் அறிவிப்பு"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"காலை வரை"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>க்கு ஆன் செய்"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> வரை"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC முடக்கப்பட்டது"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC இயக்கப்பட்டது"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCயைப் பயன்படுத்த அன்லாக் செய்யவும்"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"இந்த சாதனம் உங்கள் நிறுவனத்துக்கு சொந்தமானது"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"இந்த சாதனம் <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> நிறுவனத்துக்கு சொந்தமானது"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"ஃபோனிற்கு ஐகானிலிருந்து ஸ்வைப் செய்யவும்"</string>
     <string name="voice_hint" msgid="7476017460191291417">"குரல் உதவிக்கு ஐகானிலிருந்து ஸ்வைப் செய்யவும்"</string>
     <string name="camera_hint" msgid="4519495795000658637">"கேமராவிற்கு ஐகானிலிருந்து ஸ்வைப் செய்யவும்"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"சுயவிவரத்தைக் காட்டு"</string>
     <string name="user_add_user" msgid="4336657383006913022">"பயனரைச் சேர்"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"புதியவர்"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"விருந்தினர் அமர்வை நிறைவுசெய்யவா?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"விருந்தினர் அமர்வை நிறைவுசெய்"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"கெஸ்ட்டை அகற்றவா?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"இந்த அமர்வின் எல்லா பயன்பாடுகளும், தரவும் நீக்கப்படும்."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"அமர்வை நிறைவுசெய்"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"அகற்று"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"நல்வரவு!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"உங்கள் அமர்வைத் தொடர விருப்பமா?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"மீண்டும் தொடங்கு"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"உங்கள் நிறுவனம், பணிக் கணக்கில் சான்றிதழ் அங்கீகாரத்தை நிறுவியுள்ளது. உங்களின் பாதுகாப்பான நெட்வொர்க் ட்ராஃபிக் கண்காணிக்கப்படலாம் அல்லது மாற்றப்படலாம்."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"இந்தச் சாதனத்தில் சான்றிதழ் அங்கீகாரம் நிறுவப்பட்டுள்ளது. உங்களின் பாதுகாப்பான நெட்வொர்க் ட்ராஃபிக் கண்காணிக்கப்படலாம் அல்லது மாற்றப்படலாம்."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"உங்கள் நிர்வாகி, நெட்வொர்க் பதிவெடுத்தலை இயக்கியுள்ளார். இது சாதனத்தில் ட்ராஃபிக்கைக் கண்காணிக்கும்."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"உங்கள் நிர்வாகி \'நெட்வொர்க் பதிவெடுத்தலை\' இயக்கியுள்ளார், இது உங்கள் பணிக் கணக்கில் டிராஃபிக்கைக் கண்காணிக்கும். ஆனால் தனிப்பட்ட கணக்கில் கண்காணிக்காது."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"மின்னஞ்சல்கள், ஆப்ஸ், இணையதளங்கள் உட்பட உங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="VPN_APP">%1$s</xliff:g> உடன் இணைக்கப்பட்டுள்ளீர்கள்."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"மின்னஞ்சல்கள், ஆப்ஸ், இணையதளங்கள் உட்பட உங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <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="368812367182387320">"மின்னஞ்சல்கள், ஆப்ஸ், இணையதளங்கள் உட்பட உங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="VPN_APP">%1$s</xliff:g> உடன் உங்கள் பணிக் கணக்கு இணைக்கப்பட்டுள்ளது."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. ஒலியடக்க, தட்டவும். அணுகல்தன்மை சேவைகள் ஒலியடக்கப்படக்கூடும்."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. அதிர்விற்கு அமைக்க, தட்டவும்."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. ஒலியடக்க, தட்டவும்."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"ஒலியடக்கும்"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"ஒலி இயக்கும்"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"அதிர்வுறும்"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"சிஸ்டத்தால் தானாகவே இந்த அறிவிப்பு &lt;b&gt;நிசப்த நிலைக்குக் குறைத்து அமைக்கப்பட்டது&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"அறிவிப்பு விவரத்தில் தானாகவே இந்த அறிவிப்பின் &lt;b&gt;முக்கியத்துவம் உயர்த்தப்பட்டது&lt;/b&gt;."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"அறிவிப்பு விவரத்தில் தானாகவே இந்த அறிவிப்பின் &lt;b&gt;முக்கியத்துவம் குறைக்கப்பட்டது&lt;/b&gt;."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"இது சரியானதா?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"உங்கள் கருத்தை டெவெலப்பருக்குத் தெரியப்படுத்துங்கள். இது சரியானதா?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"உங்கள் கருத்துக்கு நன்றி!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"சரி"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g>க்கான அறிவிப்புக் கட்டுப்பாடுகள் திறக்கப்பட்டன"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g>க்கு நகர்த்தும்"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g>ல் சேர்க்கும்"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"இடம்: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"கட்டம் சேர்க்கப்பட்டது"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"கட்டம் அகற்றப்பட்டது"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"விரைவு அமைப்புகள் திருத்தி."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> அறிவிப்பு: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"அமைப்புகளைத் திற."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ஆப்ஸ் <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> பயன்படுத்துகிறது"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"சமீபத்தில் <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ஆப்ஸ் <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> பயன்படுத்தியுள்ளது"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(நிறுவனப் பதிப்பு)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"மொபைல் அழைப்பு"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"மொபைல் அழைப்பு"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> மூலம்)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"கேமரா"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"இருப்பிடம்"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"சென்சார்களை ஆஃப் செய்தல்"</string>
     <string name="device_services" msgid="1549944177856658705">"சாதன சேவைகள்"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"தலைப்பு இல்லை"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"தட்டுவதன் மூலம் இந்த ஆப்ஸை மீண்டும் தொடங்கலாம், முழுத்திரையில் பார்க்கலாம்."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"நகர்த்து"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"சிஸ்டம் நேவிகேஷன் மாற்றப்பட்டது. மாற்றங்களைச் செய்ய ‘அமைப்புகளுக்குச்’ செல்லவும்."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"சிஸ்டம் நேவிகேஷனை மாற்ற ’அமைப்புகளுக்குச்’ செல்லவும்"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"சேர்"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ஆப்ஸால் பரிந்துரைக்கப்பட்டது"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"கட்டுப்பாடுகள் மாற்றப்பட்டன"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"சாதனம் பூட்டப்பட்டது"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"பின்னில் எழுத்துகள் அல்லது குறிகள் உள்ளன"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> ஐச் சரிபார்த்தல்"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"தவறான பின்"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 45ef339..03af2a0 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"స్క్రీన్‌షాట్‌కు స్క్రోల్ చేయండి"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"స్క్రీన్‌షాట్‌ను విస్మరించు"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"స్క్రీన్‌షాట్ ప్రివ్యూ"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"ఎగువ సరిహద్దు"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"దిగువ సరిహద్దు"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"స్క్రీన్ రికార్డర్"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"స్క్రీన్ రికార్డింగ్ అవుతోంది"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"స్క్రీన్ రికార్డ్ సెషన్ కోసం ఆన్‌గోయింగ్ నోటిఫికేషన్"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"సూర్యోదయం వరకు"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> కు ఆన్ అవుతుంది"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> వరకు"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC నిలిపివేయబడింది"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ప్రారంభించబడింది"</string>
@@ -440,9 +444,11 @@
     <string name="notification_tap_again" msgid="4477318164947497249">"తెరవడానికి మళ్లీ నొక్కండి"</string>
     <string name="keyguard_unlock" msgid="8031975796351361601">"తెరవడానికి, పైకి స్వైప్ చేయండి"</string>
     <string name="keyguard_retry" msgid="886802522584053523">"మళ్ళీ ప్రయత్నించడానికి పైకి స్వైప్ చేయండి"</string>
-    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCను ఉపయోగించడానికి అన్‌లాక్ చేయండి"</string>
+    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCని ఉపయోగించడానికి అన్‌లాక్ చేయండి"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"ఈ పరికరం మీ సంస్థకు చెందినది"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"ఈ పరికరం <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>కు చెందినది"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"ఫోన్ కోసం చిహ్నాన్ని స్వైప్ చేయండి"</string>
     <string name="voice_hint" msgid="7476017460191291417">"వాయిస్ అసిస్టెంట్ చిహ్నం నుండి స్వైప్"</string>
     <string name="camera_hint" msgid="4519495795000658637">"కెమెరా కోసం చిహ్నాన్ని స్వైప్ చేయండి"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"ప్రొఫైల్‌ని చూపు"</string>
     <string name="user_add_user" msgid="4336657383006913022">"వినియోగదారుని జోడించండి"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"కొత్త వినియోగదారు"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"గెస్ట్ సెషన్‌ను ముగించాలా?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"గెస్ట్ సెషన్‌ను ముగించు"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"అతిథిని తీసివేయాలా?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ఈ సెషన్‌లోని అన్ని యాప్‌లు మరియు డేటా తొలగించబడతాయి."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"సెషన్‌ను ముగించు"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"తీసివేయి"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"పునఃస్వాగతం, అతిథి!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"మీరు మీ సెషన్‌ని కొనసాగించాలనుకుంటున్నారా?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"మొదటి నుండి ప్రారంభించు"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"మీ కార్యాలయ ప్రొఫైల్‌లో మీ సంస్థ ఒక ప్రమాణపత్ర అధికారాన్ని ఇన్‌స్టాల్ చేసింది. మీ సురక్షిత నెట్‌వర్క్ ట్రాఫిక్ పర్యవేక్షించబడవచ్చు లేదా సవరించబడవచ్చు."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"ఈ పరికరంలో ప్రమాణపత్ర అధికారం ఇన్‌స్టాల్ చేయబడింది. మీ సురక్షిత నెట్‌వర్క్ ట్రాఫిక్ పర్యవేక్షించబడవచ్చు లేదా సవరించబడవచ్చు."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"మీ నిర్వాహకులు మీ పరికరంలోని ట్రాఫిక్‌ని పర్యవేక్షించగల నెట్‌వర్క్ లాగింగ్‌ని ఆన్ చేసారు."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"మీ అడ్మిన్ నెట్‌వర్క్ లాగింగ్‌ను ఆన్ చేశారు, ఇది మీ వర్క్ ప్రొఫైల్‌లోని ట్రాఫిక్‌ను పర్యవేక్షిస్తుంది కానీ మీ వ్యక్తిగత ప్రొఫైల్‌లో కాదు."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"మీరు <xliff:g id="VPN_APP">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఇమెయిల్‌లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"మీరు ఇమెయిల్‌లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగల <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="368812367182387320">"మీ కార్యాలయ ప్రొఫైల్ ఇమెయిల్‌లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="VPN_APP">%1$s</xliff:g>కి కనెక్ట్ చేయబడింది."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. మ్యూట్ చేయడానికి నొక్కండి. యాక్సెస్ సామర్థ్య సేవలు మ్యూట్ చేయబడవచ్చు."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. వైబ్రేట్ అయ్యేలా సెట్ చేయడం కోసం నొక్కండి."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. మ్యూట్ చేయడానికి నొక్కండి."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"మ్యూట్ చేయి"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"అన్‌మ్యూట్ చేయి"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"వైబ్రేట్"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"ఈ నోటిఫికేషన్, సిస్టమ్ ద్వారా ఆటోమేటిక్‌గా &lt;b&gt;నిశ్శబ్దం స్థాయికి తగ్గించబడింది&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"మీ నోటిఫికేషన్ షేడ్‌లో ఈ నోటిఫికేషన్ ఆటోమేటిక్‌గా &lt;b&gt;ఎక్కువ ర్యాంక్‌&lt;/b&gt;కు సర్దుబాటు చేయబడింది."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"మీ నోటిఫికేషన్ షేడ్‌లో ఈ నోటిఫికేషన్ ఆటోమేటిక్‌గా &lt;b&gt;తక్కువ ర్యాంక్‌&lt;/b&gt;కు సర్దుబాటు చేయబడింది."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"ఇది సరైనదేనా?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"మీ ఫీడ్‌బ్యాక్‌ను డెవలపర్‌కు తెలియజేయండి. ఇది సరైనదేనా?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"మీ ఫీడ్‌బ్యాక్‌ను అందించినందుకు ధన్యవాదాలు!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"సరే"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> యొక్క నోటిఫికేషన్ నియంత్రణలు తెరవబడ్డాయి"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g>కు తరలించండి"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> స్థానానికి జోడించండి"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"స్థానం <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"టైల్ జోడించబడింది"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"టైల్ తీసివేయబడింది"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"శీఘ్ర సెట్టింగ్‌ల ఎడిటర్."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> నోటిఫికేషన్: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"సెట్టింగ్‌లను తెరవండి."</string>
@@ -967,23 +979,17 @@
     <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"అప్లికేషన్‌లు మీ <xliff:g id="TYPES_LIST">%s</xliff:g>ని ఉపయోగిస్తున్నాయి."</string>
     <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
     <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" మరియు "</string>
-    <!-- no translation found for ongoing_privacy_dialog_using_op (4125175620929701569) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_recent_op (4255923947334262404) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_enterprise (4082735415905550729) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_phonecall (3526223335298089311) -->
-    <skip />
-    <!-- no translation found for ongoing_privacy_dialog_attribution_text (9186683306719924646) -->
-    <skip />
+    <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>, <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>ను ఉపయోగిస్తోంది"</string>
+    <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>, ఇటీవల <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>ను ఉపయోగించింది"</string>
+    <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(ఎంటర్‌ప్రైజ్)"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"ఫోన్ కాల్"</string>
+    <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> ద్వారా)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"కెమెరా"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"లొకేషన్"</string>
     <string name="privacy_type_microphone" msgid="9136763906797732428">"మైక్రోఫోన్"</string>
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"సెన్సార్‌లు ఆఫ్"</string>
     <string name="device_services" msgid="1549944177856658705">"పరికర సేవలు"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"శీర్షిక లేదు"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"ఈ యాప్‌ను పునఃప్రారంభించేలా నొక్కి, ఆపై పూర్తి స్క్రీన్‌‍లోకి వెళ్లండి."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"తరలించు"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"సిస్టమ్ నావిగేషన్ అప్‌డేట్ చేయబడింది. మార్పులు చేయడానికి, సెట్టింగ్‌లకు వెళ్లండి."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"సిస్టమ్ నావిగేషన్‌ను అప్‌డేట్ చేయడానికి సెట్టింగ్‌లకు వెళ్లండి"</string>
@@ -1037,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"జోడించండి"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ద్వారా సూచించబడింది"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"నియంత్రణలు అప్‌డేట్ అయ్యాయి"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"పరికరంలాక్ చేయబడింది"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"పిన్ అక్షరాలను లేదా చిహ్నాలను కలిగి ఉంది"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g>ను వెరిఫై చేయండి"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"పిన్ తప్పు"</string>
diff --git a/packages/SystemUI/res/values-television/config.xml b/packages/SystemUI/res/values-television/config.xml
index 722f148..b02d8b8 100644
--- a/packages/SystemUI/res/values-television/config.xml
+++ b/packages/SystemUI/res/values-television/config.xml
@@ -28,6 +28,7 @@
     <string-array name="config_systemUIServiceComponents" translatable="false">
         <item>com.android.systemui.util.NotificationChannels</item>
         <item>com.android.systemui.volume.VolumeUI</item>
+        <item>com.android.systemui.privacy.television.TvOngoingPrivacyChip</item>
         <item>com.android.systemui.statusbar.tv.TvStatusBar</item>
         <item>com.android.systemui.statusbar.tv.notifications.TvNotificationPanel</item>
         <item>com.android.systemui.statusbar.tv.notifications.TvNotificationHandler</item>
diff --git a/packages/SystemUI/res/values-television/dimens.xml b/packages/SystemUI/res/values-television/dimens.xml
index 6da0c69..7626db9 100644
--- a/packages/SystemUI/res/values-television/dimens.xml
+++ b/packages/SystemUI/res/values-television/dimens.xml
@@ -17,4 +17,8 @@
 <resources>
     <!-- Opacity at which the background for the shutdown UI will be drawn. -->
     <item name="shutdown_scrim_behind_alpha" format="float" type="dimen">1.0</item>
+
+    <dimen name="privacy_chip_icon_margin">3dp</dimen>
+    <dimen name="privacy_chip_icon_padding">8dp</dimen>
+    <dimen name="privacy_chip_icon_size">13dp</dimen>
 </resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 8b197ac..5e37ed8 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"เลื่อนจับภาพหน้าจอ"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ปิดภาพหน้าจอ"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ตัวอย่างภาพหน้าจอ"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"ขอบเขตด้านบน"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"ขอบเขตด้านล่าง"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"โปรแกรมบันทึกหน้าจอ"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"กำลังประมวลผลการอัดหน้าจอ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"การแจ้งเตือนต่อเนื่องสำหรับเซสชันการบันทึกหน้าจอ"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"จนพระอาทิตย์ขึ้น"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"เปิดเวลา <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"จนถึง <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ถูกปิดใช้งาน"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"เปิดใช้งาน NFC แล้ว"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"ปลดล็อกเพื่อใช้ NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"องค์กรของคุณเป็นเจ้าของอุปกรณ์นี้"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> เป็นเจ้าของอุปกรณ์นี้"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"เลื่อนไอคอนโทรศัพท์"</string>
     <string name="voice_hint" msgid="7476017460191291417">"เลื่อนไอคอนตัวช่วยเสียง"</string>
     <string name="camera_hint" msgid="4519495795000658637">"เลื่อนไอคอนกล้อง"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"แสดงโปรไฟล์"</string>
     <string name="user_add_user" msgid="4336657383006913022">"เพิ่มผู้ใช้"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"ผู้ใช้ใหม่"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"จบเซสชันผู้เยี่ยมชมใช่ไหม"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"จบเซสชันผู้เยี่ยมชม"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"ต้องการนำผู้เข้าร่วมออกไหม"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ระบบจะลบแอปและข้อมูลทั้งหมดในเซสชันนี้"</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"จบเซสชัน"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"นำออก"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"ยินดีต้อนรับท่านผู้เยี่ยมชมกลับมาอีกครั้ง!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"คุณต้องการอยู่ในเซสชันต่อไปไหม"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"เริ่มต้นใหม่"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"องค์กรของคุณติดตั้งผู้ออกใบรับรองในโปรไฟล์งาน อาจมีการตรวจสอบหรือแก้ไขการจราจรของข้อมูลในเครือข่ายที่ปลอดภัยของคุณ"</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"มีการติดตั้งผู้ออกใบรับรองในอุปกรณ์นี้ อาจมีการตรวจสอบหรือแก้ไขการจราจรของข้อมูลในเครือข่ายที่ปลอดภัยของคุณ"</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"ผู้ดูแลระบบได้เปิดการบันทึกเครือข่าย ซึ่งจะตรวจสอบการจราจรของข้อมูลในอุปกรณ์ของคุณ"</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"ผู้ดูแลระบบได้เปิดการบันทึกเครือข่าย ซึ่งจะตรวจสอบการรับส่งข้อมูลในโปรไฟล์งาน แต่ไม่ตรวจสอบในโปรไฟล์ส่วนตัวของคุณ"</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"คุณเชื่อมต่ออยู่กับ <xliff:g id="VPN_APP">%1$s</xliff:g> ซึ่งสามารถตรวจสอบกิจกรรมในเครือข่ายของคุณ รวมถึงอีเมล แอป และเว็บไซต์"</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"คุณเชื่อมต่ออยู่กับ <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="368812367182387320">"โปรไฟล์งานของคุณเชื่อมต่ออยู่กับ <xliff:g id="VPN_APP">%1$s</xliff:g> ซึ่งสามารถตรวจสอบกิจกรรมในเครือข่ายของคุณ รวมถึงอีเมล แอป และเว็บไซต์"</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s แตะเพื่อปิดเสียง อาจมีการปิดเสียงบริการการเข้าถึง"</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s แตะเพื่อตั้งค่าให้สั่น"</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s แตะเพื่อปิดเสียง"</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"ปิดเสียง"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"เปิดเสียง"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"สั่น"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"ระบบ&lt;b&gt;ลดระดับการแจ้งเตือนนี้เป็นปิดเสียง&lt;/b&gt;โดยอัตโนมัติ"</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"การแจ้งเตือนนี้&lt;b&gt;มีอันดับสูงขึ้น&lt;/b&gt;ในหน้าต่างแจ้งเตือนโดยอัตโนมัติ"</string>
     <string name="feedback_demoted" msgid="951884763467110604">"การแจ้งเตือนนี้&lt;b&gt;มีอันดับต่ำลง&lt;/b&gt;ในหน้าต่างแจ้งเตือนโดยอัตโนมัติ"</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"การดำเนินการนี้ถูกต้องไหม"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"บอกความคิดเห็นให้นักพัฒนาแอปทราบ ถูกต้องไหม"</string>
     <string name="feedback_response" msgid="4671729244976641339">"ขอบคุณที่แสดงความคิดเห็น"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ตกลง"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"ส่วนควบคุมการแจ้งเตือนของ <xliff:g id="APP_NAME">%1$s</xliff:g> เปิดอยู่"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"ย้ายไปที่ <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"เพิ่มไปยังตำแหน่ง <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"ตำแหน่ง <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"เพิ่มชิ้นส่วนแล้ว"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"นำชิ้นส่วนออกแล้ว"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ตัวแก้ไขการตั้งค่าด่วน"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> การแจ้งเตือน: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"เปิดการตั้งค่า"</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> กำลังใช้<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ใช้<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>เมื่อเร็วๆ นี้"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(องค์กร)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"โทรศัพท์"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"การโทร"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(ผ่านทาง <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"กล้องถ่ายรูป"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"ตำแหน่ง"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"ปิดเซ็นเซอร์"</string>
     <string name="device_services" msgid="1549944177856658705">"บริการของอุปกรณ์"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"ไม่มีชื่อ"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"แตะเพื่อรีสตาร์ทแอปนี้และแสดงแบบเต็มหน้าจอ"</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"ย้าย"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"อัปเดตการไปยังส่วนต่างๆ ของระบบแล้ว หากต้องการเปลี่ยนแปลง ให้ไปที่การตั้งค่า"</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"ไปที่การตั้งค่าเพื่ออัปเดตการไปยังส่วนต่างๆ ของระบบ"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"เพิ่ม"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"แนะนำโดย <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"อัปเดตตัวควบคุมแล้ว"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"อุปกรณ์ถูกล็อก"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN ประกอบด้วยตัวอักษรหรือสัญลักษณ์"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"ยืนยัน <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN ไม่ถูกต้อง"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index a4a768b..18313e4 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"I-scroll ang screenshot"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"I-dismiss ang screenshot"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Preview ng screenshot"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Pinakamataas na limitasyon"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Pinakamababang limitasyon"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Recorder ng Screen"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Pinoproseso screen recording"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Kasalukuyang notification para sa session ng pag-record ng screen"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hanggang sunrise"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ma-o-on nang <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Hanggang <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Naka-disable ang NFC"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Naka-enable ang NFC"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"I-unlock para magamit ang NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Pagmamay-ari ng iyong organisasyon ang device na ito"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Pagmamay-ari ng <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ang device na ito"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Mag-swipe mula sa icon para sa telepono"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Mag-swipe mula sa icon para sa voice assist"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Mag-swipe mula sa icon para sa camera"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Ipakita ang profile"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Magdagdag ng user"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Bagong user"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Tapusin ang session ng bisita?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Tapusin ang session ng bisita"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Alisin ang bisita?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Ide-delete ang lahat ng app at data sa session na ito."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Tapusin ang session"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Alisin"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Maligayang pagbabalik, bisita!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Gusto mo bang ipagpatuloy ang iyong session?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Magsimulang muli"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Nag-install ang iyong organisasyon ng awtoridad sa certificate sa iyong profile sa trabaho. Maaaring subaybayan o baguhin ang iyong ligtas na trapiko sa network."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"May naka-install sa device na ito na isang awtoridad sa certificate. Maaaring subaybayan o baguhin ang iyong ligtas na trapiko sa network."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Na-on ng iyong admin ang pag-log sa network, na sumusubaybay sa trapiko sa device mo."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Na-on ng iyong admin ang pag-log sa network, na sumusubaybay sa trapiko sa profile mo sa trabaho pero hindi sa iyong personal na profile."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Nakakonekta ka sa <xliff:g id="VPN_APP">%1$s</xliff:g>, na maaaring sumubaybay sa iyong aktibidad sa network, kabilang ang mga email, app, at website."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Nakakonekta ka sa <xliff:g id="VPN_APP_0">%1$s</xliff:g> at <xliff:g id="VPN_APP_1">%2$s</xliff:g>, na maaaring sumubaybay sa iyong aktibidad sa network, kabilang ang mga email, app, at website."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Nakakonekta sa <xliff:g id="VPN_APP">%1$s</xliff:g> ang iyong profile sa trabaho, na maaaring sumubaybay sa aktibidad sa iyong network, kasama ang mga email, app, at website."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. I-tap upang i-mute. Maaaring i-mute ang mga serbisyo sa Accessibility."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. I-tap upang itakda na mag-vibrate."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. I-tap upang i-mute."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"i-mute"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"i-unmute"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"i-vibrate"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Awtomatikong &lt;b&gt;na-demote sa Naka-silent&lt;/b&gt; ng system ang notification na ito."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Awtomatikong &lt;b&gt;na-rank nang mas mataas&lt;/b&gt; ang notification na ito sa iyong shade."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Awtomatikong &lt;b&gt;na-rank nang mas mababa&lt;/b&gt; ang notification na ito sa iyong shade."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Tama ba ito?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Ipaalam sa developer ang iyong feedback. Tama ba ito?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Salamat sa iyong feedback!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Binuksan ang mga kontrol sa notification para sa <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Ilipat sa <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Idagdag sa posisyong <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posisyon <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Idinagdag ang tile"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Inalis ang tile"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor ng Mga mabilisang setting."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notification sa <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Buksan ang mga setting."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Ginagamit ng <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ang <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Kamakailang ginamit ng <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ang <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(enterprise)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Tawag sa telepono"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Tawag sa telepono"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(sa pamamagitan ng <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"lokasyon"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Naka-off ang mga sensor"</string>
     <string name="device_services" msgid="1549944177856658705">"Mga Serbisyo ng Device"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Walang pamagat"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"I-tap para i-restart ang app na ito at mag-full screen."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Ilipat"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Na-update na ang pag-navigate ng system. Para gumawa ng mga pagbabago, pumunta sa Mga Setting."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Pumunta sa Mga Setting para i-update ang pag-navigate sa system"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Idagdag"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Iminungkahi ng <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Na-update na ang mga kontrol"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Naka-lock ang device"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"May mga titik o simbolo ang PIN"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"I-verify ang <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Maling PIN"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 3040ea0..6b3015c 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Kayan ekran görüntüsü"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ekran görüntüsünü kapat"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Ekran görüntüsü önizlemesi"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Üst sınır"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Alt sınır"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Ekran Kaydedicisi"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran kaydı işleniyor"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekran kaydı oturumu için devam eden bildirim"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Sabaha kadar"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Açılacağı saat: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Şu saate kadar: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC devre dışı"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC etkin"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC\'yi kullanmak için kilidi açın"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Bu cihaz, kuruluşunuza ait"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Bu cihaz <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> adlı kuruluşa ait"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Telefon için, simgeden hızlıca kaydırın"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Sesli yardım için, simgeden hızlıca kaydırın"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Kamera için, simgeden hızlıca kaydırın"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Profili göster"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Kullanıcı ekle"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Yeni kullanıcı"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Misafir oturumu sonlandırılsın mı?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Misafir oturumunu sonlandır"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Misafir oturumu kaldırılsın mı?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bu oturumdaki tüm uygulamalar ve veriler silinecek."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Oturumu sonlandır"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Kaldır"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Tekrar hoş geldiniz sayın misafir!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Oturumunuza devam etmek istiyor musunuz?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Baştan başla"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Kuruluşunuz iş profilinize bir sertifika yetkilisi yükledi. Güvenli ağ trafiğiniz izlenebilir veya değiştirilebilir."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Bu cihazda bir sertifika yetkilisi yüklü. Güvenli ağ trafiğiniz izlenebilir veya değiştirilebilir."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Yöneticiniz,cihazınızdaki trafiği izleyen ağ günlük kaydını açtı."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Yöneticiniz, iş profilinizdeki trafiği izleyen ancak kişisel profilinizdeki trafiği izlemeyen ağ günlük kaydını açtı."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"E-postalarınız, uygulamalarınız ve web siteleriniz de dahil olmak üzere ağ etkinliğinizi takip edebilen <xliff:g id="VPN_APP">%1$s</xliff:g> ağına bağlısınız."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"E-postalar, uygulamalar ve web siteleri de dahil olmak üzere ağ etkinliğinizi izleyebilen <xliff:g id="VPN_APP_0">%1$s</xliff:g> ve <xliff:g id="VPN_APP_1">%2$s</xliff:g> uygulamalarına bağlısınız."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"İş profiliniz, e-postalar, uygulamalar ve web siteleri dahil olmak üzere ağ etkinliğinizi izleyebilen <xliff:g id="VPN_APP">%1$s</xliff:g> uygulamasına bağlı."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Sesi kapatmak için dokunun. Erişilebilirlik hizmetlerinin sesi kapatılabilir."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Titreşime ayarlamak için dokunun."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Sesi kapatmak için dokunun."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"sesi  kapat"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"sesi aç"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"titreşim"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Bu bildirim, sistem tarafından otomatik olarak &lt;b&gt;Sessize düşürüldü&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Bu bildirim, gölgenizde otomatik olarak &lt;b&gt;daha yüksek sıralandı&lt;/b&gt;."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Bu bildirim, gölgenizde otomatik olarak &lt;b&gt;daha düşük sıralandı&lt;/b&gt;."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Bu doğru muydu?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Görüşlerinizi geliştiriciye bildirin. Bu doğru muydu?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Geri bildiriminiz için teşekkürler!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Tamam"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> için bildirim kontrolleri açıldı"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> konumuna taşı"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> konumuna ekle"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Konum: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Kart eklendi"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Parça kaldırıldı"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Hızlı ayar düzenleyicisi."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> bildirimi: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Ayarları aç."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>, <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> uygulamasını kullanıyor"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>, yakın zamanda <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> uygulamasını kullandı"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(kurumsal)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefon çağrısı"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Sesli arama"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> aracılığıyla)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"konum"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensörler kapalı"</string>
     <string name="device_services" msgid="1549944177856658705">"Cihaz Hizmetleri"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Başlıksız"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Bu uygulamayı yeniden başlatmak ve tam ekrana geçmek için dokunun."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Taşı"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Sistemde gezinme yöntemi güncellendi. Değişiklik yapmak için Ayarlar\'a gidin."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Sistemde gezinme yöntemini güncellemek için Ayarlar\'a gidin"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Ekle"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> tarafından önerildi"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Denetimler güncellendi"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Cihaz kilitlendi"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN, harf veya simge içerir"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> cihazını doğrulayın"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Yanlış PIN"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index b6b7cee..12b4830 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Прокрутити знімок екрана"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Закрити знімок екрана"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Перегляд знімка екрана"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Верхня межа"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Нижня межа"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Відеозапис екрана"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обробка записування екрана"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Сповіщення про сеанс запису екрана"</string>
@@ -414,6 +416,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До сходу сонця"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Вмикається о <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"До <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC вимкнено"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ввімкнено"</string>
@@ -447,6 +451,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Розблокуйте екран, щоб скористатись NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Цей пристрій належить вашій організації"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Цей пристрій належить організації \"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>\""</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Телефон: проведіть пальцем від значка"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Голосові підказки: проведіть пальцем від значка"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Камера: проведіть пальцем від значка"</string>
@@ -467,9 +473,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Показати профіль"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Додати користувача"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Новий користувач"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Завершити сеанс у режимі \"Гість\"?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Завершити сеанс у режимі \"Гість\""</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Вийти з режиму гостя?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Усі додатки й дані з цього сеансу буде видалено."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Завершити сеанс"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Вийти"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"З поверненням!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Продовжити сеанс?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Почати знову"</string>
@@ -546,6 +553,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Адміністратор організації встановив центр сертифікації у вашому робочому профілі. Захищений мережевий трафік може відстежуватися або змінюватися."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"На цьому пристрої встановлено центр сертифікації. Захищений мережевий трафік може відстежуватися або змінюватися."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Ваш адміністратор увімкнув реєстрацію в мережі, під час якої на вашому пристрої відстежується трафік."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Ваш адміністратор увімкнув реєстрацію в журналі мережі, щоб відстежувати трафік вашого робочого профілю (не особистого)."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Під’єднано додаток <xliff:g id="VPN_APP">%1$s</xliff:g>, який може відстежувати вашу активність у мережі, як-от відкривання електронних листів, додатків і веб-сайтів."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Під’єднано додатки <xliff:g id="VPN_APP_1">%2$s</xliff:g> та <xliff:g id="VPN_APP_0">%1$s</xliff:g>, які можуть відстежувати вашу активність у мережі, як-от відкривання електронних листів, додатків і веб-сайтів."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Ваш робочий профіль під’єднано до додатка <xliff:g id="VPN_APP">%1$s</xliff:g>, який може відстежувати вашу активність у мережі, зокрема в електронній пошті, додатках і на веб-сайтах."</string>
@@ -626,6 +634,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Торкніться, щоб вимкнути звук. Спеціальні можливості може бути вимкнено."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Торкніться, щоб налаштувати вібросигнал."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Торкніться, щоб вимкнути звук."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"вимкнути звук"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"увімкнути звук"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"увімкнути вібросигнал"</string>
@@ -739,7 +749,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Пріоритет цього сповіщення автоматично &lt;b&gt;знижено до \"Без звуку\"&lt;/b&gt; в системі."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Пріоритет цього сповіщення на панелі сповіщень автоматично &lt;b&gt;підвищено&lt;/b&gt;."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Пріоритет цього сповіщення на панелі сповіщень автоматично &lt;b&gt;знижено&lt;/b&gt;."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Правильно?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Надішліть розробнику свій відгук. Усе правильно?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Дякуємо за відгук!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Елементи керування сповіщеннями для додатка <xliff:g id="APP_NAME">%1$s</xliff:g> відкрито"</string>
@@ -890,6 +900,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Перемістити на позицію <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Додати на позицію <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Позиція <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Опцію додано"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Опцію вилучено"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Редактор швидких налаштувань."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Сповіщення <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Відкрити налаштування."</string>
@@ -980,7 +992,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Додаток <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> використовує функцію \"<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>\""</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Додаток <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> нещодавно використав функцію \"<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>\""</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(корпоративний додаток)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Додаток для телефонних дзвінків"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Телефонний дзвінок"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(через <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"камеру"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"місце"</string>
@@ -988,7 +1000,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Датчики вимкнено"</string>
     <string name="device_services" msgid="1549944177856658705">"Сервіси на пристрої"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Без назви"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Натисніть, щоб перезапустити додаток і перейти в повноекранний режим."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Перемістити"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Навігацію в системі оновлено. Щоб внести зміни, перейдіть у налаштування."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Перейдіть у налаштування, щоб оновити навігацію в системі"</string>
@@ -1044,6 +1055,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Додати"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Запропоновано додатком <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Елементи керування оновлено"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Пристрій заблоковано"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-код містить літери чи символи"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Неправильний PIN-код"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 15c9607..3668f7e 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"اسکرین شاٹ پر اسکرول کریں"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"اسکرین شاٹ برخاست کریں"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"اسکرین شاٹ کا پیش منظر"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"اوپر کا احاطہ"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"نیچے کا احاطہ"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"سکرین ریکارڈر"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"سکرین ریکارڈنگ پروسیس ہورہی ہے"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"اسکرین ریکارڈ سیشن کیلئے جاری اطلاع"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"طلوع آفتاب تک"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"آن ہوگی بوقت <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> تک"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"‏NFC غیر فعال ہے"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"‏NFC فعال ہے"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"‏NFC استعمال کرنے کیلئے غیر مقفل کریں"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"یہ آلہ آپ کی تنظیم کا ہے"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"یہ آلہ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> کا ہے"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"فون کیلئے آئیکن سے سوائپ کریں"</string>
     <string name="voice_hint" msgid="7476017460191291417">"صوتی معاون کیلئے آئیکن سے سوائپ کریں"</string>
     <string name="camera_hint" msgid="4519495795000658637">"کیمرہ کیلئے آئیکن سے سوائپ کریں"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"پروفائل دکھائیں"</string>
     <string name="user_add_user" msgid="4336657383006913022">"صارف کو شامل کریں"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"نیا صارف"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"مہمان سیشن ختم کریں؟"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"مہمان سیشن ختم کریں"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"مہمان کو ہٹائیں؟"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"اس سیشن میں موجود سبھی ایپس اور ڈیٹا کو حذف کر دیا جائے گا۔"</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"سیشن ختم کریں"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"ہٹائیں"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"مہمان، پھر سے خوش آمدید!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"کیا آپ اپنا سیشن جاری رکھنا چاہتے ہیں؟"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"دوبارہ شروع کریں"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"آپ کی تنظیم نے آپ کے دفتری پروفائل میں ایک سرٹیفکیٹ کی اتھارٹی کو انسٹال کیا ہے۔ آپ کا محفوظ نیٹ ورک ٹریفک مانیٹر ہو سکتا ہے یا اس میں ترمیم کی جا سکتی ہے۔"</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"ایک سرٹیفکیٹ کی اتھارٹی اس آلہ پر انسٹال ہے۔ آپ کا محفوظ نیٹ ورک ٹریفک مانیٹر ہو سکتا ہے یا اس میں ترمیم کی جا سکتی ہے۔"</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"آپ کے منتظم نے نیٹ ورک لاگنگ کو آن کر دیا ہے، جو آپ کے آلے پر ٹریفک مانیٹر کرتی ہے۔"</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"آپ کے منتظم نے نیٹ ورک لاگنگ آن کر دی ہے، جو آپ کے ذاتی پروفائل پر نہیں بلکہ دفتری پروفائل پر ٹریفک کو مانیٹر کرتی ہے۔"</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"آپ <xliff:g id="VPN_APP">%1$s</xliff:g> سے منسلک ہیں جو ای میلز، ایپس اور ویب سائٹس سمیت آپ کے نیٹ ورک کی سرگرمی مانیٹر کر سکتی ہے۔"</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"آپ <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="368812367182387320">"آپ کا دفتری پروفائل <xliff:g id="VPN_APP">%1$s</xliff:g> سے منسلک ہے، جو ای میلز، ایپس اور ویب سائٹس سمیت آپ کے نیٹ ورک کی سرگرمی مانیٹر کر سکتی ہے۔"</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"‏‎%1$s۔ خاموش کرنے کیلئے تھپتھپائیں۔ ایکسیسبیلٹی سروسز شاید خاموش ہوں۔"</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"‏‎%1$s۔ ارتعاش پر سیٹ کرنے کیلئے تھپتھپائیں۔"</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"‏‎%1$s۔ خاموش کرنے کیلئے تھپتھپائیں۔"</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"خاموش کریں"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"غیر خاموش کریں"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"وائبریٹ"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"‏اس اطلاع کو خودکار طور پر سسٹم کے ذریعے &lt;b&gt;خاموش پر درجہ بند&lt;b&gt; کیا گیا۔"</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"‏اس اطلاع کو آپ کے شیڈ میں خودکار طور پر &lt;b&gt;اعلی درجہ&lt;/b&gt; دیا گیا۔"</string>
     <string name="feedback_demoted" msgid="951884763467110604">"‏اس اطلاع کو آپ کے شیڈ میں خودکار طور پر &lt;b&gt;کم درجہ&lt;/b&gt; دیا گیا۔"</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"کیا یہ درست تھا؟"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"ڈویلپر کو اپنے تاثرات فراہم کریں کیا یہ درست تھا؟"</string>
     <string name="feedback_response" msgid="4671729244976641339">"آپ کے تاثرات کا شکریہ!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ٹھیک ہے"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> کیلئے اطلاعی کنٹرولز کھلے ہیں"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> میں منتقل کریں"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"پوزیشن <xliff:g id="POSITION">%1$d</xliff:g> میں شامل کریں"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"پوزیشن <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"ٹائل کو شامل کیا گیا"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"ٹائل کو ہٹا دیا گیا"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"فوری ترتیبات کا ایڈیٹر۔"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> اطلاع: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ترتیبات کھولیں۔"</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> کا استعمال کر رہی ہے"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> نے حال ہی میں <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> کا استعمال کیا"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(انٹرپرائز)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"فون کال"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"فون کال"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> کے ذریعے)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"کیمرا"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"مقام"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"سینسرز آف ہیں"</string>
     <string name="device_services" msgid="1549944177856658705">"آلہ کی سروس"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"کوئی عنوان نہیں ہے"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"یہ ایپ دوبارہ شروع کرنے کے لیے تھپتھپائیں اور پوری اسکرین پر جائیں۔"</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"منتقل کریں"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"سسٹم نیویگیشن اپ ڈیٹ کیا گیا۔ تبدیلیاں کرنے کے لیے، ترتیبات پر جائیں۔"</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"سسٹم نیویگیشن اپ ڈیٹ کرنے کے لیے ترتیبات پر جائیں"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"شامل کریں"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> کی طرف سے تجویز کردہ"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"کنٹرولز اپ ڈیٹ کیے گئے"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"آلہ مقفل کر دیا گیا"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"‏PIN میں حروف یا علامات شامل ہیں"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"‫<xliff:g id="DEVICE">%s</xliff:g> کی تصدیق کریں"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"‏غلط PIN"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 3044a98..0732c7f 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Skrinshotni aylantirish"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Skrinshotni yopish"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Skrinshotga razm solish"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Yuqori chegara"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Quyi chegara"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Ekrandan yozib olish"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran yozib olinmoqda"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekrandan yozib olish seansi uchun joriy bildirishnoma"</string>
@@ -410,6 +412,7 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Quyosh chiqqunicha"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> da yoqiladi"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> gacha"</string>
+    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"Yorqinlikni pasaytirish"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC o‘chiq"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC yoniq"</string>
@@ -443,6 +446,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ishlatish uchun qurilma qulfini oching"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Bu qurilma tashkilotingizga tegishli"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Bu qurilma <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> tashkilotiga tegishli"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Telefonni ochish uchun suring"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Ovozli yordam: belgidan boshlab suring"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Kamerani ochish uchun suring"</string>
@@ -463,9 +468,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Profilni ko‘rsatish"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Foydalanuvchi"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Yangi foydalanuvchi"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Mehmon seansi yakunlansinmi?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Mehmon seansini yakunlash"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Mehmon hisobi o‘chirib tashlansinmi?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Ushbu seansdagi barcha ilovalar va ma’lumotlar o‘chirib tashlanadi."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Seansni yakunlash"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Olib tashlash"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Xush kelibsiz, mehmon!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Seansni davom ettirmoqchimisiz?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Boshidan boshlansin"</string>
@@ -540,6 +546,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Tashkilotingiz ishchi profilingizga CA sertifikatini o‘rnatdi. U himoyalangan tarmoq trafigini nazorat qilishi va o‘zgartirishi mumkin."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Qurilmada CA sertifikati o‘rnatilgan. U himoyalangan tarmoq trafigini nazorat qilishi va o‘zgartirishi mumkin."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Administrator qurilmangizdagi trafikni nazorat qiluvchi tarmoq jurnalini yoqdi."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Administrator ish profilingizdagi trafikni nazorat qiluvchi tarmoq jurnalini yoqdi (shaxsiy profildan maʼlumotlar olinmaydi)."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"<xliff:g id="VPN_APP">%1$s</xliff:g> ilovasi ishga tushirilgan. U internetdagi harakatlaringiz, jumladan, e-pochta, ilova va veb-saytlardagi xatti-harakatlaringizni kuzatishi mumkin."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> va <xliff:g id="VPN_APP_1">%2$s</xliff:g> ilovalari ishga tushirilgan. Ular tarmoqdagi, jumladan, e-pochta, ilova va veb-saytlardagi xatti-harakatlaringizni kuzatishi mumkin."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Ishchi profilingizda tarmoqdagi, jumladan, e-pochta, ilova va veb-saytlardagi xatti-harakatlaringizni kuzatishi mumkin bo‘lgan <xliff:g id="VPN_APP">%1$s</xliff:g> ilovasi ishga tushirilgan."</string>
@@ -620,6 +627,7 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Ovozini o‘chirish uchun ustiga bosing. Maxsus imkoniyatlar ishlamasligi mumkin."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Tebranishni yoqish uchun ustiga bosing."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Ovozsiz qilish uchun ustiga bosing."</string>
+    <string name="volume_ringer_change" msgid="3574969197796055532">"Jiringlagich rejimini oʻzgartirish uchun bosing"</string>
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"ovozsiz qilish"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"ovozni yoqish"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"tebranish"</string>
@@ -733,7 +741,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Bu bildirishnomaning muhimlik darajasi tizim tomonidan avtomatik ravishda &lt;b&gt;Sokin darajaga tushirildi&lt;/b&gt;."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Bu bildirishnomaning muhimlik darajasi tizim tomonidan avtomatik ravishda &lt;b&gt;yuqori darajaga chiqarildi&lt;/b&gt;."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Bu bildirishnomaning muhimlik darajasi tizim tomonidan avtomatik ravishda &lt;b&gt;quyi darajaga tushirildi&lt;/b&gt;."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Xatolar boʻlmadimi?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Ishlab chiquvchiga fikr-mulohazalaringizni bildiring. Xatolar boʻlmadimi?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Fikr-mulohazangiz uchun tashakkur!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun bildirishnoma sozlamalari ochildi"</string>
@@ -880,6 +888,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Bu joyga olish: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Bu joyga kiritish: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Joylashuv: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Katakcha kiritildi"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Katakcha olib tashlandi"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Tezkor sozlamalar muharriri"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> bildirishnomasi: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Sozlamalarni ochish."</string>
@@ -970,7 +980,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> hozir <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ishlatmoqda"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> yaqinda <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ishlatgan"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(korporativ)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefon chaqiruvi"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefon chaqiruvi"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> orqali)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"joylashuv"</string>
@@ -978,7 +988,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensorlar nofaol"</string>
     <string name="device_services" msgid="1549944177856658705">"Qurilma xizmatlari"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Nomsiz"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Bu ilovani qaytadan ishga tushirish va butun ekranga ochish uchun bosing."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Surish"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Tizim navigatsiyasi yangilandi. Buni Sozlamalar orqali oʻzgartirishingiz mumkin."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Tizim navigatsiyasini yangilash uchun Sozlamalarni oching"</string>
@@ -1032,6 +1041,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Kiritish"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> taklif etgan"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Boshqaruv elementlari yangilandi"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Qurilma qulflandi"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Harflar yoki maxsus belgilardan iborat PIN kod"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Tekshirish: <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN kod xato"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 4913be4..cc89303 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Cuộn để phóng to ảnh chụp màn hình"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Đóng ảnh chụp màn hình"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Xem trước ảnh chụp màn hình"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Ranh giới trên"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Ranh giới dưới"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Trình ghi màn hình"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Đang xử lý video ghi màn hình"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Thông báo đang diễn ra về phiên ghi màn hình"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Cho đến khi trời sáng"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Bật vào lúc <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Cho đến <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC đã được tắt"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC đã được bật"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Mở khóa để sử dụng NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Thiết bị này thuộc về tổ chức của bạn"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Thiết bị này thuộc về <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Vuốt từ biểu tượng để mở điện thoại"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Vuốt từ biểu tượng để mở trợ lý thoại"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Vuốt từ biểu tượng để mở máy ảnh"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Hiển thị hồ sơ"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Thêm người dùng"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Người dùng mới"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Kết thúc phiên khách?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Kết thúc phiên khách"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Xóa phiên khách?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tất cả ứng dụng và dữ liệu trong phiên này sẽ bị xóa."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Kết thúc phiên"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Xóa"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Chào mừng bạn trở lại!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Bạn có muốn tiếp tục phiên của mình không?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Bắt đầu lại"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Tổ chức của bạn đã cài đặt một tổ chức phát hành chứng chỉ trong hồ cơ công việc của bạn. Lưu lượng truy cập mạng bảo mật của bạn có thể được giám sát hoặc sửa đổi."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Một tổ chức phát hành chứng chỉ được cài đặt trên thiết bị này. Lưu lượng truy cập mạng bảo mật của bạn có thể được giám sát hoặc sửa đổi."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Quản trị viên của bạn đã bật tính năng ghi nhật ký mạng. Tính năng này giám sát lưu lượng truy cập trên thiết bị của bạn."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Quản trị viên của bạn đã bật tính năng ghi nhật ký mạng. Tính năng này giám sát lưu lượng truy cập trong hồ sơ công việc chứ không giám sát lưu lượng truy cập trong hồ sơ cá nhân của bạn."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Bạn đang kết nối với <xliff:g id="VPN_APP">%1$s</xliff:g>. Ứng dụng này có thể giám sát hoạt động mạng của bạn, bao gồm email, ứng dụng và trang web."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Bạn đang kết nối với <xliff:g id="VPN_APP_0">%1$s</xliff:g> và <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Các ứng dụng này có thể giám sát hoạt động mạng của bạn, bao gồm email, ứng dụng và trang web."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Hồ sơ công việc của bạn được kết nối với <xliff:g id="VPN_APP">%1$s</xliff:g>, ứng dụng này có thể giám sát hoạt động mạng của bạn, bao gồm email, ứng dụng và trang web."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Nhấn để tắt tiếng. Bạn có thể tắt tiếng dịch vụ trợ năng."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Nhấn để đặt chế độ rung."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Nhấn để tắt tiếng."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"tắt tiếng"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"bật tiếng"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"rung"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Hệ thống đã tự động &lt;b&gt;thay đổi thành Im lặng&lt;/b&gt; theo tầm quan trọng của thông báo này."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Hệ thống đã tự động &lt;b&gt;tăng mức độ quan trọng&lt;/b&gt; của thông báo này trong ngăn thông báo."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Hệ thống đã tự động &lt;b&gt;giảm mức độ quan trọng&lt;/b&gt; của thông báo này trong ngăn thông báo."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Thông tin này có chính xác không?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Chia sẻ ý kiến phản hồi của bạn với nhà phát triển. Thông tin này có chính xác không?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Cảm ơn bạn đã phản hồi!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Đã mở điều khiển thông báo đối với <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Di chuyển tới <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Thêm vào vị trí <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Vị trí <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Đã thêm thẻ thông tin"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Đã xóa thẻ thông tin"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Trình chỉnh sửa cài đặt nhanh."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Thông báo của <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Mở phần cài đặt."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> đang sử dụng <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Gần đây, <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> đã sử dụng <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(doanh nghiệp)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Gọi điện thoại"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Cuộc gọi điện thoại"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(thông qua <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"máy ảnh"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"vị trí"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Tắt cảm biến"</string>
     <string name="device_services" msgid="1549944177856658705">"Dịch vụ cho thiết bị"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Không có tiêu đề"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Nhấn để khởi động lại ứng dụng này và xem ở chế độ toàn màn hình."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Di chuyển"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Đã cập nhật chế độ di chuyển trên hệ thống. Để thay đổi, hãy chuyển đến phần Cài đặt."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Chuyển đến phần Cài đặt để cập nhật chế độ di chuyển trên hệ thống"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Thêm"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Do <xliff:g id="APP">%s</xliff:g> đề xuất"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Đã cập nhật các tùy chọn điều khiển"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Đã khóa thiết bị"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Mã PIN chứa các ký tự hoặc ký hiệu"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Xác minh <xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Mã PIN sai"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 3479d00..92f9e67 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"滚动抓取长截图"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"关闭屏幕截图"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"屏幕截图预览"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"顶部边界"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"底部边界"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"屏幕录制器"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"正在处理屏幕录制视频"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"持续显示屏幕录制会话通知"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"在日出时关闭"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"在<xliff:g id="TIME">%s</xliff:g> 开启"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"直到<xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC 已停用"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC 已启用"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"需要解锁才能使用 NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"此设备归贵单位所有"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"此设备归<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>所有"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"滑动图标即可拨打电话"</string>
     <string name="voice_hint" msgid="7476017460191291417">"滑动图标即可打开语音助理"</string>
     <string name="camera_hint" msgid="4519495795000658637">"滑动图标即可打开相机"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"显示个人资料"</string>
     <string name="user_add_user" msgid="4336657383006913022">"添加用户"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"新用户"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"要结束访客会话吗?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"结束访客会话"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"要移除访客吗?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"此会话中的所有应用和数据都将被删除。"</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"结束会话"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"移除"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"访客,欢迎回来!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"要继续您的会话吗?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"重新开始"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"您所在的单位已为您的工作资料安装证书授权中心。您的安全网络流量可能会受到监控或修改。"</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"此设备上已安装证书授权中心。您的安全网络流量可能会受到监控或修改。"</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"您的管理员已开启网络日志功能(该功能会监控您设备上的流量)。"</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"您的管理员已开启网络日志功能,该功能会监控您的工作资料的流量,而不会监控个人资料的流量。"</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"您已连接到“<xliff:g id="VPN_APP">%1$s</xliff:g>”(该应用能够监控您的网络活动,其中包括收发电子邮件、使用应用和浏览网站)。"</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"您已连接到“<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="368812367182387320">"您的工作资料已连接到“<xliff:g id="VPN_APP">%1$s</xliff:g>”(该应用能够监控您的网络活动,其中包括收发电子邮件、使用应用和浏览网站)。"</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s。点按即可设为静音,但可能会同时将无障碍服务设为静音。"</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s。点按即可设为振动。"</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s。点按即可设为静音。"</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"静音"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"取消静音"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"振动"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"系统已自动将此通知的重要性&lt;b&gt;降低为“静音”&lt;/b&gt;。"</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"系统已自动&lt;b&gt;调高&lt;/b&gt;此通知在通知栏中的顺序。"</string>
     <string name="feedback_demoted" msgid="951884763467110604">"系统已自动&lt;b&gt;调低&lt;/b&gt;此通知在通知栏中的顺序。"</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"是否正确?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"向开发者提供反馈。此信息是否正确?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"感谢您提供反馈!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"确定"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g>的通知控件已打开"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"移至 <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"添加到位置 <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"位置 <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"已添加卡片"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"已移除卡片"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"快捷设置编辑器。"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>通知:<xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"打开设置。"</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>正在使用<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>最近曾使用<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(企业版)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"电话"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"电话"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(通过<xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"相机"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"位置信息"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"已关闭传感器"</string>
     <string name="device_services" msgid="1549944177856658705">"设备服务"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"无标题"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"点按即可重启此应用并进入全屏模式。"</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"移动"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"系统导航已更新。要进行更改,请转到“设置”。"</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"转到“设置”即可更新系统导航"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"添加"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"来自<xliff:g id="APP">%s</xliff:g>的建议"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"控件已更新"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"设备已锁定"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN 码由字母或符号组成"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"验证<xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN 码错误"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 314b728..d2a232b 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"整頁截圖"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"關閉螢幕截圖"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"螢幕截圖預覽"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"上方邊界"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"下方邊界"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"螢幕畫面錄影工具"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"正在處理螢幕錄影內容"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"持續顯示錄影畫面工作階段通知"</string>
@@ -410,6 +412,7 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"在日出時關閉"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"於<xliff:g id="TIME">%s</xliff:g>開啟"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"直至<xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_reduce_bright_colors_label" msgid="7537352080559075175">"調低亮度"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC 已停用"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC 已啟用"</string>
@@ -440,9 +443,11 @@
     <string name="notification_tap_again" msgid="4477318164947497249">"再次輕按即可開啟"</string>
     <string name="keyguard_unlock" msgid="8031975796351361601">"向上滑動即可開啟"</string>
     <string name="keyguard_retry" msgid="886802522584053523">"請向上滑動以再試一次"</string>
-    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"解鎖以使用 NFC"</string>
+    <string name="require_unlock_for_nfc" msgid="1305686454823018831">"解鎖方可使用 NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"此裝置屬於您的機構"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"此裝置屬於「<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>」"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"從圖示滑動即可使用手機功能"</string>
     <string name="voice_hint" msgid="7476017460191291417">"從圖示滑動即可使用語音助手"</string>
     <string name="camera_hint" msgid="4519495795000658637">"從圖示滑動即可使用相機功能"</string>
@@ -463,9 +468,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"顯示個人檔案"</string>
     <string name="user_add_user" msgid="4336657383006913022">"加入使用者"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"新使用者"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"要結束訪客工作階段嗎?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"結束訪客工作階段"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"移除訪客?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"這個工作階段中的所有應用程式和資料都會被刪除。"</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"結束工作階段"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"移除"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"訪客您好,歡迎回來!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"您要繼續您的工作階段嗎?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"重新開始"</string>
@@ -540,6 +546,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"您的機構已在您的工作設定檔中安裝憑證授權單位。您的安全網絡流量可能會受監控或修改。"</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"此裝置已安裝憑證授權單位。您的安全網絡流量可能會受監控或修改。"</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"您的管理員已開啟網絡記錄功能,以監控您裝置上的流量。"</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"您的管理員已開啟網絡記錄功能,可監控您工作設定檔 (而非個人設定檔) 的流量。"</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"您已連接至「<xliff:g id="VPN_APP">%1$s</xliff:g>」,此應用程式可以監控您的網絡活動,包括電郵、應用程式及網站。"</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"您已連接至「<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="368812367182387320">"您的工作設定檔已連結至「<xliff:g id="VPN_APP">%1$s</xliff:g>」,此應用程式可以監控您的網絡活動,包括電郵、應用程式及網站。"</string>
@@ -620,6 +627,7 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s。輕按即可設為靜音。無障礙功能服務可能已經設為靜音。"</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s。輕按即可設為震動。"</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s。輕按即可設為靜音。"</string>
+    <string name="volume_ringer_change" msgid="3574969197796055532">"輕按即可變更響鈴模式"</string>
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"靜音"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"取消靜音"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"震動"</string>
@@ -733,7 +741,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"系統已自動將此通知的重要性&lt;b&gt;降低為靜音&lt;/b&gt;。"</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"系統已自動&lt;b&gt;提高&lt;/b&gt;此通知在通知欄中的次序。"</string>
     <string name="feedback_demoted" msgid="951884763467110604">"系統已自動&lt;b&gt;調低&lt;/b&gt;此通知在通知欄中的次序。"</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"是否正確?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"與開發人員分享您的意見。是否正確?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"多謝您提供意見!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"確定"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"開咗「<xliff:g id="APP_NAME">%1$s</xliff:g>」嘅通知控制項"</string>
@@ -880,6 +888,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"移去 <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"加去位置 <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"位置 <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"加咗圖塊"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"移除咗圖塊"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"快速設定編輯工具。"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> 通知:<xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"開啟設定。"</string>
@@ -970,7 +980,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"「<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>」正在使用<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"「<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>」最近曾使用<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(企業版本)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"電話"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"電話"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(透過「<xliff:g id="ATTRIBUTION">%s</xliff:g>」)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"相機"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"位置"</string>
@@ -978,7 +988,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"感應器已關閉"</string>
     <string name="device_services" msgid="1549944177856658705">"裝置服務"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"無標題"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"輕按即可重新開啟此應用程式並放大至全螢幕。"</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"移動"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"系統導覽已更新。如需變更,請前往「設定」。"</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"前往「設定」更新系統導覽"</string>
@@ -1032,6 +1041,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"新增"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"由「<xliff:g id="APP">%s</xliff:g>」提供的建議"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"已更新控制項"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"裝置已上鎖"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN 含有字母或符號"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"驗證<xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN 錯誤"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 68b631f..396484a 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -71,7 +71,7 @@
     <string name="wifi_debugging_secondary_user_message" msgid="4492383073970079751">"目前登入這部裝置的使用者無法開啟無線偵錯功能。如要使用這項功能,請切換到主要使用者。"</string>
     <string name="usb_contaminant_title" msgid="894052515034594113">"USB 連接埠已停用"</string>
     <string name="usb_contaminant_message" msgid="7730476585174719805">"為了避免液體或灰塵導致你的裝置受損,系統已停用 USB 連接埠,因此目前無法偵測任何配件。\n\n系統會在可繼續使用 USB 連接埠時通知你。"</string>
-    <string name="usb_port_enabled" msgid="531823867664717018">"USB 通訊埠已啟用,可偵測充電器和配件"</string>
+    <string name="usb_port_enabled" msgid="531823867664717018">"USB 連接埠已啟用,可偵測充電器和配件"</string>
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"啟用 USB 連接埠"</string>
     <string name="learn_more" msgid="4690632085667273811">"瞭解詳情"</string>
     <string name="compat_mode_on" msgid="4963711187149440884">"放大為全螢幕"</string>
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"以捲動畫面的方式拍攝長截圖"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"關閉螢幕截圖"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"螢幕截圖預覽"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"頂端邊界"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"底部邊界"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"螢幕錄影器"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"處理螢幕錄影內容"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"持續顯示螢幕畫面錄製工作階段通知"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"於日出時關閉"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"開啟時間:<xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"關閉時間:<xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC 已停用"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC 已啟用"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"如要使用 NFC,請先解鎖"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"這部裝置的擁有者為貴機構"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"這部裝置的擁有者為「<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>」"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"滑動手機圖示即可啟用"</string>
     <string name="voice_hint" msgid="7476017460191291417">"滑動語音小幫手圖示即可啟用"</string>
     <string name="camera_hint" msgid="4519495795000658637">"滑動相機圖示即可啟用"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"顯示設定檔"</string>
     <string name="user_add_user" msgid="4336657383006913022">"新增使用者"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"新使用者"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"要結束訪客工作階段嗎?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"結束訪客工作階段"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"移除訪客?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"這個工作階段中的所有應用程式和資料都會遭到刪除。"</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"結束工作階段"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"移除"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"訪客你好,歡迎回來!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"你要繼續這個工作階段嗎?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"重新開始"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"貴機構已為你的工作資料夾安裝憑證授權單位憑證。你的安全網路流量可能會受到監控或修改。"</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"這個裝置已安裝憑證授權單位憑證。你的安全網路流量可能會受到監控或修改。"</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"你的管理員已啟用網路記錄功能,可監控你裝置的流量。"</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"你的管理員已啟用網路記錄功能,可監控你的工作資料夾流量,但不會監控個人資料夾的流量。"</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"由於你已連結至「<xliff:g id="VPN_APP">%1$s</xliff:g>」,因此你的網路活動 (包括收發電子郵件、使用應用程式及瀏覽網站) 可能會受到這個應用程式監控。"</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"由於你已連結至「<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="368812367182387320">"由於你的工作資料夾已連結至「<xliff:g id="VPN_APP">%1$s</xliff:g>」,因此你的網路活動 (包括收發電子郵件、使用應用程式及瀏覽網站) 可能會受到這個應用程式監控。"</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s。輕觸即可設為靜音,但系統可能會將無障礙服務一併設為靜音。"</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s。輕觸即可設為震動。"</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s。輕觸即可設為靜音。"</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"靜音"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"取消靜音"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"震動"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"系統已自動將這則通知的重要性&lt;b&gt;降低為靜音&lt;/b&gt;。"</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"系統已自動&lt;b&gt;調高&lt;/b&gt;這則通知在通知欄中的順序。"</string>
     <string name="feedback_demoted" msgid="951884763467110604">"系統已自動&lt;b&gt;調降&lt;/b&gt;這則通知在通知欄中的順序。"</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"是否正確?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"與開發人員分享你的意見。是否正確?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"感謝你提供意見!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"確定"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」的通知控制項已開啟"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"移至 <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"新增到位置 <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"位置 <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"已新增資訊方塊"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"已移除資訊方塊"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"快速設定編輯器。"</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> 通知:<xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"開啟設定。"</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"「<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>」正在使用<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"「<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>」最近曾使用<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(企業版)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"電話"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"電話"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(透過「<xliff:g id="ATTRIBUTION">%s</xliff:g>」)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"相機"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"位置"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"已關閉感應器"</string>
     <string name="device_services" msgid="1549944177856658705">"裝置服務"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"無標題"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"輕觸即可重新啟動這個應用程式並進入全螢幕模式。"</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"移動"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"系統操作機制已更新。如要進行變更,請前往「設定」。"</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"請前往「設定」更新系統操作機制"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"新增"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"來自「<xliff:g id="APP">%s</xliff:g>」的建議"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"已更新控制項"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"裝置已鎖定"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN 碼含有字母或符號"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"驗證「<xliff:g id="DEVICE">%s</xliff:g>」"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN 碼錯誤"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 78c4f17..d4e05d0 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -93,6 +93,8 @@
     <string name="screenshot_scroll_description" msgid="7855773867093272175">"Isithombe seskrini sokuskrola"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Cashisa isithombe-skrini"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Ukubuka kuqala isithombe-skrini"</string>
+    <string name="screenshot_top_boundary" msgid="1500569103321300856">"Umngcele ophezulu"</string>
+    <string name="screenshot_bottom_boundary" msgid="5657242629526407311">"Umngcele ophansi"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Irekhoda yesikrini"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Icubungula okokuqopha iskrini"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Isaziso esiqhubekayo seseshini yokurekhoda isikrini"</string>
@@ -410,6 +412,8 @@
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Kuze kube sekuphumeni kwelanga"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Kuvulwe ngo-<xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Kuze kube ngu-<xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- no translation found for quick_settings_reduce_bright_colors_label (7537352080559075175) -->
+    <skip />
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"I-NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"I-NFC ikhutshaziwe"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"I-NFC inikwe amandla"</string>
@@ -443,6 +447,8 @@
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Vula ukuze usebenzise i-NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Le divayisi eyenhlangano yakho"</string>
     <string name="do_disclosure_with_name" msgid="2091641464065004091">"Le divayisi ngeye-<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for do_financed_disclosure_with_name (6723004643314467864) -->
+    <skip />
     <string name="phone_hint" msgid="6682125338461375925">"Swayiphela ifoni kusukela kusithonjana"</string>
     <string name="voice_hint" msgid="7476017460191291417">"Swayiphela isilekeleli sezwi kusukela kusithonjana"</string>
     <string name="camera_hint" msgid="4519495795000658637">"Swayiphela ikhamela kusukela kusithonjana"</string>
@@ -463,9 +469,10 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"Bonisa iphrofayela"</string>
     <string name="user_add_user" msgid="4336657383006913022">"Engeza umsebenzisi"</string>
     <string name="user_new_user_name" msgid="2019166282704195789">"Umsebenzisi omusha"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"Misa isikhathi sesihambeli?"</string>
+    <string name="guest_exit_button" msgid="3059840571760915762">"Misa isikhathi sesihambeli"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Susa isivakashi?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Zonke izinhlelo zokusebenza nedatha kulesi sikhathi zizosuswa."</string>
-    <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"Phothula iseshini"</string>
+    <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Susa"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Siyakwamukela futhi, sivakashi!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Ingabe ufuna ukuqhubeka ngesikhathi sakho?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Qala phansi"</string>
@@ -540,6 +547,7 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Inhlangano yakho ifake ukugunyaza kwesitifiketi kuphrofayela yakho yomsebenzi. Ithrafikhi yenethiwekhi yakho evikelekile ingaqashwa noma ilungiswe."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Ukugunyaza kwesitifiketi kufakwe kule divayisi. Ithrafikhi yenethiwekhi yakho evikelekile ingaqashelwa noma ilungiswe."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Umlawuli wakho uvule ukungena kwedivayisi yakho, okuqapha ithrafikhi kudivayisi yakho."</string>
+    <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Umlawuli wakho uvule ukungena kwenethiwekhi, okuhlola ithrafikhi kudivayisi yakho yephrofayela yomsebenzi kodwa hhayi kuphrofayela yakho yomuntu siqu."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Uxhumeke ku-<xliff:g id="VPN_APP">%1$s</xliff:g>, engaqapha umsebenzi wenethiwekhi yakho, ofaka ama-imeyili, izinhlelo zokusebenza, namawebhusayithi."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Uxhumeke ku-<xliff:g id="VPN_APP_0">%1$s</xliff:g> naku-<xliff:g id="VPN_APP_1">%2$s</xliff:g>, okungaqaphela umsebenzi wakho wenethiwekhi, ofaka ama-imeyili, izinhlelo zokusebenza, namawebhusayithi."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Iphrofayela yakho yomsebenzi ixhumeke ku-<xliff:g id="VPN_APP">%1$s</xliff:g>, engaqapha umsebenzi wenethiwekhi yakho, ofaka ama-imeyili, izinhlelo zokusebenza, namawebhusayithi."</string>
@@ -620,6 +628,8 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Thepha ukuze uthulise. Amasevisi okufinyelela angathuliswa."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Thepha ukuze usethele ekudlidlizeni."</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Thepha ukuze uthulise."</string>
+    <!-- no translation found for volume_ringer_change (3574969197796055532) -->
+    <skip />
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"thulisa"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"susa ukuthula"</string>
     <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"dlidliza"</string>
@@ -733,7 +743,7 @@
     <string name="feedback_silenced" msgid="9116540317466126457">"Lesi saziso sehliswe isikhundla ngokuzenzakalelayo &lt;b&gt;saba Okuthulile&lt;/b&gt; isistimu."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"Lesi saziso silinganiselwe phezulu &lt;b&gt;ngokuzenzakalelayo&lt;/b&gt; kumthunzi wakho."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"Lesi saziso silinganiselwe phansi &lt;b&gt;ngokuzenzakalelayo&lt;/b&gt; kumthunzi wakho."</string>
-    <string name="feedback_prompt" msgid="2278631214125128281">"Ingabe kade kulungile lokhu?"</string>
+    <string name="feedback_prompt" msgid="3656728972307896379">"Tshela unjiniyela impendulo yakho. Ingabe kade kulungile lokhu?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Siyabonga ngempendulo!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"KULUNGILE"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Izilawuli zesaziso ze-<xliff:g id="APP_NAME">%1$s</xliff:g> zivuliwe"</string>
@@ -880,6 +890,8 @@
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Hambisa ku-<xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Engeza kusikhundla se-<xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Isikhundla se-<xliff:g id="POSITION">%1$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Ithayela lingeziwe"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Ithayela likhishiwe"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Isihleli sezilungiselelo ezisheshayo."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> isaziso: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Vula izilungiselelo."</string>
@@ -970,7 +982,7 @@
     <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"I-<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> isebenzisa i-<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"I-<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> isebenzise i-<xliff:g id="APP_OPP_NAME">%2$s</xliff:g> kamuva nje"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(ibhizinisi)"</string>
-    <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Ikholi yefoni"</string>
+    <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Ikholi yefoni"</string>
     <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(kuya ku-<xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string>
     <string name="privacy_type_camera" msgid="7974051382167078332">"ikhamera"</string>
     <string name="privacy_type_location" msgid="7991481648444066703">"indawo"</string>
@@ -978,7 +990,6 @@
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"Izinzwa zivaliwe"</string>
     <string name="device_services" msgid="1549944177856658705">"Amasevisi edivayisi"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Asikho isihloko"</string>
-    <string name="restart_button_description" msgid="6916116576177456480">"Thepha ukuze uqale kabusha lolu hlelo lokusebenza uphinde uye kusikrini esigcwele."</string>
     <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Hambisa"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Ukuzulazula kwesistimu kubuyekeziwe. Ukuze wenze ushintsho, hamba kokuthi Izilungiselelo."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Hamba kuzilungiselelo ukuze ubuyekeze ukuzulazula kwesistimu"</string>
@@ -1032,6 +1043,7 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Engeza"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Kuphakanyiswe ngu-<xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Izilawuli zibuyekeziwe"</string>
+    <string name="controls_tile_locked" msgid="731547768182831938">"Idivayisi ikhiyiwe"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Iphinikhodi iqukethe amaletha namasimbui"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Qinisekisa i-<xliff:g id="DEVICE">%s</xliff:g>"</string>
     <string name="controls_pin_wrong" msgid="6162694056042164211">"Iphinikhodi engalungile"</string>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index a1191ae..be49e1f 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -143,6 +143,8 @@
     <attr name="handleColor" format="color" />
     <attr name="scrimColor" format="color" />
 
+    <attr name="isVertical" format="boolean" />
+
     <!-- Used display CarrierText in Keyguard or QS Footer -->
     <declare-styleable name="CarrierText">
         <attr name="allCaps" format="boolean" />
@@ -168,7 +170,6 @@
 
     <declare-styleable name="AlphaTintDrawableWrapper">
         <attr name="android:tint" />
-        <attr name="android:drawable" />
         <attr name="android:alpha" />
     </declare-styleable>
 
@@ -189,9 +190,5 @@
         <attr name="borderThickness" format="dimension" />
         <attr name="borderColor" format="color" />
     </declare-styleable>
-
-    <declare-styleable name="RoundedCornerProgressDrawable">
-        <attr name="android:drawable" />
-    </declare-styleable>
 </resources>
 
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index acd671c..3bc1c80 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -265,7 +265,6 @@
     <color name="control_enabled_cool_foreground">@color/GM2_blue_300</color>
     <color name="control_thumbnail_tint">#33000000</color>
     <color name="control_thumbnail_shadow_color">@*android:color/black</color>
-    <color name="controls_lockscreen_scrim">#AA000000</color>
 
     <!-- Docked misalignment message -->
     <color name="misalignment_text_color">#F28B82</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 13c0110..0893c14 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -91,6 +91,9 @@
     <!-- The number of columns in the QuickSettings -->
     <integer name="quick_settings_num_columns">3</integer>
 
+    <!-- The number of columns in the Quick Settings customizer -->
+    <integer name="quick_settings_edit_num_columns">@integer/quick_settings_num_columns</integer>
+
     <!-- The number of rows in the QuickSettings -->
     <integer name="quick_settings_max_rows">3</integer>
 
@@ -421,6 +424,9 @@
      vibrator is capable of subtle vibrations -->
     <bool name="config_vibrateOnIconAnimation">false</bool>
 
+    <!-- Adjust the theme on fully custom and decorated custom view notifications -->
+    <bool name="config_adjustThemeOnNotificationCustomViews">false</bool>
+
     <!-- If true, enable the advance anti-falsing classifier on the lockscreen. On some devices it
          does not work well, particularly with noisy touchscreens. Note that disabling it may
          increase the rate of unintentional unlocks. -->
@@ -574,4 +580,7 @@
 
     <!-- Whether to use the split 2-column notification shade -->
     <bool name="config_use_split_notification_shade">false</bool>
+
+    <!-- Determines whether the shell features all run on another thread. -->
+    <bool name="config_enableShellMainThread">false</bool>
 </resources>
diff --git a/packages/SystemUI/res/values/config_tv.xml b/packages/SystemUI/res/values/config_tv.xml
deleted file mode 100644
index 2e77674..0000000
--- a/packages/SystemUI/res/values/config_tv.xml
+++ /dev/null
@@ -1,21 +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>
-    <!-- Whether to enable microphone disclosure indicator
-         (com.android.systemui.statusbar.tv.micdisclosure.AudioRecordingDisclosureBar). -->
-    <bool name="audio_recording_disclosure_enabled">true</bool>
-</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index b07df9c..ea0ea5e 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -456,10 +456,12 @@
 
     <dimen name="volume_dialog_panel_transparent_padding">20dp</dimen>
 
-    <dimen name="volume_dialog_stream_padding">8dp</dimen>
+    <dimen name="volume_dialog_stream_padding">12dp</dimen>
 
     <dimen name="volume_dialog_panel_width">64dp</dimen>
 
+    <dimen name="volume_dialog_panel_width_half">32dp</dimen>
+
     <dimen name="volume_dialog_slider_height">116dp</dimen>
 
     <dimen name="volume_dialog_ringer_size">64dp</dimen>
@@ -486,6 +488,13 @@
 
     <dimen name="volume_tool_tip_arrow_corner_radius">2dp</dimen>
 
+    <!-- Size of each item in the ringer selector drawer. -->
+    <dimen name="volume_ringer_drawer_item_size">64dp</dimen>
+    <dimen name="volume_ringer_drawer_item_size_half">32dp</dimen>
+
+    <!-- Size of the icon inside each item in the ringer selector drawer. -->
+    <dimen name="volume_ringer_drawer_icon_size">24dp</dimen>
+
     <!-- Gravity for the notification panel -->
     <integer name="notification_panel_layout_gravity">0x31</integer><!-- center_horizontal|top -->
 
@@ -651,7 +660,7 @@
     </dimen>
 
     <!-- The height of a notification header -->
-    <dimen name="notification_header_height">53dp</dimen>
+    <dimen name="notification_header_height">@*android:dimen/notification_header_height</dimen>
 
     <!-- The height of the gap between adjacent notification sections. -->
     <dimen name="notification_section_divider_height">@dimen/notification_side_paddings</dimen>
@@ -966,7 +975,7 @@
     <dimen name="volume_row_padding_start">4dp</dimen>
     <dimen name="volume_row_header_padding_start">16dp</dimen>
     <dimen name="volume_row_height">64dp</dimen>
-    <dimen name="volume_row_slider_height">48dp</dimen>
+    <dimen name="volume_row_slider_height">192dp</dimen>
     <dimen name="volume_row_slider_padding_start">12dp</dimen>
 
     <dimen name="volume_expander_margin_end">2dp</dimen>
@@ -1359,11 +1368,4 @@
     <dimen name="rounded_slider_icon_size">24dp</dimen>
     <!-- rounded_slider_icon_size / 2 -->
     <dimen name="rounded_slider_icon_inset">12dp</dimen>
-
-    <dimen name="toast_width">296dp</dimen>
-    <item name="toast_icon_alpha" format="float" type="dimen">1</item>
-    <dimen name="toast_text_size">14sp</dimen>
-    <dimen name="toast_y_offset">48dp</dimen>
-    <dimen name="toast_icon_size">48dp</dimen>
-    <dimen name="toast_bg_radius">28dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/flags.xml b/packages/SystemUI/res/values/flags.xml
index d4bb128..e551892 100644
--- a/packages/SystemUI/res/values/flags.xml
+++ b/packages/SystemUI/res/values/flags.xml
@@ -42,4 +42,8 @@
     <bool name="flag_lockscreen_animations">false</bool>
 
     <bool name="flag_toast_style">false</bool>
+
+    <bool name="flag_navigation_bar_overlay">false</bool>
+
+    <bool name="flag_pm_lite">false</bool>
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 3b42600..5f8df5a 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -959,7 +959,7 @@
     <!-- QuickSettings: Secondary text for when the Dark theme or some other tile will be on until some user-selected time. [CHAR LIMIT=20] -->
     <string name="quick_settings_dark_mode_secondary_label_until">Until <xliff:g id="time" example="7 am">%s</xliff:g></string>
     <!-- QuickSettings: Label for the toggle that controls whether Reduce Brightness is enabled. [CHAR LIMIT=NONE] -->
-    <string name="quick_settings_reduce_bright_colors_label">Reduce Brightness</string>
+    <string name="quick_settings_reduce_bright_colors_label">Reduce brightness</string>
 
     <!-- QuickSettings: NFC tile [CHAR LIMIT=NONE] -->
     <string name="quick_settings_nfc_label">NFC</string>
@@ -1054,6 +1054,9 @@
     <!-- Text on keyguard screen and in Quick Settings footer indicating that user's device belongs to their organization. [CHAR LIMIT=40] -->
     <string name="do_disclosure_with_name">This device belongs to <xliff:g id="organization_name" example="Foo, Inc.">%s</xliff:g></string>
 
+    <!-- Text on keyguard screen and in Quick Settings footer indicating that the user's device is provided by the Creditor. [CHAR LIMIT=60] -->
+    <string name="do_financed_disclosure_with_name">This device is provided by <xliff:g id="organization_name" example="Foo, Inc.">%s</xliff:g></string>
+
     <!-- Shows when people have clicked on the phone icon [CHAR LIMIT=60] -->
     <string name="phone_hint">Swipe from icon for phone</string>
 
@@ -1558,6 +1561,8 @@
     <string name="volume_stream_content_description_vibrate_a11y">%1$s. Tap to set to vibrate.</string>
     <string name="volume_stream_content_description_mute_a11y">%1$s. Tap to mute.</string>
 
+    <string name="volume_ringer_change">Tap to change ringer mode</string>
+
     <!-- Hint for accessibility. For example: double tap to mute [CHAR_LIMIT=NONE] -->
     <string name="volume_ringer_hint_mute">mute</string>
     <!-- Hint for accessibility. For example: double tap to unmute [CHAR_LIMIT=NONE] -->
@@ -2717,6 +2722,9 @@
     <!-- Controls dialog confirmation [CHAR LIMIT=30] -->
     <string name="controls_dialog_confirmation">Controls updated</string>
 
+    <!-- Controls tile secondary label when device is locked and user does not want access to controls from lockscreen [CHAR LIMIT=20] -->
+    <string name="controls_tile_locked">Device locked</string>
+
     <!-- Controls PIN entry dialog, switch to alphanumeric keyboard [CHAR LIMIT=100] -->
     <string name="controls_pin_use_alphanumeric">PIN contains letters or symbols</string>
     <!-- Controls PIN entry dialog, title [CHAR LIMIT=30] -->
@@ -2837,6 +2845,8 @@
     <string name="empty_user_name" translatable="false">Your friend</string>
     <!-- Empty status shown before user has selected a friend [CHAR LIMIT=30] -->
     <string name="empty_status" translatable="false">Their status</string>
+    <!-- Default text for missed call notifications [CHAR LIMIT=30] -->
+    <string name="missed_call" translatable="false">Missed call</string>
 
     <!-- Title to display in a notification when ACTION_BATTERY_CHANGED.EXTRA_PRESENT field is false
     [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 14b376a..2d202fb 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -663,16 +663,16 @@
     </style>
 
     <style name="Theme.SystemUI.Dialog.Control.LockScreen" parent="@android:style/Theme.DeviceDefault.Dialog.NoActionBar">
-      <item name="android:windowAnimationStyle">@style/Animation.Fade</item>
+      <item name="android:windowAnimationStyle">@style/Animation.ControlDialog</item>
       <item name="android:windowFullscreen">true</item>
       <item name="android:windowIsFloating">false</item>
-      <item name="android:windowBackground">@color/controls_lockscreen_scrim</item>
+      <item name="android:windowBackground">@null</item>
       <item name="android:backgroundDimEnabled">true</item>
     </style>
 
-    <style name="Animation.Fade">
-      <item name="android:windowEnterAnimation">@android:anim/fade_in</item>
-      <item name="android:windowExitAnimation">@android:anim/fade_out</item>
+    <style name="Animation.ControlDialog">
+      <item name="android:windowEnterAnimation">@*android:anim/dialog_enter</item>
+      <item name="android:windowExitAnimation">@*android:anim/dialog_exit</item>
     </style>
 
     <style name="Control" />
diff --git a/packages/SystemUI/shared/Android.bp b/packages/SystemUI/shared/Android.bp
index 606fd2c..09e9675a 100644
--- a/packages/SystemUI/shared/Android.bp
+++ b/packages/SystemUI/shared/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"],
+}
+
 genrule {
     name: "statslog-SystemUI-java-gen",
     tools: ["stats-log-api-gen"],
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
index f6b239e..ebb6e30 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
@@ -254,6 +254,7 @@
     public Task(Task other) {
         this(other.key, other.colorPrimary, other.colorBackground, other.isDockable,
                 other.isLocked, other.taskDescription, other.topActivity);
+        lastSnapshotData.set(other.lastSnapshotData);
     }
 
     /**
@@ -281,6 +282,25 @@
                 : key.baseIntent.getComponent();
     }
 
+    public void setLastSnapshotData(ActivityManager.RecentTaskInfo rawTask) {
+        lastSnapshotData.set(rawTask.lastSnapshotData);
+    }
+
+    /**
+     * Returns the visible width to height ratio. Returns 0f if snapshot data is not available.
+     */
+    public float getVisibleThumbnailRatio() {
+        if (lastSnapshotData.taskSize == null || lastSnapshotData.contentInsets == null) {
+            return 0f;
+        }
+
+        float availableWidth = lastSnapshotData.taskSize.x - (lastSnapshotData.contentInsets.left
+                + lastSnapshotData.contentInsets.right);
+        float availableHeight = lastSnapshotData.taskSize.y - (lastSnapshotData.contentInsets.top
+                + lastSnapshotData.contentInsets.bottom);
+        return availableWidth / availableHeight;
+    }
+
     @Override
     public boolean equals(Object o) {
         // Check that the id matches
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java
index ffde841..259cca8 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java
@@ -16,13 +16,12 @@
 
 package com.android.systemui.shared.system;
 
-import android.os.Bundle;
+import android.graphics.Matrix;
 import android.os.Looper;
 import android.view.BatchedInputEventReceiver;
 import android.view.Choreographer;
 import android.view.InputChannel;
 import android.view.InputEvent;
-import android.view.InputEventSender;
 import android.view.MotionEvent;
 
 /**
@@ -53,6 +52,12 @@
         return target.addBatch(src);
     }
 
+    /** @see MotionEvent#createRotateMatrix */
+    public static Matrix createRotationMatrix(
+            /*@Surface.Rotation*/ int rotation, int displayW, int displayH) {
+        return MotionEvent.createRotateMatrix(rotation, displayW, displayH);
+    }
+
     /**
      * @see BatchedInputEventReceiver
      */
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 6c77af7..c5d5439 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
@@ -100,4 +100,10 @@
 
     /** @see ITaskStackListener#onActivityRotation(int)*/
     public void onActivityRotation(int displayId) { }
+
+    /**
+     * Called when the lock task mode changes. See ActivityManager#LOCK_TASK_MODE_* and
+     * LockTaskController.
+     */
+    public void onLockTaskModeChanged(int mode) { }
 }
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 8f08f5a..b3a29a3 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
@@ -93,6 +93,7 @@
         private static final int ON_TASK_LIST_FROZEN_UNFROZEN = 20;
         private static final int ON_TASK_DESCRIPTION_CHANGED = 21;
         private static final int ON_ACTIVITY_ROTATION = 22;
+        private static final int ON_LOCK_TASK_MODE_CHANGED = 23;
 
         /**
          * List of {@link TaskStackChangeListener} registered from {@link #addListener}.
@@ -189,7 +190,7 @@
         }
 
         @Override
-        public void onActivityDismissingDockedStack() {
+        public void onActivityDismissingDockedTask() {
             mHandler.sendEmptyMessage(ON_ACTIVITY_DISMISSING_DOCKED_STACK);
         }
 
@@ -273,6 +274,11 @@
         }
 
         @Override
+        public void onLockTaskModeChanged(int mode) {
+            mHandler.obtainMessage(ON_LOCK_TASK_MODE_CHANGED, mode, 0 /* unused */).sendToTarget();
+        }
+
+        @Override
         public boolean handleMessage(Message msg) {
             synchronized (mTaskStackListeners) {
                 switch (msg.what) {
@@ -421,6 +427,12 @@
                         }
                         break;
                     }
+                    case ON_LOCK_TASK_MODE_CHANGED: {
+                        for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+                            mTaskStackListeners.get(i).onLockTaskModeChanged(msg.arg1);
+                        }
+                        break;
+                    }
                 }
             }
             if (msg.obj instanceof SomeArgs) {
diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
index 0a117c1..1569fff 100644
--- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
@@ -21,9 +21,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.graphics.Color;
-import android.graphics.Paint;
 import android.icu.text.NumberFormat;
-import android.util.MathUtils;
 
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
@@ -94,11 +92,6 @@
         mStatusBarStateController.removeCallback(mStatusBarStateListener);
     }
 
-    float getClockTextTopPadding() {
-        Paint.FontMetrics fm = mView.getPaint().getFontMetrics();
-        return MathUtils.abs(fm.ascent - fm.top);
-    }
-
     /**
      * Updates the time for the view.
      */
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierText.java b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
index e4f6e131..f6b03c1 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierText.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
@@ -24,14 +24,41 @@
 import android.view.View;
 import android.widget.TextView;
 
+import com.android.systemui.Dependency;
 import com.android.systemui.R;
 
 import java.util.Locale;
 
 public class CarrierText extends TextView {
-    private final boolean mShowMissingSim;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
+    private static final String TAG = "CarrierText";
 
-    private final boolean mShowAirplaneMode;
+    private static CharSequence mSeparator;
+
+    private boolean mShowMissingSim;
+
+    private boolean mShowAirplaneMode;
+    private boolean mShouldMarquee;
+
+    private CarrierTextController mCarrierTextController;
+
+    private CarrierTextController.CarrierTextCallback mCarrierTextCallback =
+            new CarrierTextController.CarrierTextCallback() {
+                @Override
+                public void updateCarrierInfo(CarrierTextController.CarrierTextCallbackInfo info) {
+                    setText(info.carrierText);
+                }
+
+                @Override
+                public void startedGoingToSleep() {
+                    setSelected(false);
+                }
+
+                @Override
+                public void finishedWakingUp() {
+                    setSelected(true);
+                }
+            };
 
     public CarrierText(Context context) {
         this(context, null);
@@ -51,6 +78,30 @@
         }
         setTransformationMethod(new CarrierTextTransformationMethod(mContext, useAllCaps));
     }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mSeparator = getResources().getString(
+                com.android.internal.R.string.kg_text_message_separator);
+        mCarrierTextController = new CarrierTextController(mContext, mSeparator, mShowAirplaneMode,
+                mShowMissingSim);
+        mShouldMarquee = Dependency.get(KeyguardUpdateMonitor.class).isDeviceInteractive();
+        setSelected(mShouldMarquee); // Allow marquee to work.
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mCarrierTextController.setListening(mCarrierTextCallback);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mCarrierTextController.setListening(null);
+    }
+
     @Override
     protected void onVisibilityChanged(View changedView, int visibility) {
         super.onVisibilityChanged(changedView, visibility);
@@ -62,15 +113,7 @@
         }
     }
 
-    public boolean getShowAirplaneMode() {
-        return mShowAirplaneMode;
-    }
-
-    public boolean getShowMissingSim() {
-        return mShowMissingSim;
-    }
-
-    private static class CarrierTextTransformationMethod extends SingleLineTransformationMethod {
+    private class CarrierTextTransformationMethod extends SingleLineTransformationMethod {
         private final Locale mLocale;
         private final boolean mAllCaps;
 
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index 46a6d8b..b1e1434 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * 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.
@@ -16,61 +16,680 @@
 
 package com.android.keyguard;
 
-import com.android.systemui.util.ViewController;
+import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;
+import static android.telephony.PhoneStateListener.LISTEN_NONE;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.net.ConnectivityManager;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settingslib.WirelessUtils;
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import javax.inject.Inject;
 
 /**
- * Controller for {@link CarrierText}.
+ * Controller that generates text including the carrier names and/or the status of all the SIM
+ * interfaces in the device. Through a callback, the updates can be retrieved either as a list or
+ * separated by a given separator {@link CharSequence}.
  */
-public class CarrierTextController extends ViewController<CarrierText> {
-    private final CarrierTextManager mCarrierTextManager;
-    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+public class CarrierTextController {
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
+    private static final String TAG = "CarrierTextController";
 
-    private final CarrierTextManager.CarrierTextCallback mCarrierTextCallback =
-            new CarrierTextManager.CarrierTextCallback() {
+    private final boolean mIsEmergencyCallCapable;
+    private final Handler mMainHandler;
+    private final Handler mBgHandler;
+    private boolean mTelephonyCapable;
+    private boolean mShowMissingSim;
+    private boolean mShowAirplaneMode;
+    private final AtomicBoolean mNetworkSupported = new AtomicBoolean();
+    @VisibleForTesting
+    protected KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    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;
+    private WakefulnessLifecycle mWakefulnessLifecycle;
+    private final WakefulnessLifecycle.Observer mWakefulnessObserver =
+            new WakefulnessLifecycle.Observer() {
                 @Override
-                public void updateCarrierInfo(CarrierTextManager.CarrierTextCallbackInfo info) {
-                    mView.setText(info.carrierText);
+                public void onFinishedWakingUp() {
+                    final CarrierTextCallback callback = mCarrierTextCallback;
+                    if (callback != null) callback.finishedWakingUp();
                 }
 
                 @Override
-                public void startedGoingToSleep() {
-                    mView.setSelected(false);
-                }
-
-                @Override
-                public void finishedWakingUp() {
-                    mView.setSelected(true);
+                public void onStartedGoingToSleep() {
+                    final CarrierTextCallback callback = mCarrierTextCallback;
+                    if (callback != null) callback.startedGoingToSleep();
                 }
             };
 
-    @Inject
-    public CarrierTextController(CarrierText view,
-            CarrierTextManager.Builder carrierTextManagerBuilder,
-            KeyguardUpdateMonitor keyguardUpdateMonitor) {
-        super(view);
+    @VisibleForTesting
+    protected final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
+        @Override
+        public void onRefreshCarrierInfo() {
+            if (DEBUG) {
+                Log.d(TAG, "onRefreshCarrierInfo(), mTelephonyCapable: "
+                        + Boolean.toString(mTelephonyCapable));
+            }
+            updateCarrierText();
+        }
 
-        mCarrierTextManager = carrierTextManagerBuilder
-                .setShowAirplaneMode(mView.getShowAirplaneMode())
-                .setShowMissingSim(mView.getShowMissingSim())
-                .build();
-        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+        @Override
+        public void onTelephonyCapable(boolean capable) {
+            if (DEBUG) {
+                Log.d(TAG, "onTelephonyCapable() mTelephonyCapable: "
+                        + Boolean.toString(capable));
+            }
+            mTelephonyCapable = capable;
+            updateCarrierText();
+        }
+
+        public void onSimStateChanged(int subId, int slotId, int simState) {
+            if (slotId < 0 || slotId >= mSimSlotsNumber) {
+                Log.d(TAG, "onSimStateChanged() - slotId invalid: " + slotId
+                        + " mTelephonyCapable: " + Boolean.toString(mTelephonyCapable));
+                return;
+            }
+
+            if (DEBUG) Log.d(TAG, "onSimStateChanged: " + getStatusForIccState(simState));
+            if (getStatusForIccState(simState) == CarrierTextController.StatusMode.SimIoError) {
+                mSimErrorState[slotId] = true;
+                updateCarrierText();
+            } else if (mSimErrorState[slotId]) {
+                mSimErrorState[slotId] = false;
+                updateCarrierText();
+            }
+        }
+    };
+
+    private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+    private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+        @Override
+        public void onActiveDataSubscriptionIdChanged(int subId) {
+            mActiveMobileDataSubscription = subId;
+            if (mNetworkSupported.get() && mCarrierTextCallback != null) {
+                updateCarrierText();
+            }
+        }
+    };
+
+    /**
+     * The status of this lock screen. Primarily used for widgets on LockScreen.
+     */
+    private enum StatusMode {
+        Normal, // Normal case (sim card present, it's not locked)
+        NetworkLocked, // SIM card is 'network locked'.
+        SimMissing, // SIM card is missing.
+        SimMissingLocked, // SIM card is missing, and device isn't provisioned; don't allow access
+        SimPukLocked, // SIM card is PUK locked because SIM entered wrong too many times
+        SimLocked, // SIM card is currently locked
+        SimPermDisabled, // SIM card is permanently disabled due to PUK unlock failure
+        SimNotReady, // SIM is not ready yet. May never be on devices w/o a SIM.
+        SimIoError, // SIM card is faulty
+        SimUnknown // SIM card is unknown
     }
 
-    @Override
-    protected void onInit() {
-        super.onInit();
-        mView.setSelected(mKeyguardUpdateMonitor.isDeviceInteractive());
+    /**
+     * Controller that provides updates on text with carriers names or SIM status.
+     * Used by {@link CarrierText}.
+     *
+     * @param separator Separator between different parts of the text
+     */
+    public CarrierTextController(Context context, CharSequence separator, boolean showAirplaneMode,
+            boolean showMissingSim) {
+        mContext = context;
+        mIsEmergencyCallCapable = getTelephonyManager().isVoiceCapable();
+
+        mShowAirplaneMode = showAirplaneMode;
+        mShowMissingSim = showMissingSim;
+
+        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+        mSeparator = separator;
+        mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
+        mSimSlotsNumber = getTelephonyManager().getSupportedModemCount();
+        mSimErrorState = new boolean[mSimSlotsNumber];
+        mMainHandler = Dependency.get(Dependency.MAIN_HANDLER);
+        mBgHandler = new Handler(Dependency.get(Dependency.BG_LOOPER));
+        mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
+        mBgHandler.post(() -> {
+            boolean supported = ConnectivityManager.from(mContext).isNetworkSupported(
+                    ConnectivityManager.TYPE_MOBILE);
+            if (supported && mNetworkSupported.compareAndSet(false, supported)) {
+                // This will set/remove the listeners appropriately. Note that it will never double
+                // add the listeners.
+                handleSetListening(mCarrierTextCallback);
+            }
+        });
     }
 
-    @Override
-    protected void onViewAttached() {
-        mCarrierTextManager.setListening(mCarrierTextCallback);
+    private TelephonyManager getTelephonyManager() {
+        return (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
     }
 
-    @Override
-    protected void onViewDetached() {
-        mCarrierTextManager.setListening(null);
+    /**
+     * Checks if there are faulty cards. Adds the text depending on the slot of the card
+     *
+     * @param text:   current carrier text based on the sim state
+     * @param carrierNames names order by subscription order
+     * @param subOrderBySlot array containing the sub index for each slot ID
+     * @param noSims: whether a valid sim card is inserted
+     * @return text
+     */
+    private CharSequence updateCarrierTextWithSimIoError(CharSequence text,
+            CharSequence[] carrierNames, int[] subOrderBySlot, boolean noSims) {
+        final CharSequence carrier = "";
+        CharSequence carrierTextForSimIOError = getCarrierTextForSimState(
+                TelephonyManager.SIM_STATE_CARD_IO_ERROR, carrier);
+        // mSimErrorState has the state of each sim indexed by slotID.
+        for (int index = 0; index < getTelephonyManager().getActiveModemCount(); index++) {
+            if (!mSimErrorState[index]) {
+                continue;
+            }
+            // In the case when no sim cards are detected but a faulty card is inserted
+            // overwrite the text and only show "Invalid card"
+            if (noSims) {
+                return concatenate(carrierTextForSimIOError,
+                        getContext().getText(
+                                com.android.internal.R.string.emergency_calls_only),
+                        mSeparator);
+            } else if (subOrderBySlot[index] != -1) {
+                int subIndex = subOrderBySlot[index];
+                // prepend "Invalid card" when faulty card is inserted in slot 0 or 1
+                carrierNames[subIndex] = concatenate(carrierTextForSimIOError,
+                        carrierNames[subIndex],
+                        mSeparator);
+            } else {
+                // concatenate "Invalid card" when faulty card is inserted in other slot
+                text = concatenate(text, carrierTextForSimIOError, mSeparator);
+            }
+
+        }
+        return text;
+    }
+
+    /**
+     * This may be called internally after retrieving the correct value of {@code mNetworkSupported}
+     * (assumed false to start). In that case, the following happens:
+     * <ul>
+     *     <li> If there was a registered callback, and the network is supported, it will register
+     *          listeners.
+     *     <li> If there was not a registered callback, it will try to remove unregistered listeners
+     *          which is a no-op
+     * </ul>
+     *
+     * This call will always be processed in a background thread.
+     */
+    private void handleSetListening(CarrierTextCallback callback) {
+        TelephonyManager telephonyManager = getTelephonyManager();
+        if (callback != null) {
+            mCarrierTextCallback = callback;
+            if (mNetworkSupported.get()) {
+                // Keyguard update monitor expects callbacks from main thread
+                mMainHandler.post(() -> mKeyguardUpdateMonitor.registerCallback(mCallback));
+                mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
+                telephonyManager.listen(mPhoneStateListener,
+                        LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
+            } else {
+                // Don't listen and clear out the text when the device isn't a phone.
+                mMainHandler.post(() -> callback.updateCarrierInfo(
+                        new CarrierTextCallbackInfo("", null, false, null)
+                ));
+            }
+        } else {
+            mCarrierTextCallback = null;
+            mMainHandler.post(() -> mKeyguardUpdateMonitor.removeCallback(mCallback));
+            mWakefulnessLifecycle.removeObserver(mWakefulnessObserver);
+            telephonyManager.listen(mPhoneStateListener, LISTEN_NONE);
+        }
+    }
+
+    /**
+     * Sets the listening status of this controller. If the callback is null, it is set to
+     * not listening.
+     *
+     * @param callback Callback to provide text updates
+     */
+    public void setListening(CarrierTextCallback callback) {
+        mBgHandler.post(() -> handleSetListening(callback));
+    }
+
+    protected List<SubscriptionInfo> getSubscriptionInfo() {
+        return mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(false);
+    }
+
+    protected void updateCarrierText() {
+        boolean allSimsMissing = true;
+        boolean anySimReadyAndInService = false;
+        CharSequence displayText = null;
+        List<SubscriptionInfo> subs = getSubscriptionInfo();
+
+        final int numSubs = subs.size();
+        final int[] subsIds = new int[numSubs];
+        // This array will contain in position i, the index of subscription in slot ID i.
+        // -1 if no subscription in that slot
+        final int[] subOrderBySlot = new int[mSimSlotsNumber];
+        for (int i = 0; i < mSimSlotsNumber; i++) {
+            subOrderBySlot[i] = -1;
+        }
+        final CharSequence[] carrierNames = new CharSequence[numSubs];
+        if (DEBUG) Log.d(TAG, "updateCarrierText(): " + numSubs);
+
+        for (int i = 0; i < numSubs; i++) {
+            int subId = subs.get(i).getSubscriptionId();
+            carrierNames[i] = "";
+            subsIds[i] = subId;
+            subOrderBySlot[subs.get(i).getSimSlotIndex()] = i;
+            int simState = mKeyguardUpdateMonitor.getSimState(subId);
+            CharSequence carrierName = subs.get(i).getCarrierName();
+            CharSequence carrierTextForSimState = getCarrierTextForSimState(simState, carrierName);
+            if (DEBUG) {
+                Log.d(TAG, "Handling (subId=" + subId + "): " + simState + " " + carrierName);
+            }
+            if (carrierTextForSimState != null) {
+                allSimsMissing = false;
+                carrierNames[i] = carrierTextForSimState;
+            }
+            if (simState == TelephonyManager.SIM_STATE_READY) {
+                ServiceState ss = mKeyguardUpdateMonitor.mServiceStates.get(subId);
+                if (ss != null && ss.getDataRegistrationState() == ServiceState.STATE_IN_SERVICE) {
+                    // hack for WFC (IWLAN) not turning off immediately once
+                    // Wi-Fi is disassociated or disabled
+                    if (ss.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
+                            || (mWifiManager.isWifiEnabled()
+                            && mWifiManager.getConnectionInfo() != null
+                            && mWifiManager.getConnectionInfo().getBSSID() != null)) {
+                        if (DEBUG) {
+                            Log.d(TAG, "SIM ready and in service: subId=" + subId + ", ss=" + ss);
+                        }
+                        anySimReadyAndInService = true;
+                    }
+                }
+            }
+        }
+        // Only create "No SIM card" if no cards with CarrierName && no wifi when some sim is READY
+        // This condition will also be true always when numSubs == 0
+        if (allSimsMissing && !anySimReadyAndInService) {
+            if (numSubs != 0) {
+                // Shows "No SIM card | Emergency calls only" on devices that are voice-capable.
+                // This depends on mPlmn containing the text "Emergency calls only" when the radio
+                // has some connectivity. Otherwise, it should be null or empty and just show
+                // "No SIM card"
+                // Grab the first subscripton, because they all should contain the emergency text,
+                // described above.
+                displayText = makeCarrierStringOnEmergencyCapable(
+                        getMissingSimMessage(), subs.get(0).getCarrierName());
+            } else {
+                // We don't have a SubscriptionInfo to get the emergency calls only from.
+                // Grab it from the old sticky broadcast if possible instead. We can use it
+                // here because no subscriptions are active, so we don't have
+                // to worry about MSIM clashing.
+                CharSequence text =
+                        getContext().getText(com.android.internal.R.string.emergency_calls_only);
+                Intent i = getContext().registerReceiver(null,
+                        new IntentFilter(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED));
+                if (i != null) {
+                    String spn = "";
+                    String plmn = "";
+                    if (i.getBooleanExtra(TelephonyManager.EXTRA_SHOW_SPN, false)) {
+                        spn = i.getStringExtra(TelephonyManager.EXTRA_SPN);
+                    }
+                    if (i.getBooleanExtra(TelephonyManager.EXTRA_SHOW_PLMN, false)) {
+                        plmn = i.getStringExtra(TelephonyManager.EXTRA_PLMN);
+                    }
+                    if (DEBUG) Log.d(TAG, "Getting plmn/spn sticky brdcst " + plmn + "/" + spn);
+                    if (Objects.equals(plmn, spn)) {
+                        text = plmn;
+                    } else {
+                        text = concatenate(plmn, spn, mSeparator);
+                    }
+                }
+                displayText = makeCarrierStringOnEmergencyCapable(getMissingSimMessage(), text);
+            }
+        }
+
+        if (TextUtils.isEmpty(displayText)) displayText = joinNotEmpty(mSeparator, carrierNames);
+
+        displayText = updateCarrierTextWithSimIoError(displayText, carrierNames, subOrderBySlot,
+                allSimsMissing);
+
+        boolean airplaneMode = false;
+        // APM (airplane mode) != no carrier state. There are carrier services
+        // (e.g. WFC = Wi-Fi calling) which may operate in APM.
+        if (!anySimReadyAndInService && WirelessUtils.isAirplaneModeOn(mContext)) {
+            displayText = getAirplaneModeMessage();
+            airplaneMode = true;
+        }
+
+        final CarrierTextCallbackInfo info = new CarrierTextCallbackInfo(
+                displayText,
+                carrierNames,
+                !allSimsMissing,
+                subsIds,
+                airplaneMode);
+        postToCallback(info);
+    }
+
+    @VisibleForTesting
+    protected void postToCallback(CarrierTextCallbackInfo info) {
+        final CarrierTextCallback callback = mCarrierTextCallback;
+        if (callback != null) {
+            mMainHandler.post(() -> callback.updateCarrierInfo(info));
+        }
+    }
+
+    private Context getContext() {
+        return mContext;
+    }
+
+    private String getMissingSimMessage() {
+        return mShowMissingSim && mTelephonyCapable
+                ? getContext().getString(R.string.keyguard_missing_sim_message_short) : "";
+    }
+
+    private String getAirplaneModeMessage() {
+        return mShowAirplaneMode
+                ? getContext().getString(R.string.airplane_mode) : "";
+    }
+
+    /**
+     * Top-level function for creating carrier text. Makes text based on simState, PLMN
+     * and SPN as well as device capabilities, such as being emergency call capable.
+     *
+     * @return Carrier text if not in missing state, null otherwise.
+     */
+    private CharSequence getCarrierTextForSimState(int simState, CharSequence text) {
+        CharSequence carrierText = null;
+        CarrierTextController.StatusMode status = getStatusForIccState(simState);
+        switch (status) {
+            case Normal:
+                carrierText = text;
+                break;
+
+            case SimNotReady:
+                // Null is reserved for denoting missing, in this case we have nothing to display.
+                carrierText = ""; // nothing to display yet.
+                break;
+
+            case NetworkLocked:
+                carrierText = makeCarrierStringOnEmergencyCapable(
+                        mContext.getText(R.string.keyguard_network_locked_message), text);
+                break;
+
+            case SimMissing:
+                carrierText = null;
+                break;
+
+            case SimPermDisabled:
+                carrierText = makeCarrierStringOnEmergencyCapable(
+                        getContext().getText(
+                                R.string.keyguard_permanent_disabled_sim_message_short),
+                        text);
+                break;
+
+            case SimMissingLocked:
+                carrierText = null;
+                break;
+
+            case SimLocked:
+                carrierText = makeCarrierStringOnLocked(
+                        getContext().getText(R.string.keyguard_sim_locked_message),
+                        text);
+                break;
+
+            case SimPukLocked:
+                carrierText = makeCarrierStringOnLocked(
+                        getContext().getText(R.string.keyguard_sim_puk_locked_message),
+                        text);
+                break;
+            case SimIoError:
+                carrierText = makeCarrierStringOnEmergencyCapable(
+                        getContext().getText(R.string.keyguard_sim_error_message_short),
+                        text);
+                break;
+            case SimUnknown:
+                carrierText = null;
+                break;
+        }
+
+        return carrierText;
+    }
+
+    /*
+     * Add emergencyCallMessage to carrier string only if phone supports emergency calls.
+     */
+    private CharSequence makeCarrierStringOnEmergencyCapable(
+            CharSequence simMessage, CharSequence emergencyCallMessage) {
+        if (mIsEmergencyCallCapable) {
+            return concatenate(simMessage, emergencyCallMessage, mSeparator);
+        }
+        return simMessage;
+    }
+
+    /*
+     * Add "SIM card is locked" in parenthesis after carrier name, so it is easily associated in
+     * DSDS
+     */
+    private CharSequence makeCarrierStringOnLocked(CharSequence simMessage,
+            CharSequence carrierName) {
+        final boolean simMessageValid = !TextUtils.isEmpty(simMessage);
+        final boolean carrierNameValid = !TextUtils.isEmpty(carrierName);
+        if (simMessageValid && carrierNameValid) {
+            return mContext.getString(R.string.keyguard_carrier_name_with_sim_locked_template,
+                    carrierName, simMessage);
+        } else if (simMessageValid) {
+            return simMessage;
+        } else if (carrierNameValid) {
+            return carrierName;
+        } else {
+            return "";
+        }
+    }
+
+    /**
+     * Determine the current status of the lock screen given the SIM state and other stuff.
+     */
+    private CarrierTextController.StatusMode getStatusForIccState(int simState) {
+        final boolean missingAndNotProvisioned =
+                !mKeyguardUpdateMonitor.isDeviceProvisioned()
+                        && (simState == TelephonyManager.SIM_STATE_ABSENT
+                        || simState == TelephonyManager.SIM_STATE_PERM_DISABLED);
+
+        // Assume we're NETWORK_LOCKED if not provisioned
+        simState = missingAndNotProvisioned ? TelephonyManager.SIM_STATE_NETWORK_LOCKED : simState;
+        switch (simState) {
+            case TelephonyManager.SIM_STATE_ABSENT:
+                return CarrierTextController.StatusMode.SimMissing;
+            case TelephonyManager.SIM_STATE_NETWORK_LOCKED:
+                return CarrierTextController.StatusMode.SimMissingLocked;
+            case TelephonyManager.SIM_STATE_NOT_READY:
+                return CarrierTextController.StatusMode.SimNotReady;
+            case TelephonyManager.SIM_STATE_PIN_REQUIRED:
+                return CarrierTextController.StatusMode.SimLocked;
+            case TelephonyManager.SIM_STATE_PUK_REQUIRED:
+                return CarrierTextController.StatusMode.SimPukLocked;
+            case TelephonyManager.SIM_STATE_READY:
+                return CarrierTextController.StatusMode.Normal;
+            case TelephonyManager.SIM_STATE_PERM_DISABLED:
+                return CarrierTextController.StatusMode.SimPermDisabled;
+            case TelephonyManager.SIM_STATE_UNKNOWN:
+                return CarrierTextController.StatusMode.SimUnknown;
+            case TelephonyManager.SIM_STATE_CARD_IO_ERROR:
+                return CarrierTextController.StatusMode.SimIoError;
+        }
+        return CarrierTextController.StatusMode.SimUnknown;
+    }
+
+    private static CharSequence concatenate(CharSequence plmn, CharSequence spn,
+            CharSequence separator) {
+        final boolean plmnValid = !TextUtils.isEmpty(plmn);
+        final boolean spnValid = !TextUtils.isEmpty(spn);
+        if (plmnValid && spnValid) {
+            return new StringBuilder().append(plmn).append(separator).append(spn).toString();
+        } else if (plmnValid) {
+            return plmn;
+        } else if (spnValid) {
+            return spn;
+        } else {
+            return "";
+        }
+    }
+
+    /**
+     * Joins the strings in a sequence using a separator. Empty strings are discarded with no extra
+     * separator added so there are no extra separators that are not needed.
+     */
+    private static CharSequence joinNotEmpty(CharSequence separator, CharSequence[] sequences) {
+        int length = sequences.length;
+        if (length == 0) return "";
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < length; i++) {
+            if (!TextUtils.isEmpty(sequences[i])) {
+                if (!TextUtils.isEmpty(sb)) {
+                    sb.append(separator);
+                }
+                sb.append(sequences[i]);
+            }
+        }
+        return sb.toString();
+    }
+
+    private static List<CharSequence> append(List<CharSequence> list, CharSequence string) {
+        if (!TextUtils.isEmpty(string)) {
+            list.add(string);
+        }
+        return list;
+    }
+
+    private CharSequence getCarrierHelpTextForSimState(int simState,
+            String plmn, String spn) {
+        int carrierHelpTextId = 0;
+        CarrierTextController.StatusMode status = getStatusForIccState(simState);
+        switch (status) {
+            case NetworkLocked:
+                carrierHelpTextId = R.string.keyguard_instructions_when_pattern_disabled;
+                break;
+
+            case SimMissing:
+                carrierHelpTextId = R.string.keyguard_missing_sim_instructions_long;
+                break;
+
+            case SimPermDisabled:
+                carrierHelpTextId = R.string.keyguard_permanent_disabled_sim_instructions;
+                break;
+
+            case SimMissingLocked:
+                carrierHelpTextId = R.string.keyguard_missing_sim_instructions;
+                break;
+
+            case Normal:
+            case SimLocked:
+            case SimPukLocked:
+                break;
+        }
+
+        return mContext.getText(carrierHelpTextId);
+    }
+
+    public static class Builder {
+        private final Context mContext;
+        private final String mSeparator;
+        private boolean mShowAirplaneMode;
+        private boolean mShowMissingSim;
+
+        @Inject
+        public Builder(Context context, @Main Resources resources) {
+            mContext = context;
+            mSeparator = resources.getString(
+                    com.android.internal.R.string.kg_text_message_separator);
+        }
+
+
+        public Builder setShowAirplaneMode(boolean showAirplaneMode) {
+            mShowAirplaneMode = showAirplaneMode;
+            return this;
+        }
+
+        public Builder setShowMissingSim(boolean showMissingSim) {
+            mShowMissingSim = showMissingSim;
+            return this;
+        }
+
+        public CarrierTextController build() {
+            return new CarrierTextController(
+                    mContext, mSeparator, mShowAirplaneMode, mShowMissingSim);
+        }
+    }
+    /**
+     * Data structure for passing information to CarrierTextController subscribers
+     */
+    public static final class CarrierTextCallbackInfo {
+        public final CharSequence carrierText;
+        public final CharSequence[] listOfCarriers;
+        public final boolean anySimReady;
+        public final int[] subscriptionIds;
+        public boolean airplaneMode;
+
+        @VisibleForTesting
+        public CarrierTextCallbackInfo(CharSequence carrierText, CharSequence[] listOfCarriers,
+                boolean anySimReady, int[] subscriptionIds) {
+            this(carrierText, listOfCarriers, anySimReady, subscriptionIds, false);
+        }
+
+        @VisibleForTesting
+        public CarrierTextCallbackInfo(CharSequence carrierText, CharSequence[] listOfCarriers,
+                boolean anySimReady, int[] subscriptionIds, boolean airplaneMode) {
+            this.carrierText = carrierText;
+            this.listOfCarriers = listOfCarriers;
+            this.anySimReady = anySimReady;
+            this.subscriptionIds = subscriptionIds;
+            this.airplaneMode = airplaneMode;
+        }
+    }
+
+    /**
+     * Callback to communicate to Views
+     */
+    public interface CarrierTextCallback {
+        /**
+         * Provides updated carrier information.
+         */
+        default void updateCarrierInfo(CarrierTextCallbackInfo info) {};
+
+        /**
+         * Notifies the View that the device is going to sleep
+         */
+        default void startedGoingToSleep() {};
+
+        /**
+         * Notifies the View that the device finished waking up
+         */
+        default void finishedWakingUp() {};
     }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java
deleted file mode 100644
index 87b01e8..0000000
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java
+++ /dev/null
@@ -1,720 +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.keyguard;
-
-import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;
-import static android.telephony.PhoneStateListener.LISTEN_NONE;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.Resources;
-import android.net.ConnectivityManager;
-import android.net.wifi.WifiManager;
-import android.os.Handler;
-import android.telephony.PhoneStateListener;
-import android.telephony.ServiceState;
-import android.telephony.SubscriptionInfo;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
-import android.util.Log;
-
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import com.android.settingslib.WirelessUtils;
-import com.android.systemui.R;
-import com.android.systemui.dagger.qualifiers.Background;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.keyguard.WakefulnessLifecycle;
-
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import javax.inject.Inject;
-
-/**
- * Controller that generates text including the carrier names and/or the status of all the SIM
- * interfaces in the device. Through a callback, the updates can be retrieved either as a list or
- * separated by a given separator {@link CharSequence}.
- */
-public class CarrierTextManager {
-    private static final boolean DEBUG = KeyguardConstants.DEBUG;
-    private static final String TAG = "CarrierTextController";
-
-    private final boolean mIsEmergencyCallCapable;
-    private final Handler mMainHandler;
-    private final Handler mBgHandler;
-    private boolean mTelephonyCapable;
-    private final boolean mShowMissingSim;
-    private final boolean mShowAirplaneMode;
-    private final AtomicBoolean mNetworkSupported = new AtomicBoolean();
-    @VisibleForTesting
-    protected KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-    private final WifiManager mWifiManager;
-    private final boolean[] mSimErrorState;
-    private final int mSimSlotsNumber;
-    @Nullable // Check for nullability before dispatching
-    private CarrierTextCallback mCarrierTextCallback;
-    private final Context mContext;
-    private final TelephonyManager mTelephonyManager;
-    private final CharSequence mSeparator;
-    private final WakefulnessLifecycle mWakefulnessLifecycle;
-    private final WakefulnessLifecycle.Observer mWakefulnessObserver =
-            new WakefulnessLifecycle.Observer() {
-                @Override
-                public void onFinishedWakingUp() {
-                    final CarrierTextCallback callback = mCarrierTextCallback;
-                    if (callback != null) callback.finishedWakingUp();
-                }
-
-                @Override
-                public void onStartedGoingToSleep() {
-                    final CarrierTextCallback callback = mCarrierTextCallback;
-                    if (callback != null) callback.startedGoingToSleep();
-                }
-            };
-
-    @VisibleForTesting
-    protected final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
-        @Override
-        public void onRefreshCarrierInfo() {
-            if (DEBUG) {
-                Log.d(TAG, "onRefreshCarrierInfo(), mTelephonyCapable: "
-                        + Boolean.toString(mTelephonyCapable));
-            }
-            updateCarrierText();
-        }
-
-        @Override
-        public void onTelephonyCapable(boolean capable) {
-            if (DEBUG) {
-                Log.d(TAG, "onTelephonyCapable() mTelephonyCapable: "
-                        + Boolean.toString(capable));
-            }
-            mTelephonyCapable = capable;
-            updateCarrierText();
-        }
-
-        public void onSimStateChanged(int subId, int slotId, int simState) {
-            if (slotId < 0 || slotId >= mSimSlotsNumber) {
-                Log.d(TAG, "onSimStateChanged() - slotId invalid: " + slotId
-                        + " mTelephonyCapable: " + Boolean.toString(mTelephonyCapable));
-                return;
-            }
-
-            if (DEBUG) Log.d(TAG, "onSimStateChanged: " + getStatusForIccState(simState));
-            if (getStatusForIccState(simState) == CarrierTextManager.StatusMode.SimIoError) {
-                mSimErrorState[slotId] = true;
-                updateCarrierText();
-            } else if (mSimErrorState[slotId]) {
-                mSimErrorState[slotId] = false;
-                updateCarrierText();
-            }
-        }
-    };
-
-    private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
-        @Override
-        public void onActiveDataSubscriptionIdChanged(int subId) {
-            if (mNetworkSupported.get() && mCarrierTextCallback != null) {
-                updateCarrierText();
-            }
-        }
-    };
-
-    /**
-     * The status of this lock screen. Primarily used for widgets on LockScreen.
-     */
-    private enum StatusMode {
-        Normal, // Normal case (sim card present, it's not locked)
-        NetworkLocked, // SIM card is 'network locked'.
-        SimMissing, // SIM card is missing.
-        SimMissingLocked, // SIM card is missing, and device isn't provisioned; don't allow access
-        SimPukLocked, // SIM card is PUK locked because SIM entered wrong too many times
-        SimLocked, // SIM card is currently locked
-        SimPermDisabled, // SIM card is permanently disabled due to PUK unlock failure
-        SimNotReady, // SIM is not ready yet. May never be on devices w/o a SIM.
-        SimIoError, // SIM card is faulty
-        SimUnknown // SIM card is unknown
-    }
-
-    /**
-     * Controller that provides updates on text with carriers names or SIM status.
-     * Used by {@link CarrierText}.
-     *
-     * @param separator Separator between different parts of the text
-     */
-    private CarrierTextManager(Context context, CharSequence separator, boolean showAirplaneMode,
-            boolean showMissingSim, @Nullable WifiManager wifiManager,
-            ConnectivityManager connectivityManager, TelephonyManager telephonyManager,
-            WakefulnessLifecycle wakefulnessLifecycle, @Main Handler mainHandler,
-            @Background Handler bgHandler, KeyguardUpdateMonitor keyguardUpdateMonitor) {
-        mContext = context;
-        mIsEmergencyCallCapable = telephonyManager.isVoiceCapable();
-
-        mShowAirplaneMode = showAirplaneMode;
-        mShowMissingSim = showMissingSim;
-
-        mWifiManager = wifiManager;
-        mTelephonyManager = telephonyManager;
-        mSeparator = separator;
-        mWakefulnessLifecycle = wakefulnessLifecycle;
-        mSimSlotsNumber = getTelephonyManager().getSupportedModemCount();
-        mSimErrorState = new boolean[mSimSlotsNumber];
-        mMainHandler = mainHandler;
-        mBgHandler = bgHandler;
-        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
-        mBgHandler.post(() -> {
-            boolean supported = connectivityManager.isNetworkSupported(
-                    ConnectivityManager.TYPE_MOBILE);
-            if (supported && mNetworkSupported.compareAndSet(false, supported)) {
-                // This will set/remove the listeners appropriately. Note that it will never double
-                // add the listeners.
-                handleSetListening(mCarrierTextCallback);
-            }
-        });
-    }
-
-    private TelephonyManager getTelephonyManager() {
-        return mTelephonyManager;
-    }
-
-    /**
-     * Checks if there are faulty cards. Adds the text depending on the slot of the card
-     *
-     * @param text:   current carrier text based on the sim state
-     * @param carrierNames names order by subscription order
-     * @param subOrderBySlot array containing the sub index for each slot ID
-     * @param noSims: whether a valid sim card is inserted
-     * @return text
-     */
-    private CharSequence updateCarrierTextWithSimIoError(CharSequence text,
-            CharSequence[] carrierNames, int[] subOrderBySlot, boolean noSims) {
-        final CharSequence carrier = "";
-        CharSequence carrierTextForSimIOError = getCarrierTextForSimState(
-                TelephonyManager.SIM_STATE_CARD_IO_ERROR, carrier);
-        // mSimErrorState has the state of each sim indexed by slotID.
-        for (int index = 0; index < getTelephonyManager().getActiveModemCount(); index++) {
-            if (!mSimErrorState[index]) {
-                continue;
-            }
-            // In the case when no sim cards are detected but a faulty card is inserted
-            // overwrite the text and only show "Invalid card"
-            if (noSims) {
-                return concatenate(carrierTextForSimIOError,
-                        getContext().getText(
-                                com.android.internal.R.string.emergency_calls_only),
-                        mSeparator);
-            } else if (subOrderBySlot[index] != -1) {
-                int subIndex = subOrderBySlot[index];
-                // prepend "Invalid card" when faulty card is inserted in slot 0 or 1
-                carrierNames[subIndex] = concatenate(carrierTextForSimIOError,
-                        carrierNames[subIndex],
-                        mSeparator);
-            } else {
-                // concatenate "Invalid card" when faulty card is inserted in other slot
-                text = concatenate(text, carrierTextForSimIOError, mSeparator);
-            }
-
-        }
-        return text;
-    }
-
-    /**
-     * This may be called internally after retrieving the correct value of {@code mNetworkSupported}
-     * (assumed false to start). In that case, the following happens:
-     * <ul>
-     *     <li> If there was a registered callback, and the network is supported, it will register
-     *          listeners.
-     *     <li> If there was not a registered callback, it will try to remove unregistered listeners
-     *          which is a no-op
-     * </ul>
-     *
-     * This call will always be processed in a background thread.
-     */
-    private void handleSetListening(CarrierTextCallback callback) {
-        TelephonyManager telephonyManager = getTelephonyManager();
-        if (callback != null) {
-            mCarrierTextCallback = callback;
-            if (mNetworkSupported.get()) {
-                // Keyguard update monitor expects callbacks from main thread
-                mMainHandler.post(() -> mKeyguardUpdateMonitor.registerCallback(mCallback));
-                mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
-                telephonyManager.listen(mPhoneStateListener,
-                        LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
-            } else {
-                // Don't listen and clear out the text when the device isn't a phone.
-                mMainHandler.post(() -> callback.updateCarrierInfo(
-                        new CarrierTextCallbackInfo("", null, false, null)
-                ));
-            }
-        } else {
-            mCarrierTextCallback = null;
-            mMainHandler.post(() -> mKeyguardUpdateMonitor.removeCallback(mCallback));
-            mWakefulnessLifecycle.removeObserver(mWakefulnessObserver);
-            telephonyManager.listen(mPhoneStateListener, LISTEN_NONE);
-        }
-    }
-
-    /**
-     * Sets the listening status of this controller. If the callback is null, it is set to
-     * not listening.
-     *
-     * @param callback Callback to provide text updates
-     */
-    public void setListening(CarrierTextCallback callback) {
-        mBgHandler.post(() -> handleSetListening(callback));
-    }
-
-    protected List<SubscriptionInfo> getSubscriptionInfo() {
-        return mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(false);
-    }
-
-    protected void updateCarrierText() {
-        boolean allSimsMissing = true;
-        boolean anySimReadyAndInService = false;
-        CharSequence displayText = null;
-        List<SubscriptionInfo> subs = getSubscriptionInfo();
-
-        final int numSubs = subs.size();
-        final int[] subsIds = new int[numSubs];
-        // This array will contain in position i, the index of subscription in slot ID i.
-        // -1 if no subscription in that slot
-        final int[] subOrderBySlot = new int[mSimSlotsNumber];
-        for (int i = 0; i < mSimSlotsNumber; i++) {
-            subOrderBySlot[i] = -1;
-        }
-        final CharSequence[] carrierNames = new CharSequence[numSubs];
-        if (DEBUG) Log.d(TAG, "updateCarrierText(): " + numSubs);
-
-        for (int i = 0; i < numSubs; i++) {
-            int subId = subs.get(i).getSubscriptionId();
-            carrierNames[i] = "";
-            subsIds[i] = subId;
-            subOrderBySlot[subs.get(i).getSimSlotIndex()] = i;
-            int simState = mKeyguardUpdateMonitor.getSimState(subId);
-            CharSequence carrierName = subs.get(i).getCarrierName();
-            CharSequence carrierTextForSimState = getCarrierTextForSimState(simState, carrierName);
-            if (DEBUG) {
-                Log.d(TAG, "Handling (subId=" + subId + "): " + simState + " " + carrierName);
-            }
-            if (carrierTextForSimState != null) {
-                allSimsMissing = false;
-                carrierNames[i] = carrierTextForSimState;
-            }
-            if (simState == TelephonyManager.SIM_STATE_READY) {
-                ServiceState ss = mKeyguardUpdateMonitor.mServiceStates.get(subId);
-                if (ss != null && ss.getDataRegistrationState() == ServiceState.STATE_IN_SERVICE) {
-                    // hack for WFC (IWLAN) not turning off immediately once
-                    // Wi-Fi is disassociated or disabled
-                    if (ss.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
-                            || (mWifiManager != null && mWifiManager.isWifiEnabled()
-                            && mWifiManager.getConnectionInfo() != null
-                            && mWifiManager.getConnectionInfo().getBSSID() != null)) {
-                        if (DEBUG) {
-                            Log.d(TAG, "SIM ready and in service: subId=" + subId + ", ss=" + ss);
-                        }
-                        anySimReadyAndInService = true;
-                    }
-                }
-            }
-        }
-        // Only create "No SIM card" if no cards with CarrierName && no wifi when some sim is READY
-        // This condition will also be true always when numSubs == 0
-        if (allSimsMissing && !anySimReadyAndInService) {
-            if (numSubs != 0) {
-                // Shows "No SIM card | Emergency calls only" on devices that are voice-capable.
-                // This depends on mPlmn containing the text "Emergency calls only" when the radio
-                // has some connectivity. Otherwise, it should be null or empty and just show
-                // "No SIM card"
-                // Grab the first subscripton, because they all should contain the emergency text,
-                // described above.
-                displayText = makeCarrierStringOnEmergencyCapable(
-                        getMissingSimMessage(), subs.get(0).getCarrierName());
-            } else {
-                // We don't have a SubscriptionInfo to get the emergency calls only from.
-                // Grab it from the old sticky broadcast if possible instead. We can use it
-                // here because no subscriptions are active, so we don't have
-                // to worry about MSIM clashing.
-                CharSequence text =
-                        getContext().getText(com.android.internal.R.string.emergency_calls_only);
-                Intent i = getContext().registerReceiver(null,
-                        new IntentFilter(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED));
-                if (i != null) {
-                    String spn = "";
-                    String plmn = "";
-                    if (i.getBooleanExtra(TelephonyManager.EXTRA_SHOW_SPN, false)) {
-                        spn = i.getStringExtra(TelephonyManager.EXTRA_SPN);
-                    }
-                    if (i.getBooleanExtra(TelephonyManager.EXTRA_SHOW_PLMN, false)) {
-                        plmn = i.getStringExtra(TelephonyManager.EXTRA_PLMN);
-                    }
-                    if (DEBUG) Log.d(TAG, "Getting plmn/spn sticky brdcst " + plmn + "/" + spn);
-                    if (Objects.equals(plmn, spn)) {
-                        text = plmn;
-                    } else {
-                        text = concatenate(plmn, spn, mSeparator);
-                    }
-                }
-                displayText = makeCarrierStringOnEmergencyCapable(getMissingSimMessage(), text);
-            }
-        }
-
-        if (TextUtils.isEmpty(displayText)) displayText = joinNotEmpty(mSeparator, carrierNames);
-
-        displayText = updateCarrierTextWithSimIoError(displayText, carrierNames, subOrderBySlot,
-                allSimsMissing);
-
-        boolean airplaneMode = false;
-        // APM (airplane mode) != no carrier state. There are carrier services
-        // (e.g. WFC = Wi-Fi calling) which may operate in APM.
-        if (!anySimReadyAndInService && WirelessUtils.isAirplaneModeOn(mContext)) {
-            displayText = getAirplaneModeMessage();
-            airplaneMode = true;
-        }
-
-        final CarrierTextCallbackInfo info = new CarrierTextCallbackInfo(
-                displayText,
-                carrierNames,
-                !allSimsMissing,
-                subsIds,
-                airplaneMode);
-        postToCallback(info);
-    }
-
-    @VisibleForTesting
-    protected void postToCallback(CarrierTextCallbackInfo info) {
-        final CarrierTextCallback callback = mCarrierTextCallback;
-        if (callback != null) {
-            mMainHandler.post(() -> callback.updateCarrierInfo(info));
-        }
-    }
-
-    private Context getContext() {
-        return mContext;
-    }
-
-    private String getMissingSimMessage() {
-        return mShowMissingSim && mTelephonyCapable
-                ? getContext().getString(R.string.keyguard_missing_sim_message_short) : "";
-    }
-
-    private String getAirplaneModeMessage() {
-        return mShowAirplaneMode
-                ? getContext().getString(R.string.airplane_mode) : "";
-    }
-
-    /**
-     * Top-level function for creating carrier text. Makes text based on simState, PLMN
-     * and SPN as well as device capabilities, such as being emergency call capable.
-     *
-     * @return Carrier text if not in missing state, null otherwise.
-     */
-    private CharSequence getCarrierTextForSimState(int simState, CharSequence text) {
-        CharSequence carrierText = null;
-        CarrierTextManager.StatusMode status = getStatusForIccState(simState);
-        switch (status) {
-            case Normal:
-                carrierText = text;
-                break;
-
-            case SimNotReady:
-                // Null is reserved for denoting missing, in this case we have nothing to display.
-                carrierText = ""; // nothing to display yet.
-                break;
-
-            case NetworkLocked:
-                carrierText = makeCarrierStringOnEmergencyCapable(
-                        mContext.getText(R.string.keyguard_network_locked_message), text);
-                break;
-
-            case SimMissing:
-                carrierText = null;
-                break;
-
-            case SimPermDisabled:
-                carrierText = makeCarrierStringOnEmergencyCapable(
-                        getContext().getText(
-                                R.string.keyguard_permanent_disabled_sim_message_short),
-                        text);
-                break;
-
-            case SimMissingLocked:
-                carrierText = null;
-                break;
-
-            case SimLocked:
-                carrierText = makeCarrierStringOnLocked(
-                        getContext().getText(R.string.keyguard_sim_locked_message),
-                        text);
-                break;
-
-            case SimPukLocked:
-                carrierText = makeCarrierStringOnLocked(
-                        getContext().getText(R.string.keyguard_sim_puk_locked_message),
-                        text);
-                break;
-            case SimIoError:
-                carrierText = makeCarrierStringOnEmergencyCapable(
-                        getContext().getText(R.string.keyguard_sim_error_message_short),
-                        text);
-                break;
-            case SimUnknown:
-                carrierText = null;
-                break;
-        }
-
-        return carrierText;
-    }
-
-    /*
-     * Add emergencyCallMessage to carrier string only if phone supports emergency calls.
-     */
-    private CharSequence makeCarrierStringOnEmergencyCapable(
-            CharSequence simMessage, CharSequence emergencyCallMessage) {
-        if (mIsEmergencyCallCapable) {
-            return concatenate(simMessage, emergencyCallMessage, mSeparator);
-        }
-        return simMessage;
-    }
-
-    /*
-     * Add "SIM card is locked" in parenthesis after carrier name, so it is easily associated in
-     * DSDS
-     */
-    private CharSequence makeCarrierStringOnLocked(CharSequence simMessage,
-            CharSequence carrierName) {
-        final boolean simMessageValid = !TextUtils.isEmpty(simMessage);
-        final boolean carrierNameValid = !TextUtils.isEmpty(carrierName);
-        if (simMessageValid && carrierNameValid) {
-            return mContext.getString(R.string.keyguard_carrier_name_with_sim_locked_template,
-                    carrierName, simMessage);
-        } else if (simMessageValid) {
-            return simMessage;
-        } else if (carrierNameValid) {
-            return carrierName;
-        } else {
-            return "";
-        }
-    }
-
-    /**
-     * Determine the current status of the lock screen given the SIM state and other stuff.
-     */
-    private CarrierTextManager.StatusMode getStatusForIccState(int simState) {
-        final boolean missingAndNotProvisioned =
-                !mKeyguardUpdateMonitor.isDeviceProvisioned()
-                        && (simState == TelephonyManager.SIM_STATE_ABSENT
-                        || simState == TelephonyManager.SIM_STATE_PERM_DISABLED);
-
-        // Assume we're NETWORK_LOCKED if not provisioned
-        simState = missingAndNotProvisioned ? TelephonyManager.SIM_STATE_NETWORK_LOCKED : simState;
-        switch (simState) {
-            case TelephonyManager.SIM_STATE_ABSENT:
-                return CarrierTextManager.StatusMode.SimMissing;
-            case TelephonyManager.SIM_STATE_NETWORK_LOCKED:
-                return CarrierTextManager.StatusMode.SimMissingLocked;
-            case TelephonyManager.SIM_STATE_NOT_READY:
-                return CarrierTextManager.StatusMode.SimNotReady;
-            case TelephonyManager.SIM_STATE_PIN_REQUIRED:
-                return CarrierTextManager.StatusMode.SimLocked;
-            case TelephonyManager.SIM_STATE_PUK_REQUIRED:
-                return CarrierTextManager.StatusMode.SimPukLocked;
-            case TelephonyManager.SIM_STATE_READY:
-                return CarrierTextManager.StatusMode.Normal;
-            case TelephonyManager.SIM_STATE_PERM_DISABLED:
-                return CarrierTextManager.StatusMode.SimPermDisabled;
-            case TelephonyManager.SIM_STATE_UNKNOWN:
-                return CarrierTextManager.StatusMode.SimUnknown;
-            case TelephonyManager.SIM_STATE_CARD_IO_ERROR:
-                return CarrierTextManager.StatusMode.SimIoError;
-        }
-        return CarrierTextManager.StatusMode.SimUnknown;
-    }
-
-    private static CharSequence concatenate(CharSequence plmn, CharSequence spn,
-            CharSequence separator) {
-        final boolean plmnValid = !TextUtils.isEmpty(plmn);
-        final boolean spnValid = !TextUtils.isEmpty(spn);
-        if (plmnValid && spnValid) {
-            return new StringBuilder().append(plmn).append(separator).append(spn).toString();
-        } else if (plmnValid) {
-            return plmn;
-        } else if (spnValid) {
-            return spn;
-        } else {
-            return "";
-        }
-    }
-
-    /**
-     * Joins the strings in a sequence using a separator. Empty strings are discarded with no extra
-     * separator added so there are no extra separators that are not needed.
-     */
-    private static CharSequence joinNotEmpty(CharSequence separator, CharSequence[] sequences) {
-        int length = sequences.length;
-        if (length == 0) return "";
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < length; i++) {
-            if (!TextUtils.isEmpty(sequences[i])) {
-                if (!TextUtils.isEmpty(sb)) {
-                    sb.append(separator);
-                }
-                sb.append(sequences[i]);
-            }
-        }
-        return sb.toString();
-    }
-
-    private static List<CharSequence> append(List<CharSequence> list, CharSequence string) {
-        if (!TextUtils.isEmpty(string)) {
-            list.add(string);
-        }
-        return list;
-    }
-
-    private CharSequence getCarrierHelpTextForSimState(int simState,
-            String plmn, String spn) {
-        int carrierHelpTextId = 0;
-        CarrierTextManager.StatusMode status = getStatusForIccState(simState);
-        switch (status) {
-            case NetworkLocked:
-                carrierHelpTextId = R.string.keyguard_instructions_when_pattern_disabled;
-                break;
-
-            case SimMissing:
-                carrierHelpTextId = R.string.keyguard_missing_sim_instructions_long;
-                break;
-
-            case SimPermDisabled:
-                carrierHelpTextId = R.string.keyguard_permanent_disabled_sim_instructions;
-                break;
-
-            case SimMissingLocked:
-                carrierHelpTextId = R.string.keyguard_missing_sim_instructions;
-                break;
-
-            case Normal:
-            case SimLocked:
-            case SimPukLocked:
-                break;
-        }
-
-        return mContext.getText(carrierHelpTextId);
-    }
-
-    /** Injectable Buildeer for {@#link CarrierTextManager}. */
-    public static class Builder {
-        private final Context mContext;
-        private final String mSeparator;
-        private final WifiManager mWifiManager;
-        private final ConnectivityManager mConnectivityManager;
-        private final TelephonyManager mTelephonyManager;
-        private final WakefulnessLifecycle mWakefulnessLifecycle;
-        private final Handler mMainHandler;
-        private final Handler mBgHandler;
-        private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-        private boolean mShowAirplaneMode;
-        private boolean mShowMissingSim;
-
-        @Inject
-        public Builder(Context context, @Main Resources resources,
-                @Nullable WifiManager wifiManager, ConnectivityManager connectivityManager,
-                TelephonyManager telephonyManager, WakefulnessLifecycle wakefulnessLifecycle,
-                @Main Handler mainHandler, @Background Handler bgHandler,
-                KeyguardUpdateMonitor keyguardUpdateMonitor) {
-            mContext = context;
-            mSeparator = resources.getString(
-                    com.android.internal.R.string.kg_text_message_separator);
-            mWifiManager = wifiManager;
-            mConnectivityManager = connectivityManager;
-            mTelephonyManager = telephonyManager;
-            mWakefulnessLifecycle = wakefulnessLifecycle;
-            mMainHandler = mainHandler;
-            mBgHandler = bgHandler;
-            mKeyguardUpdateMonitor = keyguardUpdateMonitor;
-        }
-
-        /** */
-        public Builder setShowAirplaneMode(boolean showAirplaneMode) {
-            mShowAirplaneMode = showAirplaneMode;
-            return this;
-        }
-
-        /** */
-        public Builder setShowMissingSim(boolean showMissingSim) {
-            mShowMissingSim = showMissingSim;
-            return this;
-        }
-
-        /** Create a CarrierTextManager. */
-        public CarrierTextManager build() {
-            return new CarrierTextManager(
-                    mContext, mSeparator, mShowAirplaneMode, mShowMissingSim, mWifiManager,
-                    mConnectivityManager, mTelephonyManager, mWakefulnessLifecycle, mMainHandler,
-                    mBgHandler, mKeyguardUpdateMonitor);
-        }
-    }
-    /**
-     * Data structure for passing information to CarrierTextController subscribers
-     */
-    public static final class CarrierTextCallbackInfo {
-        public final CharSequence carrierText;
-        public final CharSequence[] listOfCarriers;
-        public final boolean anySimReady;
-        public final int[] subscriptionIds;
-        public boolean airplaneMode;
-
-        @VisibleForTesting
-        public CarrierTextCallbackInfo(CharSequence carrierText, CharSequence[] listOfCarriers,
-                boolean anySimReady, int[] subscriptionIds) {
-            this(carrierText, listOfCarriers, anySimReady, subscriptionIds, false);
-        }
-
-        @VisibleForTesting
-        public CarrierTextCallbackInfo(CharSequence carrierText, CharSequence[] listOfCarriers,
-                boolean anySimReady, int[] subscriptionIds, boolean airplaneMode) {
-            this.carrierText = carrierText;
-            this.listOfCarriers = listOfCarriers;
-            this.anySimReady = anySimReady;
-            this.subscriptionIds = subscriptionIds;
-            this.airplaneMode = airplaneMode;
-        }
-    }
-
-    /**
-     * Callback to communicate to Views
-     */
-    public interface CarrierTextCallback {
-        /**
-         * Provides updated carrier information.
-         */
-        default void updateCarrierInfo(CarrierTextCallbackInfo info) {};
-
-        /**
-         * Notifies the View that the device is going to sleep
-         */
-        default void startedGoingToSleep() {};
-
-        /**
-         * Notifies the View that the device finished waking up
-         */
-        default void finishedWakingUp() {};
-    }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java b/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java
index f01b67b..945c9c4 100644
--- a/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java
+++ b/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java
@@ -20,6 +20,7 @@
 
 import android.hardware.biometrics.BiometricSourceType;
 import android.view.View;
+import android.view.ViewGroup;
 
 import androidx.annotation.NonNull;
 
@@ -73,13 +74,15 @@
 
     @Override
     protected void onViewAttached() {
-        mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
         mIsBouncerShowing = mKeyguardViewController.isBouncerShowing();
-
-        mStatusBarStateController.addCallback(mStatusBarStateListener);
         mIsKeyguardShowing = mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
         mIsDozing = mStatusBarStateController.isDozing();
+        mRunningFPS = mKeyguardUpdateMonitor.isFingerprintDetectionRunning();
         mAuthenticated = false;
+        updateButtonVisibility();
+
+        mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
+        mStatusBarStateController.addCallback(mStatusBarStateListener);
     }
 
     @Override
@@ -88,6 +91,15 @@
         mStatusBarStateController.removeCallback(mStatusBarStateListener);
     }
 
+    /**
+     * Call when this controller is no longer needed. This will remove the view from its parent.
+     */
+    public void destroy() {
+        if (mView != null && mView.getParent() != null) {
+            ((ViewGroup) mView.getParent()).removeView(mView);
+        }
+    }
+
     private void updateButtonVisibility() {
         mShowButton = !mAuthenticated && !mIsDozing && mIsKeyguardShowing
                 && !mIsBouncerShowing && !mRunningFPS;
@@ -143,6 +155,14 @@
                 public void onBiometricRunningStateChanged(boolean running,
                         BiometricSourceType biometricSourceType) {
                     mRunningFPS = running && biometricSourceType == FINGERPRINT;
+                    mAuthenticated &= !mRunningFPS;
+                    updateButtonVisibility();
+                }
+
+                @Override
+                public void onBiometricAuthenticated(int userId,
+                        BiometricSourceType biometricSourceType, boolean isStrongBiometric) {
+                    mAuthenticated = true;
                     updateButtonVisibility();
                 }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
index c4b02f6..707ee29 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
@@ -16,16 +16,34 @@
 
 package com.android.keyguard;
 
+import static com.android.systemui.DejankUtils.whitelistIpcs;
+
+import android.app.ActivityOptions;
+import android.app.ActivityTaskManager;
 import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.telecom.TelecomManager;
+import android.telephony.TelephonyManager;
 import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Slog;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.widget.Button;
 
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.util.EmergencyAffordanceManager;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settingslib.Utils;
+import com.android.systemui.Dependency;
+import com.android.systemui.util.EmergencyDialerConstants;
 
 /**
  * This class implements a smart emergency button that updates itself based
@@ -35,14 +53,34 @@
  */
 public class EmergencyButton extends Button {
 
+    private static final String LOG_TAG = "EmergencyButton";
     private final EmergencyAffordanceManager mEmergencyAffordanceManager;
 
     private int mDownX;
     private int mDownY;
+    KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
+
+        @Override
+        public void onSimStateChanged(int subId, int slotId, int simState) {
+            updateEmergencyCallButton();
+        }
+
+        @Override
+        public void onPhoneStateChanged(int phoneState) {
+            updateEmergencyCallButton();
+        }
+    };
     private boolean mLongPressWasDragged;
 
-    private LockPatternUtils mLockPatternUtils;
+    public interface EmergencyButtonCallback {
+        public void onEmergencyButtonClickedWhenInCall();
+    }
 
+    private LockPatternUtils mLockPatternUtils;
+    private PowerManager mPowerManager;
+    private EmergencyButtonCallback mEmergencyButtonCallback;
+
+    private final boolean mIsVoiceCapable;
     private final boolean mEnableEmergencyCallWhileSimLocked;
 
     public EmergencyButton(Context context) {
@@ -51,15 +89,34 @@
 
     public EmergencyButton(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mIsVoiceCapable = getTelephonyManager().isVoiceCapable();
         mEnableEmergencyCallWhileSimLocked = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_enable_emergency_call_while_sim_locked);
         mEmergencyAffordanceManager = new EmergencyAffordanceManager(context);
     }
 
+    private TelephonyManager getTelephonyManager() {
+        return (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        Dependency.get(KeyguardUpdateMonitor.class).registerCallback(mInfoCallback);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        Dependency.get(KeyguardUpdateMonitor.class).removeCallback(mInfoCallback);
+    }
+
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
         mLockPatternUtils = new LockPatternUtils(mContext);
+        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+        setOnClickListener(v -> takeEmergencyCallAction());
         if (mEmergencyAffordanceManager.needsEmergencyAffordance()) {
             setOnLongClickListener(v -> {
                 if (!mLongPressWasDragged
@@ -70,6 +127,7 @@
                 return false;
             });
         }
+        whitelistIpcs(this::updateEmergencyCallButton);
     }
 
     @Override
@@ -107,13 +165,65 @@
         return super.performLongClick();
     }
 
-    void updateEmergencyCallButton(boolean isInCall, boolean isVoiceCapable, boolean simLocked) {
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        updateEmergencyCallButton();
+    }
+
+    /**
+     * Shows the emergency dialer or returns the user to the existing call.
+     */
+    public void takeEmergencyCallAction() {
+        MetricsLogger.action(mContext, MetricsEvent.ACTION_EMERGENCY_CALL);
+        if (mPowerManager != null) {
+            mPowerManager.userActivity(SystemClock.uptimeMillis(), true);
+        }
+        try {
+            ActivityTaskManager.getService().stopSystemLockTaskMode();
+        } catch (RemoteException e) {
+            Slog.w(LOG_TAG, "Failed to stop app pinning");
+        }
+        if (isInCall()) {
+            resumeCall();
+            if (mEmergencyButtonCallback != null) {
+                mEmergencyButtonCallback.onEmergencyButtonClickedWhenInCall();
+            }
+        } else {
+            KeyguardUpdateMonitor updateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
+            if (updateMonitor != null) {
+                updateMonitor.reportEmergencyCallAction(true /* bypassHandler */);
+            } else {
+                Log.w(LOG_TAG, "KeyguardUpdateMonitor was null, launching intent anyway.");
+            }
+            TelecomManager telecomManager = getTelecommManager();
+            if (telecomManager == null) {
+                Log.wtf(LOG_TAG, "TelecomManager was null, cannot launch emergency dialer");
+                return;
+            }
+            Intent emergencyDialIntent =
+                    telecomManager.createLaunchEmergencyDialerIntent(null /* number*/)
+                            .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+                                    | Intent.FLAG_ACTIVITY_CLEAR_TOP)
+                            .putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE,
+                                    EmergencyDialerConstants.ENTRY_TYPE_LOCKSCREEN_BUTTON);
+
+            getContext().startActivityAsUser(emergencyDialIntent,
+                    ActivityOptions.makeCustomAnimation(getContext(), 0, 0).toBundle(),
+                    new UserHandle(KeyguardUpdateMonitor.getCurrentUser()));
+        }
+    }
+
+    private void updateEmergencyCallButton() {
         boolean visible = false;
-        if (isVoiceCapable) {
+        if (mIsVoiceCapable) {
             // Emergency calling requires voice capability.
-            if (isInCall) {
+            if (isInCall()) {
                 visible = true; // always show "return to call" if phone is off-hook
             } else {
+                final boolean simLocked = Dependency.get(KeyguardUpdateMonitor.class)
+                        .isSimPinVoiceSecure();
                 if (simLocked) {
                     // Some countries can't handle emergency calls while SIM is locked.
                     visible = mEnableEmergencyCallWhileSimLocked;
@@ -127,7 +237,7 @@
             setVisibility(View.VISIBLE);
 
             int textId;
-            if (isInCall) {
+            if (isInCall()) {
                 textId = com.android.internal.R.string.lockscreen_return_to_call;
             } else {
                 textId = com.android.internal.R.string.lockscreen_emergency_call;
@@ -137,4 +247,26 @@
             setVisibility(View.GONE);
         }
     }
+
+    public void setCallback(EmergencyButtonCallback callback) {
+        mEmergencyButtonCallback = callback;
+    }
+
+    /**
+     * Resumes a call in progress.
+     */
+    private void resumeCall() {
+        getTelecommManager().showInCallScreen(false);
+    }
+
+    /**
+     * @return {@code true} if there is a call currently in progress.
+     */
+    private boolean isInCall() {
+        return getTelecommManager().isInCall();
+    }
+
+    private TelecomManager getTelecommManager() {
+        return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
deleted file mode 100644
index 4275189..0000000
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.keyguard;
-
-import static com.android.systemui.DejankUtils.whitelistIpcs;
-
-import android.app.ActivityOptions;
-import android.app.ActivityTaskManager;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.os.PowerManager;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.telecom.TelecomManager;
-import android.telephony.TelephonyManager;
-import android.util.Log;
-
-import androidx.annotation.Nullable;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.keyguard.dagger.KeyguardBouncerScope;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
-import com.android.systemui.util.EmergencyDialerConstants;
-import com.android.systemui.util.ViewController;
-
-import javax.inject.Inject;
-
-/** View Controller for {@link com.android.keyguard.EmergencyButton}. */
-@KeyguardBouncerScope
-public class EmergencyButtonController extends ViewController<EmergencyButton> {
-    static final String LOG_TAG = "EmergencyButton";
-    private final ConfigurationController mConfigurationController;
-    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-    private final TelephonyManager mTelephonyManager;
-    private final PowerManager mPowerManager;
-    private final ActivityTaskManager mActivityTaskManager;
-    private final TelecomManager mTelecomManager;
-    private final MetricsLogger mMetricsLogger;
-
-    private EmergencyButtonCallback mEmergencyButtonCallback;
-
-    private final KeyguardUpdateMonitorCallback mInfoCallback =
-            new KeyguardUpdateMonitorCallback() {
-        @Override
-        public void onSimStateChanged(int subId, int slotId, int simState) {
-            updateEmergencyCallButton();
-        }
-
-        @Override
-        public void onPhoneStateChanged(int phoneState) {
-            updateEmergencyCallButton();
-        }
-    };
-
-    private final ConfigurationListener mConfigurationListener = new ConfigurationListener() {
-        @Override
-        public void onConfigChanged(Configuration newConfig) {
-            updateEmergencyCallButton();
-        }
-    };
-
-    private EmergencyButtonController(@Nullable EmergencyButton view,
-            ConfigurationController configurationController,
-            KeyguardUpdateMonitor keyguardUpdateMonitor, TelephonyManager telephonyManager,
-            PowerManager powerManager, ActivityTaskManager activityTaskManager,
-            @Nullable TelecomManager telecomManager, MetricsLogger metricsLogger) {
-        super(view);
-        mConfigurationController = configurationController;
-        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
-        mTelephonyManager = telephonyManager;
-        mPowerManager = powerManager;
-        mActivityTaskManager = activityTaskManager;
-        mTelecomManager = telecomManager;
-        mMetricsLogger = metricsLogger;
-    }
-
-    @Override
-    protected void onInit() {
-        whitelistIpcs(this::updateEmergencyCallButton);
-    }
-
-    @Override
-    protected void onViewAttached() {
-        mKeyguardUpdateMonitor.registerCallback(mInfoCallback);
-        mConfigurationController.addCallback(mConfigurationListener);
-        mView.setOnClickListener(v -> takeEmergencyCallAction());
-    }
-
-    @Override
-    protected void onViewDetached() {
-        mKeyguardUpdateMonitor.removeCallback(mInfoCallback);
-        mConfigurationController.removeCallback(mConfigurationListener);
-    }
-
-    private void updateEmergencyCallButton() {
-        if (mView != null) {
-            mView.updateEmergencyCallButton(
-                    mTelecomManager != null && mTelecomManager.isInCall(),
-                    mTelephonyManager.isVoiceCapable(),
-                    mKeyguardUpdateMonitor.isSimPinVoiceSecure());
-        }
-    }
-
-    public void setEmergencyButtonCallback(EmergencyButtonCallback callback) {
-        mEmergencyButtonCallback = callback;
-    }
-    /**
-     * Shows the emergency dialer or returns the user to the existing call.
-     */
-    public void takeEmergencyCallAction() {
-        mMetricsLogger.action(MetricsEvent.ACTION_EMERGENCY_CALL);
-        if (mPowerManager != null) {
-            mPowerManager.userActivity(SystemClock.uptimeMillis(), true);
-        }
-        mActivityTaskManager.stopSystemLockTaskMode();
-        if (mTelecomManager != null && mTelecomManager.isInCall()) {
-            mTelecomManager.showInCallScreen(false);
-            if (mEmergencyButtonCallback != null) {
-                mEmergencyButtonCallback.onEmergencyButtonClickedWhenInCall();
-            }
-        } else {
-            mKeyguardUpdateMonitor.reportEmergencyCallAction(true /* bypassHandler */);
-            if (mTelecomManager == null) {
-                Log.wtf(LOG_TAG, "TelecomManager was null, cannot launch emergency dialer");
-                return;
-            }
-            Intent emergencyDialIntent =
-                    mTelecomManager.createLaunchEmergencyDialerIntent(null /* number*/)
-                            .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
-                                    | Intent.FLAG_ACTIVITY_CLEAR_TOP)
-                            .putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE,
-                                    EmergencyDialerConstants.ENTRY_TYPE_LOCKSCREEN_BUTTON);
-
-            getContext().startActivityAsUser(emergencyDialIntent,
-                    ActivityOptions.makeCustomAnimation(getContext(), 0, 0).toBundle(),
-                    new UserHandle(KeyguardUpdateMonitor.getCurrentUser()));
-        }
-    }
-
-    /** */
-    public interface EmergencyButtonCallback {
-        /** */
-        void onEmergencyButtonClickedWhenInCall();
-    }
-
-    /** Injectable Factory for creating {@link EmergencyButtonController}. */
-    public static class Factory {
-        private final ConfigurationController mConfigurationController;
-        private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-        private final TelephonyManager mTelephonyManager;
-        private final PowerManager mPowerManager;
-        private final ActivityTaskManager mActivityTaskManager;
-        @Nullable
-        private final TelecomManager mTelecomManager;
-        private final MetricsLogger mMetricsLogger;
-
-        @Inject
-        public Factory(ConfigurationController configurationController,
-                KeyguardUpdateMonitor keyguardUpdateMonitor, TelephonyManager telephonyManager,
-                PowerManager powerManager, ActivityTaskManager activityTaskManager,
-                @Nullable TelecomManager telecomManager, MetricsLogger metricsLogger) {
-
-            mConfigurationController = configurationController;
-            mKeyguardUpdateMonitor = keyguardUpdateMonitor;
-            mTelephonyManager = telephonyManager;
-            mPowerManager = powerManager;
-            mActivityTaskManager = activityTaskManager;
-            mTelecomManager = telecomManager;
-            mMetricsLogger = metricsLogger;
-        }
-
-        /** Construct an {@link com.android.keyguard.EmergencyButtonController}. */
-        public EmergencyButtonController create(EmergencyButton view) {
-            return new EmergencyButtonController(view, mConfigurationController,
-                    mKeyguardUpdateMonitor, mTelephonyManager, mPowerManager, mActivityTaskManager,
-                    mTelecomManager, mMetricsLogger);
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
index 7a05a17..5760565 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
@@ -31,7 +31,7 @@
 import com.android.internal.widget.LockPatternChecker;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.LockscreenCredential;
-import com.android.keyguard.EmergencyButtonController.EmergencyButtonCallback;
+import com.android.keyguard.EmergencyButton.EmergencyButtonCallback;
 import com.android.keyguard.KeyguardAbsKeyInputView.KeyDownListener;
 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
 import com.android.systemui.R;
@@ -41,7 +41,6 @@
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     private final LockPatternUtils mLockPatternUtils;
     private final LatencyTracker mLatencyTracker;
-    private final EmergencyButtonController mEmergencyButtonController;
     private CountDownTimer mCountdownTimer;
     protected KeyguardMessageAreaController mMessageAreaController;
     private boolean mDismissing;
@@ -71,12 +70,11 @@
             LockPatternUtils lockPatternUtils,
             KeyguardSecurityCallback keyguardSecurityCallback,
             KeyguardMessageAreaController.Factory messageAreaControllerFactory,
-            LatencyTracker latencyTracker, EmergencyButtonController emergencyButtonController) {
-        super(view, securityMode, keyguardSecurityCallback, emergencyButtonController);
+            LatencyTracker latencyTracker) {
+        super(view, securityMode, keyguardSecurityCallback);
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mLockPatternUtils = lockPatternUtils;
         mLatencyTracker = latencyTracker;
-        mEmergencyButtonController = emergencyButtonController;
         KeyguardMessageArea kma = KeyguardMessageArea.findSecurityMessageDisplay(mView);
         mMessageAreaController = messageAreaControllerFactory.create(kma);
     }
@@ -85,7 +83,6 @@
 
     @Override
     public void onInit() {
-        super.onInit();
         mMessageAreaController.init();
     }
 
@@ -94,7 +91,10 @@
         super.onViewAttached();
         mView.setKeyDownListener(mKeyDownListener);
         mView.setEnableHaptics(mLockPatternUtils.isTactileFeedbackEnabled());
-        mEmergencyButtonController.setEmergencyButtonCallback(mEmergencyButtonCallback);
+        EmergencyButton button = mView.findViewById(R.id.emergency_call_button);
+        if (button != null) {
+            button.setCallback(mEmergencyButtonCallback);
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 6eb54c2..93ed0ea 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -179,20 +179,15 @@
             setPaddingRelative(startEndPadding, 0, startEndPadding, 0);
             mSmallClockFrame.setVisibility(GONE);
             mNewLockscreenClockFrame.setVisibility(VISIBLE);
-
-            statusAreaLP.removeRule(RelativeLayout.BELOW);
+            statusAreaLP.addRule(RelativeLayout.BELOW, R.id.new_lockscreen_clock_view);
             statusAreaLP.addRule(RelativeLayout.ALIGN_PARENT_START);
-            statusAreaLP.addRule(RelativeLayout.START_OF, R.id.new_lockscreen_clock_view);
-            statusAreaLP.width = 0;
         } else {
             setPaddingRelative(0, 0, 0, 0);
             mSmallClockFrame.setVisibility(VISIBLE);
             mNewLockscreenClockFrame.setVisibility(GONE);
 
             statusAreaLP.removeRule(RelativeLayout.ALIGN_PARENT_START);
-            statusAreaLP.removeRule(RelativeLayout.START_OF);
             statusAreaLP.addRule(RelativeLayout.BELOW, R.id.clock_view);
-            statusAreaLP.width = ViewGroup.LayoutParams.MATCH_PARENT;
         }
 
         requestLayout();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index e375877..0675200 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -20,6 +20,7 @@
 import android.content.ContentResolver;
 import android.content.res.Resources;
 import android.provider.Settings;
+import android.text.TextUtils;
 import android.text.format.DateFormat;
 import android.view.View;
 import android.view.ViewGroup;
@@ -212,10 +213,10 @@
      * keep the clock centered.
      */
     void updatePosition(int x, float scale, AnimationProperties props, boolean animate) {
-        x = Math.abs(x);
+        x = getCurrentLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? -x : x;
         if (mNewLockScreenClockFrame != null) {
             PropertyAnimator.setProperty(mNewLockScreenClockFrame, AnimatableProperty.TRANSLATION_X,
-                    -x, props, animate);
+                    x, props, animate);
             PropertyAnimator.setProperty(mNewLockScreenLargeClockFrame, AnimatableProperty.SCALE_X,
                     scale, props, animate);
             PropertyAnimator.setProperty(mNewLockScreenLargeClockFrame, AnimatableProperty.SCALE_Y,
@@ -277,15 +278,6 @@
         refreshFormat(mTimeFormat);
     }
 
-    float getClockTextTopPadding() {
-        if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1
-                && mNewLockScreenClockViewController != null) {
-            return mNewLockScreenClockViewController.getClockTextTopPadding();
-        }
-
-        return mView.getClockTextTopPadding();
-    }
-
     private void updateAodIcons() {
         NotificationIconContainer nic = (NotificationIconContainer)
                 mView.findViewById(
@@ -337,4 +329,8 @@
             sCacheKey = key;
         }
     }
+
+    private int getCurrentLayoutDirection() {
+        return TextUtils.getLayoutDirectionFromLocale(Locale.getDefault());
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
index 76a7473..276036c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
@@ -36,6 +36,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.keyguard.dagger.KeyguardStatusViewComponent;
+import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.dagger.qualifiers.UiBackground;
 import com.android.systemui.navigationbar.NavigationBarController;
@@ -45,15 +46,12 @@
 
 import javax.inject.Inject;
 
-import dagger.Lazy;
-
 public class KeyguardDisplayManager {
     protected static final String TAG = "KeyguardDisplayManager";
     private static boolean DEBUG = KeyguardConstants.DEBUG;
 
     private MediaRouter mMediaRouter = null;
     private final DisplayManager mDisplayService;
-    private final Lazy<NavigationBarController> mNavigationBarControllerLazy;
     private final KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
     private final Context mContext;
 
@@ -87,11 +85,9 @@
 
     @Inject
     public KeyguardDisplayManager(Context context,
-            Lazy<NavigationBarController> navigationBarControllerLazy,
             KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory,
             @UiBackground Executor uiBgExecutor) {
         mContext = context;
-        mNavigationBarControllerLazy = navigationBarControllerLazy;
         mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory;
         uiBgExecutor.execute(() -> mMediaRouter = mContext.getSystemService(MediaRouter.class));
         mDisplayService = mContext.getSystemService(DisplayManager.class);
@@ -244,7 +240,7 @@
         // Leave this task to {@link StatusBarKeyguardViewManager}
         if (displayId == DEFAULT_DISPLAY) return;
 
-        NavigationBarView navBarView = mNavigationBarControllerLazy.get()
+        NavigationBarView navBarView = Dependency.get(NavigationBarController.class)
                 .getNavigationBarView(displayId);
         // We may not have nav bar on a display.
         if (navBarView == null) return;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
index a0c5958..957882d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
@@ -42,7 +42,6 @@
     private final SecurityMode mSecurityMode;
     private final KeyguardSecurityCallback mKeyguardSecurityCallback;
     private final EmergencyButton mEmergencyButton;
-    private final EmergencyButtonController mEmergencyButtonController;
     private boolean mPaused;
 
 
@@ -70,18 +69,11 @@
     };
 
     protected KeyguardInputViewController(T view, SecurityMode securityMode,
-            KeyguardSecurityCallback keyguardSecurityCallback,
-            EmergencyButtonController emergencyButtonController) {
+            KeyguardSecurityCallback keyguardSecurityCallback) {
         super(view);
         mSecurityMode = securityMode;
         mKeyguardSecurityCallback = keyguardSecurityCallback;
         mEmergencyButton = view == null ? null : view.findViewById(R.id.emergency_call_button);
-        mEmergencyButtonController = emergencyButtonController;
-    }
-
-    @Override
-    protected void onInit() {
-        mEmergencyButtonController.init();
     }
 
     @Override
@@ -163,9 +155,8 @@
         private final InputMethodManager mInputMethodManager;
         private final DelayableExecutor mMainExecutor;
         private final Resources mResources;
-        private final LiftToActivateListener mLiftToActivateListener;
-        private final TelephonyManager mTelephonyManager;
-        private final EmergencyButtonController.Factory mEmergencyButtonControllerFactory;
+        private LiftToActivateListener mLiftToActivateListener;
+        private TelephonyManager mTelephonyManager;
         private final FalsingCollector mFalsingCollector;
         private final boolean mIsNewLayoutEnabled;
 
@@ -177,7 +168,6 @@
                 InputMethodManager inputMethodManager, @Main DelayableExecutor mainExecutor,
                 @Main Resources resources, LiftToActivateListener liftToActivateListener,
                 TelephonyManager telephonyManager,
-                EmergencyButtonController.Factory emergencyButtonControllerFactory,
                 FalsingCollector falsingCollector,
                 FeatureFlags featureFlags) {
             mKeyguardUpdateMonitor = keyguardUpdateMonitor;
@@ -189,7 +179,6 @@
             mResources = resources;
             mLiftToActivateListener = liftToActivateListener;
             mTelephonyManager = telephonyManager;
-            mEmergencyButtonControllerFactory = emergencyButtonControllerFactory;
             mFalsingCollector = falsingCollector;
             mIsNewLayoutEnabled = featureFlags.isKeyguardLayoutEnabled();
         }
@@ -197,40 +186,31 @@
         /** Create a new {@link KeyguardInputViewController}. */
         public KeyguardInputViewController create(KeyguardInputView keyguardInputView,
                 SecurityMode securityMode, KeyguardSecurityCallback keyguardSecurityCallback) {
-            EmergencyButtonController emergencyButtonController =
-                    mEmergencyButtonControllerFactory.create(
-                            keyguardInputView.findViewById(R.id.emergency_call_button));
-
             if (keyguardInputView instanceof KeyguardPatternView) {
                 return new KeyguardPatternViewController((KeyguardPatternView) keyguardInputView,
                         mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
-                        keyguardSecurityCallback, mLatencyTracker,
-                        emergencyButtonController,
-                        mMessageAreaControllerFactory);
+                        keyguardSecurityCallback, mLatencyTracker, mMessageAreaControllerFactory);
             } else if (keyguardInputView instanceof KeyguardPasswordView) {
                 return new KeyguardPasswordViewController((KeyguardPasswordView) keyguardInputView,
                         mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
                         keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
-                        mInputMethodManager, emergencyButtonController, mMainExecutor, mResources);
+                        mInputMethodManager, mMainExecutor, mResources);
             } else if (keyguardInputView instanceof KeyguardPINView) {
                 return new KeyguardPinViewController((KeyguardPINView) keyguardInputView,
                         mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
                         keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
-                        mLiftToActivateListener, emergencyButtonController, mFalsingCollector,
-                        mIsNewLayoutEnabled);
+                        mLiftToActivateListener, mFalsingCollector, mIsNewLayoutEnabled);
             } else if (keyguardInputView instanceof KeyguardSimPinView) {
                 return new KeyguardSimPinViewController((KeyguardSimPinView) keyguardInputView,
                         mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
                         keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
                         mLiftToActivateListener, mTelephonyManager,
-                        emergencyButtonController,
                         mFalsingCollector, mIsNewLayoutEnabled);
             } else if (keyguardInputView instanceof KeyguardSimPukView) {
                 return new KeyguardSimPukViewController((KeyguardSimPukView) keyguardInputView,
                         mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
                         keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
                         mLiftToActivateListener, mTelephonyManager,
-                        emergencyButtonController,
                         mFalsingCollector, mIsNewLayoutEnabled);
             }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index 92b65b2..533bec1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -136,14 +136,23 @@
 
     @Override
     public void startAppearAnimation() {
-        // Reset state, and let IME animation reveal the view as it slides in
+        // Reset state, and let IME animation reveal the view as it slides in, if one exists.
+        // It is possible for an IME to have no view, so provide a default animation since no
+        // calls to animateForIme would occur
         setAlpha(0f);
+        animate()
+            .alpha(1f)
+            .setDuration(500)
+            .setStartDelay(300)
+            .start();
+
         setTranslationY(0f);
     }
 
     @Override
     public void animateForIme(float interpolatedFraction) {
-        setAlpha(interpolatedFraction);
+        animate().cancel();
+        setAlpha(Math.max(interpolatedFraction, getAlpha()));
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
index 2e45545..0f1c3c8 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
@@ -111,11 +111,10 @@
             KeyguardMessageAreaController.Factory messageAreaControllerFactory,
             LatencyTracker latencyTracker,
             InputMethodManager inputMethodManager,
-            EmergencyButtonController emergencyButtonController,
             @Main DelayableExecutor mainExecutor,
             @Main Resources resources) {
         super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
-                messageAreaControllerFactory, latencyTracker, emergencyButtonController);
+                messageAreaControllerFactory, latencyTracker);
         mKeyguardSecurityCallback = keyguardSecurityCallback;
         mInputMethodManager = inputMethodManager;
         mMainExecutor = mainExecutor;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
index 55e348c..2aaf748 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
@@ -31,7 +31,7 @@
 import com.android.internal.widget.LockPatternView;
 import com.android.internal.widget.LockPatternView.Cell;
 import com.android.internal.widget.LockscreenCredential;
-import com.android.keyguard.EmergencyButtonController.EmergencyButtonCallback;
+import com.android.keyguard.EmergencyButton.EmergencyButtonCallback;
 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
@@ -50,7 +50,6 @@
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     private final LockPatternUtils mLockPatternUtils;
     private final LatencyTracker mLatencyTracker;
-    private final EmergencyButtonController mEmergencyButtonController;
     private final KeyguardMessageAreaController.Factory mMessageAreaControllerFactory;
 
     private KeyguardMessageAreaController mMessageAreaController;
@@ -180,13 +179,11 @@
             LockPatternUtils lockPatternUtils,
             KeyguardSecurityCallback keyguardSecurityCallback,
             LatencyTracker latencyTracker,
-            EmergencyButtonController emergencyButtonController,
             KeyguardMessageAreaController.Factory messageAreaControllerFactory) {
-        super(view, securityMode, keyguardSecurityCallback, emergencyButtonController);
+        super(view, securityMode, keyguardSecurityCallback);
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mLockPatternUtils = lockPatternUtils;
         mLatencyTracker = latencyTracker;
-        mEmergencyButtonController = emergencyButtonController;
         mMessageAreaControllerFactory = messageAreaControllerFactory;
         KeyguardMessageArea kma = KeyguardMessageArea.findSecurityMessageDisplay(mView);
         mMessageAreaController = mMessageAreaControllerFactory.create(kma);
@@ -208,7 +205,11 @@
                 KeyguardUpdateMonitor.getCurrentUser()));
         // vibrate mode will be the same for the life of this screen
         mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
-        mEmergencyButtonController.setEmergencyButtonCallback(mEmergencyButtonCallback);
+
+        EmergencyButton button = mView.findViewById(R.id.emergency_call_button);
+        if (button != null) {
+            button.setCallback(mEmergencyButtonCallback);
+        }
 
         View cancelBtn = mView.findViewById(R.id.cancel_button);
         if (cancelBtn != null) {
@@ -223,7 +224,10 @@
     protected void onViewDetached() {
         super.onViewDetached();
         mLockPatternView.setOnPatternListener(null);
-        mEmergencyButtonController.setEmergencyButtonCallback(null);
+        EmergencyButton button = mView.findViewById(R.id.emergency_call_button);
+        if (button != null) {
+            button.setCallback(null);
+        }
         View cancelBtn = mView.findViewById(R.id.cancel_button);
         if (cancelBtn != null) {
             cancelBtn.setOnClickListener(null);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
index 1b5aa45..f247948 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
@@ -71,10 +71,9 @@
             KeyguardMessageAreaController.Factory messageAreaControllerFactory,
             LatencyTracker latencyTracker,
             LiftToActivateListener liftToActivateListener,
-            EmergencyButtonController emergencyButtonController,
             FalsingCollector falsingCollector) {
         super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
-                messageAreaControllerFactory, latencyTracker, emergencyButtonController);
+                messageAreaControllerFactory, latencyTracker);
         mLiftToActivateListener = liftToActivateListener;
         mFalsingCollector = falsingCollector;
         mPasswordEntry = mView.findViewById(mView.getPasswordTextViewId());
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
index a456d42..49099fa 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
@@ -34,11 +34,10 @@
             KeyguardSecurityCallback keyguardSecurityCallback,
             KeyguardMessageAreaController.Factory messageAreaControllerFactory,
             LatencyTracker latencyTracker, LiftToActivateListener liftToActivateListener,
-            EmergencyButtonController emergencyButtonController,
             FalsingCollector falsingCollector, boolean isNewLayoutEnabled) {
         super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
                 messageAreaControllerFactory, latencyTracker, liftToActivateListener,
-                emergencyButtonController, falsingCollector);
+                falsingCollector);
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         view.setIsNewLayoutEnabled(isNewLayoutEnabled);
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
index bacd29f..c77c867 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
@@ -23,6 +23,7 @@
 import android.telephony.TelephonyManager;
 
 import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.Dependency;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 
@@ -48,27 +49,24 @@
     private final boolean mIsPukScreenAvailable;
 
     private final LockPatternUtils mLockPatternUtils;
-    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
 
     @Inject
-    KeyguardSecurityModel(@Main Resources resources, LockPatternUtils lockPatternUtils,
-            KeyguardUpdateMonitor keyguardUpdateMonitor) {
+    KeyguardSecurityModel(@Main Resources resources, LockPatternUtils lockPatternUtils) {
         mIsPukScreenAvailable = resources.getBoolean(
                 com.android.internal.R.bool.config_enable_puk_unlock_screen);
         mLockPatternUtils = lockPatternUtils;
-        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
     }
 
     public SecurityMode getSecurityMode(int userId) {
+        KeyguardUpdateMonitor monitor = Dependency.get(KeyguardUpdateMonitor.class);
+
         if (mIsPukScreenAvailable && SubscriptionManager.isValidSubscriptionId(
-                mKeyguardUpdateMonitor.getNextSubIdForState(
-                        TelephonyManager.SIM_STATE_PUK_REQUIRED))) {
+                monitor.getNextSubIdForState(TelephonyManager.SIM_STATE_PUK_REQUIRED))) {
             return SecurityMode.SimPuk;
         }
 
         if (SubscriptionManager.isValidSubscriptionId(
-                mKeyguardUpdateMonitor.getNextSubIdForState(
-                        TelephonyManager.SIM_STATE_PIN_REQUIRED))) {
+                monitor.getNextSubIdForState(TelephonyManager.SIM_STATE_PIN_REQUIRED))) {
             return SecurityMode.SimPin;
         }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java
index 33d47fe..f1b504e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java
@@ -44,18 +44,15 @@
     private final List<KeyguardInputViewController<KeyguardInputView>> mChildren =
             new ArrayList<>();
     private final LayoutInflater mLayoutInflater;
-    private final EmergencyButtonController.Factory mEmergencyButtonControllerFactory;
     private final Factory mKeyguardSecurityViewControllerFactory;
 
     @Inject
     protected KeyguardSecurityViewFlipperController(KeyguardSecurityViewFlipper view,
             LayoutInflater layoutInflater,
-            KeyguardInputViewController.Factory keyguardSecurityViewControllerFactory,
-            EmergencyButtonController.Factory emergencyButtonControllerFactory) {
+            KeyguardInputViewController.Factory keyguardSecurityViewControllerFactory) {
         super(view);
         mKeyguardSecurityViewControllerFactory = keyguardSecurityViewControllerFactory;
         mLayoutInflater = layoutInflater;
-        mEmergencyButtonControllerFactory = emergencyButtonControllerFactory;
     }
 
     @Override
@@ -114,8 +111,7 @@
 
         if (childController == null) {
             childController = new NullKeyguardInputViewController(
-                    securityMode, keyguardSecurityCallback,
-                    mEmergencyButtonControllerFactory.create(null));
+                    securityMode, keyguardSecurityCallback);
         }
 
         return childController;
@@ -144,9 +140,8 @@
     private static class NullKeyguardInputViewController
             extends KeyguardInputViewController<KeyguardInputView> {
         protected NullKeyguardInputViewController(SecurityMode securityMode,
-                KeyguardSecurityCallback keyguardSecurityCallback,
-                EmergencyButtonController emergencyButtonController) {
-            super(null, securityMode, keyguardSecurityCallback, emergencyButtonController);
+                KeyguardSecurityCallback keyguardSecurityCallback) {
+            super(null, securityMode, keyguardSecurityCallback);
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
index 4d2ebbb..cdbbfe6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
@@ -78,11 +78,11 @@
             KeyguardSecurityCallback keyguardSecurityCallback,
             KeyguardMessageAreaController.Factory messageAreaControllerFactory,
             LatencyTracker latencyTracker, LiftToActivateListener liftToActivateListener,
-            TelephonyManager telephonyManager, EmergencyButtonController emergencyButtonController,
+            TelephonyManager telephonyManager,
             FalsingCollector falsingCollector, boolean isNewLayoutEnabled) {
         super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
                 messageAreaControllerFactory, latencyTracker, liftToActivateListener,
-                emergencyButtonController, falsingCollector);
+                falsingCollector);
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mTelephonyManager = telephonyManager;
         mSimImageView = mView.findViewById(R.id.keyguard_sim);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java
index 0d9bb6f..8fff342 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java
@@ -37,6 +37,7 @@
 import com.android.internal.util.LatencyTracker;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.classifier.FalsingCollector;
 
@@ -84,11 +85,11 @@
             KeyguardSecurityCallback keyguardSecurityCallback,
             KeyguardMessageAreaController.Factory messageAreaControllerFactory,
             LatencyTracker latencyTracker, LiftToActivateListener liftToActivateListener,
-            TelephonyManager telephonyManager, EmergencyButtonController emergencyButtonController,
+            TelephonyManager telephonyManager,
             FalsingCollector falsingCollector, boolean isNewLayoutEnabled) {
         super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
                 messageAreaControllerFactory, latencyTracker, liftToActivateListener,
-                emergencyButtonController, falsingCollector);
+                falsingCollector);
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mTelephonyManager = telephonyManager;
         mSimImageView = mView.findViewById(R.id.keyguard_sim);
@@ -197,7 +198,8 @@
         if (count < 2) {
             msg = rez.getString(R.string.kg_puk_enter_puk_hint);
         } else {
-            SubscriptionInfo info = mKeyguardUpdateMonitor.getSubscriptionInfoForSubId(mSubId);
+            SubscriptionInfo info = Dependency.get(KeyguardUpdateMonitor.class)
+                    .getSubscriptionInfoForSubId(mSubId);
             CharSequence displayName = info != null ? info.getDisplayName() : "";
             msg = rez.getString(R.string.kg_puk_enter_puk_hint_multi, displayName);
             if (info != null) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index 1fbf71d..2373d75 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -49,8 +49,10 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.graphics.ColorUtils;
 import com.android.settingslib.Utils;
+import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.util.wakelock.KeepAwakeAnimationListener;
 
 import java.io.FileDescriptor;
@@ -83,10 +85,6 @@
      */
     private Runnable mContentChangeListener;
     private boolean mHasHeader;
-    private final int mRowWithHeaderPadding;
-    private final int mRowPadding;
-    private float mRowTextSize;
-    private float mRowWithHeaderTextSize;
     private View.OnClickListener mOnClickListener;
 
     private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
@@ -95,9 +93,6 @@
         super(context, attrs);
 
         Resources resources = context.getResources();
-        mRowPadding = resources.getDimensionPixelSize(R.dimen.subtitle_clock_padding);
-        mRowWithHeaderPadding = resources.getDimensionPixelSize(R.dimen.header_subtitle_padding);
-
         mLayoutTransition = new LayoutTransition();
         mLayoutTransition.setStagger(LayoutTransition.CHANGE_APPEARING, DEFAULT_ANIM_DURATION / 2);
         mLayoutTransition.setDuration(LayoutTransition.APPEARING, DEFAULT_ANIM_DURATION);
@@ -118,10 +113,6 @@
         mTextColor = Utils.getColorAttrDefaultColor(mContext, R.attr.wallpaperTextColor);
         mIconSize = (int) mContext.getResources().getDimension(R.dimen.widget_icon_size);
         mIconSizeWithHeader = (int) mContext.getResources().getDimension(R.dimen.header_icon_size);
-        mRowTextSize = mContext.getResources().getDimensionPixelSize(
-                R.dimen.widget_label_font_size);
-        mRowWithHeaderTextSize = mContext.getResources().getDimensionPixelSize(
-                R.dimen.header_row_font_size);
         mTitle.setBreakStrategy(LineBreaker.BREAK_STRATEGY_BALANCED);
     }
 
@@ -202,7 +193,6 @@
         LinearLayout.LayoutParams layoutParams = (LayoutParams) mRow.getLayoutParams();
         layoutParams.gravity = mLockScreenMode !=  KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL
                 ? Gravity.START :  Gravity.CENTER;
-        layoutParams.topMargin = mHasHeader ? mRowWithHeaderPadding : mRowPadding;
         mRow.setLayoutParams(layoutParams);
 
         for (int i = startIndex; i < subItemsCount; i++) {
@@ -228,8 +218,6 @@
             final SliceItem titleItem = rc.getTitleItem();
             button.setText(titleItem == null ? null : titleItem.getText());
             button.setContentDescription(rc.getContentDescription());
-            button.setTextSize(TypedValue.COMPLEX_UNIT_PX,
-                    mHasHeader ? mRowWithHeaderTextSize : mRowTextSize);
 
             Drawable iconDrawable = null;
             SliceItem icon = SliceQuery.find(item.getSlice(),
@@ -311,26 +299,6 @@
     void onDensityOrFontScaleChanged() {
         mIconSize = mContext.getResources().getDimensionPixelSize(R.dimen.widget_icon_size);
         mIconSizeWithHeader = (int) mContext.getResources().getDimension(R.dimen.header_icon_size);
-        mRowTextSize = mContext.getResources().getDimensionPixelSize(
-                R.dimen.widget_label_font_size);
-        mRowWithHeaderTextSize = mContext.getResources().getDimensionPixelSize(
-                R.dimen.header_row_font_size);
-
-        for (int i = 0; i < mRow.getChildCount(); i++) {
-            View child = mRow.getChildAt(i);
-            if (child instanceof KeyguardSliceTextView) {
-                ((KeyguardSliceTextView) child).onDensityOrFontScaleChanged();
-            }
-        }
-    }
-
-    void onOverlayChanged() {
-        for (int i = 0; i < mRow.getChildCount(); i++) {
-            View child = mRow.getChildAt(i);
-            if (child instanceof KeyguardSliceTextView) {
-                ((KeyguardSliceTextView) child).onOverlayChanged();
-            }
-        }
     }
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -493,7 +461,8 @@
      * Representation of an item that appears under the clock on main keyguard message.
      */
     @VisibleForTesting
-    static class KeyguardSliceTextView extends TextView {
+    static class KeyguardSliceTextView extends TextView implements
+            ConfigurationController.ConfigurationListener {
         private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
 
         @StyleRes
@@ -505,10 +474,24 @@
             setEllipsize(TruncateAt.END);
         }
 
+        @Override
+        protected void onAttachedToWindow() {
+            super.onAttachedToWindow();
+            Dependency.get(ConfigurationController.class).addCallback(this);
+        }
+
+        @Override
+        protected void onDetachedFromWindow() {
+            super.onDetachedFromWindow();
+            Dependency.get(ConfigurationController.class).removeCallback(this);
+        }
+
+        @Override
         public void onDensityOrFontScaleChanged() {
             updatePadding();
         }
 
+        @Override
         public void onOverlayChanged() {
             setTextAppearance(sStyleId);
         }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceViewController.java
index 8038ce4..1b0a7fa 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceViewController.java
@@ -83,10 +83,6 @@
         public void onDensityOrFontScaleChanged() {
             mView.onDensityOrFontScaleChanged();
         }
-        @Override
-        public void onOverlayChanged() {
-            mView.onOverlayChanged();
-        }
     };
 
     Observer<Slice> mObserver = new Observer<Slice>() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 5db4f9e..fea152a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -34,6 +34,7 @@
 import androidx.core.graphics.ColorUtils;
 
 import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.Dependency;
 import com.android.systemui.R;
 
 import java.io.FileDescriptor;
@@ -55,6 +56,7 @@
     private final IActivityManager mIActivityManager;
 
     private TextView mLogoutView;
+    private boolean mCanShowLogout = true; // by default, try to show the logout button here
     private KeyguardClockSwitch mClockView;
     private TextView mOwnerInfo;
     private boolean mCanShowOwnerInfo = true; // by default, try to show the owner information here
@@ -128,6 +130,11 @@
         }
     }
 
+    void setCanShowLogout(boolean canShowLogout) {
+        mCanShowLogout = canShowLogout;
+        updateLogoutView();
+    }
+
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
@@ -152,7 +159,10 @@
         mKeyguardSlice.setContentChangeListener(this::onSliceContentChanged);
         onSliceContentChanged();
 
+        boolean shouldMarquee = Dependency.get(KeyguardUpdateMonitor.class).isDeviceInteractive();
+        setEnableMarquee(shouldMarquee);
         updateOwnerInfo();
+        updateLogoutView();
         updateDark();
     }
 
@@ -199,11 +209,11 @@
         return mOwnerInfo.getVisibility() == VISIBLE ? mOwnerInfo.getHeight() : 0;
     }
 
-    void updateLogoutView(boolean shouldShowLogout) {
+    void updateLogoutView() {
         if (mLogoutView == null) {
             return;
         }
-        mLogoutView.setVisibility(shouldShowLogout ? VISIBLE : GONE);
+        mLogoutView.setVisibility(mCanShowLogout && shouldShowLogout() ? VISIBLE : GONE);
         // Logout button will stay in language of user 0 if we don't set that manually.
         mLogoutView.setText(mContext.getResources().getString(
                 com.android.internal.R.string.global_action_logout));
@@ -303,6 +313,11 @@
         }
     }
 
+    private boolean shouldShowLogout() {
+        return Dependency.get(KeyguardUpdateMonitor.class).isLogoutEnabled()
+                && KeyguardUpdateMonitor.getCurrentUser() != UserHandle.USER_SYSTEM;
+    }
+
     private void onLogoutClicked(View view) {
         int currentUserId = KeyguardUpdateMonitor.getCurrentUser();
         try {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index bfe7f8c7..934e768 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -16,7 +16,6 @@
 
 package com.android.keyguard;
 
-import android.os.UserHandle;
 import android.util.Slog;
 import android.view.View;
 
@@ -79,8 +78,6 @@
     @Override
     public void onInit() {
         mKeyguardClockSwitchController.init();
-        mView.setEnableMarquee(mKeyguardUpdateMonitor.isDeviceInteractive());
-        mView.updateLogoutView(shouldShowLogout());
     }
 
     @Override
@@ -248,11 +245,6 @@
         }
     }
 
-    private boolean shouldShowLogout() {
-        return mKeyguardUpdateMonitor.isLogoutEnabled()
-                && KeyguardUpdateMonitor.getCurrentUser() != UserHandle.USER_SYSTEM;
-    }
-
     private final ConfigurationController.ConfigurationListener mConfigurationListener =
             new ConfigurationController.ConfigurationListener() {
         @Override
@@ -274,17 +266,11 @@
             mKeyguardClockSwitchController.updateLockScreenMode(mode);
             mKeyguardSliceViewController.updateLockScreenMode(mode);
             if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) {
-                // align the top of keyguard_status_area with the top of the clock text instead
-                // of the top of the view
-                mKeyguardSliceViewController.updateTopMargin(
-                        mKeyguardClockSwitchController.getClockTextTopPadding());
                 mView.setCanShowOwnerInfo(false);
-                mView.updateLogoutView(false);
+                mView.setCanShowLogout(false);
             } else {
-                // reset margin
-                mKeyguardSliceViewController.updateTopMargin(0);
                 mView.setCanShowOwnerInfo(true);
-                mView.updateLogoutView(false);
+                mView.setCanShowLogout(false);
             }
             updateAodIcons();
         }
@@ -310,7 +296,7 @@
                 if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing);
                 refreshTime();
                 mView.updateOwnerInfo();
-                mView.updateLogoutView(shouldShowLogout());
+                mView.updateLogoutView();
             }
         }
 
@@ -328,12 +314,12 @@
         public void onUserSwitchComplete(int userId) {
             mKeyguardClockSwitchController.refreshFormat();
             mView.updateOwnerInfo();
-            mView.updateLogoutView(shouldShowLogout());
+            mView.updateLogoutView();
         }
 
         @Override
         public void onLogoutEnabledChanged() {
-            mView.updateLogoutView(shouldShowLogout());
+            mView.updateLogoutView();
         }
     };
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index d9a1eb6..a4054be 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -305,6 +305,7 @@
     private boolean mLogoutEnabled;
     // cached value to avoid IPCs
     private boolean mIsUdfpsEnrolled;
+    private boolean mKeyguardQsUserSwitchEnabled;
     // If the user long pressed the lock icon, disabling face auth for the current session.
     private boolean mLockIconPressed;
     private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -1916,7 +1917,7 @@
             return isFaceAuthEnabledForUser(KeyguardUpdateMonitor.getCurrentUser())
                     && !isUdfpsEnrolled();
         }
-        return true;
+        return !isKeyguardQsUserSwitchEnabled();
     }
 
     /**
@@ -1926,6 +1927,17 @@
         return mIsUdfpsEnrolled;
     }
 
+    /**
+     * @return true if the keyguard qs user switcher shortcut is enabled
+     */
+    public boolean isKeyguardQsUserSwitchEnabled() {
+        return mKeyguardQsUserSwitchEnabled;
+    }
+
+    public void setKeyguardQsUserSwitchEnabled(boolean enabled) {
+        mKeyguardQsUserSwitchEnabled = enabled;
+    }
+
     private final UserSwitchObserver mUserSwitchObserver = new UserSwitchObserver() {
         @Override
         public void onUserSwitching(int newUserId, IRemoteCallback reply) {
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java
index 8cb1bc4..5db3349 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java
@@ -69,7 +69,9 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent event) {
-        if (mAnimator != null) mAnimator.start();
+        if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+            if (mAnimator != null) mAnimator.start();
+        }
         return super.onTouchEvent(event);
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
index a4a781d..e6a9d4f 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
@@ -160,10 +160,9 @@
     public boolean onTouchEvent(MotionEvent event) {
         if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
             doHapticKeyClick();
+            if (mAnimator != null) mAnimator.start();
         }
 
-        if (mAnimator != null) mAnimator.start();
-
         return super.onTouchEvent(event);
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockOptionsProvider.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockOptionsProvider.java
index b6413cb..5ef35be 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockOptionsProvider.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockOptionsProvider.java
@@ -28,12 +28,11 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.Dependency;
 
 import java.io.FileNotFoundException;
 import java.util.List;
-
-import javax.inject.Inject;
-import javax.inject.Provider;
+import java.util.function.Supplier;
 
 /**
  * Exposes custom clock face options and provides realistic preview images.
@@ -66,12 +65,15 @@
     private static final String CONTENT_SCHEME = "content";
     private static final String AUTHORITY = "com.android.keyguard.clock";
 
-    @Inject
-    public Provider<List<ClockInfo>> mClockInfosProvider;
+    private final Supplier<List<ClockInfo>> mClocksSupplier;
+
+    public ClockOptionsProvider() {
+        this(() -> Dependency.get(ClockManager.class).getClockInfos());
+    }
 
     @VisibleForTesting
-    ClockOptionsProvider(Provider<List<ClockInfo>> clockInfosProvider) {
-        mClockInfosProvider = clockInfosProvider;
+    ClockOptionsProvider(Supplier<List<ClockInfo>> clocksSupplier) {
+        mClocksSupplier = clocksSupplier;
     }
 
     @Override
@@ -97,7 +99,7 @@
         }
         MatrixCursor cursor = new MatrixCursor(new String[] {
                 COLUMN_NAME, COLUMN_TITLE, COLUMN_ID, COLUMN_THUMBNAIL, COLUMN_PREVIEW});
-        List<ClockInfo> clocks = mClockInfosProvider.get();
+        List<ClockInfo> clocks = mClocksSupplier.get();
         for (int i = 0; i < clocks.size(); i++) {
             ClockInfo clock = clocks.get(i);
             cursor.newRow()
@@ -137,7 +139,7 @@
             throw new FileNotFoundException("Invalid preview url, missing id");
         }
         ClockInfo clock = null;
-        List<ClockInfo> clocks = mClockInfosProvider.get();
+        List<ClockInfo> clocks = mClocksSupplier.get();
         for (int i = 0; i < clocks.size(); i++) {
             if (id.equals(clocks.get(i).getId())) {
                 clock = clocks.get(i);
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewComponent.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewComponent.java
deleted file mode 100644
index 49a617e..0000000
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewComponent.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.keyguard.dagger;
-
-import com.android.keyguard.KeyguardStatusViewController;
-import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
-import com.android.systemui.statusbar.phone.KeyguardStatusBarViewController;
-
-import dagger.BindsInstance;
-import dagger.Subcomponent;
-
-/**
- * Subcomponent for helping work with KeyguardStatusView and its children.
- *
- * TODO: unify this with {@link KeyguardStatusViewComponent}
- */
-@Subcomponent(modules = {KeyguardStatusBarViewModule.class})
-@KeyguardStatusBarViewScope
-public interface KeyguardStatusBarViewComponent {
-    /** Simple factory for {@link KeyguardStatusBarViewComponent}. */
-    @Subcomponent.Factory
-    interface Factory {
-        KeyguardStatusBarViewComponent build(@BindsInstance KeyguardStatusBarView view);
-    }
-
-    /** Builds a {@link KeyguardStatusViewController}. */
-    KeyguardStatusBarViewController getKeyguardStatusBarViewController();
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewModule.java
deleted file mode 100644
index a672523..0000000
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewModule.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.keyguard.dagger;
-
-import com.android.keyguard.CarrierText;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
-
-import dagger.Module;
-import dagger.Provides;
-
-/** Dagger module for {@link KeyguardStatusBarViewComponent}. */
-@Module
-public abstract class KeyguardStatusBarViewModule {
-    @Provides
-    @KeyguardStatusBarViewScope
-    static CarrierText getCarrierText(KeyguardStatusBarView view) {
-        return view.findViewById(R.id.keyguard_carrier_text);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewScope.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewScope.java
deleted file mode 100644
index ba0642f..0000000
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewScope.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.keyguard.dagger;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Scope;
-
-/**
- * Scope annotation for singleton items within the StatusBarComponent.
- */
-@Documented
-@Retention(RUNTIME)
-@Scope
-public @interface KeyguardStatusBarViewScope {}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewComponent.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewComponent.java
index d342377..1b6476c 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewComponent.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewComponent.java
@@ -25,8 +25,6 @@
 
 /**
  * Subcomponent for helping work with KeyguardStatusView and its children.
- *
- * TODO: unify this with {@link KeyguardStatusBarViewComponent}
  */
 @Subcomponent(modules = {KeyguardStatusViewModule.class})
 @KeyguardStatusViewScope
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 71ec33e..a9b4c49 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -16,7 +16,10 @@
 
 package com.android.systemui;
 
+import android.app.WallpaperColors;
+import android.graphics.Bitmap;
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.SystemClock;
@@ -26,13 +29,16 @@
 import android.util.Size;
 import android.view.SurfaceHolder;
 
+import androidx.annotation.NonNull;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.glwallpaper.EglHelper;
-import com.android.systemui.glwallpaper.GLWallpaperRenderer;
 import com.android.systemui.glwallpaper.ImageWallpaperRenderer;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
 
 import javax.inject.Inject;
 
@@ -45,8 +51,13 @@
     // We delayed destroy render context that subsequent render requests have chance to cancel it.
     // This is to avoid destroying then recreating render context in a very short time.
     private static final int DELAY_FINISH_RENDERING = 1000;
+    private static final @android.annotation.NonNull RectF LOCAL_COLOR_BOUNDS =
+            new RectF(0, 0, 1, 1);
     private static final boolean DEBUG = false;
+    private ArrayList<RectF> mLocalColorsToAdd = new ArrayList<>();
     private HandlerThread mWorker;
+    // scaled down version
+    private Bitmap mMiniBitmap;
 
     @Inject
     public ImageWallpaper() {
@@ -70,6 +81,7 @@
         super.onDestroy();
         mWorker.quitSafely();
         mWorker = null;
+        mMiniBitmap = null;
     }
 
     class GLEngine extends Engine {
@@ -80,7 +92,7 @@
         @VisibleForTesting
         static final int MIN_SURFACE_HEIGHT = 64;
 
-        private GLWallpaperRenderer mRenderer;
+        private ImageWallpaperRenderer mRenderer;
         private EglHelper mEglHelper;
         private final Runnable mFinishRenderingTask = this::finishRendering;
         private boolean mNeedRedraw;
@@ -101,6 +113,10 @@
             setFixedSizeAllowed(true);
             setOffsetNotificationsEnabled(false);
             updateSurfaceSize();
+            mMiniBitmap = null;
+            if (mWorker != null && mWorker.getThreadHandler() != null) {
+                mWorker.getThreadHandler().post(this::updateMiniBitmap);
+            }
         }
 
         EglHelper getEglHelperInstance() {
@@ -111,6 +127,20 @@
             return new ImageWallpaperRenderer(getDisplayContext());
         }
 
+        private void updateMiniBitmap() {
+            mRenderer.useBitmap(b -> {
+                int size = Math.min(b.getWidth(), b.getHeight());
+                float scale = 1.0f;
+                if (size > MIN_SURFACE_WIDTH) {
+                    scale = (float) MIN_SURFACE_WIDTH / (float) size;
+                }
+                mMiniBitmap = Bitmap.createScaledBitmap(b, Math.round(scale * b.getWidth()),
+                        Math.round(scale * b.getHeight()), false);
+                computeAndNotifyLocalColors(mLocalColorsToAdd, mMiniBitmap);
+                mLocalColorsToAdd.clear();
+            });
+        }
+
         private void updateSurfaceSize() {
             SurfaceHolder holder = getSurfaceHolder();
             Size frameSize = mRenderer.reportSurfaceSize();
@@ -126,6 +156,7 @@
 
         @Override
         public void onDestroy() {
+            mMiniBitmap = null;
             mWorker.getThreadHandler().post(() -> {
                 mRenderer.finish();
                 mRenderer = null;
@@ -135,6 +166,59 @@
         }
 
         @Override
+        public boolean supportsLocalColorExtraction() {
+            return true;
+        }
+
+        @Override
+        public void addLocalColorsAreas(@NonNull List<RectF> regions) {
+            mWorker.getThreadHandler().post(() -> {
+                Bitmap bitmap = mMiniBitmap;
+                if (bitmap == null) {
+                    mLocalColorsToAdd.addAll(regions);
+                } else {
+                    computeAndNotifyLocalColors(regions, bitmap);
+                }
+            });
+        }
+
+        private void computeAndNotifyLocalColors(@NonNull List<RectF> regions, Bitmap b) {
+            List<WallpaperColors> colors = getLocalWallpaperColors(regions, b);
+            try {
+                notifyLocalColorsChanged(regions, colors);
+            } catch (RuntimeException e) {
+                Log.e(TAG, e.getMessage(), e);
+            }
+        }
+
+        @Override
+        public void removeLocalColorsAreas(@NonNull List<RectF> regions) {
+            // No-OP
+        }
+
+        private List<WallpaperColors> getLocalWallpaperColors(@NonNull List<RectF> areas,
+                Bitmap b) {
+            List<WallpaperColors> colors = new ArrayList<>(areas.size());
+            for (int i = 0; i < areas.size(); i++) {
+                RectF area = areas.get(i);
+                if (area == null || !LOCAL_COLOR_BOUNDS.contains(area)) {
+                    colors.add(null);
+                    continue;
+                }
+                Rect subImage = new Rect(
+                        Math.round(area.left * b.getWidth()),
+                        Math.round(area.top * b.getHeight()),
+                        Math.round(area.right * b.getWidth()),
+                        Math.round(area.bottom * b.getHeight()));
+                Bitmap colorImg = Bitmap.createBitmap(b,
+                        subImage.left, subImage.top, subImage.width(), subImage.height());
+                WallpaperColors color = WallpaperColors.fromBitmap(colorImg);
+                colors.add(color);
+            }
+            return colors;
+        }
+
+        @Override
         public void onSurfaceCreated(SurfaceHolder holder) {
             if (mWorker == null) return;
             mWorker.getThreadHandler().post(() -> {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 19520df..9d00262 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -115,7 +115,8 @@
                     .setShellCommandHandler(mWMComponent.getShellCommandHandler())
                     .setAppPairs(mWMComponent.getAppPairs())
                     .setTaskViewFactory(mWMComponent.getTaskViewFactory())
-                    .setTransitions(mWMComponent.getTransitions());
+                    .setTransitions(mWMComponent.getTransitions())
+                    .setStartingSurface(mWMComponent.getStartingSurface());
         } else {
             // TODO: Call on prepareSysUIComponentBuilder but not with real components. Other option
             // is separating this logic into newly creating SystemUITestsFactory.
@@ -129,7 +130,8 @@
                     .setShellCommandHandler(Optional.ofNullable(null))
                     .setAppPairs(Optional.ofNullable(null))
                     .setTaskViewFactory(Optional.ofNullable(null))
-                    .setTransitions(Transitions.createEmptyForTesting());
+                    .setTransitions(Transitions.createEmptyForTesting())
+                    .setStartingSurface(Optional.ofNullable(null));
         }
         mSysUIComponent = builder.build();
         if (initializeComponents) {
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index d8ca639..2040347 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -16,8 +16,8 @@
 
 package com.android.systemui.appops;
 
-import static android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_CAMERA;
-import static android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE;
+import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
+import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
 import static android.media.AudioManager.ACTION_MICROPHONE_MUTE_CHANGED;
 
 import android.Manifest;
@@ -40,6 +40,7 @@
 
 import androidx.annotation.WorkerThread;
 
+import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.Dumpable;
@@ -78,6 +79,7 @@
     private static final boolean DEBUG = false;
 
     private final BroadcastDispatcher mDispatcher;
+    private final Context mContext;
     private final AppOpsManager mAppOps;
     private final AudioManager mAudioManager;
     private final LocationManager mLocationManager;
@@ -137,10 +139,11 @@
         mAudioManager = audioManager;
         mSensorPrivacyController = sensorPrivacyController;
         mMicMuted = audioManager.isMicrophoneMute()
-                || mSensorPrivacyController.isSensorBlocked(INDIVIDUAL_SENSOR_MICROPHONE);
-        mCameraDisabled = mSensorPrivacyController.isSensorBlocked(INDIVIDUAL_SENSOR_CAMERA);
+                || mSensorPrivacyController.isSensorBlocked(MICROPHONE);
+        mCameraDisabled = mSensorPrivacyController.isSensorBlocked(CAMERA);
         mLocationManager = context.getSystemService(LocationManager.class);
         mPackageManager = context.getPackageManager();
+        mContext = context;
         dumpManager.registerDumpable(TAG, this);
     }
 
@@ -159,8 +162,8 @@
             mSensorPrivacyController.addCallback(this);
 
             mMicMuted = mAudioManager.isMicrophoneMute()
-                    || mSensorPrivacyController.isSensorBlocked(INDIVIDUAL_SENSOR_MICROPHONE);
-            mCameraDisabled = mSensorPrivacyController.isSensorBlocked(INDIVIDUAL_SENSOR_CAMERA);
+                    || mSensorPrivacyController.isSensorBlocked(MICROPHONE);
+            mCameraDisabled = mSensorPrivacyController.isSensorBlocked(CAMERA);
 
             mBGHandler.post(() -> mAudioRecordingCallback.onRecordingConfigChanged(
                     mAudioManager.getActiveRecordingConfigurations()));
@@ -357,6 +360,15 @@
         return mLocationProviderPackages.contains(packageName);
     }
 
+    private boolean isSpeechRecognizerUsage(int opCode, String packageName) {
+        if (AppOpsManager.OP_RECORD_AUDIO != opCode) {
+            return false;
+        }
+
+        return packageName.equals(
+                mContext.getString(R.string.config_systemSpeechRecognizer));
+    }
+
     // TODO ntmyren: remove after teamfood is finished
     private boolean shouldShowAppPredictor(String pkgName) {
         if (!DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, "permissions_hub_2_enabled",
@@ -388,7 +400,8 @@
         }
         // TODO ntmyren: Replace this with more robust check if this moves beyond teamfood
         if ((appOpCode == AppOpsManager.OP_CAMERA && isLocationProvider(packageName))
-                || shouldShowAppPredictor(packageName)) {
+                || shouldShowAppPredictor(packageName)
+                || isSpeechRecognizerUsage(appOpCode, packageName)) {
             return true;
         }
 
@@ -473,7 +486,8 @@
 
     @Override
     public void onOpNoted(int code, int uid, String packageName,
-            @AppOpsManager.OpFlags int flags, @AppOpsManager.Mode int result) {
+            String attributionTag, @AppOpsManager.OpFlags int flags,
+            @AppOpsManager.Mode int result) {
         if (DEBUG) {
             Log.w(TAG, "Noted op: " + code + " with result "
                     + AppOpsManager.MODE_NAMES[result] + " for package " + packageName);
@@ -582,16 +596,16 @@
     @Override
     public void onReceive(Context context, Intent intent) {
         mMicMuted = mAudioManager.isMicrophoneMute()
-                || mSensorPrivacyController.isSensorBlocked(INDIVIDUAL_SENSOR_MICROPHONE);
+                || mSensorPrivacyController.isSensorBlocked(MICROPHONE);
         updateSensorDisabledStatus();
     }
 
     @Override
     public void onSensorBlockedChanged(int sensor, boolean blocked) {
         mBGHandler.post(() -> {
-            if (sensor == INDIVIDUAL_SENSOR_CAMERA) {
+            if (sensor == CAMERA) {
                 mCameraDisabled = blocked;
-            } else if (sensor == INDIVIDUAL_SENSOR_MICROPHONE) {
+            } else if (sensor == MICROPHONE) {
                 mMicMuted = mAudioManager.isMicrophoneMute() || blocked;
             }
             updateSensorDisabledStatus();
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java
index 3ea8140..3bf75d1 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java
@@ -19,8 +19,10 @@
 import android.content.Context;
 import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
+import android.view.View;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import com.android.systemui.R;
 
@@ -33,6 +35,7 @@
 
     @NonNull protected final Context mContext;
     @NonNull protected final Drawable mFingerprintDrawable;
+    @Nullable private View mView;
 
     public UdfpsAnimation(@NonNull Context context) {
         mContext = context;
@@ -53,6 +56,10 @@
         mFingerprintDrawable.setAlpha(alpha);
     }
 
+    public void setAnimationView(UdfpsAnimationView view) {
+        mView = view;
+    }
+
     /**
      * @return The amount of padding that's needed on each side of the sensor, in pixels.
      */
@@ -66,4 +73,10 @@
     public int getPaddingY() {
         return 0;
     }
+
+    protected void postInvalidateView() {
+        if (mView != null) {
+            mView.postInvalidate();
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationKeyguard.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationKeyguard.java
index 501de9d..8664e44 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationKeyguard.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationKeyguard.java
@@ -23,7 +23,6 @@
 import android.graphics.Color;
 import android.graphics.ColorFilter;
 import android.util.MathUtils;
-import android.view.View;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -42,7 +41,6 @@
 
     private static final String TAG = "UdfpsAnimationKeyguard";
 
-    @NonNull private final View mParent;
     @NonNull private final Context mContext;
     private final int mMaxBurnInOffsetX;
     private final int mMaxBurnInOffsetY;
@@ -52,10 +50,9 @@
     private float mBurnInOffsetX;
     private float mBurnInOffsetY;
 
-    UdfpsAnimationKeyguard(@NonNull View parent, @NonNull Context context,
+    UdfpsAnimationKeyguard(@NonNull Context context,
             @NonNull StatusBarStateController statusBarStateController) {
         super(context);
-        mParent = parent;
         mContext = context;
 
         mMaxBurnInOffsetX = context.getResources()
@@ -73,10 +70,10 @@
                 mInterpolatedDarkAmount);
         mBurnInOffsetY = MathUtils.lerp(0f,
                 getBurnInOffset(mMaxBurnInOffsetY * 2, false /* xAxis */)
-                        - 0.5f * mMaxBurnInOffsetY,
+                        - mMaxBurnInOffsetY,
                 mInterpolatedDarkAmount);
         updateColor();
-        mParent.postInvalidate();
+        postInvalidateView();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationView.java
index 41ea4d6..44122cb 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationView.java
@@ -74,7 +74,14 @@
     }
 
     void setAnimation(@Nullable UdfpsAnimation animation) {
+        if (mUdfpsAnimation != null) {
+            mUdfpsAnimation.setAnimationView(null);
+        }
+
         mUdfpsAnimation = animation;
+        if (mUdfpsAnimation != null) {
+            mUdfpsAnimation.setAnimationView(this);
+        }
     }
 
     void onSensorRectUpdated(@NonNull RectF sensorRect) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index e7b08e7..71fba33 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -44,7 +44,6 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.doze.DozeReceiver;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 
@@ -69,6 +68,7 @@
 
     private final Context mContext;
     private final FingerprintManager mFingerprintManager;
+    @NonNull private final LayoutInflater mInflater;
     private final WindowManager mWindowManager;
     private final DelayableExecutor mFgExecutor;
     private final StatusBarStateController mStatusBarStateController;
@@ -76,10 +76,8 @@
     // sensors, this, in addition to a lot of the code here, will be updated.
     @VisibleForTesting final FingerprintSensorPropertiesInternal mSensorProps;
     private final WindowManager.LayoutParams mCoreLayoutParams;
-    private final UdfpsView mView;
-    // Indicates whether the overlay is currently showing. Even if it has been requested, it might
-    // not be showing.
-    private boolean mIsOverlayShowing;
+
+    @Nullable private UdfpsView mView;
     // Indicates whether the overlay has been requested.
     private boolean mIsOverlayRequested;
     // Reason the overlay has been requested. See IUdfpsOverlayController for definitions.
@@ -112,20 +110,48 @@
 
         @Override
         public void onEnrollmentProgress(int sensorId, int remaining) {
+            if (mView == null) {
+                return;
+            }
             mView.onEnrollmentProgress(remaining);
         }
 
         @Override
         public void onEnrollmentHelp(int sensorId) {
+            if (mView == null) {
+                return;
+            }
             mView.onEnrollmentHelp();
         }
 
         @Override
         public void setDebugMessage(int sensorId, String message) {
+            if (mView == null) {
+                return;
+            }
             mView.setDebugMessage(message);
         }
     }
 
+    @VisibleForTesting
+    final StatusBar.ExpansionChangedListener mStatusBarExpansionListener =
+            (expansion, expanded) -> {
+                if (mView != null) {
+                    mView.onExpansionChanged(expansion, expanded);
+                }
+    };
+
+    @VisibleForTesting
+    final StatusBarStateController.StateListener mStatusBarStateListener =
+            new StatusBarStateController.StateListener() {
+                @Override
+                public void onStateChanged(int newState) {
+                    if (mView != null) {
+                        mView.onStateChanged(newState);
+                    }
+                }
+    };
+
     @SuppressLint("ClickableViewAccessibility")
     private final UdfpsView.OnTouchListener mOnTouchListener = (v, event) -> {
         UdfpsView view = (UdfpsView) v;
@@ -158,13 +184,14 @@
     @Inject
     public UdfpsController(@NonNull Context context,
             @Main Resources resources,
-            LayoutInflater inflater,
+            @NonNull LayoutInflater inflater,
             @Nullable FingerprintManager fingerprintManager,
             WindowManager windowManager,
             @NonNull StatusBarStateController statusBarStateController,
             @Main DelayableExecutor fgExecutor,
             @Nullable StatusBar statusBar) {
         mContext = context;
+        mInflater = inflater;
         // The fingerprint manager is queried for UDFPS before this class is constructed, so the
         // fingerprint manager should never be null.
         mFingerprintManager = checkNotNull(fingerprintManager);
@@ -190,15 +217,10 @@
                 WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
         mCoreLayoutParams.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
 
-        mView = (UdfpsView) inflater.inflate(R.layout.udfps_view, null, false);
-        mView.setSensorProperties(mSensorProps);
-        mView.setHbmCallback(this);
-
-        statusBar.addExpansionChangedListener(mView);
-        statusBarStateController.addCallback(mView);
+        statusBar.addExpansionChangedListener(mStatusBarExpansionListener);
+        mStatusBarStateController.addCallback(mStatusBarStateListener);
 
         mFingerprintManager.setUdfpsOverlayController(new UdfpsOverlayController());
-        mIsOverlayShowing = false;
     }
 
     @Nullable
@@ -221,7 +243,13 @@
      * @return where the UDFPS exists on the screen in pixels.
      */
     public RectF getSensorLocation() {
-        return mView.getSensorRect();
+        // This is currently used to calculate the amount of space available for notifications
+        // on lockscreen. Keyguard is only shown in portrait mode for now, so this will need to
+        // be updated if that ever changes.
+        return new RectF(mSensorProps.sensorLocationX - mSensorProps.sensorRadius,
+                mSensorProps.sensorLocationY - mSensorProps.sensorRadius,
+                mSensorProps.sensorLocationX + mSensorProps.sensorRadius,
+                mSensorProps.sensorLocationY + mSensorProps.sensorRadius);
     }
 
     private void showOverlay(int reason) {
@@ -299,14 +327,18 @@
 
     private void showUdfpsOverlay(int reason) {
         mFgExecutor.execute(() -> {
-            if (!mIsOverlayShowing) {
+            if (mView == null) {
                 try {
                     Log.v(TAG, "showUdfpsOverlay | adding window");
+
+                    mView = (UdfpsView) mInflater.inflate(R.layout.udfps_view, null, false);
+                    mView.setSensorProperties(mSensorProps);
+                    mView.setHbmCallback(this);
+
                     final UdfpsAnimation animation = getUdfpsAnimationForReason(reason);
                     mView.setExtras(animation, mEnrollHelper);
                     mWindowManager.addView(mView, computeLayoutParams(animation));
                     mView.setOnTouchListener(mOnTouchListener);
-                    mIsOverlayShowing = true;
                 } catch (RuntimeException e) {
                     Log.e(TAG, "showUdfpsOverlay | failed to add window", e);
                 }
@@ -324,7 +356,7 @@
             case IUdfpsOverlayController.REASON_ENROLL_ENROLLING:
                 return new UdfpsAnimationEnroll(mContext);
             case IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD:
-                return new UdfpsAnimationKeyguard(mView, mContext, mStatusBarStateController);
+                return new UdfpsAnimationKeyguard(mContext, mStatusBarStateController);
             case IUdfpsOverlayController.REASON_AUTH_FPM_OTHER:
                 return new UdfpsAnimationFpmOther(mContext);
             default:
@@ -335,14 +367,12 @@
 
     private void hideUdfpsOverlay() {
         mFgExecutor.execute(() -> {
-            if (mIsOverlayShowing) {
+            if (mView != null) {
                 Log.v(TAG, "hideUdfpsOverlay | removing window");
-                mView.setExtras(null, null);
-                mView.setOnTouchListener(null);
                 // Reset the controller back to its starting state.
                 onFingerUp();
                 mWindowManager.removeView(mView);
-                mIsOverlayShowing = false;
+                mView = null;
             } else {
                 Log.v(TAG, "hideUdfpsOverlay | the overlay is already hidden");
             }
@@ -389,12 +419,20 @@
 
     // This method can be called from the UI thread.
     private void onFingerDown(int x, int y, float minor, float major) {
+        if (mView == null) {
+            Log.w(TAG, "Null view in onFingerDown");
+            return;
+        }
         mView.startIllumination(() ->
                 mFingerprintManager.onPointerDown(mSensorProps.sensorId, x, y, minor, major));
     }
 
     // This method can be called from the UI thread.
     private void onFingerUp() {
+        if (mView == null) {
+            Log.w(TAG, "Null view in onFingerUp");
+            return;
+        }
         mFingerprintManager.onPointerUp(mSensorProps.sensorId);
         mView.stopIllumination();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
index 00cb28b..3997943 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
@@ -113,6 +113,7 @@
 
     void setExtras(@Nullable UdfpsAnimation animation, @Nullable UdfpsEnrollHelper enrollHelper) {
         mAnimationView.setAnimation(animation);
+
         mEnrollHelper = enrollHelper;
 
         if (enrollHelper != null) {
@@ -135,17 +136,13 @@
     }
 
     @Override
-    public void onExpandedChanged(boolean isExpanded) {
-        mNotificationShadeExpanded = isExpanded;
-    }
-
-    @Override
     public void onStateChanged(int newState) {
         mStatusBarState = newState;
     }
 
     @Override
     public void onExpansionChanged(float expansion, boolean expanded) {
+        mNotificationShadeExpanded = expanded;
         mAnimationView.onExpansionChanged(expansion, expanded);
     }
 
@@ -191,10 +188,6 @@
         }
     }
 
-    RectF getSensorRect() {
-        return new RectF(mSensorRect);
-    }
-
     void setDebugMessage(String message) {
         mDebugMessage = message;
         postInvalidate();
diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
index 36937d6..6b7a1ac 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
@@ -91,7 +91,7 @@
     }
 
     /**
-     * @return true if controls are feature-enabled and have available services to serve controls
+     * @return true if controls are feature-enabled and the user has the setting enabled
      */
     fun isEnabled() = featureEnabled && lazyControlsController.get().available
 
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsAnimations.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsAnimations.kt
index cad166d..1ea1d97 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsAnimations.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsAnimations.kt
@@ -41,7 +41,7 @@
 
 object ControlsAnimations {
 
-    private const val ALPHA_EXIT_DURATION = 167L
+    private const val ALPHA_EXIT_DURATION = 183L
     private const val ALPHA_ENTER_DELAY = ALPHA_EXIT_DURATION
     private const val ALPHA_ENTER_DURATION = 350L - ALPHA_ENTER_DELAY
 
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
index 40c2386..fc89783 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
@@ -32,6 +32,8 @@
 import com.android.systemui.controls.CustomIconCache
 import com.android.systemui.controls.controller.ControlsControllerImpl
 import com.android.systemui.controls.controller.StructureInfo
+import com.android.systemui.controls.ui.ControlsDialog
+import com.android.systemui.controls.ui.ControlsUiController
 import com.android.systemui.globalactions.GlobalActionsComponent
 import com.android.systemui.settings.CurrentUserTracker
 import com.android.systemui.util.LifecycleActivity
@@ -42,9 +44,10 @@
  */
 class ControlsEditingActivity @Inject constructor(
     private val controller: ControlsControllerImpl,
-    broadcastDispatcher: BroadcastDispatcher,
+    private val broadcastDispatcher: BroadcastDispatcher,
     private val globalActionsComponent: GlobalActionsComponent,
-    private val customIconCache: CustomIconCache
+    private val customIconCache: CustomIconCache,
+    private val uiController: ControlsUiController
 ) : LifecycleActivity() {
 
     companion object {
@@ -59,6 +62,7 @@
     private lateinit var model: FavoritesModel
     private lateinit var subtitle: TextView
     private lateinit var saveButton: View
+    private var backToGlobalActions = true
 
     private val currentUserTracker = object : CurrentUserTracker(broadcastDispatcher) {
         private val startingUser = controller.currentUserId
@@ -82,6 +86,11 @@
             structure = it
         } ?: run(this::finish)
 
+        backToGlobalActions = intent.getBooleanExtra(
+            ControlsUiController.BACK_TO_GLOBAL_ACTIONS,
+            true
+        )
+
         bindViews()
 
         bindButtons()
@@ -100,7 +109,11 @@
     }
 
     override fun onBackPressed() {
-        globalActionsComponent.handleShowGlobalActionsMenu()
+        if (backToGlobalActions) {
+            globalActionsComponent.handleShowGlobalActionsMenu()
+        } else {
+            ControlsDialog(applicationContext, broadcastDispatcher).show(uiController)
+        }
         animateExitAndFinish()
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
index b282157..2d647a9 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
@@ -40,6 +40,8 @@
 import com.android.systemui.controls.TooltipManager
 import com.android.systemui.controls.controller.ControlsControllerImpl
 import com.android.systemui.controls.controller.StructureInfo
+import com.android.systemui.controls.ui.ControlsDialog
+import com.android.systemui.controls.ui.ControlsUiController
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.globalactions.GlobalActionsComponent
 import com.android.systemui.settings.CurrentUserTracker
@@ -53,8 +55,9 @@
     @Main private val executor: Executor,
     private val controller: ControlsControllerImpl,
     private val listingController: ControlsListingController,
-    broadcastDispatcher: BroadcastDispatcher,
-    private val globalActionsComponent: GlobalActionsComponent
+    private val broadcastDispatcher: BroadcastDispatcher,
+    private val globalActionsComponent: GlobalActionsComponent,
+    private val uiController: ControlsUiController
 ) : LifecycleActivity() {
 
     companion object {
@@ -89,6 +92,7 @@
     private lateinit var comparator: Comparator<StructureContainer>
     private var cancelLoadRunnable: Runnable? = null
     private var isPagerLoaded = false
+    private var backToGlobalActions = true
 
     private val currentUserTracker = object : CurrentUserTracker(broadcastDispatcher) {
         private val startingUser = controller.currentUserId
@@ -114,7 +118,7 @@
 
     override fun onBackPressed() {
         if (!fromProviderSelector) {
-            globalActionsComponent.handleShowGlobalActionsMenu()
+            openControlsOrigin()
         }
         animateExitAndFinish()
     }
@@ -129,6 +133,11 @@
         component = intent.getParcelableExtra<ComponentName>(Intent.EXTRA_COMPONENT_NAME)
         fromProviderSelector = intent.getBooleanExtra(EXTRA_FROM_PROVIDER_SELECTOR, false)
 
+        backToGlobalActions = intent.getBooleanExtra(
+            ControlsUiController.BACK_TO_GLOBAL_ACTIONS,
+            true
+        )
+
         bindViews()
     }
 
@@ -304,6 +313,10 @@
             setOnClickListener {
                 val i = Intent().apply {
                     component = ComponentName(context, ControlsProviderSelectorActivity::class.java)
+                    putExtra(
+                        ControlsUiController.BACK_TO_GLOBAL_ACTIONS,
+                        backToGlobalActions
+                    )
                 }
                 if (doneButton.isEnabled) {
                     // The user has made changes
@@ -330,11 +343,19 @@
                     )
                 }
                 animateExitAndFinish()
-                globalActionsComponent.handleShowGlobalActionsMenu()
+                openControlsOrigin()
             }
         }
     }
 
+    private fun openControlsOrigin() {
+        if (backToGlobalActions) {
+            globalActionsComponent.handleShowGlobalActionsMenu()
+        } else {
+            ControlsDialog(applicationContext, broadcastDispatcher).show(uiController)
+        }
+    }
+
     override fun onPause() {
         super.onPause()
         mTooltipManager?.hide(false)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
index 0814774..d5e41d0 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
@@ -32,6 +32,8 @@
 import com.android.systemui.R
 import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.controls.controller.ControlsController
+import com.android.systemui.controls.ui.ControlsDialog
+import com.android.systemui.controls.ui.ControlsUiController
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.globalactions.GlobalActionsComponent
@@ -49,13 +51,15 @@
     private val listingController: ControlsListingController,
     private val controlsController: ControlsController,
     private val globalActionsComponent: GlobalActionsComponent,
-    broadcastDispatcher: BroadcastDispatcher
+    private val broadcastDispatcher: BroadcastDispatcher,
+    private val uiController: ControlsUiController
 ) : LifecycleActivity() {
 
     companion object {
         private const val TAG = "ControlsProviderSelectorActivity"
     }
 
+    private var backToGlobalActions = true
     private lateinit var recyclerView: RecyclerView
     private val currentUserTracker = object : CurrentUserTracker(broadcastDispatcher) {
         private val startingUser = listingController.currentUserId
@@ -101,10 +105,19 @@
             }
         }
         requireViewById<View>(R.id.done).visibility = View.GONE
+
+        backToGlobalActions = intent.getBooleanExtra(
+            ControlsUiController.BACK_TO_GLOBAL_ACTIONS,
+            true
+        )
     }
 
     override fun onBackPressed() {
-        globalActionsComponent.handleShowGlobalActionsMenu()
+        if (backToGlobalActions) {
+            globalActionsComponent.handleShowGlobalActionsMenu()
+        } else {
+            ControlsDialog(applicationContext, broadcastDispatcher).show(uiController)
+        }
         animateExitAndFinish()
     }
 
@@ -152,8 +165,13 @@
                             listingController.getAppLabel(it))
                     putExtra(Intent.EXTRA_COMPONENT_NAME, it)
                     putExtra(ControlsFavoritingActivity.EXTRA_FROM_PROVIDER_SELECTOR, true)
+                    putExtra(
+                        ControlsUiController.BACK_TO_GLOBAL_ACTIONS,
+                        backToGlobalActions
+                    )
                 }
                 startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle())
+                animateExitAndFinish()
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialog.kt
index db68d17..537334a 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialog.kt
@@ -67,7 +67,7 @@
 
         val vg = requireViewById<ViewGroup>(com.android.systemui.R.id.global_actions_controls)
         vg.alpha = 0f
-        controller.show(vg, { /* do nothing */ }, false /* startedFromGlobalActions */)
+        controller.show(vg, { dismiss() }, false /* startedFromGlobalActions */)
 
         vg.animate()
             .alpha(1f)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
index 9448877..20bdf60 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
@@ -27,6 +27,7 @@
     companion object {
         public const val TAG = "ControlsUiController"
         public const val EXTRA_ANIMATE = "extra_animate"
+        public const val BACK_TO_GLOBAL_ACTIONS = "back_to_global_actions"
     }
 
     fun show(parent: ViewGroup, onDismiss: Runnable, startedFromGlobalActions: Boolean)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index 762362c..c94d85a 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -266,6 +266,10 @@
     private fun startActivity(context: Context, intent: Intent) {
         // Force animations when transitioning from a dialog to an activity
         intent.putExtra(ControlsUiController.EXTRA_ANIMATE, true)
+        intent.putExtra(
+            ControlsUiController.BACK_TO_GLOBAL_ACTIONS,
+            controlActionCoordinator.startedFromGlobalActions
+        )
         onDismiss.run()
 
         activityStarter.dismissKeyguardThenExecute({
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
index 2b362b9..8d2639d 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
@@ -22,6 +22,7 @@
 import com.android.systemui.keyguard.WorkLockActivity;
 import com.android.systemui.people.PeopleSpaceActivity;
 import com.android.systemui.screenrecord.ScreenRecordDialog;
+import com.android.systemui.screenshot.LongScreenshotActivity;
 import com.android.systemui.settings.brightness.BrightnessDialog;
 import com.android.systemui.statusbar.tv.notifications.TvNotificationPanelActivity;
 import com.android.systemui.tuner.TunerActivity;
@@ -99,4 +100,10 @@
     @IntoMap
     @ClassKey(PeopleSpaceActivity.class)
     public abstract Activity bindPeopleSpaceActivity(PeopleSpaceActivity activity);
+
+    /** Inject into LongScreenshotActivity. */
+    @Binds
+    @IntoMap
+    @ClassKey(LongScreenshotActivity.class)
+    public abstract Activity bindLongScreenshotActivity(LongScreenshotActivity activity);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index 91c2dcf..8f79de5 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.dagger;
 
-import com.android.keyguard.clock.ClockOptionsProvider;
 import com.android.systemui.BootCompleteCacheImpl;
 import com.android.systemui.Dependency;
 import com.android.systemui.InitController;
@@ -34,6 +33,7 @@
 import com.android.wm.shell.onehanded.OneHanded;
 import com.android.wm.shell.pip.Pip;
 import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.startingsurface.StartingSurface;
 import com.android.wm.shell.transition.RemoteTransitions;
 
 import java.util.Optional;
@@ -89,6 +89,9 @@
         @BindsInstance
         Builder setTransitions(RemoteTransitions t);
 
+        @BindsInstance
+        Builder setStartingSurface(Optional<StartingSurface> s);
+
         SysUIComponent build();
     }
 
@@ -147,9 +150,4 @@
      * Member injection into the supplied argument.
      */
     void inject(KeyguardSliceProvider keyguardSliceProvider);
-
-    /**
-     * Member injection into the supplied argument.
-     */
-    void inject(ClockOptionsProvider clockOptionsProvider);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
index ec3188a..5d226d5 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
@@ -29,6 +29,7 @@
 import com.android.systemui.media.systemsounds.HomeSoundEffectController;
 import com.android.systemui.people.widget.PeopleSpaceWidgetEnabler;
 import com.android.systemui.power.PowerUI;
+import com.android.systemui.privacy.television.TvOngoingPrivacyChip;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsModule;
 import com.android.systemui.shortcut.ShortcutKeyDispatcher;
@@ -155,6 +156,12 @@
     @ClassKey(TvNotificationPanel.class)
     public abstract SystemUI bindsTvNotificationPanel(TvNotificationPanel sysui);
 
+    /** Inject into TvOngoingPrivacyChip. */
+    @Binds
+    @IntoMap
+    @ClassKey(TvOngoingPrivacyChip.class)
+    public abstract SystemUI bindsTvOngoingPrivacyChip(TvOngoingPrivacyChip sysui);
+
     /** Inject into VolumeUI. */
     @Binds
     @IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index b67db03..b0067cd 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -22,7 +22,6 @@
 import androidx.annotation.Nullable;
 
 import com.android.internal.statusbar.IStatusBarService;
-import com.android.keyguard.clock.ClockModule;
 import com.android.keyguard.dagger.KeyguardBouncerComponent;
 import com.android.systemui.BootCompleteCache;
 import com.android.systemui.BootCompleteCacheImpl;
@@ -91,7 +90,6 @@
 @Module(includes = {
             AppOpsModule.class,
             AssistModule.class,
-            ClockModule.class,
             ControlsModule.class,
             DemoModeModule.class,
             FalsingModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
index f3726a3..1b77d1c 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
@@ -32,6 +32,7 @@
 import com.android.wm.shell.onehanded.OneHanded;
 import com.android.wm.shell.pip.Pip;
 import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.startingsurface.StartingSurface;
 import com.android.wm.shell.transition.RemoteTransitions;
 
 import java.util.Optional;
@@ -98,4 +99,7 @@
 
     @WMSingleton
     RemoteTransitions getTransitions();
+
+    @WMSingleton
+    Optional<StartingSurface> getStartingSurface();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 5c8c9f2..4418696 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.os.Handler;
 import android.os.SystemClock;
+import android.provider.Settings;
 import android.text.format.Formatter;
 import android.util.Log;
 
@@ -31,7 +32,9 @@
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.doze.dagger.DozeScope;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.tuner.TunerService;
 import com.android.systemui.util.AlarmTimeout;
 import com.android.systemui.util.wakelock.WakeLock;
 
@@ -39,12 +42,15 @@
 
 import javax.inject.Inject;
 
+import dagger.Lazy;
+
 /**
  * The policy controlling doze.
  */
 @DozeScope
-public class DozeUi implements DozeMachine.Part {
-
+public class DozeUi implements DozeMachine.Part, TunerService.Tunable {
+    // if enabled, calls dozeTimeTick() whenever the time changes:
+    private static final boolean BURN_IN_TESTING_ENABLED = false;
     private static final long TIME_TICK_DEADLINE_MILLIS = 90 * 1000; // 1.5min
     private final Context mContext;
     private final DozeHost mHost;
@@ -55,16 +61,28 @@
     private final boolean mCanAnimateTransition;
     private final DozeParameters mDozeParameters;
     private final DozeLog mDozeLog;
+    private final Lazy<StatusBarStateController> mStatusBarStateController;
 
     private boolean mKeyguardShowing;
     private final KeyguardUpdateMonitorCallback mKeyguardVisibilityCallback =
             new KeyguardUpdateMonitorCallback() {
-
                 @Override
                 public void onKeyguardVisibilityChanged(boolean showing) {
                     mKeyguardShowing = showing;
                     updateAnimateScreenOff();
                 }
+
+                @Override
+                public void onTimeChanged() {
+                    if (BURN_IN_TESTING_ENABLED && mStatusBarStateController != null
+                            && mStatusBarStateController.get().isDozing()) {
+                        // update whenever the time changes for manual burn in testing
+                        mHost.dozeTimeTick();
+
+                        // Keep wakelock until a frame has been pushed.
+                        mHandler.post(mWakeLock.wrap(() -> {}));
+                    }
+                }
             };
 
     private long mLastTimeTickElapsed = 0;
@@ -73,7 +91,8 @@
     public DozeUi(Context context, AlarmManager alarmManager,
             WakeLock wakeLock, DozeHost host, @Main Handler handler,
             DozeParameters params, KeyguardUpdateMonitor keyguardUpdateMonitor,
-            DozeLog dozeLog) {
+            DozeLog dozeLog, TunerService tunerService,
+            Lazy<StatusBarStateController> statusBarStateController) {
         mContext = context;
         mWakeLock = wakeLock;
         mHost = host;
@@ -83,6 +102,8 @@
         mTimeTicker = new AlarmTimeout(alarmManager, this::onTimeTick, "doze_time_tick", handler);
         keyguardUpdateMonitor.registerCallback(mKeyguardVisibilityCallback);
         mDozeLog = dozeLog;
+        tunerService.addTunable(this, Settings.Secure.DOZE_ALWAYS_ON);
+        mStatusBarStateController = statusBarStateController;
     }
 
     @Override
@@ -238,4 +259,11 @@
     KeyguardUpdateMonitorCallback getKeyguardCallback() {
         return mKeyguardVisibilityCallback;
     }
+
+    @Override
+    public void onTuningChanged(String key, String newValue) {
+        if (key.equals(Settings.Secure.DOZE_ALWAYS_ON)) {
+            updateAnimateScreenOff();
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagReader.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagReader.java
index b77fcc8..073586e 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagReader.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagReader.java
@@ -16,24 +16,18 @@
 
 package com.android.systemui.flags;
 
-import android.annotation.NonNull;
 import android.content.res.Resources;
-import android.provider.DeviceConfig;
 import android.util.SparseArray;
 
 import androidx.annotation.BoolRes;
 import androidx.annotation.Nullable;
 
 import com.android.systemui.R;
-import com.android.systemui.assist.DeviceConfigHelper;
 import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.util.wrapper.BuildInfo;
 
-import java.util.concurrent.Executor;
-
 import javax.inject.Inject;
 /**
  * Reads and caches feature flags for quick access
@@ -60,23 +54,19 @@
 @SysUISingleton
 public class FeatureFlagReader {
     private final Resources mResources;
-    private final DeviceConfigHelper mDeviceConfig;
     private final boolean mAreFlagsOverrideable;
-
+    private final SystemPropertiesHelper mSystemPropertiesHelper;
     private final SparseArray<CachedFlag> mCachedFlags = new SparseArray<>();
 
     @Inject
     public FeatureFlagReader(
             @Main Resources resources,
             BuildInfo build,
-            DeviceConfigHelper deviceConfig,
-            @Background Executor executor) {
+            SystemPropertiesHelper systemPropertiesHelper) {
         mResources = resources;
-        mDeviceConfig = deviceConfig;
+        mSystemPropertiesHelper = systemPropertiesHelper;
         mAreFlagsOverrideable =
                 build.isDebuggable() && mResources.getBoolean(R.bool.are_flags_overrideable);
-
-        mDeviceConfig.addOnPropertiesChangedListener(executor, this::onPropertiesChanged);
     }
 
     /**
@@ -93,7 +83,7 @@
                 String name = resourceIdToFlagName(resId);
                 boolean value = mResources.getBoolean(resId);
                 if (mAreFlagsOverrideable) {
-                    value = mDeviceConfig.getBoolean(flagNameToStorageKey(name), value);
+                    value = mSystemPropertiesHelper.getBoolean(flagNameToStorageKey(name), value);
                 }
 
                 cachedFlag = new CachedFlag(name, value);
@@ -104,27 +94,6 @@
         }
     }
 
-    private void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
-        synchronized (mCachedFlags) {
-            for (String key : properties.getKeyset()) {
-                String flagName = storageKeyToFlagName(key);
-                if (flagName != null) {
-                    clearCachedFlag(flagName);
-                }
-            }
-        }
-    }
-
-    private void clearCachedFlag(String flagName) {
-        for (int i = 0; i < mCachedFlags.size(); i++) {
-            CachedFlag flag = mCachedFlags.valueAt(i);
-            if (flag.name.equals(flagName)) {
-                mCachedFlags.removeAt(i);
-                break;
-            }
-        }
-    }
-
     private String resourceIdToFlagName(@BoolRes int resId) {
         String resName = mResources.getResourceEntryName(resId);
         if (resName.startsWith(RESNAME_PREFIX)) {
@@ -160,6 +129,6 @@
         }
     }
 
-    private static final String STORAGE_KEY_PREFIX = "flag_";
+    private static final String STORAGE_KEY_PREFIX = "persist.systemui.flag_";
     private static final String RESNAME_PREFIX = "flag_";
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockModule.java b/packages/SystemUI/src/com/android/systemui/flags/SystemPropertiesHelper.kt
similarity index 60%
copy from packages/SystemUI/src/com/android/keyguard/clock/ClockModule.java
copy to packages/SystemUI/src/com/android/systemui/flags/SystemPropertiesHelper.kt
index c4be1ba535..28f63b0 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockModule.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/SystemPropertiesHelper.kt
@@ -14,20 +14,19 @@
  * limitations under the License.
  */
 
-package com.android.keyguard.clock;
+package com.android.systemui.flags
 
-import java.util.List;
+import android.os.SystemProperties
+import com.android.systemui.dagger.SysUISingleton
 
-import dagger.Module;
-import dagger.Provides;
+import javax.inject.Inject
 
-/** Dagger Module for clock package. */
-@Module
-public abstract class ClockModule {
-
-    /** */
-    @Provides
-    public static List<ClockInfo> provideClockInfoList(ClockManager clockManager) {
-        return clockManager.getClockInfos();
+/**
+ * Proxy to make {@link SystemProperties} easily testable.
+ */
+@SysUISingleton
+class SystemPropertiesHelper @Inject constructor() {
+    fun getBoolean(name: String, default: Boolean): Boolean {
+        return SystemProperties.getBoolean(name, default)
     }
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
index 1a0356c..01a353c 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
@@ -58,6 +58,14 @@
         mWallpaper = new ImageGLWallpaper(mProgram);
     }
 
+    /**
+     * @hide
+     * @return
+     */
+    public void useBitmap(Consumer<Bitmap> c) {
+        mTexture.use(c);
+    }
+
     @Override
     public boolean isWcgContent() {
         return mTexture.isWcgContent();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
index d4678f3..127128d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
@@ -103,6 +103,11 @@
      */
     public void updateIndication(@IndicationType int type, KeyguardIndication newIndication,
             boolean showImmediately) {
+        if (type == INDICATION_TYPE_NOW_PLAYING
+                || type == INDICATION_TYPE_REVERSE_CHARGING) {
+            // temporarily don't show here, instead use AmbientContainer b/181049781
+            return;
+        }
         final boolean hasPreviousIndication = mIndicationMessages.get(type) != null;
         final boolean hasNewIndication = newIndication != null;
         if (!hasNewIndication) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 91cf710..eef41e0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -2395,6 +2395,9 @@
             return;
         }
         mDozing = dozing;
+        if (!dozing) {
+            mAnimatingScreenOff = false;
+        }
         setShowingLocked(mShowing);
     }
 
@@ -2404,7 +2407,7 @@
         // is 1f), then show the activity lock screen.
         if (mAnimatingScreenOff && mDozing && linear == 1f) {
             mAnimatingScreenOff = false;
-            setShowingLocked(mShowing);
+            setShowingLocked(mShowing, true);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index a747edd..de2e7c47 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -30,7 +30,6 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardViewController;
 import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
-import com.android.keyguard.dagger.KeyguardStatusBarViewComponent;
 import com.android.keyguard.dagger.KeyguardStatusViewComponent;
 import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
 import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -64,11 +63,8 @@
 /**
  * Dagger Module providing {@link StatusBar}.
  */
-@Module(subcomponents = {
-        KeyguardQsUserSwitchComponent.class,
-        KeyguardStatusBarViewComponent.class,
-        KeyguardStatusViewComponent.class,
-        KeyguardUserSwitcherComponent.class},
+@Module(subcomponents = {KeyguardStatusViewComponent.class,
+        KeyguardQsUserSwitchComponent.class, KeyguardUserSwitcherComponent.class},
         includes = {FalsingModule.class})
 public class KeyguardModule {
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index dab4d0b..5536237 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -855,6 +855,14 @@
 
     @Override
     public void onRotationProposal(final int rotation, boolean isValid) {
+        if (mNavigationBarView == null) {
+            if (RotationContextButton.DEBUG_ROTATION) {
+                Log.v(TAG, "onRotationProposal proposedRotation=" +
+                        Surface.rotationToString(rotation) + ", mNavigationBarView is null");
+            }
+            return;
+        }
+
         final int winRotation = mNavigationBarView.getDisplay().getRotation();
         final boolean rotateSuggestionsDisabled = RotationButtonController
                 .hasDisable2RotateSuggestionFlag(mDisabledFlags2);
@@ -1116,7 +1124,7 @@
         }
         // If an incoming call is ringing, HOME is totally disabled.
         // (The user is already on the InCallUI at this point,
-        // and his ONLY options are to answer or reject the call.)
+        // and their ONLY options are to answer or reject the call.)
         switch (event.getAction()) {
             case MotionEvent.ACTION_DOWN:
                 mHomeBlockedThisTouch = false;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index 27ea64f8..70b7b04 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -25,7 +25,6 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.RemoteException;
-import android.os.UserHandle;
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.Display;
@@ -54,7 +53,6 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.recents.Recents;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -116,7 +114,7 @@
     // Tracks config changes that will actually recreate the nav bar
     private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges(
             ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_LOCALE
-                    | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS
+                    | ActivityInfo.CONFIG_SCREEN_LAYOUT
                     | ActivityInfo.CONFIG_UI_MODE);
 
     @Inject
@@ -171,6 +169,7 @@
         configurationController.addCallback(this);
         mConfigChanges.applyNewConfig(mContext.getResources());
         mNavBarOverlayController = navBarOverlayController;
+        mNavigationModeController.addListener(this);
     }
 
     @Override
@@ -188,17 +187,18 @@
 
     @Override
     public void onNavigationModeChanged(int mode) {
-        // Workaround for b/132825155, for secondary users, we currently don't receive configuration
-        // changes on overlay package change since SystemUI runs for the system user. In this case,
-        // trigger a new configuration change to ensure that the nav bar is updated in the same way.
-        int userId = ActivityManagerWrapper.getInstance().getCurrentUserId();
-        if (userId != UserHandle.USER_SYSTEM) {
-            mHandler.post(() -> {
-                for (int i = 0; i < mNavigationBars.size(); i++) {
-                    recreateNavigationBar(mNavigationBars.keyAt(i));
+        mHandler.post(() -> {
+            for (int i = 0; i < mNavigationBars.size(); i++) {
+                NavigationBar navBar = mNavigationBars.valueAt(i);
+                if (navBar == null) {
+                    continue;
                 }
-            });
-        }
+                NavigationBarView view = (NavigationBarView) mNavigationBars.get(i).getView();
+                if (view != null) {
+                    view.updateStates();
+                }
+            }
+        });
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarOverlayController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarOverlayController.java
index c526c5d..62b9458 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarOverlayController.java
@@ -21,6 +21,7 @@
 import android.view.View;
 
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.statusbar.FeatureFlags;
 
 import java.util.function.Consumer;
 
@@ -31,16 +32,22 @@
 public class NavigationBarOverlayController {
 
     protected final Context mContext;
+    protected final FeatureFlags mFeatureFlags;
 
     @Inject
-    public NavigationBarOverlayController(Context context) {
+    public NavigationBarOverlayController(Context context, FeatureFlags featureFlags) {
         mContext = context;
+        mFeatureFlags = featureFlags;
     }
 
     public Context getContext() {
         return mContext;
     }
 
+    public boolean isNavigationBarOverlayEnabled() {
+        return mFeatureFlags.isNavigationBarOverlayEnabled();
+    }
+
     /**
      * Initialize the controller with visibility change callback and light/dark icon color.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
index b55fa4d..61e1d61 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
@@ -192,6 +192,7 @@
             buttonDispatchers.valueAt(i).setDarkIntensity(darkIntensity);
         }
         mView.getRotationButtonController().setDarkIntensity(darkIntensity);
+
         Dependency.get(NavigationBarOverlayController.class).setDarkIntensity(darkIntensity);
         for (DarkIntensityListener listener : mDarkIntensityListeners) {
             listener.onDarkIntensity(darkIntensity);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index c07404c..19e3278 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -76,6 +76,7 @@
 import com.android.systemui.navigationbar.buttons.ContextualButtonGroup;
 import com.android.systemui.navigationbar.buttons.DeadZone;
 import com.android.systemui.navigationbar.buttons.KeyButtonDrawable;
+import com.android.systemui.navigationbar.buttons.NearestTouchFrame;
 import com.android.systemui.navigationbar.buttons.RotationContextButton;
 import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
 import com.android.systemui.navigationbar.gestural.FloatingRotationButton;
@@ -97,6 +98,8 @@
 import com.android.wm.shell.pip.Pip;
 
 import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.function.Consumer;
 
 public class NavigationBarView extends FrameLayout implements
@@ -129,6 +132,7 @@
     private final Region mTmpRegion = new Region();
     private final int[] mTmpPosition = new int[2];
     private Rect mTmpBounds = new Rect();
+    private Map<View, Rect> mButtonFullTouchableRegions = new HashMap<>();
 
     private KeyButtonDrawable mBackIcon;
     private KeyButtonDrawable mHomeDefaultIcon;
@@ -167,6 +171,7 @@
     private NotificationPanelViewController mPanelView;
     private FloatingRotationButton mFloatingRotationButton;
     private RotationButtonController mRotationButtonController;
+    private NavigationBarOverlayController mNavBarOverlayController;
 
     /**
      * Helper that is responsible for showing the right toast when a disallowed activity operation
@@ -335,8 +340,11 @@
                 isGesturalMode ? mFloatingRotationButton : rotateSuggestionButton,
                 mRotationButtonListener);
 
-        Dependency.get(NavigationBarOverlayController.class).init(
-                mNavbarOverlayVisibilityChangeCallback, mLightIconColor, mDarkIconColor);
+        mNavBarOverlayController = Dependency.get(NavigationBarOverlayController.class);
+        if (mNavBarOverlayController.isNavigationBarOverlayEnabled()) {
+            mNavBarOverlayController.init(
+                    mNavbarOverlayVisibilityChangeCallback, mLightIconColor, mDarkIconColor);
+        }
 
         mConfiguration = new Configuration();
         mTmpLastConfiguration = new Configuration();
@@ -427,8 +435,9 @@
 
         // The visibility of the navigation bar buttons is dependent on the transient state of
         // the navigation bar.
-        Dependency.get(NavigationBarOverlayController.class).setButtonState(
-                isTransient, /* force */ false);
+        if (mNavBarOverlayController.isNavigationBarOverlayEnabled()) {
+            mNavBarOverlayController.setButtonState(isTransient, /* force */ false);
+        }
     }
 
     void onBarTransition(int newMode) {
@@ -662,7 +671,9 @@
         }
         mImeVisible = visible;
         mRotationButtonController.getRotationButton().setCanShowRotationButton(!mImeVisible);
-        Dependency.get(NavigationBarOverlayController.class).setCanShow(!mImeVisible);
+        if (mNavBarOverlayController.isNavigationBarOverlayEnabled()) {
+            mNavBarOverlayController.setCanShow(!mImeVisible);
+        }
     }
 
     public void setDisabledFlags(int disabledFlags) {
@@ -973,9 +984,18 @@
                 getButtonLocations(true /* includeFloatingRotationButton */, true /* inScreen */));
     }
 
+    private void updateButtonTouchRegionCache() {
+        FrameLayout navBarLayout = mIsVertical
+                ? mNavigationInflaterView.mVertical
+                : mNavigationInflaterView.mHorizontal;
+        mButtonFullTouchableRegions = ((NearestTouchFrame) navBarLayout
+                .findViewById(R.id.nav_buttons)).getFullTouchableChildRegions();
+    }
+
     private Region getButtonLocations(boolean includeFloatingRotationButton,
             boolean inScreenSpace) {
         mTmpRegion.setEmpty();
+        updateButtonTouchRegionCache();
         updateButtonLocation(getBackButton(), inScreenSpace);
         updateButtonLocation(getHomeButton(), inScreenSpace);
         updateButtonLocation(getRecentsButton(), inScreenSpace);
@@ -986,10 +1006,9 @@
         } else {
             updateButtonLocation(getRotateSuggestionButton(), inScreenSpace);
         }
-        final NavigationBarOverlayController navBarButtonsController =
-                Dependency.get(NavigationBarOverlayController.class);
-        if (navBarButtonsController.isVisible()) {
-            updateButtonLocation(navBarButtonsController.getCurrentView(), inScreenSpace);
+        if (mNavBarOverlayController.isNavigationBarOverlayEnabled()
+                && mNavBarOverlayController.isVisible()) {
+            updateButtonLocation(mNavBarOverlayController.getCurrentView(), inScreenSpace);
         }
         return mTmpRegion;
     }
@@ -999,6 +1018,12 @@
         if (view == null || !button.isVisible()) {
             return;
         }
+        // If the button is tappable from perspective of NearestTouchFrame, then we'll
+        // include the regions where the tap is valid instead of just the button layout location
+        if (mButtonFullTouchableRegions.containsKey(view)) {
+            mTmpRegion.op(mButtonFullTouchableRegions.get(view), Op.UNION);
+            return;
+        }
         updateButtonLocation(view, inScreenSpace);
     }
 
@@ -1211,7 +1236,9 @@
         if (mRotationButtonController != null) {
             mRotationButtonController.registerListeners();
         }
-        Dependency.get(NavigationBarOverlayController.class).registerListeners();
+        if (mNavBarOverlayController.isNavigationBarOverlayEnabled()) {
+            mNavBarOverlayController.registerListeners();
+        }
 
         getViewTreeObserver().addOnComputeInternalInsetsListener(mOnComputeInternalInsetsListener);
         updateNavButtonIcons();
@@ -1228,7 +1255,10 @@
         if (mRotationButtonController != null) {
             mRotationButtonController.unregisterListeners();
         }
-        Dependency.get(NavigationBarOverlayController.class).unregisterListeners();
+
+        if (mNavBarOverlayController.isNavigationBarOverlayEnabled()) {
+            mNavBarOverlayController.unregisterListeners();
+        }
 
         mEdgeBackGestureHandler.onNavBarDetached();
         getViewTreeObserver().removeOnComputeInternalInsetsListener(
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java
index 65d4e23..870e3be 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java
@@ -132,7 +132,7 @@
             Settings.Secure.putString(mCurrentUserContext.getContentResolver(),
                     Secure.NAVIGATION_MODE, String.valueOf(mode)));
         if (DEBUG) {
-            Log.e(TAG, "updateCurrentInteractionMode: mode=" + mode);
+            Log.d(TAG, "updateCurrentInteractionMode: mode=" + mode);
             dumpAssetPaths(mCurrentUserContext);
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/NearestTouchFrame.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/NearestTouchFrame.java
index 88c8fea..8ff7b7a 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/NearestTouchFrame.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/NearestTouchFrame.java
@@ -18,8 +18,9 @@
 
 import android.content.Context;
 import android.content.res.Configuration;
+import android.content.res.TypedArray;
+import android.graphics.Rect;
 import android.util.AttributeSet;
-import android.util.Pair;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
@@ -27,8 +28,13 @@
 
 import androidx.annotation.VisibleForTesting;
 
+import com.android.systemui.R;
+
 import java.util.ArrayList;
 import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * Redirects touches that aren't handled by any child view to the nearest
@@ -36,11 +42,32 @@
  */
 public class NearestTouchFrame extends FrameLayout {
 
-    private final ArrayList<View> mClickableChildren = new ArrayList<>();
+    private final List<View> mClickableChildren = new ArrayList<>();
+    private final List<View> mAttachedChildren = new ArrayList<>();
     private final boolean mIsActive;
     private final int[] mTmpInt = new int[2];
     private final int[] mOffset = new int[2];
+    private boolean mIsVertical;
     private View mTouchingChild;
+    private final Map<View, Rect> mTouchableRegions = new HashMap<>();
+    /**
+     * Used to sort all child views either by their left position or their top position,
+     * depending on if this layout is used horizontally or vertically, respectively
+     */
+    private final Comparator<View> mChildRegionComparator =
+            (view1, view2) -> {
+                int leftTopIndex = 0;
+                if (mIsVertical) {
+                    // Compare view bound's "top" values
+                    leftTopIndex = 1;
+                }
+                view1.getLocationInWindow(mTmpInt);
+                int startingCoordView1 = mTmpInt[leftTopIndex] - mOffset[leftTopIndex];
+                view2.getLocationInWindow(mTmpInt);
+                int startingCoordView2 = mTmpInt[leftTopIndex] - mOffset[leftTopIndex];
+
+                return startingCoordView1 - startingCoordView2;
+            };
 
     public NearestTouchFrame(Context context, AttributeSet attrs) {
         this(context, attrs, context.getResources().getConfiguration());
@@ -50,19 +77,100 @@
     NearestTouchFrame(Context context, AttributeSet attrs, Configuration c) {
         super(context, attrs);
         mIsActive = c.smallestScreenWidthDp < 600;
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        mClickableChildren.clear();
-        addClickableChildren(this);
+        int[] attrsArray = new int[] {R.attr.isVertical};
+        TypedArray ta = context.obtainStyledAttributes(attrs, attrsArray);
+        mIsVertical = ta.getBoolean(0, false);
+        ta.recycle();
     }
 
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
+        mClickableChildren.clear();
+        mAttachedChildren.clear();
+        mTouchableRegions.clear();
+        addClickableChildren(this);
         getLocationInWindow(mOffset);
+        cacheClosestChildLocations();
+    }
+
+    /**
+     * Populates {@link #mTouchableRegions} with the regions where each clickable child is the
+     * closest for a given point on this layout.
+     */
+    private void cacheClosestChildLocations() {
+        if (getWidth() == 0 || getHeight() == 0) {
+            return;
+        }
+
+        // Sort by either top or left depending on mIsVertical, then take out all children
+        // that are not attached to window
+        mClickableChildren.sort(mChildRegionComparator);
+        mClickableChildren.stream()
+                .filter(View::isAttachedToWindow)
+                .forEachOrdered(mAttachedChildren::add);
+
+        // Cache bounds of children
+        // Mark coordinates where the actual child layout resides in this frame's window
+        for (int i = 0; i < mAttachedChildren.size(); i++) {
+            View child = mAttachedChildren.get(i);
+            if (!child.isAttachedToWindow()) {
+                continue;
+            }
+            Rect childRegion = getChildsBounds(child);
+
+            // We compute closest child from this child to the previous one
+            if (i == 0) {
+                // First child, nothing to the left/top of it
+                if (mIsVertical) {
+                    childRegion.top = 0;
+                } else {
+                    childRegion.left = 0;
+                }
+                mTouchableRegions.put(child, childRegion);
+                continue;
+            }
+
+            View previousChild = mAttachedChildren.get(i - 1);
+            Rect previousChildBounds = mTouchableRegions.get(previousChild);
+            int midPoint;
+            if (mIsVertical) {
+                int distance = childRegion.top - previousChildBounds.bottom;
+                midPoint = distance / 2;
+                childRegion.top -= midPoint;
+                previousChildBounds.bottom += midPoint - ((distance % 2) == 0 ? 1 : 0);
+            } else {
+                int distance = childRegion.left - previousChildBounds.right;
+                midPoint = distance / 2;
+                childRegion.left -= midPoint;
+                previousChildBounds.right += midPoint - ((distance % 2) == 0 ? 1 : 0);
+            }
+
+            if (i == mClickableChildren.size() - 1) {
+                // Last child, nothing to right/bottom of it
+                if (mIsVertical) {
+                    childRegion.bottom = getHeight();
+                } else {
+                    childRegion.right = getWidth();
+                }
+            }
+
+            mTouchableRegions.put(child, childRegion);
+        }
+    }
+
+    @VisibleForTesting
+    void setIsVertical(boolean isVertical) {
+        mIsVertical = isVertical;
+    }
+
+    private Rect getChildsBounds(View child) {
+        child.getLocationInWindow(mTmpInt);
+        int left = mTmpInt[0] - mOffset[0];
+        int top = mTmpInt[1] - mOffset[1];
+        int right = left + child.getWidth();
+        int bottom = top + child.getHeight();
+        return new Rect(left, top, right, bottom);
     }
 
     private void addClickableChildren(ViewGroup group) {
@@ -77,47 +185,45 @@
         }
     }
 
+    /**
+     * @return A Map where the key is the view object of the button and the value
+     * is the Rect where that button will receive a touch event if pressed. This Rect will
+     * usually be larger than the layout bounds for the button.
+     * The Rect is in screen coordinates.
+     */
+    public Map<View, Rect> getFullTouchableChildRegions() {
+        Map<View, Rect> fullTouchRegions = new HashMap<>(mTouchableRegions.size());
+        getLocationOnScreen(mTmpInt);
+        for (Map.Entry<View, Rect> entry : mTouchableRegions.entrySet()) {
+            View child = entry.getKey();
+            Rect screenRegion = new Rect(entry.getValue());
+            screenRegion.offset(mTmpInt[0], mTmpInt[1]);
+            fullTouchRegions.put(child, screenRegion);
+        }
+        return fullTouchRegions;
+    }
+
     @Override
     public boolean onTouchEvent(MotionEvent event) {
         if (mIsActive) {
+            int x = (int) event.getX();
+            int y = (int) event.getY();
             if (event.getAction() == MotionEvent.ACTION_DOWN) {
-                mTouchingChild = findNearestChild(event);
+                mTouchingChild = mClickableChildren
+                        .stream()
+                        .filter(View::isAttachedToWindow)
+                        .filter(view -> mTouchableRegions.get(view).contains(x, y))
+                        .findFirst()
+                        .orElse(null);
+
             }
             if (mTouchingChild != null) {
-                event.offsetLocation(mTouchingChild.getWidth() / 2 - event.getX(),
-                        mTouchingChild.getHeight() / 2 - event.getY());
+                event.offsetLocation(mTouchingChild.getWidth() / 2 - x,
+                        mTouchingChild.getHeight() / 2 - y);
                 return mTouchingChild.getVisibility() == VISIBLE
                         && mTouchingChild.dispatchTouchEvent(event);
             }
         }
         return super.onTouchEvent(event);
     }
-
-    private View findNearestChild(MotionEvent event) {
-        if (mClickableChildren.isEmpty()) {
-            return null;
-        }
-        return mClickableChildren
-                .stream()
-                .filter(View::isAttachedToWindow)
-                .map(v -> new Pair<>(distance(v, event), v))
-                .min(Comparator.comparingInt(f -> f.first))
-                .map(data -> data.second)
-                .orElse(null);
-    }
-
-    private int distance(View v, MotionEvent event) {
-        v.getLocationInWindow(mTmpInt);
-        int left = mTmpInt[0] - mOffset[0];
-        int top = mTmpInt[1] - mOffset[1];
-        int right = left + v.getWidth();
-        int bottom = top + v.getHeight();
-
-        int x = Math.min(Math.abs(left - (int) event.getX()),
-                Math.abs((int) event.getX() - right));
-        int y = Math.min(Math.abs(top - (int) event.getY()),
-                Math.abs((int) event.getY() - bottom));
-
-        return Math.max(x, y);
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index d7a3537..088743c 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -38,6 +38,7 @@
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.Choreographer;
+import android.view.Display;
 import android.view.ISystemGestureExclusionListener;
 import android.view.InputDevice;
 import android.view.InputEvent;
@@ -92,10 +93,16 @@
     private static final int MAX_LONG_PRESS_TIMEOUT = SystemProperties.getInt(
             "gestures.back_timeout", 250);
 
+    private static final int MAX_NUM_LOGGED_PREDICTIONS = 10;
+    private static final int MAX_NUM_LOGGED_GESTURES = 10;
+
     // Temporary log until b/176302696 is resolved
     static final boolean DEBUG_MISSING_GESTURE = true;
     static final String DEBUG_MISSING_GESTURE_TAG = "NoBackGesture";
 
+    private static final boolean ENABLE_PER_WINDOW_INPUT_ROTATION =
+            SystemProperties.getBoolean("persist.debug.per_window_input_rotation", false);
+
     private ISystemGestureExclusionListener mGestureExclusionListener =
             new ISystemGestureExclusionListener.Stub() {
                 @Override
@@ -218,8 +225,9 @@
     private String mPackageName;
     private float mMLResults;
 
-    private static final int MAX_LOGGED_PREDICTIONS = 10;
+    // For debugging
     private ArrayDeque<String> mPredictionLog = new ArrayDeque<>();
+    private ArrayDeque<String> mGestureLog = new ArrayDeque<>();
 
     private final GestureNavigationSettingsObserver mGestureNavigationSettingsObserver;
 
@@ -505,9 +513,19 @@
     }
 
     private void onInputEvent(InputEvent ev) {
-        if (ev instanceof MotionEvent) {
-            onMotionEvent((MotionEvent) ev);
+        if (!(ev instanceof MotionEvent)) return;
+        MotionEvent event = (MotionEvent) ev;
+        if (ENABLE_PER_WINDOW_INPUT_ROTATION) {
+            final Display display = mContext.getDisplay();
+            int rotation = display.getRotation();
+            if (rotation != Surface.ROTATION_0) {
+                Point sz = new Point();
+                display.getRealSize(sz);
+                event = MotionEvent.obtain(event);
+                event.transform(MotionEvent.createRotateMatrix(rotation, sz.x, sz.y));
+            }
         }
+        onMotionEvent(event);
     }
 
     private void updateMLModelState() {
@@ -593,7 +611,7 @@
         }
         // Check if we are within the tightest bounds beyond which
         // we would not need to run the ML model.
-        boolean withinRange = x <= mMLEnableWidth + mLeftInset
+        boolean withinRange = x < mMLEnableWidth + mLeftInset
                 || x >= (mDisplaySize.x - mMLEnableWidth - mRightInset);
         if (!withinRange) {
             int results = -1;
@@ -603,17 +621,20 @@
                 // Denotes whether we should proceed with the gesture.
                 // Even if it is false, we may want to log it assuming
                 // it is not invalid due to exclusion.
-                withinRange = x <= mEdgeWidthLeft + mLeftInset
+                withinRange = x < mEdgeWidthLeft + mLeftInset
                         || x >= (mDisplaySize.x - mEdgeWidthRight - mRightInset);
             }
         }
 
         // For debugging purposes
-        if (mPredictionLog.size() >= MAX_LOGGED_PREDICTIONS) {
+        if (mPredictionLog.size() >= MAX_NUM_LOGGED_PREDICTIONS) {
             mPredictionLog.removeFirst();
         }
-        mPredictionLog.addLast(String.format("[%d,%d,%d,%f,%d]",
-                x, y, app, mMLResults, withinRange ? 1 : 0));
+        mPredictionLog.addLast(String.format("Prediction [%d,%d,%d,%d,%f,%d]",
+                System.currentTimeMillis(), x, y, app, mMLResults, withinRange ? 1 : 0));
+        if (DEBUG_MISSING_GESTURE) {
+            Log.d(DEBUG_MISSING_GESTURE_TAG, mPredictionLog.peekLast());
+        }
 
         // Always allow if the user is in a transient sticky immersive state
         if (mIsNavBarShownTransiently) {
@@ -675,6 +696,10 @@
     private void onMotionEvent(MotionEvent ev) {
         int action = ev.getActionMasked();
         if (action == MotionEvent.ACTION_DOWN) {
+            if (DEBUG_MISSING_GESTURE) {
+                Log.d(DEBUG_MISSING_GESTURE_TAG, "Start gesture: " + ev);
+            }
+
             // Verify if this is in within the touch region and we aren't in immersive mode, and
             // either the bouncer is showing or the notification panel is hidden
             mInputEventReceiver.setBatchingEnabled(false);
@@ -695,6 +720,19 @@
                 mEndPoint.set(-1, -1);
                 mThresholdCrossed = false;
             }
+
+            // For debugging purposes
+            if (mGestureLog.size() >= MAX_NUM_LOGGED_GESTURES) {
+                mGestureLog.removeFirst();
+            }
+            mGestureLog.addLast(String.format(
+                    "Gesture [%d,alw=%B,%B, %B,%B,disp=%s,wl=%d,il=%d,wr=%d,ir=%d,excl=%s]",
+                    System.currentTimeMillis(), mAllowGesture, mIsOnLeftEdge, mIsBackGestureAllowed,
+                    QuickStepContract.isBackGestureDisabled(mSysUiFlags), mDisplaySize,
+                    mEdgeWidthLeft, mLeftInset, mEdgeWidthRight, mRightInset, mExcludeRegion));
+            if (DEBUG_MISSING_GESTURE) {
+                Log.d(DEBUG_MISSING_GESTURE_TAG, mGestureLog.peekLast());
+            }
         } else if (mAllowGesture || mLogGesture) {
             if (!mThresholdCrossed) {
                 mEndPoint.x = (int) ev.getX();
@@ -813,18 +851,29 @@
     public void dump(PrintWriter pw) {
         pw.println("EdgeBackGestureHandler:");
         pw.println("  mIsEnabled=" + mIsEnabled);
+        pw.println("  mIsAttached=" + mIsAttached);
         pw.println("  mIsBackGestureAllowed=" + mIsBackGestureAllowed);
+        pw.println("  mIsGesturalModeEnabled=" + mIsGesturalModeEnabled);
+        pw.println("  mIsNavBarShownTransiently=" + mIsNavBarShownTransiently);
+        pw.println("  mGestureBlockingActivityRunning=" + mGestureBlockingActivityRunning);
         pw.println("  mAllowGesture=" + mAllowGesture);
+        pw.println("  mUseMLModel=" + mUseMLModel);
         pw.println("  mDisabledForQuickstep=" + mDisabledForQuickstep);
         pw.println("  mStartingQuickstepRotation=" + mStartingQuickstepRotation);
         pw.println("  mInRejectedExclusion" + mInRejectedExclusion);
         pw.println("  mExcludeRegion=" + mExcludeRegion);
         pw.println("  mUnrestrictedExcludeRegion=" + mUnrestrictedExcludeRegion);
-        pw.println("  mIsAttached=" + mIsAttached);
+        pw.println("  mPipExcludedBounds=" + mPipExcludedBounds);
         pw.println("  mEdgeWidthLeft=" + mEdgeWidthLeft);
         pw.println("  mEdgeWidthRight=" + mEdgeWidthRight);
-        pw.println("  mIsNavBarShownTransiently=" + mIsNavBarShownTransiently);
-        pw.println("  mPredictionLog=" + String.join(";", mPredictionLog));
+        pw.println("  mLeftInset=" + mLeftInset);
+        pw.println("  mRightInset=" + mRightInset);
+        pw.println("  mMLEnableWidth=" + mMLEnableWidth);
+        pw.println("  mMLModelThreshold=" + mMLModelThreshold);
+        pw.println("  mTouchSlop=" + mTouchSlop);
+        pw.println("  mBottomGestureHeight=" + mBottomGestureHeight);
+        pw.println("  mPredictionLog=" + String.join("\n", mPredictionLog));
+        pw.println("  mGestureLog=" + String.join("\n", mGestureLog));
         pw.println("  mEdgeBackPlugin=" + mEdgeBackPlugin);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
index 2f9b17a..2ea8657 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
@@ -19,8 +19,6 @@
 import static android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID;
 import static android.appwidget.AppWidgetManager.INVALID_APPWIDGET_ID;
 
-import static com.android.systemui.people.PeopleSpaceUtils.getUserHandle;
-
 import android.app.Activity;
 import android.app.INotificationManager;
 import android.app.people.IPeopleManager;
@@ -155,7 +153,7 @@
                 if (DEBUG) Log.d(TAG, "Caching shortcut for PeopleTile: " + tile.getId());
                 mLauncherApps.cacheShortcuts(tile.getPackageName(),
                         Collections.singletonList(tile.getId()),
-                        getUserHandle(tile), LauncherApps.FLAG_CACHE_PEOPLE_TILE_SHORTCUTS);
+                        tile.getUserHandle(), LauncherApps.FLAG_CACHE_PEOPLE_TILE_SHORTCUTS);
             } catch (Exception e) {
                 Log.w(TAG, "Exception caching shortcut:" + e);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceTileView.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceTileView.java
index 9ae7847..6f89332 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceTileView.java
@@ -21,7 +21,6 @@
 import android.content.pm.LauncherApps;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
-import android.os.UserHandle;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -82,7 +81,7 @@
     public void setOnClickListener(LauncherApps launcherApps, PeopleSpaceTile tile) {
         mTileView.setOnClickListener(v ->
                 launcherApps.startShortcut(tile.getPackageName(), tile.getId(), null, null,
-                        UserHandle.getUserHandleForUid(tile.getUid())));
+                        tile.getUserHandle()));
     }
 
     /** Sets the click listener of the tile directly. */
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
index cd1131b..41080af 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.people;
 
+import static android.app.Notification.CATEGORY_MISSED_CALL;
 import static android.app.Notification.EXTRA_MESSAGES;
 import static android.app.people.ConversationStatus.ACTIVITY_ANNIVERSARY;
 import static android.app.people.ConversationStatus.ACTIVITY_BIRTHDAY;
@@ -54,7 +55,6 @@
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.os.ServiceManager;
-import android.os.UserHandle;
 import android.provider.ContactsContract;
 import android.provider.Settings;
 import android.service.notification.ConversationChannelWrapper;
@@ -159,7 +159,6 @@
         List<ConversationChannelWrapper> conversations =
                 notificationManager.getConversations(
                         false).getList();
-
         // Add priority conversations to tiles list.
         Stream<ShortcutInfo> priorityConversations = conversations.stream()
                 .filter(c -> c.getNotificationChannel() != null
@@ -189,7 +188,7 @@
             tiles.addAll(recentTiles);
         }
 
-        tiles = augmentTilesFromVisibleNotifications(tiles, notificationEntryManager);
+        tiles = augmentTilesFromVisibleNotifications(context, tiles, notificationEntryManager);
         return tiles;
     }
 
@@ -251,7 +250,11 @@
             }
 
             // If tile is null, we need to retrieve from persisted storage.
-            if (DEBUG) Log.d(TAG, "Retrieving from storage after reboots");
+            if (DEBUG) {
+                Log.d(TAG,
+                        "Retrieving from storage after reboots: " + shortcutId + " user: " + userId
+                                + " pkg: " + pkg);
+            }
             LauncherApps launcherApps = context.getSystemService(LauncherApps.class);
             ConversationChannel channel = peopleManager.getConversation(pkg, userId, shortcutId);
             if (channel == null) {
@@ -357,8 +360,8 @@
                 && storedUserId == userId;
     }
 
-    static List<PeopleSpaceTile> augmentTilesFromVisibleNotifications(List<PeopleSpaceTile> tiles,
-            NotificationEntryManager notificationEntryManager) {
+    static List<PeopleSpaceTile> augmentTilesFromVisibleNotifications(Context context,
+            List<PeopleSpaceTile> tiles, NotificationEntryManager notificationEntryManager) {
         if (notificationEntryManager == null) {
             Log.w(TAG, "NotificationEntryManager is null");
             return tiles;
@@ -374,22 +377,23 @@
         }
         return tiles
                 .stream()
-                .map(entry -> augmentTileFromVisibleNotifications(entry, visibleNotifications))
+                .map(entry -> augmentTileFromVisibleNotifications(
+                        context, entry, visibleNotifications))
                 .collect(Collectors.toList());
     }
 
-    static PeopleSpaceTile augmentTileFromVisibleNotifications(PeopleSpaceTile tile,
-            Map<String, NotificationEntry> visibleNotifications) {
+    static PeopleSpaceTile augmentTileFromVisibleNotifications(Context context,
+            PeopleSpaceTile tile, Map<String, NotificationEntry> visibleNotifications) {
         String shortcutId = tile.getId();
         String packageName = tile.getPackageName();
-        int userId = UserHandle.getUserHandleForUid(tile.getUid()).getIdentifier();
+        int userId = getUserId(tile);
         String key = getKey(shortcutId, packageName, userId);
         if (!visibleNotifications.containsKey(key)) {
             if (DEBUG) Log.d(TAG, "No existing notifications for key:" + key);
             return tile;
         }
         if (DEBUG) Log.d(TAG, "Augmenting tile from visible notifications, key:" + key);
-        return augmentTileFromNotification(tile, visibleNotifications.get(key).getSbn());
+        return augmentTileFromNotification(context, tile, visibleNotifications.get(key).getSbn());
     }
 
     /**
@@ -408,7 +412,7 @@
         }
         if (notificationAction == PeopleSpaceUtils.NotificationAction.POSTED) {
             if (DEBUG) Log.i(TAG, "Adding notification to storage, appWidgetId: " + appWidgetId);
-            storedTile = augmentTileFromNotification(storedTile, sbn);
+            storedTile = augmentTileFromNotification(context, storedTile, sbn);
         } else {
             if (DEBUG) {
                 Log.i(TAG, "Removing notification from storage, appWidgetId: " + appWidgetId);
@@ -418,23 +422,40 @@
                     .setNotificationKey(null)
                     .setNotificationContent(null)
                     .setNotificationDataUri(null)
+                    .setNotificationCategory(null)
                     .build();
         }
         updateAppWidgetOptionsAndView(appWidgetManager, context, appWidgetId, storedTile);
     }
 
-    static PeopleSpaceTile augmentTileFromNotification(PeopleSpaceTile tile,
+    static PeopleSpaceTile augmentTileFromNotification(Context context, PeopleSpaceTile tile,
             StatusBarNotification sbn) {
-        Notification.MessagingStyle.Message message = getLastMessagingStyleMessage(sbn);
-        if (message == null) {
-            if (DEBUG) Log.i(TAG, "Notification doesn't have content, skipping.");
+        Notification notification = sbn.getNotification();
+        if (notification == null) {
+            if (DEBUG) Log.d(TAG, "Notification is null");
             return tile;
         }
+        boolean isMissedCall = Objects.equals(notification.category, CATEGORY_MISSED_CALL);
+        Notification.MessagingStyle.Message message = getLastMessagingStyleMessage(notification);
+
+        if (!isMissedCall && message == null) {
+            if (DEBUG) Log.d(TAG, "Notification has no content");
+            return tile;
+        }
+
+        // If it's a missed call notification and it doesn't include content, use fallback value,
+        // otherwise, use notification content.
+        boolean hasMessageText = message != null && !TextUtils.isEmpty(message.getText());
+        CharSequence content = (isMissedCall && !hasMessageText)
+                ? context.getString(R.string.missed_call) : message.getText();
+        Uri dataUri = message != null ? message.getDataUri() : null;
+
         return tile
                 .toBuilder()
                 .setNotificationKey(sbn.getKey())
-                .setNotificationContent(message.getText())
-                .setNotificationDataUri(message.getDataUri())
+                .setNotificationCategory(notification.category)
+                .setNotificationContent(content)
+                .setNotificationDataUri(dataUri)
                 .build();
     }
 
@@ -462,6 +483,11 @@
      * content, then birthdays, then the most recent status, and finally last interaction.
      */
     private static RemoteViews getViewForTile(Context context, PeopleSpaceTile tile) {
+        if (Objects.equals(tile.getNotificationCategory(), CATEGORY_MISSED_CALL)) {
+            if (DEBUG) Log.d(TAG, "Create missed call view");
+            return createMissedCallRemoteViews(context, tile);
+        }
+
         if (tile.getNotificationKey() != null) {
             if (DEBUG) Log.d(TAG, "Create notification view");
             return createNotificationRemoteViews(context, tile);
@@ -617,7 +643,8 @@
             activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_TILE_ID, tile.getId());
             activityIntent.putExtra(
                     PeopleSpaceWidgetProvider.EXTRA_PACKAGE_NAME, tile.getPackageName());
-            activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_UID, tile.getUid());
+            activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_USER_HANDLE,
+                    tile.getUserHandle());
             views.setOnClickPendingIntent(R.id.item, PendingIntent.getActivity(
                     context,
                     appWidgetId,
@@ -630,6 +657,16 @@
         return views;
     }
 
+    private static RemoteViews createMissedCallRemoteViews(Context context,
+            PeopleSpaceTile tile) {
+        RemoteViews views = new RemoteViews(
+                context.getPackageName(), R.layout.people_space_small_avatar_tile);
+        views.setTextViewText(R.id.status, tile.getNotificationContent());
+        views.setImageViewResource(R.id.status_defined_icon, R.drawable.ic_phone_missed);
+        views.setBoolean(R.id.content_background, "setClipToOutline", true);
+        return views;
+    }
+
     private static RemoteViews createNotificationRemoteViews(Context context,
             PeopleSpaceTile tile) {
         RemoteViews views = new RemoteViews(
@@ -715,8 +752,7 @@
     /** Gets the most recent {@link Notification.MessagingStyle.Message} from the notification. */
     @VisibleForTesting
     public static Notification.MessagingStyle.Message getLastMessagingStyleMessage(
-            StatusBarNotification sbn) {
-        Notification notification = sbn.getNotification();
+            Notification notification) {
         if (notification == null) {
             return null;
         }
@@ -755,7 +791,6 @@
             Log.i(TAG, "ConversationChannel is null");
             return null;
         }
-
         PeopleSpaceTile tile = new PeopleSpaceTile.Builder(channel, launcherApps).build();
         if (!PeopleSpaceUtils.shouldKeepConversation(tile)) {
             Log.i(TAG, "PeopleSpaceTile is not valid");
@@ -1036,11 +1071,6 @@
 
     /** Returns the userId associated with a {@link PeopleSpaceTile} */
     public static int getUserId(PeopleSpaceTile tile) {
-        return getUserHandle(tile).getIdentifier();
-    }
-
-    /** Returns the {@link UserHandle} associated with a {@link PeopleSpaceTile} */
-    public static UserHandle getUserHandle(PeopleSpaceTile tile) {
-        return UserHandle.getUserHandleForUid(tile.getUid());
+        return tile.getUserHandle().getIdentifier();
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/LaunchConversationActivity.java b/packages/SystemUI/src/com/android/systemui/people/widget/LaunchConversationActivity.java
index 358f311..13e30f9 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/LaunchConversationActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/LaunchConversationActivity.java
@@ -41,7 +41,8 @@
         Intent intent = getIntent();
         String tileId = intent.getStringExtra(PeopleSpaceWidgetProvider.EXTRA_TILE_ID);
         String packageName = intent.getStringExtra(PeopleSpaceWidgetProvider.EXTRA_PACKAGE_NAME);
-        int uid = intent.getIntExtra(PeopleSpaceWidgetProvider.EXTRA_UID, 0);
+        UserHandle userHandle = intent.getParcelableExtra(
+                PeopleSpaceWidgetProvider.EXTRA_USER_HANDLE);
 
         if (tileId != null && !tileId.isEmpty()) {
             if (DEBUG) {
@@ -52,7 +53,7 @@
                 LauncherApps launcherApps =
                         getApplicationContext().getSystemService(LauncherApps.class);
                 launcherApps.startShortcut(
-                        packageName, tileId, null, null, UserHandle.getUserHandleForUid(uid));
+                        packageName, tileId, null, null, userHandle);
             } catch (Exception e) {
                 Log.e(TAG, "Exception starting shortcut:" + e);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetEnabler.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetEnabler.java
index b188acb..3df2644 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetEnabler.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetEnabler.java
@@ -23,6 +23,7 @@
 
 import com.android.systemui.SystemUI;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.people.PeopleSpaceActivity;
 import com.android.systemui.statusbar.FeatureFlags;
 
 import javax.inject.Inject;
@@ -54,6 +55,12 @@
                             ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
                             : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                     PackageManager.DONT_KILL_APP);
+            mContext.getPackageManager().setComponentEnabledSetting(
+                    new ComponentName(mContext, PeopleSpaceActivity.class),
+                    showPeopleSpace
+                            ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+                            : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                    PackageManager.DONT_KILL_APP);
         } catch (Exception e) {
             Log.w(TAG, "Error enabling People Space widget:", e);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
index bee9889..9e5c786 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
@@ -29,7 +29,6 @@
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
 import android.util.Log;
-import android.widget.RemoteViews;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.appwidget.IAppWidgetService;
@@ -124,8 +123,6 @@
      */
     public void updateWidgetWithNotificationChanged(StatusBarNotification sbn,
             PeopleSpaceUtils.NotificationAction notificationAction) {
-        RemoteViews views = new RemoteViews(
-                mContext.getPackageName(), R.layout.people_space_small_avatar_tile);
         if (DEBUG) Log.d(TAG, "updateWidgetWithNotificationChanged called");
         boolean showSingleConversation = Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java
index 3d1055f..90baf56 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java
@@ -48,7 +48,7 @@
 
     public static final String EXTRA_TILE_ID = "extra_tile_id";
     public static final String EXTRA_PACKAGE_NAME = "extra_package_name";
-    public static final String EXTRA_UID = "extra_uid";
+    public static final String EXTRA_USER_HANDLE = "extra_user_handle";
 
     public UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
 
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetRemoteViewsFactory.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetRemoteViewsFactory.java
index 80794cb..0503522 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetRemoteViewsFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetRemoteViewsFactory.java
@@ -123,7 +123,8 @@
             fillInIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_TILE_ID, tile.getId());
             fillInIntent.putExtra(
                     PeopleSpaceWidgetProvider.EXTRA_PACKAGE_NAME, tile.getPackageName());
-            fillInIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_UID, tile.getUid());
+            fillInIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_USER_HANDLE,
+                    tile.getUserHandle());
             personView.setOnClickFillInIntent(R.id.item, fillInIntent);
         } catch (Exception e) {
             Log.e(TAG, "Couldn't retrieve shortcut information", e);
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java b/packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java
new file mode 100644
index 0000000..0fa7b59
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.privacy.television;
+
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.annotation.IntDef;
+import android.annotation.UiThread;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.WindowManager;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import com.android.systemui.R;
+import com.android.systemui.SystemUI;
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.privacy.PrivacyChipBuilder;
+import com.android.systemui.privacy.PrivacyItem;
+import com.android.systemui.privacy.PrivacyItemController;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+
+import javax.inject.Inject;
+
+/**
+ * A SystemUI component responsible for notifying the user whenever an application is
+ * recording audio, accessing the camera or accessing the location.
+ */
+@SysUISingleton
+public class TvOngoingPrivacyChip extends SystemUI implements PrivacyItemController.Callback {
+    private static final String TAG = "TvOngoingPrivacyChip";
+    static final boolean DEBUG = false;
+
+    // This title is used in CameraMicIndicatorsPermissionTest and
+    // RecognitionServiceMicIndicatorTest.
+    private static final String LAYOUT_PARAMS_TITLE = "MicrophoneCaptureIndicator";
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"STATE_"}, value = {
+            STATE_NOT_SHOWN,
+            STATE_APPEARING,
+            STATE_SHOWN,
+            STATE_DISAPPEARING
+    })
+    public @interface State {
+    }
+
+    private static final int STATE_NOT_SHOWN = 0;
+    private static final int STATE_APPEARING = 1;
+    private static final int STATE_SHOWN = 2;
+    private static final int STATE_DISAPPEARING = 3;
+
+    private static final int ANIMATION_DURATION_MS = 200;
+
+    private final Context mContext;
+    private final PrivacyItemController mPrivacyItemController;
+
+    private View mIndicatorView;
+    private boolean mViewAndWindowAdded;
+    private ObjectAnimator mAnimator;
+
+    private boolean mAllIndicatorsFlagEnabled;
+    private boolean mMicCameraIndicatorFlagEnabled;
+    private boolean mLocationIndicatorEnabled;
+    private List<PrivacyItem> mPrivacyItems;
+
+    private LinearLayout mIconsContainer;
+    private final int mIconSize;
+    private final int mIconMarginStart;
+
+    @State
+    private int mState = STATE_NOT_SHOWN;
+
+    @Inject
+    public TvOngoingPrivacyChip(Context context, PrivacyItemController privacyItemController) {
+        super(context);
+        Log.d(TAG, "Privacy chip running without id");
+        mContext = context;
+        mPrivacyItemController = privacyItemController;
+
+        Resources res = mContext.getResources();
+        mIconMarginStart = Math.round(res.getDimension(R.dimen.privacy_chip_icon_margin));
+        mIconSize = res.getDimensionPixelSize(R.dimen.privacy_chip_icon_size);
+
+        mAllIndicatorsFlagEnabled = privacyItemController.getAllIndicatorsAvailable();
+        mMicCameraIndicatorFlagEnabled = privacyItemController.getMicCameraAvailable();
+        mLocationIndicatorEnabled = privacyItemController.getLocationAvailable();
+
+        if (DEBUG) {
+            Log.d(TAG, "allIndicators: " + mAllIndicatorsFlagEnabled);
+            Log.d(TAG, "micCameraIndicators: " + mMicCameraIndicatorFlagEnabled);
+            Log.d(TAG, "locationIndicators: " + mLocationIndicatorEnabled);
+        }
+    }
+
+    @Override
+    public void start() {
+        mPrivacyItemController.addCallback(this);
+    }
+
+    @Override
+    public void onPrivacyItemsChanged(List<PrivacyItem> privacyItems) {
+        if (DEBUG) Log.d(TAG, "PrivacyItemsChanged");
+        mPrivacyItems = privacyItems;
+        updateUI();
+    }
+
+    @Override
+    public void onFlagAllChanged(boolean flag) {
+        if (DEBUG) Log.d(TAG, "all indicators enabled: " + flag);
+        mAllIndicatorsFlagEnabled = flag;
+    }
+
+    @Override
+    public void onFlagMicCameraChanged(boolean flag) {
+        if (DEBUG) Log.d(TAG, "mic/camera indicators enabled: " + flag);
+        mMicCameraIndicatorFlagEnabled = flag;
+    }
+
+    @Override
+    public void onFlagLocationChanged(boolean flag) {
+        if (DEBUG) Log.d(TAG, "location indicators enabled: " + flag);
+        mLocationIndicatorEnabled = flag;
+    }
+
+    private void updateUI() {
+        if (DEBUG) Log.d(TAG, mPrivacyItems.size() + " privacy items");
+
+        if ((mMicCameraIndicatorFlagEnabled || mAllIndicatorsFlagEnabled
+                || mLocationIndicatorEnabled) && !mPrivacyItems.isEmpty()) {
+            if (mState == STATE_NOT_SHOWN || mState == STATE_DISAPPEARING) {
+                showIndicator();
+            } else {
+                if (DEBUG) Log.d(TAG, "only updating icons");
+                PrivacyChipBuilder builder = new PrivacyChipBuilder(mContext, mPrivacyItems);
+                setIcons(builder.generateIcons(), mIconsContainer);
+                mIconsContainer.requestLayout();
+            }
+        } else {
+            hideIndicatorIfNeeded();
+        }
+    }
+
+    @UiThread
+    private void hideIndicatorIfNeeded() {
+        if (mState == STATE_NOT_SHOWN || mState == STATE_DISAPPEARING) return;
+
+        if (mViewAndWindowAdded) {
+            mState = STATE_DISAPPEARING;
+            animateDisappearance();
+        } else {
+            // Appearing animation has not started yet, as we were still waiting for the View to be
+            // laid out.
+            mState = STATE_NOT_SHOWN;
+            removeIndicatorView();
+        }
+    }
+
+    @UiThread
+    private void showIndicator() {
+        mState = STATE_APPEARING;
+
+        // Inflate the indicator view
+        mIndicatorView = LayoutInflater.from(mContext).inflate(
+                R.layout.tv_ongoing_privacy_chip, null);
+
+        // 1. Set alpha to 0.
+        // 2. Wait until the window is shown and the view is laid out.
+        // 3. Start a "fade in" (alpha) animation.
+        mIndicatorView.setAlpha(0f);
+        mIndicatorView
+                .getViewTreeObserver()
+                .addOnGlobalLayoutListener(
+                        new ViewTreeObserver.OnGlobalLayoutListener() {
+                            @Override
+                            public void onGlobalLayout() {
+                                // State could have changed to NOT_SHOWN (if all the recorders are
+                                // already gone)
+                                if (mState != STATE_APPEARING) return;
+
+                                mViewAndWindowAdded = true;
+                                // Remove the observer
+                                mIndicatorView.getViewTreeObserver().removeOnGlobalLayoutListener(
+                                        this);
+
+                                animateAppearance();
+                            }
+                        });
+
+        mIconsContainer = mIndicatorView.findViewById(R.id.icons_container);
+        PrivacyChipBuilder builder = new PrivacyChipBuilder(mContext, mPrivacyItems);
+        setIcons(builder.generateIcons(), mIconsContainer);
+
+        final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
+                WRAP_CONTENT,
+                WRAP_CONTENT,
+                WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
+                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+                PixelFormat.TRANSLUCENT);
+        layoutParams.gravity = Gravity.TOP | Gravity.END;
+        layoutParams.setTitle(LAYOUT_PARAMS_TITLE);
+        layoutParams.packageName = mContext.getPackageName();
+        final WindowManager windowManager = mContext.getSystemService(WindowManager.class);
+        windowManager.addView(mIndicatorView, layoutParams);
+
+    }
+
+    private void setIcons(List<Drawable> icons, ViewGroup iconsContainer) {
+        iconsContainer.removeAllViews();
+        for (int i = 0; i < icons.size(); i++) {
+            Drawable icon = icons.get(i);
+            icon.mutate().setTint(Color.WHITE);
+            ImageView imageView = new ImageView(mContext);
+            imageView.setImageDrawable(icon);
+            imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
+            mIconsContainer.addView(imageView, mIconSize, mIconSize);
+            if (i != 0) {
+                ViewGroup.MarginLayoutParams layoutParams =
+                        (ViewGroup.MarginLayoutParams) imageView.getLayoutParams();
+                layoutParams.setMarginStart(mIconMarginStart);
+                imageView.setLayoutParams(layoutParams);
+            }
+        }
+    }
+
+    private void animateAppearance() {
+        animateAlphaTo(1f);
+    }
+
+    private void animateDisappearance() {
+        animateAlphaTo(0f);
+    }
+
+    private void animateAlphaTo(final float endValue) {
+        if (mAnimator == null) {
+            if (DEBUG) Log.d(TAG, "set up animator");
+
+            mAnimator = new ObjectAnimator();
+            mAnimator.setTarget(mIndicatorView);
+            mAnimator.setProperty(View.ALPHA);
+            mAnimator.addListener(new AnimatorListenerAdapter() {
+                boolean mCancelled;
+
+                @Override
+                public void onAnimationStart(Animator animation, boolean isReverse) {
+                    if (DEBUG) Log.d(TAG, "AnimatorListenerAdapter#onAnimationStart");
+                    mCancelled = false;
+                }
+
+                @Override
+                public void onAnimationCancel(Animator animation) {
+                    if (DEBUG) Log.d(TAG, "AnimatorListenerAdapter#onAnimationCancel");
+                    mCancelled = true;
+                }
+
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    if (DEBUG) Log.d(TAG, "AnimatorListenerAdapter#onAnimationEnd");
+                    // When ValueAnimator#cancel() is called it always calls onAnimationCancel(...)
+                    // and then onAnimationEnd(...). We, however, only want to proceed here if the
+                    // animation ended "naturally".
+                    if (!mCancelled) {
+                        onAnimationFinished();
+                    }
+                }
+            });
+        } else if (mAnimator.isRunning()) {
+            if (DEBUG) Log.d(TAG, "cancel running animation");
+            mAnimator.cancel();
+        }
+
+        final float currentValue = mIndicatorView.getAlpha();
+        if (DEBUG) Log.d(TAG, "animate alpha to " + endValue + " from " + currentValue);
+
+        mAnimator.setDuration((int) (Math.abs(currentValue - endValue) * ANIMATION_DURATION_MS));
+        mAnimator.setFloatValues(endValue);
+        mAnimator.start();
+    }
+
+    private void onAnimationFinished() {
+        if (DEBUG) Log.d(TAG, "onAnimationFinished");
+
+        if (mState == STATE_APPEARING) {
+            mState = STATE_SHOWN;
+        } else if (mState == STATE_DISAPPEARING) {
+            removeIndicatorView();
+            mState = STATE_NOT_SHOWN;
+        }
+    }
+
+    private void removeIndicatorView() {
+        if (DEBUG) Log.d(TAG, "removeIndicatorView");
+
+        final WindowManager windowManager = mContext.getSystemService(WindowManager.class);
+        if (windowManager != null) {
+            windowManager.removeView(mIndicatorView);
+        }
+
+        mIndicatorView = null;
+        mAnimator = null;
+
+        mViewAndWindowAdded = false;
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index eaf2123..fcb56a4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -71,7 +71,6 @@
     private int mMinRows = 1;
     private int mMaxColumns = TileLayout.NO_MAX_COLUMNS;
 
-    private boolean mShowLabels = true;
     private final boolean mSideLabels;
 
     public PagedTileLayout(Context context, AttributeSet attrs) {
@@ -91,16 +90,6 @@
     }
     private int mLastMaxHeight = -1;
 
-    @Override
-    public void setShowLabels(boolean show) {
-        mShowLabels = show;
-        for (TileLayout p : mPages) {
-            p.setShowLabels(show);
-        }
-        mDistributeTiles = true;
-        requestLayout();
-    }
-
     public void saveInstanceState(Bundle outState) {
         outState.putInt(CURRENT_PAGE, getCurrentItem());
     }
@@ -239,7 +228,6 @@
                         : R.layout.qs_paged_page, this, false);
         page.setMinRows(mMinRows);
         page.setMaxColumns(mMaxColumns);
-        page.setShowLabels(mShowLabels);
         return page;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index c8edaec..fe76668 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -29,7 +29,6 @@
 import com.android.systemui.qs.TouchAnimator.Builder;
 import com.android.systemui.qs.TouchAnimator.Listener;
 import com.android.systemui.qs.dagger.QSScope;
-import com.android.systemui.qs.tileimpl.QSTileBaseView;
 import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
@@ -56,7 +55,8 @@
     private final ArrayList<View> mAllViews = new ArrayList<>();
     /**
      * List of {@link View}s representing Quick Settings that are being animated from the quick QS
-     * position to the normal QS panel.
+     * position to the normal QS panel. These views will only show once the animation is complete,
+     * to prevent overlapping of semi transparent views
      */
     private final ArrayList<View> mQuickQsViews = new ArrayList<>();
     private final QuickQSPanel mQuickQsPanel;
@@ -233,7 +233,6 @@
                 // Quick tiles.
                 QSTileView quickTileView = mQuickQSPanelController.getTileView(tile);
                 if (quickTileView == null) continue;
-                View qqsBgCircle = ((QSTileBaseView) quickTileView).getBgCircle();
 
                 getRelativePosition(loc1, quickTileView.getIcon().getIconView(), view);
                 getRelativePosition(loc2, tileIcon, view);
@@ -255,11 +254,6 @@
                     translationXBuilder.addFloat(tileView, "translationX", -xDiff, 0);
                     translationYBuilder.addFloat(tileView, "translationY", -yDiff, 0);
 
-                    if (mFeatureFlags.isQSLabelsEnabled()) {
-                        firstPageBuilder.addFloat(qqsBgCircle, "alpha", 1, 1, 0);
-                        mAllViews.add(qqsBgCircle);
-                    }
-
                 } else { // These tiles disappear when expanding
                     firstPageBuilder.addFloat(quickTileView, "alpha", 1, 0);
                     translationYBuilder.addFloat(quickTileView, "translationY", 0, yDiff);
@@ -271,7 +265,11 @@
                             translationX);
                 }
 
-                mQuickQsViews.add(tileView.getIconWithBackground());
+                if (mFeatureFlags.isQSLabelsEnabled()) {
+                    mQuickQsViews.add(tileView);
+                } else {
+                    mQuickQsViews.add(tileView.getIconWithBackground());
+                }
                 mAllViews.add(tileView.getIcon());
                 mAllViews.add(quickTileView);
             } else if (mFullRows && isIconInAnimatedRow(count)) {
@@ -362,7 +360,7 @@
         if(view == parent || view == null) return;
         // Ignore tile pages as they can have some offset we don't want to take into account in
         // RTL.
-        if (!(view instanceof PagedTileLayout.TilePage || view instanceof SideLabelTileLayout)) {
+        if (!isAPage(view)) {
             loc1[0] += view.getLeft();
             loc1[1] += view.getTop();
         }
@@ -374,6 +372,16 @@
         getRelativePositionInt(loc1, (View) view.getParent(), parent);
     }
 
+    // Returns true if the view is a possible page in PagedTileLayout
+    private boolean isAPage(View view) {
+        if (view instanceof PagedTileLayout.TilePage) {
+            return true;
+        } else if (view instanceof SideLabelTileLayout) {
+            return !(view instanceof QuickQSPanel.QQSSideLabelTileLayout);
+        }
+        return false;
+    }
+
     public void setPosition(float position) {
         if (mNeedsAnimatorUpdate) {
             updateAnimators();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
index 8110fda..2bea72c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.qs;
 
+import static com.android.systemui.qs.dagger.QSFlagsModule.PM_LITE_ENABLED;
+
 import android.content.ClipData;
 import android.content.ClipboardManager;
 import android.content.Intent;
@@ -41,6 +43,7 @@
 import com.android.systemui.util.ViewController;
 
 import javax.inject.Inject;
+import javax.inject.Named;
 
 /**
  * Controller for {@link QSFooterView}.
@@ -63,6 +66,8 @@
     private final View mEdit;
     private final MultiUserSwitch mMultiUserSwitch;
     private final PageIndicator mPageIndicator;
+    private final View mPowerMenuLite;
+    private final boolean mShowPMLiteButton;
 
     private final UserInfoController.OnUserInfoChangedListener mOnUserInfoChangedListener =
             new UserInfoController.OnUserInfoChangedListener() {
@@ -95,7 +100,6 @@
                     mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
                         if (isTunerEnabled()) {
                             mTunerService.showResetRequest(
-                                    mUserTracker.getUserHandle(),
                                     () -> {
                                         // Relaunch settings so that the tuner disappears.
                                         startSettingsActivity();
@@ -103,7 +107,7 @@
                         } else {
                             Toast.makeText(getContext(), R.string.tuner_toast,
                                     Toast.LENGTH_LONG).show();
-                            mTunerService.setTunerEnabled(mUserTracker.getUserHandle(), true);
+                            mTunerService.setTunerEnabled(true);
                         }
                         startSettingsActivity();
 
@@ -124,7 +128,8 @@
             DeviceProvisionedController deviceProvisionedController, UserTracker userTracker,
             QSPanelController qsPanelController, QSDetailDisplayer qsDetailDisplayer,
             QuickQSPanelController quickQSPanelController,
-            TunerService tunerService, MetricsLogger metricsLogger) {
+            TunerService tunerService, MetricsLogger metricsLogger,
+            @Named(PM_LITE_ENABLED) boolean showPMLiteButton) {
         super(view);
         mUserManager = userManager;
         mUserInfoController = userInfoController;
@@ -142,10 +147,15 @@
         mEdit = mView.findViewById(android.R.id.edit);
         mMultiUserSwitch = mView.findViewById(R.id.multi_user_switch);
         mPageIndicator = mView.findViewById(R.id.footer_page_indicator);
+        mPowerMenuLite = mView.findViewById(R.id.pm_lite);
+        mShowPMLiteButton = showPMLiteButton;
     }
 
     @Override
     protected void onViewAttached() {
+        if (mShowPMLiteButton) {
+            mPowerMenuLite.setVisibility(View.VISIBLE);
+        }
         mView.addOnLayoutChangeListener(
                 (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
                         mView.updateAnimator(
@@ -238,6 +248,6 @@
     }
 
     private boolean isTunerEnabled() {
-        return mTunerService.isTunerEnabled(mUserTracker.getUserHandle());
+        return mTunerService.isTunerEnabled();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 91ae571..7657dce 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -112,7 +112,7 @@
     private int mMediaTotalBottomMargin;
     private int mFooterMarginStartHorizontal;
     private Consumer<Boolean> mMediaVisibilityChangedListener;
-    private boolean mSideLabels;
+    protected boolean mSideLabels;
 
     public QSPanel(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -201,16 +201,20 @@
                 mFooterPageIndicator.setNumPages(((PagedTileLayout) mTileLayout).getNumPages());
             }
 
-            // Allow the UI to be as big as it want's to, we're in a scroll view
-            int newHeight = 10000;
-            int availableHeight = MeasureSpec.getSize(heightMeasureSpec);
-            int excessHeight = newHeight - availableHeight;
-            // Measure with EXACTLY. That way, The content will only use excess height and will
-            // be measured last, after other views and padding is accounted for. This only
-            // works because our Layouts in here remeasure themselves with the exact content
-            // height.
-            heightMeasureSpec = MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.EXACTLY);
-            ((PagedTileLayout) mTileLayout).setExcessHeight(excessHeight);
+            // In landscape, mTileLayout's parent is not the panel but a view that contains the
+            // tile layout and the media controls.
+            if (((View) mTileLayout).getParent() == this) {
+                // Allow the UI to be as big as it want's to, we're in a scroll view
+                int newHeight = 10000;
+                int availableHeight = MeasureSpec.getSize(heightMeasureSpec);
+                int excessHeight = newHeight - availableHeight;
+                // Measure with EXACTLY. That way, The content will only use excess height and will
+                // be measured last, after other views and padding is accounted for. This only
+                // works because our Layouts in here remeasure themselves with the exact content
+                // height.
+                heightMeasureSpec = MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.EXACTLY);
+                ((PagedTileLayout) mTileLayout).setExcessHeight(excessHeight);
+            }
         }
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
@@ -758,7 +762,7 @@
                 // Let's use 3 columns to match the current layout
                 int columns;
                 if (mSideLabels) {
-                    columns = horizontal ? 1 : 2;
+                    columns = horizontal ? 2 : 4;
                 } else {
                     columns = horizontal ? 3 : TileLayout.NO_MAX_COLUMNS;
                 }
@@ -843,8 +847,6 @@
         default void setExpansion(float expansion) {}
 
         int getNumVisibleTiles();
-
-        default void setShowLabels(boolean show) {}
     }
 
     interface OnConfigurationChangedListener {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index fcb35e2..eda1abb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -18,7 +18,6 @@
 
 import static com.android.systemui.media.dagger.MediaModule.QS_PANEL;
 import static com.android.systemui.qs.QSPanel.QS_SHOW_BRIGHTNESS;
-import static com.android.systemui.qs.dagger.QSFlagsModule.QS_LABELS_FLAG;
 import static com.android.systemui.qs.dagger.QSFragmentModule.QS_USING_MEDIA_PLAYER;
 
 import android.annotation.NonNull;
@@ -66,7 +65,6 @@
 
     private BrightnessMirrorController mBrightnessMirrorController;
     private boolean mGridContentVisible = true;
-    private boolean mQsLabelsFlag;
 
     private final QSPanel.OnConfigurationChangedListener mOnConfigurationChangedListener =
             new QSPanel.OnConfigurationChangedListener() {
@@ -93,7 +91,6 @@
             DumpManager dumpManager, MetricsLogger metricsLogger, UiEventLogger uiEventLogger,
             QSLogger qsLogger, BrightnessController.Factory brightnessControllerFactory,
             BrightnessSlider.Factory brightnessSliderFactory,
-            @Named(QS_LABELS_FLAG) boolean qsLabelsFlag,
             FeatureFlags featureFlags) {
         super(view, qstileHost, qsCustomizerController, usingMediaPlayer, mediaHost,
                 metricsLogger, uiEventLogger, qsLogger, dumpManager, featureFlags);
@@ -108,9 +105,6 @@
         mView.setBrightnessView(mBrightnessSlider.getRootView());
 
         mBrightnessController = brightnessControllerFactory.create(mBrightnessSlider);
-
-        mQsLabelsFlag = qsLabelsFlag;
-        mSideLabels = qsLabelsFlag;
     }
 
     @Override
@@ -130,7 +124,6 @@
         updateMediaDisappearParameters();
 
         mTunerService.addTunable(mView, QS_SHOW_BRIGHTNESS);
-        mTunerService.addTunable(mTunable, QS_REMOVE_LABELS);
         mView.updateResources();
         if (mView.isListening()) {
             refreshAllTiles();
@@ -144,13 +137,6 @@
     }
 
     @Override
-    boolean switchTileLayout(boolean force) {
-        boolean result = super.switchTileLayout(force);
-        getTileLayout().setShowLabels(mShowLabels);
-        return result;
-    }
-
-    @Override
     protected QSTileRevealController createTileRevealController() {
         return mQsTileRevealControllerFactory.create(
                 this, (PagedTileLayout) mView.createRegularTileLayout());
@@ -158,7 +144,6 @@
 
     @Override
     protected void onViewDetached() {
-        mTunerService.removeTunable(mTunable);
         mTunerService.removeTunable(mView);
         mView.removeOnConfigurationChangedListener(mOnConfigurationChangedListener);
         if (mBrightnessMirrorController != null) {
@@ -324,22 +309,5 @@
     public boolean isExpanded() {
         return mView.isExpanded();
     }
-
-    private TunerService.Tunable mTunable = new TunerService.Tunable() {
-        @Override
-        public void onTuningChanged(String key, String newValue) {
-            if (QS_REMOVE_LABELS.equals(key)) {
-                if (!mQsLabelsFlag) return;
-                boolean newShowLabels = newValue == null || "0".equals(newValue);
-                if (mShowLabels == newShowLabels) return;
-                mShowLabels = newShowLabels;
-                for (TileRecord t : mRecords) {
-                    t.tileView.setShowLabels(mShowLabels);
-                }
-                getTileLayout().setShowLabels(mShowLabels);
-                mView.requestLayout();
-            }
-        }
-    };
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index 9426e71..8ab1743 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -75,7 +75,7 @@
 
     private final QSHost.Callback mQSHostCallback = this::setTiles;
     protected boolean mShowLabels = true;
-    protected boolean mSideLabels;
+    protected boolean mQSLabelFlag;
 
     private final QSPanel.OnConfigurationChangedListener mOnConfigurationChangedListener =
             new QSPanel.OnConfigurationChangedListener() {
@@ -118,11 +118,12 @@
         mQSLogger = qsLogger;
         mDumpManager = dumpManager;
         mFeatureFlags = featureFlags;
+        mQSLabelFlag = featureFlags.isQSLabelsEnabled();
     }
 
     @Override
     protected void onInit() {
-        mView.initialize(mSideLabels);
+        mView.initialize(mQSLabelFlag);
         mQSLogger.logAllTilesChangeListening(mView.isListening(), mView.getDumpableTag(), "");
     }
 
@@ -197,7 +198,6 @@
         final TileRecord r = new TileRecord();
         r.tile = tile;
         r.tileView = mHost.createTileView(tile, collapsedView);
-        r.tileView.setShowLabels(mShowLabels);
         mView.addTile(r);
         mRecords.add(r);
         mCachedSpecs = getTilesSpecs();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index a29ac3b..9b66b59 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -69,12 +69,22 @@
 
     @Override
     public TileLayout createRegularTileLayout() {
-        return new QuickQSPanel.HeaderTileLayout(mContext);
+        if (mSideLabels) {
+            return new QQSSideLabelTileLayout(mContext);
+        } else {
+            return new QuickQSPanel.HeaderTileLayout(mContext);
+        }
     }
 
     @Override
     protected QSTileLayout createHorizontalTileLayout() {
-        return new DoubleLineTileLayout(mContext);
+        if (mSideLabels) {
+            TileLayout t = createRegularTileLayout();
+            t.setMaxColumns(2);
+            return t;
+        } else {
+            return new DoubleLineTileLayout(mContext);
+        }
     }
 
     @Override
@@ -331,4 +341,38 @@
             }
         }
     }
+
+    static class QQSSideLabelTileLayout extends SideLabelTileLayout {
+        QQSSideLabelTileLayout(Context context) {
+            super(context, null);
+            setClipChildren(false);
+            setClipToPadding(false);
+            LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
+                    LayoutParams.WRAP_CONTENT);
+            lp.gravity = Gravity.CENTER_HORIZONTAL;
+            setLayoutParams(lp);
+            setMaxColumns(4);
+        }
+
+        @Override
+        public boolean updateResources() {
+            boolean b = super.updateResources();
+            mMaxAllowedRows = 2;
+            return b;
+        }
+
+        @Override
+        protected void onConfigurationChanged(Configuration newConfig) {
+            super.onConfigurationChanged(newConfig);
+            updateResources();
+        }
+
+        @Override
+        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            // Make sure to always use the correct number of rows. As it's determined by the
+            // columns, just use as many as needed.
+            updateMaxRows(10000, mRecords.size());
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
index 383e932..671f8f7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
@@ -17,7 +17,6 @@
 package com.android.systemui.qs;
 
 import static com.android.systemui.media.dagger.MediaModule.QUICK_QS_PANEL;
-import static com.android.systemui.qs.dagger.QSFlagsModule.QS_LABELS_FLAG;
 import static com.android.systemui.qs.dagger.QSFragmentModule.QS_USING_MEDIA_PLAYER;
 
 import com.android.internal.logging.MetricsLogger;
@@ -42,8 +41,6 @@
 @QSScope
 public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> {
 
-    private boolean mUseSideLabels;
-
     private final QSPanel.OnConfigurationChangedListener mOnConfigurationChangedListener =
             newConfig -> {
                 int newMaxTiles = getResources().getInteger(R.integer.quick_qs_panel_max_columns);
@@ -58,12 +55,10 @@
             @Named(QS_USING_MEDIA_PLAYER) boolean usingMediaPlayer,
             @Named(QUICK_QS_PANEL) MediaHost mediaHost,
             MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger,
-            DumpManager dumpManager, @Named(QS_LABELS_FLAG) boolean qsLabelsFlag,
-            FeatureFlags featureFlags
+            DumpManager dumpManager, FeatureFlags featureFlags
     ) {
         super(view, qsTileHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger,
                 uiEventLogger, qsLogger, dumpManager, featureFlags);
-        mUseSideLabels = qsLabelsFlag;
     }
 
     @Override
@@ -104,19 +99,7 @@
                 break;
             }
         }
-        if (mUseSideLabels) {
-            List<QSTile> newTiles = new ArrayList<>();
-            for (int i = 0; i < tiles.size(); i += 2) {
-                newTiles.add(tiles.get(i));
-            }
-            for (int i = 1; i < tiles.size(); i += 2) {
-                newTiles.add(tiles.get(i));
-            }
-            super.setTiles(newTiles, true);
-
-        } else {
-            super.setTiles(tiles, true);
-        }
+        super.setTiles(tiles, !mQSLabelFlag);
     }
 
     /** */
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 87252ff..a0bf584 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -90,6 +90,7 @@
     private OngoingPrivacyChip mPrivacyChip;
     private Space mSpace;
     private BatteryMeterView mBatteryRemainingIcon;
+    private TintedIconManager mTintedIconManager;
 
     // Used for RingerModeTracker
     private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
@@ -144,6 +145,7 @@
     }
 
     void onAttach(TintedIconManager iconManager) {
+        mTintedIconManager = iconManager;
         int fillColor = Utils.getColorAttrDefaultColor(getContext(),
                 android.R.attr.textColorPrimary);
 
@@ -268,6 +270,9 @@
                     android.R.attr.textColorSecondary);
             mTextColorPrimary = textColor;
             mClockView.setTextColor(textColor);
+            if (mTintedIconManager != null) {
+                mTintedIconManager.setTint(textColor);
+            }
             mBatteryRemainingIcon.updateColors(mTextColorPrimary, textColorSecondary,
                     mTextColorPrimary);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt
index 74a7ac1..c3cc3af 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt
@@ -20,11 +20,13 @@
 import android.util.AttributeSet
 import com.android.systemui.R
 
-open class SideLabelTileLayout(context: Context, attrs: AttributeSet) : TileLayout(context, attrs) {
+open class SideLabelTileLayout(
+    context: Context,
+    attrs: AttributeSet?
+) : TileLayout(context, attrs) {
 
     override fun updateResources(): Boolean {
         return super.updateResources().also {
-            mResourceColumns = 2
             mMaxAllowedRows = 4
             mCellMarginHorizontal = (mCellMarginHorizontal * 1.2).toInt()
             mCellMarginVertical = mCellMarginHorizontal
@@ -32,8 +34,6 @@
         }
     }
 
-    override fun setShowLabels(show: Boolean) { }
-
     override fun isFull(): Boolean {
         return mRecords.size >= maxTiles()
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index d559e07..c1ce4a5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -36,7 +36,6 @@
     private int mCellMarginTop;
     protected boolean mListening;
     protected int mMaxAllowedRows = 3;
-    private boolean mShowLabels = true;
 
     // Prototyping with less rows
     private final boolean mLessRows;
@@ -57,12 +56,6 @@
     }
 
     @Override
-    public void setShowLabels(boolean show) {
-        mShowLabels = show;
-        updateResources();
-    }
-
-    @Override
     public int getOffsetTop(TileRecord tile) {
         return getTop();
     }
@@ -124,15 +117,13 @@
     public boolean updateResources() {
         final Resources res = mContext.getResources();
         mResourceColumns = Math.max(1, res.getInteger(R.integer.quick_settings_num_columns));
+        updateColumns();
         mMaxCellHeight = mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_height);
         mCellMarginHorizontal = res.getDimensionPixelSize(R.dimen.qs_tile_margin_horizontal);
         mCellMarginVertical= res.getDimensionPixelSize(R.dimen.qs_tile_margin_vertical);
-        if (!mShowLabels && mCellMarginVertical == 0) {
-            mCellMarginVertical = mCellMarginHorizontal;
-        }
         mCellMarginTop = res.getDimensionPixelSize(R.dimen.qs_tile_margin_top);
         mMaxAllowedRows = Math.max(1, getResources().getInteger(R.integer.quick_settings_max_rows));
-        if (mLessRows && mShowLabels) mMaxAllowedRows = Math.max(mMinRows, mMaxAllowedRows - 1);
+        if (mLessRows) mMaxAllowedRows = Math.max(mMinRows, mMaxAllowedRows - 1);
         if (updateColumns()) {
             requestLayout();
             return true;
@@ -193,9 +184,8 @@
                 + mCellMarginVertical;
         final int previousRows = mRows;
         mRows = availableHeight / (getCellHeight() + mCellMarginVertical);
-        final int minRows = mShowLabels ? mMinRows : mMinRows + 1;
-        if (mRows < minRows) {
-            mRows = minRows;
+        if (mRows < mMinRows) {
+            mRows = mMinRows;
         } else if (mRows >= mMaxAllowedRows) {
             mRows = mMaxAllowedRows;
         }
@@ -215,7 +205,7 @@
     }
 
     protected int getCellHeight() {
-        return mShowLabels ? mMaxCellHeight : mMaxCellHeight / 2;
+        return mMaxCellHeight;
     }
 
     protected void layoutTileRecords(int numRecords) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java
index aa6bbbd..0dc0b30 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java
@@ -34,7 +34,7 @@
 
 import androidx.annotation.VisibleForTesting;
 
-import com.android.keyguard.CarrierTextManager;
+import com.android.keyguard.CarrierTextController;
 import com.android.settingslib.AccessibilityContentDescriptions;
 import com.android.settingslib.mobile.TelephonyIcons;
 import com.android.systemui.R;
@@ -42,6 +42,7 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators;
 
 import java.util.function.Consumer;
 
@@ -58,7 +59,7 @@
     private final ActivityStarter mActivityStarter;
     private final Handler mBgHandler;
     private final NetworkController mNetworkController;
-    private final CarrierTextManager mCarrierTextManager;
+    private final CarrierTextController mCarrierTextController;
     private final TextView mNoSimTextView;
     private final H mMainHandler;
     private final Callback mCallback;
@@ -74,30 +75,25 @@
     private final NetworkController.SignalCallback mSignalCallback =
             new NetworkController.SignalCallback() {
                 @Override
-                public void setMobileDataIndicators(NetworkController.IconState statusIcon,
-                        NetworkController.IconState qsIcon, int statusType, int qsType,
-                        boolean activityIn, boolean activityOut,
-                        CharSequence typeContentDescription,
-                        CharSequence typeContentDescriptionHtml, CharSequence description,
-                        boolean isWide, int subId, boolean roaming, boolean showTriangle) {
+                public void setMobileDataIndicators(MobileDataIndicators indicators) {
                     if (mProviderModel) {
                         return;
                     }
-                    int slotIndex = getSlotIndex(subId);
+                    int slotIndex = getSlotIndex(indicators.subId);
                     if (slotIndex >= SIM_SLOTS) {
                         Log.w(TAG, "setMobileDataIndicators - slot: " + slotIndex);
                         return;
                     }
                     if (slotIndex == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
-                        Log.e(TAG, "Invalid SIM slot index for subscription: " + subId);
+                        Log.e(TAG, "Invalid SIM slot index for subscription: " + indicators.subId);
                         return;
                     }
                     mInfos[slotIndex] = new CellSignalState(
-                            statusIcon.visible,
-                            statusIcon.icon,
-                            statusIcon.contentDescription,
-                            typeContentDescription.toString(),
-                            roaming
+                            indicators.statusIcon.visible,
+                            indicators.statusIcon.icon,
+                            indicators.statusIcon.contentDescription,
+                            indicators.typeContentDescription.toString(),
+                            indicators.roaming
                     );
                     mMainHandler.obtainMessage(H.MSG_UPDATE_STATE).sendToTarget();
                 }
@@ -153,7 +149,7 @@
                 }
             };
 
-    private static class Callback implements CarrierTextManager.CarrierTextCallback {
+    private static class Callback implements CarrierTextController.CarrierTextCallback {
         private H mHandler;
 
         Callback(H handler) {
@@ -161,7 +157,7 @@
         }
 
         @Override
-        public void updateCarrierInfo(CarrierTextManager.CarrierTextCallbackInfo info) {
+        public void updateCarrierInfo(CarrierTextController.CarrierTextCallbackInfo info) {
             mHandler.obtainMessage(H.MSG_UPDATE_CARRIER_INFO, info).sendToTarget();
         }
     }
@@ -169,7 +165,7 @@
     private QSCarrierGroupController(QSCarrierGroup view, ActivityStarter activityStarter,
             @Background Handler bgHandler, @Main Looper mainLooper,
             NetworkController networkController,
-            CarrierTextManager.Builder carrierTextManagerBuilder, Context context) {
+            CarrierTextController.Builder carrierTextControllerBuilder, Context context) {
         if (FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL)) {
             mProviderModel = true;
         } else {
@@ -178,7 +174,7 @@
         mActivityStarter = activityStarter;
         mBgHandler = bgHandler;
         mNetworkController = networkController;
-        mCarrierTextManager = carrierTextManagerBuilder
+        mCarrierTextController = carrierTextControllerBuilder
                 .setShowAirplaneMode(false)
                 .setShowMissingSim(false)
                 .build();
@@ -196,6 +192,7 @@
         mMainHandler = new H(mainLooper, this::handleUpdateCarrierInfo, this::handleUpdateState);
         mCallback = new Callback(mMainHandler);
 
+
         mCarrierGroups[0] = view.getCarrier1View();
         mCarrierGroups[1] = view.getCarrier2View();
         mCarrierGroups[2] = view.getCarrier3View();
@@ -246,10 +243,10 @@
             if (mNetworkController.hasVoiceCallingFeature()) {
                 mNetworkController.addCallback(mSignalCallback);
             }
-            mCarrierTextManager.setListening(mCallback);
+            mCarrierTextController.setListening(mCallback);
         } else {
             mNetworkController.removeCallback(mSignalCallback);
-            mCarrierTextManager.setListening(null);
+            mCarrierTextController.setListening(null);
         }
     }
 
@@ -276,7 +273,7 @@
     }
 
     @MainThread
-    private void handleUpdateCarrierInfo(CarrierTextManager.CarrierTextCallbackInfo info) {
+    private void handleUpdateCarrierInfo(CarrierTextController.CarrierTextCallbackInfo info) {
         if (!mMainHandler.getLooper().isCurrentThread()) {
             mMainHandler.obtainMessage(H.MSG_UPDATE_CARRIER_INFO, info).sendToTarget();
             return;
@@ -330,13 +327,13 @@
     }
 
     private static class H extends Handler {
-        private Consumer<CarrierTextManager.CarrierTextCallbackInfo> mUpdateCarrierInfo;
+        private Consumer<CarrierTextController.CarrierTextCallbackInfo> mUpdateCarrierInfo;
         private Runnable mUpdateState;
         static final int MSG_UPDATE_CARRIER_INFO = 0;
         static final int MSG_UPDATE_STATE = 1;
 
         H(Looper looper,
-                Consumer<CarrierTextManager.CarrierTextCallbackInfo> updateCarrierInfo,
+                Consumer<CarrierTextController.CarrierTextCallbackInfo> updateCarrierInfo,
                 Runnable updateState) {
             super(looper);
             mUpdateCarrierInfo = updateCarrierInfo;
@@ -348,7 +345,7 @@
             switch (msg.what) {
                 case MSG_UPDATE_CARRIER_INFO:
                     mUpdateCarrierInfo.accept(
-                            (CarrierTextManager.CarrierTextCallbackInfo) msg.obj);
+                            (CarrierTextController.CarrierTextCallbackInfo) msg.obj);
                     break;
                 case MSG_UPDATE_STATE:
                     mUpdateState.run();
@@ -365,13 +362,13 @@
         private final Handler mHandler;
         private final Looper mLooper;
         private final NetworkController mNetworkController;
-        private final CarrierTextManager.Builder mCarrierTextControllerBuilder;
+        private final CarrierTextController.Builder mCarrierTextControllerBuilder;
         private final Context mContext;
 
         @Inject
         public Builder(ActivityStarter activityStarter, @Background Handler handler,
                 @Main Looper looper, NetworkController networkController,
-                CarrierTextManager.Builder carrierTextControllerBuilder, Context context) {
+                CarrierTextController.Builder carrierTextControllerBuilder, Context context) {
             mActivityStarter = activityStarter;
             mHandler = handler;
             mLooper = looper;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 9fe949b..dce081f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -25,7 +25,6 @@
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
 import android.view.Menu;
-import android.view.MenuItem;
 import android.view.View;
 import android.widget.LinearLayout;
 import android.widget.Toolbar;
@@ -48,7 +47,6 @@
 public class QSCustomizer extends LinearLayout {
 
     static final int MENU_RESET = Menu.FIRST;
-    static final int MENU_REMOVE_LABELS = Menu.FIRST + 1;
     static final String EXTRA_QS_CUSTOMIZING = "qs_customizing";
 
     private final QSDetailClipper mClipper;
@@ -77,10 +75,6 @@
 
         toolbar.getMenu().add(Menu.NONE, MENU_RESET, 0,
                 mContext.getString(com.android.internal.R.string.reset));
-        // Prototype menu item
-        toolbar.getMenu()
-                .add(Menu.NONE, MENU_REMOVE_LABELS, Menu.NONE, R.string.qs_remove_labels)
-                .setCheckable(true);
         toolbar.setTitle(R.string.qs_edit);
         mRecyclerView = findViewById(android.R.id.list);
         mTransparentView = findViewById(R.id.customizer_transparent_view);
@@ -89,11 +83,6 @@
         mRecyclerView.setItemAnimator(animator);
     }
 
-    MenuItem getRemoveItem() {
-        return ((Toolbar) findViewById(com.android.internal.R.id.action_bar))
-                .getMenu().findItem(MENU_REMOVE_LABELS);
-    }
-
     void updateResources() {
         LayoutParams lp = (LayoutParams) mTransparentView.getLayoutParams();
         lp.height = mContext.getResources().getDimensionPixelSize(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
index d4bab21..f56a2bb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
@@ -17,9 +17,7 @@
 package com.android.systemui.qs.customize;
 
 import static com.android.systemui.qs.customize.QSCustomizer.EXTRA_QS_CUSTOMIZING;
-import static com.android.systemui.qs.customize.QSCustomizer.MENU_REMOVE_LABELS;
 import static com.android.systemui.qs.customize.QSCustomizer.MENU_RESET;
-import static com.android.systemui.qs.dagger.QSFlagsModule.QS_LABELS_FLAG;
 
 import android.content.res.Configuration;
 import android.os.Bundle;
@@ -38,7 +36,6 @@
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.qs.QSEditEvent;
 import com.android.systemui.qs.QSFragment;
-import com.android.systemui.qs.QSPanelController;
 import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.qs.dagger.QSScope;
 import com.android.systemui.statusbar.phone.LightBarController;
@@ -46,14 +43,12 @@
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.tuner.TunerService;
 import com.android.systemui.util.ViewController;
 
 import java.util.ArrayList;
 import java.util.List;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 
 /** {@link ViewController} for {@link QSCustomizer}. */
 @QSScope
@@ -67,8 +62,6 @@
     private final ConfigurationController mConfigurationController;
     private final UiEventLogger mUiEventLogger;
     private final Toolbar mToolbar;
-    private final TunerService mTunerService;
-    private final boolean mQsLabelsFlag;
 
     private final OnMenuItemClickListener mOnMenuItemClickListener = new OnMenuItemClickListener() {
         @Override
@@ -76,11 +69,6 @@
             if (item.getItemId() == MENU_RESET) {
                 mUiEventLogger.log(QSEditEvent.QS_EDIT_RESET);
                 reset();
-            } else if (item.getItemId() == MENU_REMOVE_LABELS) {
-                item.setChecked(!item.isChecked());
-                mTunerService.setValue(
-                        QSPanelController.QS_REMOVE_LABELS, item.isChecked() ? "1" : "0");
-                return false;
             }
             return false;
         }
@@ -111,20 +99,11 @@
         }
     };
 
-    private final TunerService.Tunable mTunable = new TunerService.Tunable() {
-        @Override
-        public void onTuningChanged(String key, String newValue) {
-            mToolbar.getMenu().findItem(MENU_REMOVE_LABELS)
-                    .setChecked(newValue != null && !("0".equals(newValue)));
-        }
-    };
-
     @Inject
     protected QSCustomizerController(QSCustomizer view, TileQueryHelper tileQueryHelper,
             QSTileHost qsTileHost, TileAdapter tileAdapter, ScreenLifecycle screenLifecycle,
             KeyguardStateController keyguardStateController, LightBarController lightBarController,
-            ConfigurationController configurationController, UiEventLogger uiEventLogger,
-            TunerService tunerService, @Named(QS_LABELS_FLAG) boolean qsLabelsFlag) {
+            ConfigurationController configurationController, UiEventLogger uiEventLogger) {
         super(view);
         mTileQueryHelper = tileQueryHelper;
         mQsTileHost = qsTileHost;
@@ -136,21 +115,12 @@
         mUiEventLogger = uiEventLogger;
 
         mToolbar = mView.findViewById(com.android.internal.R.id.action_bar);
-        mQsLabelsFlag = qsLabelsFlag;
-
-        mTunerService = tunerService;
     }
 
-    @Override
-    protected void onInit() {
-        super.onInit();
-        mView.getRemoveItem().setVisible(mQsLabelsFlag);
-    }
 
     @Override
     protected void onViewAttached() {
         mView.updateNavBackDrop(getResources().getConfiguration(), mLightBarController);
-        mTunerService.addTunable(mTunable, QSPanelController.QS_REMOVE_LABELS);
 
         mConfigurationController.addCallback(mConfigurationListener);
 
@@ -181,7 +151,6 @@
 
     @Override
     protected void onViewDetached() {
-        mTunerService.removeTunable(mTunable);
         mTileQueryHelper.setListener(null);
         mToolbar.setOnMenuItemClickListener(null);
         mConfigurationController.removeCallback(mConfigurationListener);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 048fdc3..7a91421 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -75,6 +75,8 @@
     private static final int ACTION_ADD = 1;
     private static final int ACTION_MOVE = 2;
 
+    private static final int NUM_COLUMNS_ID = R.integer.quick_settings_edit_num_columns;
+
     private final Context mContext;
 
     private final Handler mHandler = new Handler();
@@ -87,6 +89,7 @@
     private int mEditIndex;
     private int mTileDividerIndex;
     private int mFocusIndex;
+
     private boolean mNeedsFocus;
     private List<String> mCurrentSpecs;
     private List<TileInfo> mOtherTiles;
@@ -109,7 +112,7 @@
         mDecoration = new TileItemDecoration(context);
         mMarginDecoration = new MarginTileDecoration();
         mMinNumTiles = context.getResources().getInteger(R.integer.quick_settings_min_num_tiles);
-        mNumColumns = context.getResources().getInteger(R.integer.quick_settings_num_columns);
+        mNumColumns = context.getResources().getInteger(NUM_COLUMNS_ID);
         mAccessibilityDelegate = new TileAdapterDelegate();
     }
 
@@ -129,7 +132,7 @@
      * @return {@code true} if the number of columns changed, {@code false} otherwise
      */
     public boolean updateNumColumns() {
-        int numColumns = mContext.getResources().getInteger(R.integer.quick_settings_num_columns);
+        int numColumns = mContext.getResources().getInteger(NUM_COLUMNS_ID);
         if (numColumns != mNumColumns) {
             mNumColumns = numColumns;
             return true;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFlagsModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFlagsModule.java
index 35a8257..10192bc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFlagsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFlagsModule.java
@@ -21,6 +21,7 @@
 
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.statusbar.FeatureFlags;
+import com.android.systemui.util.settings.GlobalSettings;
 
 import javax.inject.Named;
 
@@ -31,6 +32,8 @@
 public interface QSFlagsModule {
     String QS_LABELS_FLAG = "qs_labels_flag";
     String RBC_AVAILABLE = "rbc_available";
+    String PM_LITE_ENABLED = "pm_lite";
+    String PM_LITE_SETTING = "sysui_pm_lite";
 
     @Provides
     @SysUISingleton
@@ -46,4 +49,11 @@
     static boolean isReduceBrightColorsAvailable(Context context) {
         return ColorDisplayManager.isReduceBrightColorsAvailable(context);
     }
+
+    @Provides
+    @SysUISingleton
+    @Named(PM_LITE_ENABLED)
+    static boolean isPMLiteEnabled(FeatureFlags featureFlags, GlobalSettings globalSettings) {
+        return featureFlags.isPMLiteEnabled() && globalSettings.getInt(PM_LITE_SETTING, 0) != 0;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
index a699e2e..207b25d0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
@@ -105,24 +105,27 @@
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        mLabel.setSingleLine(false);
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
-        // Remeasure view if the primary label requires more then 2 lines or the secondary label
-        // text will be cut off.
-        if (mLabel.getLineCount() > mMaxLabelLines || !TextUtils.isEmpty(mSecondLine.getText())
-                        && mSecondLine.getLineHeight() > mSecondLine.getHeight()) {
-            if (!mLabel.isSingleLine()) {
-                mLabel.setSingleLine();
-                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-            }
-        } else {
-            if (mLabel.isSingleLine()) {
-                mLabel.setSingleLine(false);
-                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-            }
+        // Remeasure view if the primary label requires more than mMaxLabelLines lines or the
+        // secondary label text will be cut off.
+        if (shouldLabelBeSingleLine()) {
+            mLabel.setSingleLine();
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         }
     }
 
+    private boolean shouldLabelBeSingleLine() {
+        if (mLabel.getLineCount() > mMaxLabelLines) {
+            return true;
+        } else if (!TextUtils.isEmpty(mSecondLine.getText())
+                && mLabel.getLineCount() > mMaxLabelLines - 1) {
+            return true;
+        }
+        return false;
+    }
+
     @Override
     protected void handleStateChanged(QSTile.State state) {
         super.handleStateChanged(state);
@@ -171,9 +174,4 @@
         mLabelContainer.setClickable(false);
         mLabelContainer.setLongClickable(false);
     }
-
-    @Override
-    public void setShowLabels(boolean show) {
-        mHandler.post(() -> mLabelContainer.setVisibility(show ? VISIBLE : GONE));
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewHorizontal.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewHorizontal.kt
index dc81b702..07d48f3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewHorizontal.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewHorizontal.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs.tileimpl
 
+import android.animation.ValueAnimator
 import android.content.Context
 import android.content.res.ColorStateList
 import android.graphics.Color
@@ -24,20 +25,24 @@
 import android.graphics.drawable.RippleDrawable
 import android.service.quicksettings.Tile.STATE_ACTIVE
 import android.view.Gravity
-import android.view.View
 import android.widget.LinearLayout
+import android.widget.RelativeLayout
 import com.android.systemui.R
 import com.android.systemui.plugins.qs.QSIconView
 import com.android.systemui.plugins.qs.QSTile
 import com.android.systemui.qs.tileimpl.QSTileImpl.getColorForState
 
+// Placeholder
+private const val CORNER_RADIUS = 40f
+
 class QSTileViewHorizontal(
     context: Context,
     icon: QSIconView
 ) : QSTileView(context, icon, false) {
 
     private var paintDrawable: PaintDrawable? = null
-    private var divider: View? = null
+    private var paintColor = Color.TRANSPARENT
+    private var paintAnimator: ValueAnimator? = null
 
     init {
         orientation = HORIZONTAL
@@ -49,7 +54,12 @@
 
     override fun createLabel() {
         super.createLabel()
-        findViewById<LinearLayout>(R.id.label_group)?.gravity = Gravity.START
+        findViewById<LinearLayout>(R.id.label_group)?.apply {
+            gravity = Gravity.START
+            (layoutParams as? RelativeLayout.LayoutParams)?.apply {
+                removeRule(RelativeLayout.ALIGN_PARENT_TOP)
+            }
+        }
         mLabel.gravity = Gravity.START
         mLabel.textDirection = TEXT_DIRECTION_LOCALE
         mSecondLine.gravity = Gravity.START
@@ -57,7 +67,7 @@
         val padding = context.resources.getDimensionPixelSize(R.dimen.qs_tile_side_label_padding)
         mLabelContainer.setPaddingRelative(0, padding, padding, padding)
         (mLabelContainer.layoutParams as LayoutParams).gravity =
-                Gravity.CENTER_VERTICAL or Gravity.START
+            Gravity.CENTER_VERTICAL or Gravity.START
     }
 
     override fun updateRippleSize() {
@@ -66,8 +76,8 @@
     override fun newTileBackground(): Drawable? {
         val d = super.newTileBackground()
         if (paintDrawable == null) {
-            paintDrawable = PaintDrawable(Color.WHITE).apply {
-                setCornerRadius(50f)
+            paintDrawable = PaintDrawable(paintColor).apply {
+                setCornerRadius(CORNER_RADIUS)
             }
         }
         if (d is RippleDrawable) {
@@ -90,10 +100,39 @@
 
     override fun handleStateChanged(state: QSTile.State) {
         super.handleStateChanged(state)
-        paintDrawable?.setTint(getCircleColor(state.state))
         mSecondLine.setTextColor(mLabel.textColors)
         mLabelContainer.background = null
-        divider?.backgroundTintList = mLabel.textColors
+
+        val allowAnimations = animationsEnabled() && paintColor != Color.TRANSPARENT
+        val newColor = getCircleColor(state.state)
+        if (allowAnimations) {
+            animateToNewState(newColor)
+        } else {
+            if (newColor != paintColor) {
+                clearAnimator()
+                paintDrawable?.paint?.color = newColor
+                paintDrawable?.invalidateSelf()
+            }
+        }
+        paintColor = newColor
+    }
+
+    private fun animateToNewState(newColor: Int) {
+        if (newColor != paintColor) {
+            clearAnimator()
+            paintAnimator = ValueAnimator.ofArgb(paintColor, newColor)
+                .setDuration(QSIconViewImpl.QS_ANIM_LENGTH).apply {
+                    addUpdateListener { animation: ValueAnimator ->
+                        paintDrawable?.paint?.color = animation.animatedValue as Int
+                        paintDrawable?.invalidateSelf()
+                    }
+                    start()
+                }
+        }
+    }
+
+    private fun clearAnimator() {
+        paintAnimator?.cancel()?.also { paintAnimator = null }
     }
 
     override fun handleExpand(dualTarget: Boolean) {}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
index 3841dac..70287cd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
@@ -16,10 +16,13 @@
 
 package com.android.systemui.qs.tiles;
 
-import static android.service.SensorPrivacyIndividualEnabledSensorProto.CAMERA;
+import static android.content.pm.PackageManager.FEATURE_CAMERA_TOGGLE;
+import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
 
 import static com.android.systemui.DejankUtils.whitelistIpcs;
 
+import android.hardware.SensorPrivacyManager;
+import android.hardware.SensorPrivacyManager.Sensors.Sensor;
 import android.os.Handler;
 import android.os.Looper;
 import android.provider.DeviceConfig;
@@ -58,8 +61,8 @@
 
     @Override
     public boolean isAvailable() {
-        return /*getHost().getContext().getPackageManager().hasSystemFeature(FEATURE_CAMERA_TOGGLE)
-                && */whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+        return getHost().getContext().getPackageManager().hasSystemFeature(FEATURE_CAMERA_TOGGLE)
+                && whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
                 "camera_toggle_enabled",
                 false));
     }
@@ -75,7 +78,7 @@
     }
 
     @Override
-    public int getSensorId() {
+    public @Sensor int getSensorId() {
         return CAMERA;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 1dddc45..f03ce2c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -54,6 +54,7 @@
 import com.android.systemui.statusbar.policy.HotspotController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.NetworkController.WifiIndicators;
 
 import java.util.ArrayList;
 import java.util.LinkedHashMap;
@@ -269,13 +270,10 @@
     private final NetworkController.SignalCallback mSignalCallback =
             new NetworkController.SignalCallback() {
                 @Override
-                public void setWifiIndicators(boolean enabled,
-                        NetworkController.IconState statusIcon,
-                        NetworkController.IconState qsIcon, boolean activityIn, boolean activityOut,
-                        String description, boolean isTransient, String statusLabel) {
+                public void setWifiIndicators(WifiIndicators indicators) {
                     // statusIcon.visible has the connected status information
-                    boolean enabledAndConnected =
-                            enabled && (qsIcon == null ? false : qsIcon.visible);
+                    boolean enabledAndConnected = indicators.enabled
+                            && (indicators.qsIcon == null ? false : indicators.qsIcon.visible);
                     if (enabledAndConnected != mWifiConnected) {
                         mWifiConnected = enabledAndConnected;
                         // Hotspot is not connected, so changes here should update
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 720c5dc..6a574d1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -56,6 +56,7 @@
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 
 import javax.inject.Inject;
@@ -264,21 +265,17 @@
         private final CallbackInfo mInfo = new CallbackInfo();
 
         @Override
-        public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
-                int qsType, boolean activityIn, boolean activityOut,
-                CharSequence typeContentDescription,
-                CharSequence typeContentDescriptionHtml, CharSequence description,
-                boolean isWide, int subId, boolean roaming, boolean showTriangle) {
-            if (qsIcon == null) {
+        public void setMobileDataIndicators(MobileDataIndicators indicators) {
+            if (indicators.qsIcon == null) {
                 // Not data sim, don't display.
                 return;
             }
             mInfo.dataSubscriptionName = mController.getMobileDataNetworkName();
-            mInfo.dataContentDescription =
-                    (description != null) ? typeContentDescriptionHtml : null;
-            mInfo.activityIn = activityIn;
-            mInfo.activityOut = activityOut;
-            mInfo.roaming = roaming;
+            mInfo.dataContentDescription = indicators.description != null
+                    ? indicators.typeContentDescriptionHtml : null;
+            mInfo.activityIn = indicators.activityIn;
+            mInfo.activityOut = indicators.activityOut;
+            mInfo.roaming = indicators.roaming;
             mInfo.multipleSubs = mController.getNumberSubscriptions() > 1;
             refreshState(mInfo);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
index 4144591..3b9f5dc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
@@ -25,7 +25,7 @@
 import com.android.systemui.R
 import com.android.systemui.controls.ControlsServiceInfo
 import com.android.systemui.controls.dagger.ControlsComponent
-import com.android.systemui.controls.dagger.ControlsComponent.Visibility.UNAVAILABLE
+import com.android.systemui.controls.dagger.ControlsComponent.Visibility.AVAILABLE
 import com.android.systemui.controls.management.ControlsListingController
 import com.android.systemui.controls.ui.ControlsDialog
 import com.android.systemui.dagger.qualifiers.Background
@@ -92,7 +92,7 @@
     override fun isAvailable(): Boolean {
         return featureFlags.isKeyguardLayoutEnabled &&
                 controlsLockscreen &&
-                controlsComponent.getVisibility() != UNAVAILABLE
+                controlsComponent.getControlsController().isPresent
     }
 
     override fun newTileState(): QSTile.State {
@@ -119,7 +119,7 @@
     }
 
     override fun handleClick() {
-        if (state.state != Tile.STATE_UNAVAILABLE) {
+        if (state.state == Tile.STATE_ACTIVE) {
             mUiHandler.post {
                 createDialog()
                 controlsDialog?.show(controlsComponent.getControlsUiController().get())
@@ -129,15 +129,21 @@
 
     override fun handleUpdateState(state: QSTile.State, arg: Any?) {
         state.label = tileLabel
-        state.secondaryLabel = ""
-        state.stateDescription = ""
+
         state.contentDescription = state.label
         state.icon = icon
-        if (hasControlsApps.get()) {
-            state.state = Tile.STATE_ACTIVE
+        if (controlsComponent.isEnabled() && hasControlsApps.get()) {
             if (controlsDialog == null) {
                 mUiHandler.post(this::createDialog)
             }
+            if (controlsComponent.getVisibility() == AVAILABLE) {
+                state.state = Tile.STATE_ACTIVE
+                state.secondaryLabel = ""
+            } else {
+                state.state = Tile.STATE_INACTIVE
+                state.secondaryLabel = mContext.getText(R.string.controls_tile_locked)
+            }
+            state.stateDescription = state.secondaryLabel
         } else {
             state.state = Tile.STATE_UNAVAILABLE
             dismissDialog()
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
index 0abff77..e1a1fd2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
@@ -51,7 +51,9 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
+import com.android.systemui.statusbar.policy.NetworkController.WifiIndicators;
 import com.android.systemui.statusbar.policy.WifiIcons;
 
 import java.io.FileDescriptor;
@@ -234,72 +236,44 @@
 
 
         @Override
-        public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
-                boolean activityIn, boolean activityOut, String description, boolean isTransient,
-                String statusLabel) {
+        public void setWifiIndicators(WifiIndicators indicators) {
             if (DEBUG) {
-                Log.d(TAG, "setWifiIndicators: "
-                        + "enabled = " + enabled + ","
-                        + "statusIcon = " + (statusIcon == null ? "" : statusIcon.toString()) + ","
-                        + "qsIcon = " + (qsIcon == null ? "" : qsIcon.toString()) + ","
-                        + "activityIn = " + activityIn + ","
-                        + "activityOut = " + activityOut + ","
-                        + "description = " + description + ","
-                        + "isTransient = " + isTransient + ","
-                        + "statusLabel = " + statusLabel);
+                Log.d(TAG, "setWifiIndicators: " + indicators);
             }
-            // When airplane mode is enabled, we need to refresh the Internet Tile even if the WiFi
-            // is not the default network.
-            if (qsIcon == null) {
+            mWifiInfo.mEnabled = indicators.enabled;
+            if (indicators.qsIcon == null) {
                 return;
             }
-            mWifiInfo.mConnected = qsIcon.visible;
-            mWifiInfo.mWifiSignalIconId = qsIcon.icon;
-            mWifiInfo.mWifiSignalContentDescription = qsIcon.contentDescription;
-            mWifiInfo.mEnabled = enabled;
-            mWifiInfo.mSsid = description;
-            mWifiInfo.mActivityIn = activityIn;
-            mWifiInfo.mActivityOut = activityOut;
-            mWifiInfo.mIsTransient = isTransient;
-            mWifiInfo.mStatusLabel = statusLabel;
+            mWifiInfo.mConnected = indicators.qsIcon.visible;
+            mWifiInfo.mWifiSignalIconId = indicators.qsIcon.icon;
+            mWifiInfo.mWifiSignalContentDescription = indicators.qsIcon.contentDescription;
+            mWifiInfo.mEnabled = indicators.enabled;
+            mWifiInfo.mSsid = indicators.description;
+            mWifiInfo.mActivityIn = indicators.activityIn;
+            mWifiInfo.mActivityOut = indicators.activityOut;
+            mWifiInfo.mIsTransient = indicators.isTransient;
+            mWifiInfo.mStatusLabel = indicators.statusLabel;
             refreshState(mWifiInfo);
         }
 
         @Override
-        public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
-                int qsType, boolean activityIn, boolean activityOut,
-                CharSequence typeContentDescription,
-                CharSequence typeContentDescriptionHtml, CharSequence description,
-                boolean isWide, int subId, boolean roaming, boolean showTriangle) {
+        public void setMobileDataIndicators(MobileDataIndicators indicators) {
             if (DEBUG) {
-                Log.d(TAG, "setMobileDataIndicators: "
-                        + "statusIcon = " + (statusIcon == null ? "" :  statusIcon.toString()) + ","
-                        + "qsIcon = " + (qsIcon == null ? "" : qsIcon.toString()) + ","
-                        + "statusType = " + statusType + ","
-                        + "qsType = " + qsType + ","
-                        + "activityIn = " + activityIn + ","
-                        + "activityOut = " + activityOut + ","
-                        + "typeContentDescription = " + typeContentDescription + ","
-                        + "typeContentDescriptionHtml = " + typeContentDescriptionHtml + ","
-                        + "description = " + description + ","
-                        + "isWide = " + isWide + ","
-                        + "subId = " + subId + ","
-                        + "roaming = " + roaming + ","
-                        + "showTriangle = " + showTriangle);
+                Log.d(TAG, "setMobileDataIndicators: " + indicators);
             }
-            if (qsIcon == null) {
+            if (indicators.qsIcon == null) {
                 // Not data sim, don't display.
                 return;
             }
-            mCellularInfo.mDataSubscriptionName =
-                    description == null ? mController.getMobileDataNetworkName() : description;
-            mCellularInfo.mDataContentDescription =
-                    (description != null) ? typeContentDescriptionHtml : null;
-            mCellularInfo.mMobileSignalIconId = qsIcon.icon;
-            mCellularInfo.mQsTypeIcon = qsType;
-            mCellularInfo.mActivityIn = activityIn;
-            mCellularInfo.mActivityOut = activityOut;
-            mCellularInfo.mRoaming = roaming;
+            mCellularInfo.mDataSubscriptionName = indicators.description == null
+                    ? mController.getMobileDataNetworkName() : indicators.description;
+            mCellularInfo.mDataContentDescription = indicators.description != null
+                    ? indicators.typeContentDescriptionHtml : null;
+            mCellularInfo.mMobileSignalIconId = indicators.qsIcon.icon;
+            mCellularInfo.mQsTypeIcon = indicators.qsType;
+            mCellularInfo.mActivityIn = indicators.activityIn;
+            mCellularInfo.mActivityOut = indicators.activityOut;
+            mCellularInfo.mRoaming = indicators.roaming;
             mCellularInfo.mMultipleSubs = mController.getNumberSubscriptions() > 1;
             refreshState(mCellularInfo);
         }
@@ -465,14 +439,13 @@
         }
         minimalContentDescription.append(
             mContext.getString(R.string.quick_settings_internet_label)).append(",");
-        if (state.value) {
-            if (wifiConnected) {
-                minimalStateDescription.append(cb.mWifiSignalContentDescription);
-                minimalContentDescription.append(removeDoubleQuotes(cb.mSsid));
-            } else if (!TextUtils.isEmpty(state.secondaryLabel)) {
-                minimalContentDescription.append(",").append(state.secondaryLabel);
-            }
+        if (state.value && wifiConnected) {
+            minimalStateDescription.append(cb.mWifiSignalContentDescription);
+            minimalContentDescription.append(removeDoubleQuotes(cb.mSsid));
+        } else if (!TextUtils.isEmpty(state.secondaryLabel)) {
+            minimalContentDescription.append(",").append(state.secondaryLabel);
         }
+
         state.stateDescription = minimalStateDescription.toString();
         state.contentDescription = minimalContentDescription.toString();
         state.dualLabelContentDescription = r.getString(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java
index 2f0071a..e9b712d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java
@@ -16,10 +16,13 @@
 
 package com.android.systemui.qs.tiles;
 
-import static android.service.SensorPrivacyIndividualEnabledSensorProto.MICROPHONE;
+import static android.content.pm.PackageManager.FEATURE_MICROPHONE_TOGGLE;
+import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
 
 import static com.android.systemui.DejankUtils.whitelistIpcs;
 
+import android.hardware.SensorPrivacyManager;
+import android.hardware.SensorPrivacyManager.Sensors.Sensor;
 import android.os.Handler;
 import android.os.Looper;
 import android.provider.DeviceConfig;
@@ -58,7 +61,9 @@
 
     @Override
     public boolean isAvailable() {
-        return whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+        return getHost().getContext().getPackageManager()
+                .hasSystemFeature(FEATURE_MICROPHONE_TOGGLE)
+                && whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
                 "mic_toggle_enabled",
                 false));
     }
@@ -74,7 +79,7 @@
     }
 
     @Override
-    public int getSensorId() {
+    public @Sensor int getSensorId() {
         return MICROPHONE;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java
index 00703e7..0c582bd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java
@@ -17,7 +17,7 @@
 package com.android.systemui.qs.tiles;
 
 import android.content.Intent;
-import android.hardware.SensorPrivacyManager.IndividualSensor;
+import android.hardware.SensorPrivacyManager.Sensors.Sensor;
 import android.os.Handler;
 import android.os.Looper;
 import android.service.quicksettings.Tile;
@@ -49,7 +49,7 @@
     /**
      * @return Id of the sensor that will be toggled
      */
-    public abstract @IndividualSensor int getSensorId();
+    public abstract @Sensor int getSensorId();
 
     /**
      * @return icon for the QS tile
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index a6fd011..341e67c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -51,8 +51,8 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
-import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
+import com.android.systemui.statusbar.policy.NetworkController.WifiIndicators;
 import com.android.systemui.statusbar.policy.WifiIcons;
 import com.android.wifitrackerlib.WifiEntry;
 
@@ -303,22 +303,20 @@
         final CallbackInfo mInfo = new CallbackInfo();
 
         @Override
-        public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
-                boolean activityIn, boolean activityOut, String description, boolean isTransient,
-                String statusLabel) {
-            if (DEBUG) Log.d(TAG, "onWifiSignalChanged enabled=" + enabled);
-            if (qsIcon == null) {
+        public void setWifiIndicators(WifiIndicators indicators) {
+            if (DEBUG) Log.d(TAG, "onWifiSignalChanged enabled=" + indicators.enabled);
+            if (indicators.qsIcon == null) {
                 return;
             }
-            mInfo.enabled = enabled;
-            mInfo.connected = qsIcon.visible;
-            mInfo.wifiSignalIconId = qsIcon.icon;
-            mInfo.ssid = description;
-            mInfo.activityIn = activityIn;
-            mInfo.activityOut = activityOut;
-            mInfo.wifiSignalContentDescription = qsIcon.contentDescription;
-            mInfo.isTransient = isTransient;
-            mInfo.statusLabel = statusLabel;
+            mInfo.enabled = indicators.enabled;
+            mInfo.connected = indicators.qsIcon.visible;
+            mInfo.wifiSignalIconId = indicators.qsIcon.icon;
+            mInfo.ssid = indicators.description;
+            mInfo.activityIn = indicators.activityIn;
+            mInfo.activityOut = indicators.activityOut;
+            mInfo.wifiSignalContentDescription = indicators.qsIcon.contentDescription;
+            mInfo.isTransient = indicators.isTransient;
+            mInfo.statusLabel = indicators.statusLabel;
             if (isShowingDetail()) {
                 mDetailAdapter.updateItems();
             }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java b/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java
index 1386ddf..5b55864 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java
@@ -97,8 +97,8 @@
         float bottom = mBottomCrop + mBottomDelta;
         drawShade(canvas, 0, top);
         drawShade(canvas, bottom, 1f);
-        drawHandle(canvas, top);
-        drawHandle(canvas, bottom);
+        drawHandle(canvas, top, /* draw the handle tab down */ false);
+        drawHandle(canvas, bottom, /* draw the handle tab up */ true);
     }
 
     @Override
@@ -122,7 +122,7 @@
                     } else {  // Bottom
                         mBottomDelta = pixelsToFraction((int) MathUtils.constrain(delta,
                                 topPx + 2 * mCropTouchMargin - bottomPx,
-                                getMeasuredHeight() - bottomPx));
+                                getHeight() - bottomPx));
                     }
                     updateListener(event);
                     invalidate();
@@ -140,6 +140,25 @@
     }
 
     /**
+     * Set the given boundary to the given value without animation.
+     */
+    public void setBoundaryTo(CropBoundary boundary, float value) {
+        switch (boundary) {
+            case TOP:
+                mTopCrop = value;
+                break;
+            case BOTTOM:
+                mBottomCrop = value;
+                break;
+            case NONE:
+                Log.w(TAG, "No boundary selected for animation");
+                break;
+        }
+
+        invalidate();
+    }
+
+    /**
      * Animate the given boundary to the given value.
      */
     public void animateBoundaryTo(CropBoundary boundary, float value) {
@@ -212,21 +231,25 @@
     }
 
     private void drawShade(Canvas canvas, float fracStart, float fracEnd) {
-        canvas.drawRect(0, fractionToPixels(fracStart), getMeasuredWidth(),
+        canvas.drawRect(0, fractionToPixels(fracStart), getWidth(),
                 fractionToPixels(fracEnd), mShadePaint);
     }
 
-    private void drawHandle(Canvas canvas, float frac) {
+    private void drawHandle(Canvas canvas, float frac, boolean handleTabUp) {
         int y = fractionToPixels(frac);
-        canvas.drawLine(0, y, getMeasuredWidth(), y, mHandlePaint);
+        canvas.drawLine(0, y, getWidth(), y, mHandlePaint);
+        float radius = 15 * getResources().getDisplayMetrics().density;
+        float x = getWidth() * .9f;
+        canvas.drawArc(x - radius, y - radius, x + radius, y + radius, handleTabUp ? 180 : 0, 180,
+                true, mHandlePaint);
     }
 
     private int fractionToPixels(float frac) {
-        return (int) (frac * getMeasuredHeight());
+        return (int) (frac * getHeight());
     }
 
     private float pixelsToFraction(int px) {
-        return px / (float) getMeasuredHeight();
+        return px / (float) getHeight();
     }
 
     private CropBoundary nearestBoundary(MotionEvent event, int topPx, int bottomPx) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
new file mode 100644
index 0000000..5a13ea55
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.HardwareRenderer;
+import android.graphics.RecordingCanvas;
+import android.graphics.Rect;
+import android.graphics.RenderNode;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageView;
+
+import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.time.ZonedDateTime;
+import java.util.UUID;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+
+import javax.inject.Inject;
+
+/**
+ * LongScreenshotActivity acquires bitmap data for a long screenshot and lets the user trim the top
+ * and bottom before saving/sharing/editing.
+ */
+public class LongScreenshotActivity extends Activity {
+    private static final String TAG = "LongScreenshotActivity";
+
+    private static final String IMAGE_PATH_KEY = "saved-image";
+    private static final String TOP_BOUNDARY_KEY = "top-boundary";
+    private static final String BOTTOM_BOUNDARY_KEY = "bottom-boundary";
+
+    private final UiEventLogger mUiEventLogger;
+    private final ScrollCaptureController mScrollCaptureController;
+    private final ScrollCaptureClient.Connection mConnection;
+    private final Executor mUiExecutor;
+    private final Executor mBackgroundExecutor;
+    private final ImageExporter mImageExporter;
+
+    private String mSavedImagePath;
+    // If true, the activity is re-loading an image from storage, which should either succeed and
+    // populate the UI or fail and finish the activity.
+    private boolean mRestoringInstance;
+
+    private ImageView mPreview;
+    private View mSave;
+    private View mCancel;
+    private View mEdit;
+    private View mShare;
+    private CropView mCropView;
+    private MagnifierView mMagnifierView;
+
+    private enum PendingAction {
+        SHARE,
+        EDIT,
+        SAVE
+    }
+
+    @Inject
+    public LongScreenshotActivity(UiEventLogger uiEventLogger,
+            ImageExporter imageExporter,
+            @Main Executor mainExecutor,
+            @Background Executor bgExecutor,
+            Context context) {
+        mUiEventLogger = uiEventLogger;
+        mUiExecutor = mainExecutor;
+        mBackgroundExecutor = bgExecutor;
+        mImageExporter = imageExporter;
+
+        mScrollCaptureController = new ScrollCaptureController(context, mainExecutor, bgExecutor,
+                imageExporter);
+
+        mConnection = ScreenshotController.takeScrollCaptureConnection();
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.long_screenshot);
+
+        mPreview = findViewById(R.id.preview);
+        mSave = findViewById(R.id.save);
+        mCancel = findViewById(R.id.cancel);
+        mEdit = findViewById(R.id.edit);
+        mShare = findViewById(R.id.share);
+        mCropView = findViewById(R.id.crop_view);
+        mMagnifierView = findViewById(R.id.magnifier);
+        mCropView.setCropInteractionListener(mMagnifierView);
+
+        mSave.setOnClickListener(this::onClicked);
+        mCancel.setOnClickListener(this::onClicked);
+        mEdit.setOnClickListener(this::onClicked);
+        mShare.setOnClickListener(this::onClicked);
+
+        if (savedInstanceState != null) {
+            String imagePath = savedInstanceState.getString(IMAGE_PATH_KEY);
+            if (!TextUtils.isEmpty(imagePath)) {
+                mRestoringInstance = true;
+                mBackgroundExecutor.execute(() -> {
+                    Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
+                    if (bitmap == null) {
+                        Log.e(TAG, "Failed to read bitmap from " + imagePath);
+                        finishAndRemoveTask();
+                    } else {
+                        runOnUiThread(() -> {
+                            BitmapDrawable drawable = new BitmapDrawable(getResources(), bitmap);
+                            mPreview.setImageDrawable(drawable);
+                            mMagnifierView.setDrawable(drawable, bitmap.getWidth(),
+                                    bitmap.getHeight());
+
+                            mCropView.setBoundaryTo(CropView.CropBoundary.TOP,
+                                    savedInstanceState.getFloat(TOP_BOUNDARY_KEY, 0f));
+                            mCropView.setBoundaryTo(CropView.CropBoundary.BOTTOM,
+                                    savedInstanceState.getFloat(BOTTOM_BOUNDARY_KEY, 1f));
+                            mRestoringInstance = false;
+                            // Reuse the same path for subsequent restoration.
+                            mSavedImagePath = imagePath;
+                            Log.d(TAG, "Loaded bitmap from " + imagePath);
+                        });
+                    }
+                });
+            }
+        }
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        if (mPreview.getDrawable() == null && !mRestoringInstance) {
+            if (mConnection == null) {
+                Log.e(TAG, "Failed to get scroll capture connection, bailing out");
+                finishAndRemoveTask();
+                return;
+            }
+            doCapture();
+        }
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putString(IMAGE_PATH_KEY, mSavedImagePath);
+        outState.putFloat(TOP_BOUNDARY_KEY, mCropView.getTopBoundary());
+        outState.putFloat(BOTTOM_BOUNDARY_KEY, mCropView.getBottomBoundary());
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        if (isFinishing() && !TextUtils.isEmpty(mSavedImagePath)) {
+            Log.d(TAG, "Deleting " + mSavedImagePath);
+            File file = new File(mSavedImagePath);
+            file.delete();
+        }
+    }
+
+    private void setButtonsEnabled(boolean enabled) {
+        mSave.setEnabled(enabled);
+        mCancel.setEnabled(enabled);
+        mEdit.setEnabled(enabled);
+        mShare.setEnabled(enabled);
+    }
+
+    private void doEdit(Uri uri) {
+        String editorPackage = getString(R.string.config_screenshotEditor);
+        Intent intent = new Intent(Intent.ACTION_EDIT);
+        if (!TextUtils.isEmpty(editorPackage)) {
+            intent.setComponent(ComponentName.unflattenFromString(editorPackage));
+        }
+        intent.setDataAndType(uri, "image/png");
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
+                | Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+        startActivityAsUser(intent, UserHandle.CURRENT);
+        finishAndRemoveTask();
+    }
+
+    private void doShare(Uri uri) {
+        Intent intent = new Intent(Intent.ACTION_SEND);
+        intent.setType("image/png");
+        intent.putExtra(Intent.EXTRA_STREAM, uri);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
+                | Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        Intent sharingChooserIntent = Intent.createChooser(intent, null)
+                .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+        startActivityAsUser(sharingChooserIntent, UserHandle.CURRENT);
+    }
+
+    private void onClicked(View v) {
+        int id = v.getId();
+        v.setPressed(true);
+        setButtonsEnabled(false);
+        if (id == R.id.save) {
+            startExport(PendingAction.SAVE);
+        } else if (id == R.id.cancel) {
+            finishAndRemoveTask();
+        } else if (id == R.id.edit) {
+            mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_EDIT);
+            startExport(PendingAction.EDIT);
+        } else if (id == R.id.share) {
+            mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_SHARE);
+            startExport(PendingAction.SHARE);
+        }
+    }
+
+    private void startExport(PendingAction action) {
+        Drawable drawable = mPreview.getDrawable();
+
+        Rect croppedPortion = new Rect(
+                0,
+                (int) (drawable.getIntrinsicHeight() * mCropView.getTopBoundary()),
+                drawable.getIntrinsicWidth(),
+                (int) (drawable.getIntrinsicHeight() * mCropView.getBottomBoundary()));
+        ListenableFuture<ImageExporter.Result> exportFuture = mImageExporter.export(
+                mBackgroundExecutor, UUID.randomUUID(), getBitmap(croppedPortion, drawable),
+                ZonedDateTime.now());
+        exportFuture.addListener(() -> {
+            try {
+                ImageExporter.Result result = exportFuture.get();
+                setButtonsEnabled(true);
+                switch (action) {
+                    case EDIT:
+                        doEdit(result.uri);
+                        break;
+                    case SHARE:
+                        doShare(result.uri);
+                        break;
+                    case SAVE:
+                        // Nothing more to do
+                        finishAndRemoveTask();
+                        break;
+                }
+            } catch (InterruptedException | ExecutionException e) {
+                Log.e(TAG, "failed to export", e);
+                setButtonsEnabled(true);
+            }
+        }, mUiExecutor);
+    }
+
+    private Bitmap getBitmap(Rect bounds, Drawable drawable) {
+        final RenderNode output = new RenderNode("Bitmap Export");
+        output.setPosition(0, 0, bounds.width(), bounds.height());
+        RecordingCanvas canvas = output.beginRecording();
+        // Translating the canvas instead of setting drawable bounds since the drawable is still
+        // used in the preview.
+        canvas.translate(0, -bounds.top);
+        drawable.draw(canvas);
+        output.endRecording();
+        return HardwareRenderer.createHardwareBitmap(output, bounds.width(), bounds.height());
+    }
+
+    private void saveCacheBitmap(ImageTileSet tileSet) {
+        long startTime = SystemClock.uptimeMillis();
+        Bitmap bitmap = tileSet.toBitmap();
+        // TODO(b/181562529) Remove this
+        mPreview.setImageDrawable(tileSet.getDrawable());
+        try {
+            File file = File.createTempFile("long_screenshot", ".png", null);
+            FileOutputStream stream = new FileOutputStream(file);
+            bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
+            stream.flush();
+            stream.close();
+            mSavedImagePath = file.getAbsolutePath();
+            Log.d(TAG, "Saved to " + file.getAbsolutePath() + " in "
+                    + (SystemClock.uptimeMillis() - startTime) + "ms");
+        } catch (IOException e) {
+            Log.e(TAG, "Failed to save bitmap", e);
+        }
+    }
+
+    private void doCapture() {
+        mScrollCaptureController.start(mConnection,
+                new ScrollCaptureController.ScrollCaptureCallback() {
+                    @Override
+                    public void onError() {
+                        Log.e(TAG, "Error capturing long screenshot!");
+                        finishAndRemoveTask();
+                    }
+
+                    @Override
+                    public void onComplete(ImageTileSet imageTileSet) {
+                        Log.i(TAG, "Got tiles " + imageTileSet.getWidth() + " x "
+                                + imageTileSet.getHeight());
+                        mPreview.setImageDrawable(imageTileSet.getDrawable());
+                        mMagnifierView.setDrawable(imageTileSet.getDrawable(),
+                                imageTileSet.getWidth(), imageTileSet.getHeight());
+                        mCropView.animateBoundaryTo(CropView.CropBoundary.BOTTOM, 0.5f);
+                        mBackgroundExecutor.execute(() -> saveCacheBitmap(imageTileSet));
+                    }
+                });
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/MagnifierView.java b/packages/SystemUI/src/com/android/systemui/screenshot/MagnifierView.java
index f8f1d3a..7a0ec4c 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/MagnifierView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/MagnifierView.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.screenshot;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
@@ -77,13 +78,12 @@
         mCheckerboardPaint.setColor(Color.GRAY);
     }
 
-    public void setImageTileset(ImageTileSet tiles) {
-        if (tiles != null) {
-            mDrawable = tiles.getDrawable();
-            mDrawable.setBounds(0, 0, tiles.getWidth(), tiles.getHeight());
-        } else {
-            mDrawable = null;
-        }
+    /**
+     * Set the drawable to be displayed by the magnifier.
+     */
+    public void setDrawable(@NonNull Drawable drawable, int width, int height) {
+        mDrawable = drawable;
+        mDrawable.setBounds(0, 0, width, height);
         invalidate();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 953b40b..805ac7c 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -41,6 +41,7 @@
 import android.app.WindowContext;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.graphics.Bitmap;
 import android.graphics.Insets;
@@ -100,6 +101,8 @@
 public class ScreenshotController {
     private static final String TAG = logTag(ScreenshotController.class);
 
+    private static ScrollCaptureClient.Connection sScrollConnection;
+
     /**
      * POD used in the AsyncTask which saves an image in the background.
      */
@@ -219,6 +222,12 @@
                     | ActivityInfo.CONFIG_SCREEN_LAYOUT
                     | ActivityInfo.CONFIG_ASSETS_PATHS);
 
+    public static @Nullable ScrollCaptureClient.Connection takeScrollCaptureConnection() {
+        ScrollCaptureClient.Connection connection = sScrollConnection;
+        sScrollConnection = null;
+        return connection;
+    }
+
     @Inject
     ScreenshotController(
             Context context,
@@ -316,6 +325,7 @@
 
         attachWindow();
         mWindow.setContentView(mScreenshotView);
+        mScreenshotView.requestApplyInsets();
 
         mScreenshotView.takePartialScreenshot(
                 rect -> takeScreenshotInternal(finisher, rect));
@@ -597,21 +607,12 @@
     }
 
     private void runScrollCapture(ScrollCaptureClient.Connection connection) {
-        cancelTimeout();
-        ScrollCaptureController controller = new ScrollCaptureController(mContext, connection,
-                mMainExecutor, mBgExecutor, mImageExporter, mUiEventLogger);
-        controller.attach(mWindow);
-        controller.start(new TakeScreenshotService.RequestCallback() {
-            @Override
-            public void reportError() {
-            }
+        sScrollConnection = connection;  // For LongScreenshotActivity to pick up.
 
-            @Override
-            public void onFinish() {
-                Log.d(TAG, "onFinish from ScrollCaptureController");
-                finishDismiss();
-            }
-        });
+        Intent intent = new Intent(mContext, LongScreenshotActivity.class);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        mContext.startActivity(intent);
+        dismissScreenshot(false);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java
index dc639dc..54b99bb 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java
@@ -21,24 +21,25 @@
 import static java.lang.Math.min;
 import static java.util.Objects.requireNonNull;
 
+import android.annotation.BinderThread;
 import android.annotation.UiContext;
 import android.app.ActivityTaskManager;
 import android.content.Context;
 import android.graphics.PixelFormat;
-import android.graphics.Point;
 import android.graphics.Rect;
 import android.hardware.HardwareBuffer;
 import android.media.Image;
 import android.media.ImageReader;
 import android.os.IBinder;
+import android.os.ICancellationSignal;
 import android.os.RemoteException;
 import android.util.Log;
 import android.view.IScrollCaptureCallbacks;
 import android.view.IScrollCaptureConnection;
 import android.view.IWindowManager;
+import android.view.ScrollCaptureResponse;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.view.ScrollCaptureViewSupport;
 
 import java.util.function.Consumer;
 
@@ -62,16 +63,19 @@
      */
     public interface Connection {
         /**
-         * Session start should be deferred until UI is active because of resource allocation and
-         * potential visible side effects in the target window.
-         *
+         * Start a session.
+
          * @param sessionConsumer listener to receive the session once active
          * @param maxPages the capture buffer size expressed as a multiple of the content height
          */
+        // TODO ListenableFuture
         void start(Consumer<Session> sessionConsumer, float maxPages);
 
         /**
-         * Close the connection.
+         * Close the connection. Must end capture if started to avoid potential unwanted visual
+         * artifacts.
+         *
+         * @see Session#end(Runnable)
          */
         void close();
     }
@@ -119,6 +123,7 @@
          * @param top the top (y) position of the tile to capture, in content rect space
          * @param consumer listener to be informed of the result
          */
+        // TODO ListenableFuture
         void requestTile(int top, Consumer<CaptureResult> consumer);
 
         /**
@@ -129,16 +134,31 @@
          */
         int getMaxTiles();
 
+        /**
+         * @return the height of each image tile
+         */
         int getTileHeight();
 
+        /**
+         * @return the height of scrollable content being captured
+         */
         int getPageHeight();
 
+        /**
+         * @return the width of the scrollable page
+         */
         int getPageWidth();
 
         /**
+         * @return the bounds on screen of the window being captured.
+         */
+        Rect getWindowBounds();
+
+        /**
          * End the capture session, return the target app to original state. The listener
          * will be called when the target app is ready to before visible and interactive.
          */
+        // TODO ListenableFuture
         void end(Runnable listener);
     }
 
@@ -185,13 +205,13 @@
                         + ", taskId=" + taskId + ", consumer=" + consumer + ")");
             }
             mWindowManagerService.requestScrollCapture(displayId, mHostWindowToken, taskId,
-                    new ControllerCallbacks(consumer));
+                    new ClientCallbacks(consumer));
         } catch (RemoteException e) {
             Log.e(TAG, "Ignored remote exception", e);
         }
     }
 
-    private static class ControllerCallbacks extends IScrollCaptureCallbacks.Stub implements
+    private static class ClientCallbacks extends IScrollCaptureCallbacks.Stub implements
             Connection, Session, IBinder.DeathRecipient {
 
         private IScrollCaptureConnection mConnection;
@@ -206,46 +226,63 @@
         private int mTileWidth;
         private Rect mRequestRect;
         private boolean mStarted;
+
+        private ICancellationSignal mCancellationSignal;
+        private Rect mWindowBounds;
+        private Rect mBoundsInWindow;
         private int mMaxTiles;
 
-        private ControllerCallbacks(Consumer<Connection> connectionConsumer) {
+        private ClientCallbacks(Consumer<Connection> connectionConsumer) {
             mConnectionConsumer = connectionConsumer;
         }
 
-        // IScrollCaptureCallbacks
-
+        @BinderThread
         @Override
-        public void onConnected(IScrollCaptureConnection connection, Rect scrollBounds,
-                Point positionInWindow) throws RemoteException {
+        public void onScrollCaptureResponse(ScrollCaptureResponse response) throws RemoteException {
             if (DEBUG_SCROLL) {
-                Log.d(TAG, "onConnected(connection=" + connection + ", scrollBounds=" + scrollBounds
-                        + ", positionInWindow=" + positionInWindow + ")");
+                Log.d(TAG, "onScrollCaptureResponse(response=" + response + ")");
             }
-            mConnection = connection;
-            mConnection.asBinder().linkToDeath(this, 0);
-            mScrollBounds = scrollBounds;
-            mConnectionConsumer.accept(this);
+            if (response.isConnected()) {
+                mConnection = response.getConnection();
+                mConnection.asBinder().linkToDeath(this, 0);
+                mWindowBounds = response.getWindowBounds();
+                mBoundsInWindow = response.getBoundsInWindow();
+
+                int pxPerPage = mBoundsInWindow.width() * mBoundsInWindow.height();
+                int pxPerTile = min(TILE_SIZE_PX_MAX, (pxPerPage / TILES_PER_PAGE));
+                mTileWidth = mBoundsInWindow.width();
+                mTileHeight = pxPerTile  / mBoundsInWindow.width();
+                if (DEBUG_SCROLL) {
+                    Log.d(TAG, "boundsInWindow: " + mBoundsInWindow);
+                    Log.d(TAG, "tile size: " + mTileWidth + "x" + mTileHeight);
+                    Log.d(TAG, "maxHeight: " + (mMaxTiles * mTileHeight) + "px");
+                }
+                mConnectionConsumer.accept(this);
+            }
             mConnectionConsumer = null;
-
-            int pxPerPage = mScrollBounds.width() * mScrollBounds.height();
-            int pxPerTile = min(TILE_SIZE_PX_MAX, (pxPerPage / TILES_PER_PAGE));
-            mTileWidth = mScrollBounds.width();
-            mTileHeight = pxPerTile  / mScrollBounds.width();
-            if (DEBUG_SCROLL) {
-                Log.d(TAG, "scrollBounds: " + mScrollBounds);
-                Log.d(TAG, "tile dimen: " + mTileWidth + "x" + mTileHeight);
-            }
         }
 
         @Override
-        public void onUnavailable() throws RemoteException {
+        public void start(Consumer<Session> sessionConsumer, float maxPages) {
             if (DEBUG_SCROLL) {
-                Log.d(TAG, "onUnavailable");
+                Log.d(TAG, "start(sessionConsumer=" + sessionConsumer + ","
+                        + " maxPages=" + maxPages + ")");
             }
-            // The targeted app does not support scroll capture
-            // or the window could not be found... etc etc.
+            mMaxTiles = (int) Math.ceil(maxPages * TILES_PER_PAGE);
+            mReader = ImageReader.newInstance(mTileWidth, mTileHeight, PixelFormat.RGBA_8888,
+                    mMaxTiles, HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE);
+            mSessionConsumer = sessionConsumer;
+
+            try {
+                mCancellationSignal = mConnection.startCapture(mReader.getSurface());
+                mStarted = true;
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed to start", e);
+                mReader.close();
+            }
         }
 
+        @BinderThread
         @Override
         public void onCaptureStarted() {
             if (DEBUG_SCROLL) {
@@ -256,13 +293,25 @@
         }
 
         @Override
-        public void onCaptureBufferSent(long frameNumber, Rect contentArea) {
-            Image image = null;
-            if (frameNumber != ScrollCaptureViewSupport.NO_FRAME_PRODUCED) {
-                image = mReader.acquireNextImage();
-            }
+        public void requestTile(int top, Consumer<CaptureResult> consumer) {
             if (DEBUG_SCROLL) {
-                Log.d(TAG, "onCaptureBufferSent(frameNumber=" + frameNumber
+                Log.d(TAG, "requestTile(top=" + top + ", consumer=" + consumer + ")");
+            }
+            cancelPendingRequest();
+            mRequestRect = new Rect(0, top, mTileWidth, top + mTileHeight);
+            mResultConsumer = consumer;
+            try {
+                mCancellationSignal = mConnection.requestImage(mRequestRect);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Caught remote exception from requestImage", e);
+            }
+        }
+
+        @Override
+        public void onImageRequestCompleted(int flags, Rect contentArea) {
+            Image image = mReader.acquireLatestImage();
+            if (DEBUG_SCROLL) {
+                Log.d(TAG, "onCaptureBufferSent(flags=" + flags
                         + ", contentArea=" + contentArea + ") image=" + image);
             }
             // Save and clear first, since the consumer will likely request the next
@@ -273,61 +322,13 @@
         }
 
         @Override
-        public void onConnectionClosed() {
-            if (DEBUG_SCROLL) {
-                Log.d(TAG, "onConnectionClosed()");
-            }
-            disconnect();
-            if (mShutdownListener != null) {
-                mShutdownListener.run();
-                mShutdownListener = null;
-            }
-        }
-
-        // Misc
-
-        private void disconnect() {
-            if (mConnection != null) {
-                mConnection.asBinder().unlinkToDeath(this, 0);
-            }
-            mConnection = null;
-        }
-
-        // ScrollCaptureController.Connection
-
-        @Override
-        public void start(Consumer<Session> sessionConsumer, float maxPages) {
-            if (DEBUG_SCROLL) {
-                Log.d(TAG, "start(sessionConsumer=" + sessionConsumer + ","
-                        + " maxPages=" + maxPages + ")"
-                        + " [maxHeight: " + (mMaxTiles * mTileHeight) + "px]");
-            }
-            mMaxTiles = (int) Math.ceil(maxPages * TILES_PER_PAGE);
-            mReader = ImageReader.newInstance(mTileWidth, mTileHeight, PixelFormat.RGBA_8888,
-                    mMaxTiles, HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE);
-            mSessionConsumer = sessionConsumer;
-            try {
-                mConnection.startCapture(mReader.getSurface());
-                mStarted = true;
-            } catch (RemoteException e) {
-                Log.w(TAG, "Failed to start", e);
-            }
-        }
-
-        @Override
-        public void close() {
-            end(null);
-        }
-
-        // ScrollCaptureController.Session
-
-        @Override
         public void end(Runnable listener) {
             if (DEBUG_SCROLL) {
                 Log.d(TAG, "end(listener=" + listener + ")");
             }
             if (mStarted) {
                 mShutdownListener = listener;
+                mReader.close();
                 try {
                     // listener called from onConnectionClosed callback
                     mConnection.endCapture();
@@ -342,40 +343,37 @@
             }
         }
 
+        @BinderThread
         @Override
-        public int getPageHeight() {
-            return mScrollBounds.height();
-        }
-
-        @Override
-        public int getPageWidth() {
-            return mScrollBounds.width();
-        }
-
-        @Override
-        public int getTileHeight() {
-            return mTileHeight;
-        }
-
-        @Override
-        public int getMaxTiles() {
-            return mMaxTiles;
-        }
-
-        @Override
-        public void requestTile(int top, Consumer<CaptureResult> consumer) {
-            if (DEBUG_SCROLL) {
-                Log.d(TAG, "requestTile(top=" + top + ", consumer=" + consumer + ")");
+        public void onCaptureEnded() {
+            close();
+            if (mShutdownListener != null) {
+                mShutdownListener.run();
+                mShutdownListener = null;
             }
-            mRequestRect = new Rect(0, top, mTileWidth, top + mTileHeight);
-            mResultConsumer = consumer;
-            try {
-                mConnection.requestImage(mRequestRect);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Caught remote exception from requestImage", e);
+        }
+
+        @Override
+        public void close() {
+            if (mConnection != null) {
+                try {
+                    mConnection.close();
+                } catch (RemoteException e) {
+                    /* ignore */
+                }
+                disconnect();
             }
         }
 
+        // Misc
+
+        private void disconnect() {
+            if (mConnection != null) {
+                mConnection.asBinder().unlinkToDeath(this, 0);
+            }
+            mConnection = null;
+        }
+
         /**
          * The process hosting the window went away abruptly!
          */
@@ -386,5 +384,40 @@
             }
             disconnect();
         }
+
+        @Override
+        public int getPageHeight() {
+            return mBoundsInWindow.height();
+        }
+
+        @Override
+        public int getPageWidth() {
+            return mBoundsInWindow.width();
+        }
+
+        @Override
+        public int getTileHeight() {
+            return mTileHeight;
+        }
+
+        public Rect getWindowBounds() {
+            return new Rect(mWindowBounds);
+        }
+
+        @Override
+        public int getMaxTiles() {
+            return mMaxTiles;
+        }
+
+        private void cancelPendingRequest() {
+            if (mCancellationSignal != null) {
+                try {
+                    mCancellationSignal.cancel();
+                } catch (RemoteException e) {
+                    /* ignore */
+                }
+                mCancellationSignal = null;
+            }
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java
index ad5e637..bf65132 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java
@@ -16,41 +16,24 @@
 
 package com.android.systemui.screenshot;
 
-import android.annotation.IdRes;
 import android.annotation.UiThread;
-import android.content.ComponentName;
 import android.content.Context;
-import android.content.Intent;
-import android.graphics.Rect;
 import android.net.Uri;
-import android.os.UserHandle;
 import android.provider.Settings;
-import android.text.TextUtils;
 import android.util.Log;
-import android.view.View;
-import android.view.ViewTreeObserver.InternalInsetsInfo;
-import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
-import android.view.Window;
-import android.widget.ImageView;
 
-import com.android.internal.logging.UiEventLogger;
-import com.android.systemui.R;
 import com.android.systemui.screenshot.ScrollCaptureClient.CaptureResult;
 import com.android.systemui.screenshot.ScrollCaptureClient.Connection;
 import com.android.systemui.screenshot.ScrollCaptureClient.Session;
-import com.android.systemui.screenshot.TakeScreenshotService.RequestCallback;
-
-import com.google.common.util.concurrent.ListenableFuture;
 
 import java.time.ZonedDateTime;
 import java.util.UUID;
-import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
 
 /**
  * Interaction controller between the UI and ScrollCaptureClient.
  */
-public class ScrollCaptureController implements OnComputeInternalInsetsListener {
+public class ScrollCaptureController {
     private static final String TAG = "ScrollCaptureController";
     private static final float MAX_PAGES_DEFAULT = 3f;
 
@@ -64,188 +47,44 @@
     private boolean mAtTopEdge;
     private Session mSession;
 
-    // TODO: Support saving without additional action.
-    private enum PendingAction {
-        SHARE,
-        EDIT,
-        SAVE
-    }
-
     public static final int MAX_HEIGHT = 12000;
 
-    private final Connection mConnection;
     private final Context mContext;
 
     private final Executor mUiExecutor;
     private final Executor mBgExecutor;
     private final ImageExporter mImageExporter;
     private final ImageTileSet mImageTileSet;
-    private final UiEventLogger mUiEventLogger;
 
     private ZonedDateTime mCaptureTime;
     private UUID mRequestId;
-    private RequestCallback mCallback;
-    private Window mWindow;
-    private ImageView mPreview;
-    private View mSave;
-    private View mCancel;
-    private View mEdit;
-    private View mShare;
-    private CropView mCropView;
-    private MagnifierView mMagnifierView;
+    private ScrollCaptureCallback mCaptureCallback;
 
-    public ScrollCaptureController(Context context, Connection connection, Executor uiExecutor,
-            Executor bgExecutor, ImageExporter exporter, UiEventLogger uiEventLogger) {
+    public ScrollCaptureController(Context context, Executor uiExecutor, Executor bgExecutor,
+            ImageExporter exporter) {
         mContext = context;
-        mConnection = connection;
         mUiExecutor = uiExecutor;
         mBgExecutor = bgExecutor;
         mImageExporter = exporter;
-        mUiEventLogger = uiEventLogger;
         mImageTileSet = new ImageTileSet(context.getMainThreadHandler());
     }
 
     /**
-     * @param window the window to display the preview
-     */
-    public void attach(Window window) {
-        mWindow = window;
-    }
-
-    /**
      * Run scroll capture!
      *
+     * @param connection connection to the remote window to be used
      * @param callback request callback to report back to the service
      */
-    public void start(RequestCallback callback) {
+    public void start(Connection connection, ScrollCaptureCallback callback) {
         mCaptureTime = ZonedDateTime.now();
         mRequestId = UUID.randomUUID();
-        mCallback = callback;
-
-        setContentView(R.layout.long_screenshot);
-        mWindow.getDecorView().getViewTreeObserver()
-                .addOnComputeInternalInsetsListener(this);
-        mPreview = findViewById(R.id.preview);
-
-        mSave = findViewById(R.id.save);
-        mCancel = findViewById(R.id.cancel);
-        mEdit = findViewById(R.id.edit);
-        mShare = findViewById(R.id.share);
-        mCropView = findViewById(R.id.crop_view);
-        mMagnifierView = findViewById(R.id.magnifier);
-        mCropView.setCropInteractionListener(mMagnifierView);
-
-        mSave.setOnClickListener(this::onClicked);
-        mCancel.setOnClickListener(this::onClicked);
-        mEdit.setOnClickListener(this::onClicked);
-        mShare.setOnClickListener(this::onClicked);
+        mCaptureCallback = callback;
 
         float maxPages = Settings.Secure.getFloat(mContext.getContentResolver(),
                 SETTING_KEY_MAX_PAGES, MAX_PAGES_DEFAULT);
-        mConnection.start(this::startCapture, maxPages);
+        connection.start(this::startCapture, maxPages);
     }
 
-
-    /** Ensure the entire window is touchable */
-    public void onComputeInternalInsets(InternalInsetsInfo inoutInfo) {
-        inoutInfo.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
-    }
-
-    void disableButtons() {
-        mSave.setEnabled(false);
-        mCancel.setEnabled(false);
-        mEdit.setEnabled(false);
-        mShare.setEnabled(false);
-    }
-
-    private void onClicked(View v) {
-        Log.d(TAG, "button clicked!");
-
-        int id = v.getId();
-        v.setPressed(true);
-        disableButtons();
-        if (id == R.id.save) {
-            startExport(PendingAction.SAVE);
-        } else if (id == R.id.cancel) {
-            doFinish();
-        } else if (id == R.id.edit) {
-            mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_EDIT);
-            startExport(PendingAction.EDIT);
-        } else if (id == R.id.share) {
-            mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_SHARE);
-            startExport(PendingAction.SHARE);
-        }
-    }
-
-    private void doFinish() {
-        mPreview.setImageDrawable(null);
-        mMagnifierView.setImageTileset(null);
-        mImageTileSet.clear();
-        mCallback.onFinish();
-        mWindow.getDecorView().getViewTreeObserver()
-                .removeOnComputeInternalInsetsListener(this);
-    }
-
-    private void startExport(PendingAction action) {
-        Rect croppedPortion = new Rect(
-                0,
-                (int) (mImageTileSet.getHeight() * mCropView.getTopBoundary()),
-                mImageTileSet.getWidth(),
-                (int) (mImageTileSet.getHeight() * mCropView.getBottomBoundary()));
-        ListenableFuture<ImageExporter.Result> exportFuture = mImageExporter.export(
-                mBgExecutor, mRequestId, mImageTileSet.toBitmap(croppedPortion), mCaptureTime);
-        exportFuture.addListener(() -> {
-            try {
-                ImageExporter.Result result = exportFuture.get();
-                if (action == PendingAction.EDIT) {
-                    doEdit(result.uri);
-                } else if (action == PendingAction.SHARE) {
-                    doShare(result.uri);
-                }
-                doFinish();
-            } catch (InterruptedException | ExecutionException e) {
-                Log.e(TAG, "failed to export", e);
-                mCallback.onFinish();
-            }
-        }, mUiExecutor);
-    }
-
-    private void doEdit(Uri uri) {
-        String editorPackage = mContext.getString(R.string.config_screenshotEditor);
-        Intent intent = new Intent(Intent.ACTION_EDIT);
-        if (!TextUtils.isEmpty(editorPackage)) {
-            intent.setComponent(ComponentName.unflattenFromString(editorPackage));
-        }
-        intent.setType("image/png");
-        intent.setData(uri);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
-                | Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-
-        mContext.startActivityAsUser(intent, UserHandle.CURRENT);
-    }
-
-    private void doShare(Uri uri) {
-        Intent intent = new Intent(Intent.ACTION_SEND);
-        intent.setType("image/png");
-        intent.setData(uri);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
-                | Intent.FLAG_GRANT_READ_URI_PERMISSION);
-        Intent sharingChooserIntent = Intent.createChooser(intent, null)
-                .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK
-                        | Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
-        mContext.startActivityAsUser(sharingChooserIntent, UserHandle.CURRENT);
-    }
-
-    private void setContentView(@IdRes int id) {
-        mWindow.setContentView(id);
-    }
-
-    <T extends View> T findViewById(@IdRes int res) {
-        return mWindow.findViewById(res);
-    }
-
-
     private void onCaptureResult(CaptureResult result) {
         Log.d(TAG, "onCaptureResult: " + result);
         boolean emptyResult = result.captured.height() == 0;
@@ -327,11 +166,26 @@
         Log.d(TAG, "afterCaptureComplete");
 
         if (mImageTileSet.isEmpty()) {
-            session.end(mCallback::onFinish);
+            mCaptureCallback.onError();
         } else {
-            mPreview.setImageDrawable(mImageTileSet.getDrawable());
-            mMagnifierView.setImageTileset(mImageTileSet);
-            mCropView.animateBoundaryTo(CropView.CropBoundary.BOTTOM, 0.5f);
+            mCaptureCallback.onComplete(mImageTileSet);
         }
     }
+
+    /**
+     * Callback for image capture completion or error.
+     */
+    public interface ScrollCaptureCallback {
+        void onComplete(ImageTileSet imageTileSet);
+        void onError();
+    }
+
+    /**
+     * Callback for image export completion or error.
+     */
+    public interface ExportCallback {
+        void onExportComplete(Uri outputUri);
+        void onError();
+    }
+
 }
diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
index 9f182e1..6586137 100644
--- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
@@ -25,8 +25,8 @@
 import android.content.res.Resources
 import android.hardware.SensorPrivacyManager
 import android.hardware.SensorPrivacyManager.EXTRA_SENSOR
-import android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_CAMERA
-import android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE
+import android.hardware.SensorPrivacyManager.Sensors.CAMERA
+import android.hardware.SensorPrivacyManager.Sensors.MICROPHONE
 import android.os.Bundle
 import android.os.Handler
 import android.text.Html
@@ -81,7 +81,7 @@
                 dismiss()
             }
         }
-        if (!sensorPrivacyManager.isIndividualSensorPrivacyEnabled(sensor)) {
+        if (!sensorPrivacyManager.isSensorPrivacyEnabled(sensor)) {
             finish()
             return
         }
@@ -89,9 +89,9 @@
         mAlertParams.apply {
             try {
                 mMessage = Html.fromHtml(getString(when (sensor) {
-                    INDIVIDUAL_SENSOR_MICROPHONE ->
+                    MICROPHONE ->
                         R.string.sensor_privacy_start_use_mic_dialog_content
-                    INDIVIDUAL_SENSOR_CAMERA ->
+                    CAMERA ->
                         R.string.sensor_privacy_start_use_camera_dialog_content
                     else -> Resources.ID_NULL
                 }, packageManager.getApplicationInfo(sensorUsePackageName, 0)
@@ -102,9 +102,9 @@
             }
 
             mIconId = when (sensor) {
-                INDIVIDUAL_SENSOR_MICROPHONE ->
+                MICROPHONE ->
                     com.android.internal.R.drawable.perm_group_microphone
-                INDIVIDUAL_SENSOR_CAMERA -> com.android.internal.R.drawable.perm_group_camera
+                CAMERA -> com.android.internal.R.drawable.perm_group_camera
                 else -> Resources.ID_NULL
             }
 
@@ -121,7 +121,7 @@
     override fun onStart() {
         super.onStart()
 
-        sensorPrivacyManager.suppressIndividualSensorPrivacyReminders(sensorUsePackageName, true)
+        sensorPrivacyManager.suppressSensorPrivacyReminders(sensorUsePackageName, true)
         unsuppressImmediately = false
     }
 
@@ -156,11 +156,11 @@
 
         if (unsuppressImmediately) {
             sensorPrivacyManager
-                    .suppressIndividualSensorPrivacyReminders(sensorUsePackageName, false)
+                    .suppressSensorPrivacyReminders(sensorUsePackageName, false)
         } else {
             Handler(mainLooper).postDelayed({
                 sensorPrivacyManager
-                        .suppressIndividualSensorPrivacyReminders(sensorUsePackageName, false)
+                        .suppressSensorPrivacyReminders(sensorUsePackageName, false)
             }, SUPPRESS_REMINDERS_REMOVAL_DELAY_MILLIS)
         }
     }
@@ -170,7 +170,7 @@
     }
 
     private fun disableSensorPrivacy() {
-        sensorPrivacyManager.setIndividualSensorPrivacyForProfileGroup(sensor, false)
+        sensorPrivacyManager.setSensorPrivacyForProfileGroup(sensor, false)
         unsuppressImmediately = true
         setResult(RESULT_OK)
     }
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
index 0bfc8e5..fea521f 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
@@ -72,8 +72,6 @@
     private static final Uri BRIGHTNESS_FOR_VR_FLOAT_URI =
             Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT);
 
-    private final float mMinimumBacklight;
-    private final float mMaximumBacklight;
     private final float mDefaultBacklight;
     private final float mMinimumBacklightForVr;
     private final float mMaximumBacklightForVr;
@@ -314,10 +312,6 @@
 
         mDisplayId = mContext.getDisplayId();
         PowerManager pm = context.getSystemService(PowerManager.class);
-        mMinimumBacklight = pm.getBrightnessConstraint(
-                PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);
-        mMaximumBacklight = pm.getBrightnessConstraint(
-                PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);
         mDefaultBacklight = mContext.getDisplay().getBrightnessDefault();
         mMinimumBacklightForVr = pm.getBrightnessConstraint(
                 PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR);
@@ -375,8 +369,8 @@
             metric = mAutomatic
                     ? MetricsEvent.ACTION_BRIGHTNESS_AUTO
                     : MetricsEvent.ACTION_BRIGHTNESS;
-            minBacklight = mMinimumBacklight;
-            maxBacklight = mMaximumBacklight;
+            minBacklight = PowerManager.BRIGHTNESS_MIN;
+            maxBacklight = PowerManager.BRIGHTNESS_MAX;
             settingToChange = Settings.System.SCREEN_BRIGHTNESS_FLOAT;
         }
         final float valFloat = MathUtils.min(convertGammaToLinearFloat(value,
@@ -439,8 +433,8 @@
             min = mMinimumBacklightForVr;
             max = mMaximumBacklightForVr;
         } else {
-            min = mMinimumBacklight;
-            max = mMaximumBacklight;
+            min = PowerManager.BRIGHTNESS_MIN;
+            max = PowerManager.BRIGHTNESS_MAX;
         }
         // convertGammaToLinearFloat returns 0-1
         if (BrightnessSynchronizer.floatEquals(brightnessValue,
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
index a6aec3b..0b40e22 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
@@ -17,8 +17,6 @@
 package com.android.systemui.settings.brightness;
 
 import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -29,10 +27,8 @@
 import androidx.annotation.Nullable;
 
 import com.android.settingslib.RestrictedLockUtils;
-import com.android.settingslib.Utils;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.BrightnessMirrorController;
-import com.android.systemui.util.RoundedCornerProgressDrawable;
 import com.android.systemui.util.ViewController;
 
 import javax.inject.Inject;
@@ -274,9 +270,6 @@
         private BrightnessSlider fromTree(ViewGroup root, boolean useMirror) {
             BrightnessSliderView v = root.requireViewById(R.id.brightness_slider);
 
-            // TODO(175026098) Workaround. Remove when b/175026098 is fixed
-            applyTheme(v);
-
             return new BrightnessSlider(root, v, useMirror);
         }
 
@@ -286,32 +279,5 @@
                     ? R.layout.quick_settings_brightness_dialog_thick
                     : R.layout.quick_settings_brightness_dialog;
         }
-
-        private LayerDrawable findProgressClippableDrawable(BrightnessSliderView v) {
-            SeekBar b = v.requireViewById(R.id.slider);
-            if (b.getProgressDrawable() instanceof LayerDrawable) {
-                Drawable progress = ((LayerDrawable) b.getProgressDrawable())
-                        .findDrawableByLayerId(com.android.internal.R.id.progress);
-                if (progress instanceof RoundedCornerProgressDrawable) {
-                    Drawable inner = ((RoundedCornerProgressDrawable) progress).getDrawable();
-                    if (inner instanceof LayerDrawable) {
-                        return (LayerDrawable) inner;
-                    }
-                }
-            }
-            return null;
-        }
-
-        private void applyTheme(BrightnessSliderView v) {
-            LayerDrawable layer = findProgressClippableDrawable(v);
-            if (layer != null) {
-                layer.findDrawableByLayerId(R.id.slider_foreground).setTintList(
-                        Utils.getColorAttr(v.getContext(),
-                                com.android.internal.R.attr.colorControlActivated));
-                layer.findDrawableByLayerId(R.id.slider_icon).setTintList(
-                        Utils.getColorAttr(v.getContext(),
-                                com.android.internal.R.attr.colorBackground));
-            }
-        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
index 862c279..1d59257 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
@@ -82,4 +82,12 @@
     public boolean isMonetEnabled() {
         return mFlagReader.isEnabled(R.bool.flag_monet);
     }
+
+    public boolean isNavigationBarOverlayEnabled() {
+        return mFlagReader.isEnabled(R.bool.flag_navigation_bar_overlay);
+    }
+
+    public boolean isPMLiteEnabled() {
+        return mFlagReader.isEnabled(R.bool.flag_pm_lite);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java b/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java
index f2adaf0..9ed9659 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java
@@ -207,7 +207,7 @@
             sb.append(g.toJson());
             count++;
         }
-        mLastSaveLen = count;
+        mLastSaveLen += count;
         sb.append("]");
         return sb.toString();
     }
@@ -249,7 +249,9 @@
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         save();
         if (mLastSaveLen >= 0) {
-            pw.println(String.valueOf(mLastSaveLen) + " gestures written to " + mLogfile);
+            pw.println(String.valueOf(mLastSaveLen)
+                    + " gestures since last dump written to " + mLogfile);
+            mLastSaveLen = 0;
         } else {
             pw.println("error writing gestures");
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 7e2d27a..a4e97a1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar;
 
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
 
@@ -41,6 +42,7 @@
 import android.content.IntentFilter;
 import android.content.pm.UserInfo;
 import android.content.res.ColorStateList;
+import android.content.res.Resources;
 import android.graphics.Color;
 import android.hardware.biometrics.BiometricSourceType;
 import android.hardware.face.FaceManager;
@@ -277,10 +279,7 @@
         // avoid calling this method since it has an IPC
         if (whitelistIpcs(this::isOrganizationOwnedDevice)) {
             final CharSequence organizationName = getOrganizationOwnedDeviceOrganizationName();
-            final CharSequence disclosure =  organizationName != null
-                    ? mContext.getResources().getString(R.string.do_disclosure_with_name,
-                    organizationName)
-                    : mContext.getResources().getText(R.string.do_disclosure_generic);
+            final CharSequence disclosure = getDisclosureText(organizationName);
             mRotateTextViewController.updateIndication(
                     INDICATION_TYPE_DISCLOSURE,
                     new KeyguardIndication.Builder()
@@ -297,6 +296,22 @@
         }
     }
 
+    private CharSequence getDisclosureText(@Nullable CharSequence organizationName) {
+        final Resources packageResources = mContext.getResources();
+        if (organizationName == null) {
+            return packageResources.getText(R.string.do_disclosure_generic);
+        } else if (mDevicePolicyManager.isDeviceManaged()
+                && mDevicePolicyManager.getDeviceOwnerType(
+                mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser())
+                == DEVICE_OWNER_TYPE_FINANCED) {
+            return packageResources.getString(R.string.do_financed_disclosure_with_name,
+                    organizationName);
+        } else {
+            return packageResources.getString(R.string.do_disclosure_with_name,
+                    organizationName);
+        }
+    }
+
     private void updateOwnerInfo() {
         if (!isKeyguardLayoutEnabled()) {
             mRotateTextViewController.hideIndication(INDICATION_TYPE_OWNER_INFO);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index cfadcd7..34b29ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -133,10 +133,11 @@
     protected Callback mCallback;
     protected final ArrayList<NotificationLifetimeExtender> mLifetimeExtenders = new ArrayList<>();
 
-    private final RemoteViews.OnClickHandler mOnClickHandler = new RemoteViews.OnClickHandler() {
+    private final RemoteViews.InteractionHandler
+            mInteractionHandler = new RemoteViews.InteractionHandler() {
 
         @Override
-        public boolean onClickHandler(
+        public boolean onInteraction(
                 View view, PendingIntent pendingIntent, RemoteViews.RemoteResponse response) {
             mStatusBarLazy.get().wakeUpIfDozing(SystemClock.uptimeMillis(), view,
                     "NOTIFICATION_CLICK");
@@ -164,11 +165,11 @@
             Notification.Action action = getActionFromView(view, entry, pendingIntent);
             return mCallback.handleRemoteViewClick(view, pendingIntent,
                     action == null ? false : action.isAuthenticationRequired(), () -> {
-                Pair<Intent, ActivityOptions> options = response.getLaunchOptions(view);
-                options.second.setLaunchWindowingMode(
-                        WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
-                mLogger.logStartingIntentWithDefaultHandler(entry, pendingIntent);
-                return RemoteViews.startPendingIntent(view, pendingIntent, options);
+                    Pair<Intent, ActivityOptions> options = response.getLaunchOptions(view);
+                    options.second.setLaunchWindowingMode(
+                            WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
+                    mLogger.logStartingIntentWithDefaultHandler(entry, pendingIntent);
+                    return RemoteViews.startPendingIntent(view, pendingIntent, options);
             });
         }
 
@@ -690,8 +691,8 @@
      *
      * @return on-click handler
      */
-    public RemoteViews.OnClickHandler getRemoteViewsOnClickHandler() {
-        return mOnClickHandler;
+    public RemoteViews.InteractionHandler getRemoteViewsOnClickHandler() {
+        return mInteractionHandler;
     }
 
     @VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 20efa32..d2ddd21 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -1002,10 +1002,6 @@
         return false;
     }
 
-    public void onUiModeChanged() {
-        updateBackgroundColors();
-    }
-
     public void setController(NotificationShelfController notificationShelfController) {
         mController = notificationShelfController;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
index d562726..138c811 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
@@ -24,7 +24,6 @@
 
 import android.content.Context;
 import android.content.res.ColorStateList;
-import android.graphics.Color;
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.util.FeatureFlagUtils;
@@ -238,11 +237,7 @@
     @Override
     public void setStaticDrawableColor(int color) {
         ColorStateList list = ColorStateList.valueOf(color);
-        float intensity = color == Color.WHITE ? 0 : 1;
-        // We want the ability to change the theme from the one set by SignalDrawable in certain
-        // surfaces. In this way, we can pass a theme to the view.
-        mMobileDrawable.setTintList(
-                ColorStateList.valueOf(mDualToneHandler.getSingleColor(intensity)));
+        mMobileDrawable.setTintList(list);
         mIn.setImageTintList(list);
         mOut.setImageTintList(list);
         mMobileType.setImageTintList(list);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java
index edcf6d4..4b4e513 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java
@@ -109,10 +109,10 @@
                 && newImportance < NotificationManager.IMPORTANCE_DEFAULT) {
             return STATUS_SILENCED;
         } else if (oldImportance < newImportance
-                || ranking.getRankingAdjustment() == ranking.RANKING_PROMOTED) {
+                || ranking.getRankingAdjustment() == Ranking.RANKING_PROMOTED) {
             return STATUS_PROMOTED;
         } else if (oldImportance > newImportance
-                || ranking.getRankingAdjustment() == ranking.RANKING_DEMOTED) {
+                || ranking.getRankingAdjustment() == Ranking.RANKING_DEMOTED) {
             return STATUS_DEMOTED;
         } else {
             return STATUS_UNCHANGED;
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 7c3b791..c8c0755 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -548,8 +548,6 @@
         try {
             mStatusBarService.onNotificationClear(
                     notification.getPackageName(),
-                    notification.getTag(),
-                    notification.getId(),
                     notification.getUser().getIdentifier(),
                     notification.getKey(),
                     dismissedByUserStats.dismissalSurface,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
index 73c7fd1..f21771a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
@@ -128,15 +128,6 @@
             // this is a foreground-service disclosure for a user that does not need to show one
             return true;
         }
-        if (getFsc().isSystemAlertNotification(sbn)) {
-            final String[] apps = sbn.getNotification().extras.getStringArray(
-                    Notification.EXTRA_FOREGROUND_APPS);
-            if (apps != null && apps.length >= 1) {
-                if (!getFsc().isSystemAlertWarningNeeded(sbn.getUserId(), apps[0])) {
-                    return true;
-                }
-            }
-        }
 
         if (mIsMediaFlagEnabled && isMediaNotification(sbn)) {
             return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index e391250..50cbbd5d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -264,6 +264,20 @@
     }
 
     override fun onStateChanged(newState: Int) {
+        if (dozeParameters.shouldControlUnlockedScreenOff()) {
+            if (animatingScreenOff &&
+                    state == StatusBarState.KEYGUARD &&
+                    newState == StatusBarState.SHADE) {
+                // If we're animating the screen off and going from KEYGUARD back to SHADE, the
+                // animation was cancelled and we are unlocking. Override the doze amount to 0f (not
+                // dozing) so that the notifications are no longer hidden.
+                setDozeAmount(0f, 0f)
+            }
+
+            animatingScreenOff =
+                    state == StatusBarState.SHADE && newState == StatusBarState.KEYGUARD
+        }
+
         overrideDozeAmountIfBypass()
         if (bypassController.bypassEnabled &&
                 newState == StatusBarState.KEYGUARD && state == StatusBarState.SHADE_LOCKED &&
@@ -273,13 +287,6 @@
             setNotificationsVisible(visible = false, increaseSpeed = false, animate = true)
         }
 
-        // If we want to control the screen off animation, check whether we are going from SHADE to
-        // KEYGUARD.
-        if (dozeParameters.shouldControlUnlockedScreenOff()) {
-            animatingScreenOff =
-                state == StatusBarState.SHADE && newState == StatusBarState.KEYGUARD
-        }
-
         this.state = newState
     }
 
@@ -386,8 +393,6 @@
     override fun onDozingChanged(isDozing: Boolean) {
         if (isDozing) {
             setNotificationsVisible(visible = false, animate = false, increaseSpeed = false)
-        } else {
-            animatingScreenOff = false
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index d617dff..6b96ee4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -254,8 +254,6 @@
                 try {
                     mStatusBarService.onNotificationClear(
                             entry.getSbn().getPackageName(),
-                            entry.getSbn().getTag(),
-                            entry.getSbn().getId(),
                             entry.getSbn().getUser().getIdentifier(),
                             entry.getSbn().getKey(),
                             stats.dismissalSurface,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
index 998ae9e..3a87f68 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
@@ -95,18 +95,6 @@
                             sbn.getUser().getIdentifier())) {
                 return true;
             }
-
-            // Filters out system alert notifications when unneeded
-            if (mForegroundServiceController.isSystemAlertNotification(sbn)) {
-                final String[] apps = sbn.getNotification().extras.getStringArray(
-                        Notification.EXTRA_FOREGROUND_APPS);
-                if (apps != null && apps.length >= 1) {
-                    if (!mForegroundServiceController.isSystemAlertWarningNeeded(
-                            sbn.getUser().getIdentifier(), apps[0])) {
-                        return true;
-                    }
-                }
-            }
             return false;
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index 724921b..31d052d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -191,7 +191,10 @@
         initDimens();
     }
 
-    protected void updateBackgroundColors() {
+    /**
+     * Reload background colors from resources and invalidate views.
+     */
+    public void updateBackgroundColors() {
         updateColors();
         initBackground();
         updateBackgroundTint();
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 845d321..1251b58 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
@@ -104,7 +104,7 @@
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
-import com.android.systemui.statusbar.policy.InflatedSmartReplies.SmartRepliesAndActions;
+import com.android.systemui.statusbar.policy.InflatedSmartReplyState;
 import com.android.systemui.wmshell.BubblesManager;
 
 import java.io.FileDescriptor;
@@ -3196,8 +3196,8 @@
     /**
      * Returns the Smart Suggestions backing the smart suggestion buttons in the notification.
      */
-    public SmartRepliesAndActions getExistingSmartRepliesAndActions() {
-        return mPrivateLayout.getCurrentSmartRepliesAndActions();
+    public InflatedSmartReplyState getExistingSmartReplyState() {
+        return mPrivateLayout.getCurrentSmartReplyState();
     }
 
     @VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java
index 35f3561..14683ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java
@@ -16,8 +16,14 @@
 
 package com.android.systemui.statusbar.notification.row;
 
+import static android.service.notification.NotificationAssistantService.FEEDBACK_RATING;
+
+import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_ALERTED;
+import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_DEMOTED;
+import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_PROMOTED;
+import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_SILENCED;
+
 import android.annotation.SuppressLint;
-import android.app.Notification;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -36,20 +42,17 @@
 import android.widget.TextView;
 
 import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.statusbar.NotificationVisibility;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
 import com.android.systemui.statusbar.notification.AssistantFeedbackController;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 
 public class FeedbackInfo extends LinearLayout implements NotificationGuts.GutsContent {
 
     private static final String TAG = "FeedbackInfo";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    private static final String FEEDBACK_KEY = "feedback_key";
 
     private NotificationGuts mGutsContainer;
     private NotificationListenerService.Ranking mRanking;
@@ -146,15 +149,15 @@
             sb.append(String.format(
                     "[DEBUG]: oldImportance=%d, newImportance=%d, ranking=%d\n\n",
                     mRanking.getChannel().getImportance(), mRanking.getImportance(),
-                    mRanking.getRankingAdjustment()));
+                    mRanking.getRankingScore()));
         }
-        if (status == mFeedbackController.STATUS_ALERTED) {
+        if (status == STATUS_ALERTED) {
             sb.append(mContext.getText(R.string.feedback_alerted));
-        } else if (status == mFeedbackController.STATUS_SILENCED) {
+        } else if (status == STATUS_SILENCED) {
             sb.append(mContext.getText(R.string.feedback_silenced));
-        } else if (status == mFeedbackController.STATUS_PROMOTED) {
+        } else if (status == STATUS_PROMOTED) {
             sb.append(mContext.getText(R.string.feedback_promoted));
-        } else if (status == mFeedbackController.STATUS_DEMOTED) {
+        } else if (status == STATUS_DEMOTED) {
             sb.append(mContext.getText(R.string.feedback_demoted));
         }
         sb.append(" ");
@@ -182,7 +185,8 @@
 
     private void handleFeedback(boolean positive) {
         Bundle feedback = new Bundle();
-        feedback.putBoolean(FEEDBACK_KEY, positive);
+        feedback.putInt(FEEDBACK_RATING, positive ? 1 : -1);
+
         sendFeedbackToAssistant(feedback);
     }
 
@@ -191,19 +195,8 @@
             return;
         }
 
-        //TODO(b/154257994): remove this when feedback apis are in place
-        final int count = mNotificationEntryManager.getActiveNotificationsCount();
-        final int rank = mEntry.getRanking().getRank();
-        NotificationVisibility.NotificationLocation location =
-                NotificationLogger.getNotificationLocation(mEntry);
-        final NotificationVisibility nv = NotificationVisibility.obtain(
-                mEntry.getKey(), rank, count, true, location);
-        Notification.Action action = new Notification.Action.Builder(null, null,
-                null)
-                .addExtras(feedback)
-                .build();
         try {
-            mStatusBarService.onNotificationActionClick(mRanking.getKey(), -1, action, nv, true);
+            mStatusBarService.onNotificationFeedbackReceived(mRanking.getKey(), feedback);
         } catch (RemoteException e) {
             if (DEBUG) {
                 Log.e(TAG, "Failed to send feedback to assistant", e);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index c2c4590..fdd8f34 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -48,9 +48,9 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
 import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.policy.InflatedSmartReplies;
-import com.android.systemui.statusbar.policy.InflatedSmartReplies.SmartRepliesAndActions;
-import com.android.systemui.statusbar.policy.SmartRepliesAndActionsInflater;
+import com.android.systemui.statusbar.policy.InflatedSmartReplyState;
+import com.android.systemui.statusbar.policy.InflatedSmartReplyViewHolder;
+import com.android.systemui.statusbar.policy.SmartReplyStateInflater;
 import com.android.systemui.util.Assert;
 
 import java.util.HashMap;
@@ -74,7 +74,7 @@
     private final NotifRemoteViewCache mRemoteViewCache;
     private final ConversationNotificationProcessor mConversationProcessor;
     private final Executor mBgExecutor;
-    private final SmartRepliesAndActionsInflater mSmartRepliesAndActionsInflater;
+    private final SmartReplyStateInflater mSmartReplyStateInflater;
 
     @Inject
     NotificationContentInflater(
@@ -83,13 +83,13 @@
             ConversationNotificationProcessor conversationProcessor,
             MediaFeatureFlag mediaFeatureFlag,
             @Background Executor bgExecutor,
-            SmartRepliesAndActionsInflater smartRepliesInflater) {
+            SmartReplyStateInflater smartRepliesInflater) {
         mRemoteViewCache = remoteViewCache;
         mRemoteInputManager = remoteInputManager;
         mConversationProcessor = conversationProcessor;
         mIsMediaInQS = mediaFeatureFlag.getEnabled();
         mBgExecutor = bgExecutor;
-        mSmartRepliesAndActionsInflater = smartRepliesInflater;
+        mSmartReplyStateInflater = smartRepliesInflater;
     }
 
     @Override
@@ -133,7 +133,7 @@
                 callback,
                 mRemoteInputManager.getRemoteViewsOnClickHandler(),
                 mIsMediaInQS,
-                mSmartRepliesAndActionsInflater);
+                mSmartReplyStateInflater);
         if (mInflateSynchronously) {
             task.onPostExecute(task.doInBackground());
         } else {
@@ -150,7 +150,7 @@
             @InflationFlag int reInflateFlags,
             Notification.Builder builder,
             Context packageContext,
-            SmartRepliesAndActionsInflater smartRepliesInflater) {
+            SmartReplyStateInflater smartRepliesInflater) {
         InflationProgress result = createRemoteViews(reInflateFlags,
                 builder,
                 bindParams.isLowPriority,
@@ -160,7 +160,7 @@
 
         result = inflateSmartReplyViews(result, reInflateFlags, entry,
                 row.getContext(), packageContext,
-                row.getExistingSmartRepliesAndActions(),
+                row.getExistingSmartReplyState(),
                 smartRepliesInflater);
 
         apply(
@@ -268,15 +268,26 @@
             NotificationEntry entry,
             Context context,
             Context packageContext,
-            SmartRepliesAndActions previousSmartRepliesAndActions,
-            SmartRepliesAndActionsInflater inflater) {
-        if ((reInflateFlags & FLAG_CONTENT_VIEW_EXPANDED) != 0 && result.newExpandedView != null) {
-            result.expandedInflatedSmartReplies = inflater.inflateSmartReplies(
-                    context, packageContext, entry, previousSmartRepliesAndActions);
+            InflatedSmartReplyState previousSmartReplyState,
+            SmartReplyStateInflater inflater) {
+        boolean inflateContracted = (reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0
+                && result.newContentView != null;
+        boolean inflateExpanded = (reInflateFlags & FLAG_CONTENT_VIEW_EXPANDED) != 0
+                && result.newExpandedView != null;
+        boolean inflateHeadsUp = (reInflateFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0
+                && result.newHeadsUpView != null;
+        if (inflateContracted || inflateExpanded || inflateHeadsUp) {
+            result.inflatedSmartReplyState = inflater.inflateSmartReplyState(entry);
         }
-        if ((reInflateFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0 && result.newHeadsUpView != null) {
-            result.headsUpInflatedSmartReplies = inflater.inflateSmartReplies(
-                    context, packageContext, entry, previousSmartRepliesAndActions);
+        if (inflateExpanded) {
+            result.expandedInflatedSmartReplies = inflater.inflateSmartReplyViewHolder(
+                    context, packageContext, entry, previousSmartReplyState,
+                    result.inflatedSmartReplyState);
+        }
+        if (inflateHeadsUp) {
+            result.headsUpInflatedSmartReplies = inflater.inflateSmartReplyViewHolder(
+                    context, packageContext, entry, previousSmartReplyState,
+                    result.inflatedSmartReplyState);
         }
         return result;
     }
@@ -317,7 +328,7 @@
             NotifRemoteViewCache remoteViewCache,
             NotificationEntry entry,
             ExpandableNotificationRow row,
-            RemoteViews.OnClickHandler remoteViewClickHandler,
+            RemoteViews.InteractionHandler remoteViewClickHandler,
             @Nullable InflationCallback callback) {
         NotificationContentView privateLayout = row.getPrivateLayout();
         NotificationContentView publicLayout = row.getPublicLayout();
@@ -442,7 +453,7 @@
             final NotificationEntry entry,
             final ExpandableNotificationRow row,
             boolean isNewView,
-            RemoteViews.OnClickHandler remoteViewClickHandler,
+            RemoteViews.InteractionHandler remoteViewClickHandler,
             @Nullable final InflationCallback callback,
             NotificationContentView parentLayout,
             View existingView,
@@ -566,6 +577,7 @@
         NotificationContentView privateLayout = row.getPrivateLayout();
         NotificationContentView publicLayout = row.getPublicLayout();
         if (runningInflations.isEmpty()) {
+            boolean setRepliesAndActions = true;
             if ((reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0) {
                 if (result.inflatedContentView != null) {
                     // New view case
@@ -578,6 +590,7 @@
                     remoteViewCache.putCachedView(entry, FLAG_CONTENT_VIEW_CONTRACTED,
                             result.newContentView);
                 }
+                setRepliesAndActions = true;
             }
 
             if ((reInflateFlags & FLAG_CONTENT_VIEW_EXPANDED) != 0) {
@@ -599,6 +612,7 @@
                     privateLayout.setExpandedInflatedSmartReplies(null);
                 }
                 row.setExpandable(result.newExpandedView != null);
+                setRepliesAndActions = true;
             }
 
             if ((reInflateFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0) {
@@ -619,6 +633,10 @@
                 } else {
                     privateLayout.setHeadsUpInflatedSmartReplies(null);
                 }
+                setRepliesAndActions = true;
+            }
+            if (setRepliesAndActions) {
+                privateLayout.setInflatedSmartReplyState(result.inflatedSmartReplyState);
             }
 
             if ((reInflateFlags & FLAG_CONTENT_VIEW_PUBLIC) != 0) {
@@ -705,11 +723,11 @@
         private final Executor mBgExecutor;
         private ExpandableNotificationRow mRow;
         private Exception mError;
-        private RemoteViews.OnClickHandler mRemoteViewClickHandler;
+        private RemoteViews.InteractionHandler mRemoteViewClickHandler;
         private CancellationSignal mCancellationSignal;
         private final ConversationNotificationProcessor mConversationProcessor;
         private final boolean mIsMediaInQS;
-        private final SmartRepliesAndActionsInflater mSmartRepliesInflater;
+        private final SmartReplyStateInflater mSmartRepliesInflater;
 
         private AsyncInflationTask(
                 Executor bgExecutor,
@@ -723,9 +741,9 @@
                 boolean usesIncreasedHeight,
                 boolean usesIncreasedHeadsUpHeight,
                 InflationCallback callback,
-                RemoteViews.OnClickHandler remoteViewClickHandler,
+                RemoteViews.InteractionHandler remoteViewClickHandler,
                 boolean isMediaFlagEnabled,
-                SmartRepliesAndActionsInflater smartRepliesInflater) {
+                SmartReplyStateInflater smartRepliesInflater) {
             mEntry = entry;
             mRow = row;
             mBgExecutor = bgExecutor;
@@ -776,15 +794,14 @@
                 InflationProgress inflationProgress = createRemoteViews(mReInflateFlags,
                         recoveredBuilder, mIsLowPriority, mUsesIncreasedHeight,
                         mUsesIncreasedHeadsUpHeight, packageContext);
-                SmartRepliesAndActions repliesAndActions =
-                        mRow.getExistingSmartRepliesAndActions();
+                InflatedSmartReplyState previousSmartReplyState = mRow.getExistingSmartReplyState();
                 return inflateSmartReplyViews(
                         inflationProgress,
                         mReInflateFlags,
                         mEntry,
                         mContext,
                         packageContext,
-                        repliesAndActions,
+                        previousSmartReplyState,
                         mSmartRepliesInflater);
             } catch (Exception e) {
                 mError = e;
@@ -879,8 +896,9 @@
         private CharSequence headsUpStatusBarText;
         private CharSequence headsUpStatusBarTextPublic;
 
-        private InflatedSmartReplies expandedInflatedSmartReplies;
-        private InflatedSmartReplies headsUpInflatedSmartReplies;
+        private InflatedSmartReplyState inflatedSmartReplyState;
+        private InflatedSmartReplyViewHolder expandedInflatedSmartReplies;
+        private InflatedSmartReplyViewHolder headsUpInflatedSmartReplies;
     }
 
     @VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index d2774df..7691761 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -17,15 +17,11 @@
 package com.android.systemui.statusbar.notification.row;
 
 
-import static android.provider.Settings.Global.NOTIFICATION_BUBBLES;
-import static android.provider.Settings.Secure.SHOW_NOTIFICATION_SNOOZE;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.content.Context;
-import android.content.res.Resources;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
@@ -58,16 +54,18 @@
 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
 import com.android.systemui.statusbar.notification.row.wrapper.NotificationCustomViewWrapper;
 import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
-import com.android.systemui.statusbar.policy.InflatedSmartReplies;
-import com.android.systemui.statusbar.policy.InflatedSmartReplies.SmartRepliesAndActions;
+import com.android.systemui.statusbar.policy.InflatedSmartReplyState;
+import com.android.systemui.statusbar.policy.InflatedSmartReplyViewHolder;
 import com.android.systemui.statusbar.policy.RemoteInputView;
-import com.android.systemui.statusbar.policy.SmartRepliesAndActionsInflaterKt;
 import com.android.systemui.statusbar.policy.SmartReplyConstants;
+import com.android.systemui.statusbar.policy.SmartReplyStateInflaterKt;
 import com.android.systemui.statusbar.policy.SmartReplyView;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * A frame layout containing the actual payload of the notification, including the contracted,
@@ -106,9 +104,9 @@
     private SmartReplyView mExpandedSmartReplyView;
     private SmartReplyView mHeadsUpSmartReplyView;
     private SmartReplyController mSmartReplyController;
-    private InflatedSmartReplies mExpandedInflatedSmartReplies;
-    private InflatedSmartReplies mHeadsUpInflatedSmartReplies;
-    private SmartRepliesAndActions mCurrentSmartRepliesAndActions;
+    private InflatedSmartReplyViewHolder mExpandedInflatedSmartReplies;
+    private InflatedSmartReplyViewHolder mHeadsUpInflatedSmartReplies;
+    private InflatedSmartReplyState mCurrentSmartReplyState;
 
     private NotificationViewWrapper mContractedWrapper;
     private NotificationViewWrapper mExpandedWrapper;
@@ -1189,29 +1187,19 @@
 
         applyRemoteInput(entry, hasFreeformRemoteInput(entry));
 
-        if (mExpandedInflatedSmartReplies == null && mHeadsUpInflatedSmartReplies == null) {
+        if (mCurrentSmartReplyState == null) {
             if (DEBUG) {
-                Log.d(TAG, "Both expanded, and heads-up InflatedSmartReplies are null, "
-                        + "don't add smart replies.");
+                Log.d(TAG, "InflatedSmartReplies are null, don't add smart replies.");
             }
             return;
         }
-        // The inflated smart-reply objects for the expanded view and the heads-up view both contain
-        // the same SmartRepliesAndActions to avoid discrepancies between the two views. We here
-        // reuse that object for our local SmartRepliesAndActions to avoid discrepancies between
-        // this class and the InflatedSmartReplies classes.
-        mCurrentSmartRepliesAndActions = mExpandedInflatedSmartReplies != null
-                ? mExpandedInflatedSmartReplies.getSmartRepliesAndActions()
-                : mHeadsUpInflatedSmartReplies.getSmartRepliesAndActions();
         if (DEBUG) {
             Log.d(TAG, String.format("Adding suggestions for %s, %d actions, and %d replies.",
                     entry.getSbn().getKey(),
-                    mCurrentSmartRepliesAndActions.smartActions == null ? 0 :
-                            mCurrentSmartRepliesAndActions.smartActions.actions.size(),
-                    mCurrentSmartRepliesAndActions.smartReplies == null ? 0 :
-                            mCurrentSmartRepliesAndActions.smartReplies.choices.size()));
+                    mCurrentSmartReplyState.getSmartActionsList().size(),
+                    mCurrentSmartReplyState.getSmartRepliesList().size()));
         }
-        applySmartReplyView(mCurrentSmartRepliesAndActions, entry);
+        applySmartReplyView(mCurrentSmartReplyState, entry);
     }
 
     private void applyRemoteInput(NotificationEntry entry, boolean hasFreeformRemoteInput) {
@@ -1325,7 +1313,7 @@
 
     private boolean isBubblesEnabled() {
         return Settings.Global.getInt(mContext.getContentResolver(),
-                NOTIFICATION_BUBBLES, 0) == 1;
+                Settings.Global.NOTIFICATION_BUBBLES, 0) == 1;
     }
 
     /**
@@ -1381,27 +1369,26 @@
         }
         ImageView snoozeButton = layout.findViewById(com.android.internal.R.id.snooze_button);
         View actionContainer = layout.findViewById(com.android.internal.R.id.actions_container);
-        LinearLayout actionContainerLayout =
-                layout.findViewById(com.android.internal.R.id.actions_container_layout);
-        if (snoozeButton == null || actionContainer == null || actionContainerLayout == null) {
+        if (snoozeButton == null || actionContainer == null) {
             return;
         }
         final boolean showSnooze = Settings.Secure.getInt(mContext.getContentResolver(),
-                SHOW_NOTIFICATION_SNOOZE, 0) == 1;
-        if (!showSnooze) {
+                Settings.Secure.SHOW_NOTIFICATION_SNOOZE, 0) == 1;
+        // Notification.Builder can 'disable' the snooze button to prevent it from being shown here
+        boolean snoozeDisabled = !snoozeButton.isEnabled();
+        if (!showSnooze || snoozeDisabled) {
             snoozeButton.setVisibility(GONE);
             return;
         }
 
-        Resources res = mContext.getResources();
-        Drawable snoozeDrawable = res.getDrawable(R.drawable.ic_snooze);
+        Drawable snoozeDrawable = mContext.getDrawable(R.drawable.ic_snooze);
         mContainingNotification.updateNotificationColor();
         snoozeDrawable.setTint(mContainingNotification.getNotificationColor());
         snoozeButton.setImageDrawable(snoozeDrawable);
 
         final NotificationSnooze snoozeGuts = (NotificationSnooze) LayoutInflater.from(mContext)
                 .inflate(R.layout.notification_snooze, null, false);
-        final String snoozeDescription = res.getString(
+        final String snoozeDescription = mContext.getString(
                 R.string.notification_menu_snooze_description);
         final NotificationMenuRowPlugin.MenuItem snoozeMenuItem =
                 new NotificationMenuRow.NotificationMenuItem(
@@ -1415,41 +1402,74 @@
     }
 
     private void applySmartReplyView(
-            SmartRepliesAndActions smartRepliesAndActions,
+            InflatedSmartReplyState state,
             NotificationEntry entry) {
+        if (mContractedChild != null) {
+            applyExternalSmartReplyState(mContractedChild, state);
+        }
         if (mExpandedChild != null) {
-            mExpandedSmartReplyView = applySmartReplyView(mExpandedChild, smartRepliesAndActions,
+            applyExternalSmartReplyState(mExpandedChild, state);
+            mExpandedSmartReplyView = applySmartReplyView(mExpandedChild, state,
                     entry, mExpandedInflatedSmartReplies);
             if (mExpandedSmartReplyView != null) {
-                if (smartRepliesAndActions.smartReplies != null
-                        || smartRepliesAndActions.smartActions != null) {
-                    int numSmartReplies = smartRepliesAndActions.smartReplies == null
-                            ? 0 : smartRepliesAndActions.smartReplies.choices.size();
-                    int numSmartActions = smartRepliesAndActions.smartActions == null
-                            ? 0 : smartRepliesAndActions.smartActions.actions.size();
-                    boolean fromAssistant = smartRepliesAndActions.smartReplies == null
-                            ? smartRepliesAndActions.smartActions.fromAssistant
-                            : smartRepliesAndActions.smartReplies.fromAssistant;
-                    boolean editBeforeSending = smartRepliesAndActions.smartReplies != null
+                SmartReplyView.SmartReplies smartReplies = state.getSmartReplies();
+                SmartReplyView.SmartActions smartActions = state.getSmartActions();
+                if (smartReplies != null || smartActions != null) {
+                    int numSmartReplies = smartReplies == null ? 0 : smartReplies.choices.size();
+                    int numSmartActions = smartActions == null ? 0 : smartActions.actions.size();
+                    boolean fromAssistant = smartReplies == null
+                            ? smartActions.fromAssistant
+                            : smartReplies.fromAssistant;
+                    boolean editBeforeSending = smartReplies != null
                             && mSmartReplyConstants.getEffectiveEditChoicesBeforeSending(
-                                    smartRepliesAndActions.smartReplies.remoteInput
-                                            .getEditChoicesBeforeSending());
+                                    smartReplies.remoteInput.getEditChoicesBeforeSending());
 
                     mSmartReplyController.smartSuggestionsAdded(entry, numSmartReplies,
                             numSmartActions, fromAssistant, editBeforeSending);
                 }
             }
         }
-        if (mHeadsUpChild != null && mSmartReplyConstants.getShowInHeadsUp()) {
-            mHeadsUpSmartReplyView = applySmartReplyView(mHeadsUpChild, smartRepliesAndActions,
-                    entry, mHeadsUpInflatedSmartReplies);
+        if (mHeadsUpChild != null) {
+            applyExternalSmartReplyState(mHeadsUpChild, state);
+            if (mSmartReplyConstants.getShowInHeadsUp()) {
+                mHeadsUpSmartReplyView = applySmartReplyView(mHeadsUpChild, state,
+                        entry, mHeadsUpInflatedSmartReplies);
+            }
+        }
+    }
+
+    private void applyExternalSmartReplyState(View view, InflatedSmartReplyState state) {
+        boolean hasPhishingAlert = state != null && state.getHasPhishingAction();
+        View phishingAlertIcon = view.findViewById(com.android.internal.R.id.phishing_alert);
+        if (phishingAlertIcon != null) {
+            if (DEBUG) {
+                Log.d(TAG, "Setting 'phishing_alert' view visible=" + hasPhishingAlert + ".");
+            }
+            phishingAlertIcon.setVisibility(hasPhishingAlert ? View.VISIBLE : View.GONE);
+        }
+        List<Integer> suppressedActionIndices = state != null
+                ? state.getSuppressedActionIndices()
+                : Collections.emptyList();
+        ViewGroup actionsList = view.findViewById(com.android.internal.R.id.actions);
+        if (actionsList != null) {
+            if (DEBUG && !suppressedActionIndices.isEmpty()) {
+                Log.d(TAG, "Suppressing actions with indices: " + suppressedActionIndices);
+            }
+            for (int i = 0; i < actionsList.getChildCount(); i++) {
+                View actionBtn = actionsList.getChildAt(i);
+                Object actionIndex =
+                        actionBtn.getTag(com.android.internal.R.id.notification_action_index_tag);
+                boolean suppressAction = actionIndex instanceof Integer
+                        && suppressedActionIndices.contains(actionIndex);
+                actionBtn.setVisibility(suppressAction ? View.GONE : View.VISIBLE);
+            }
         }
     }
 
     @Nullable
     private SmartReplyView applySmartReplyView(View view,
-            SmartRepliesAndActions smartRepliesAndActions,
-            NotificationEntry entry, InflatedSmartReplies inflatedSmartReplyView) {
+            InflatedSmartReplyState smartReplyState,
+            NotificationEntry entry, InflatedSmartReplyViewHolder inflatedSmartReplyViewHolder) {
         View smartReplyContainerCandidate = view.findViewById(
                 com.android.internal.R.id.smart_reply_container);
         if (!(smartReplyContainerCandidate instanceof LinearLayout)) {
@@ -1457,8 +1477,7 @@
         }
 
         LinearLayout smartReplyContainer = (LinearLayout) smartReplyContainerCandidate;
-        if (!SmartRepliesAndActionsInflaterKt
-                .shouldShowSmartReplyView(entry, smartRepliesAndActions)) {
+        if (!SmartReplyStateInflaterKt.shouldShowSmartReplyView(entry, smartReplyState)) {
             smartReplyContainer.setVisibility(View.GONE);
             return null;
         }
@@ -1471,15 +1490,15 @@
             smartReplyContainer.removeAllViews();
         }
         if (smartReplyContainer.getChildCount() == 0
-                && inflatedSmartReplyView != null
-                && inflatedSmartReplyView.getSmartReplyView() != null) {
-            smartReplyView = inflatedSmartReplyView.getSmartReplyView();
+                && inflatedSmartReplyViewHolder != null
+                && inflatedSmartReplyViewHolder.getSmartReplyView() != null) {
+            smartReplyView = inflatedSmartReplyViewHolder.getSmartReplyView();
             smartReplyContainer.addView(smartReplyView);
         }
         if (smartReplyView != null) {
             smartReplyView.resetSmartSuggestions(smartReplyContainer);
             smartReplyView.addPreInflatedButtons(
-                    inflatedSmartReplyView.getSmartSuggestionButtons());
+                    inflatedSmartReplyViewHolder.getSmartSuggestionButtons());
             // Ensure the colors of the smart suggestion buttons are up-to-date.
             smartReplyView.setBackgroundTintColor(entry.getRow().getCurrentBackgroundTint());
             smartReplyContainer.setVisibility(View.VISIBLE);
@@ -1495,7 +1514,7 @@
      * {@link SmartReplyView} related to the expanded notification state is cleared.
      */
     public void setExpandedInflatedSmartReplies(
-            @Nullable InflatedSmartReplies inflatedSmartReplies) {
+            @Nullable InflatedSmartReplyViewHolder inflatedSmartReplies) {
         mExpandedInflatedSmartReplies = inflatedSmartReplies;
         if (inflatedSmartReplies == null) {
             mExpandedSmartReplyView = null;
@@ -1510,7 +1529,7 @@
      * {@link SmartReplyView} related to the heads-up notification state is cleared.
      */
     public void setHeadsUpInflatedSmartReplies(
-            @Nullable InflatedSmartReplies inflatedSmartReplies) {
+            @Nullable InflatedSmartReplyViewHolder inflatedSmartReplies) {
         mHeadsUpInflatedSmartReplies = inflatedSmartReplies;
         if (inflatedSmartReplies == null) {
             mHeadsUpSmartReplyView = null;
@@ -1518,10 +1537,21 @@
     }
 
     /**
+     * Set pre-inflated replies and actions for the notification.
+     * This can be relevant to any state of the notification, even contracted, because smart actions
+     * may cause a phishing alert to be made visible.
+     * @param smartReplyState the pre-inflated list of replies and actions
+     */
+    public void setInflatedSmartReplyState(
+            @NonNull InflatedSmartReplyState smartReplyState) {
+        mCurrentSmartReplyState = smartReplyState;
+    }
+
+    /**
      * Returns the smart replies and actions currently shown in the notification.
      */
-    @Nullable public SmartRepliesAndActions getCurrentSmartRepliesAndActions() {
-        return mCurrentSmartRepliesAndActions;
+    @Nullable public InflatedSmartReplyState getCurrentSmartReplyState() {
+        return mCurrentSmartReplyState;
     }
 
     public void closeRemoteInput() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapper.java
index 1d36ad3..7248bce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapper.java
@@ -40,8 +40,6 @@
     public void onContentUpdated(ExpandableNotificationRow row) {
         super.onContentUpdated(row);
         updateImageTag(row.getEntry().getSbn());
-        // Round the corners of the big picture content
-        mView.findViewById(com.android.internal.R.id.big_picture).setClipToOutline(true);
     }
 
     private void updateImageTag(StatusBarNotification notification) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
index 414d620..222735a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
@@ -49,7 +49,7 @@
 
         // Custom views will most likely use just white or black as their text color.
         // We need to scan through and replace these colors by Material NEXT colors.
-        ensureThemeOnChildren();
+        ensureThemeOnChildren(mView);
 
         // Let's invert the notification colors when we're in night mode and
         // the notification background isn't colorized.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java
index 301c372..d21ae13 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java
@@ -64,7 +64,7 @@
 
         // Custom views will most likely use just white or black as their text color.
         // We need to scan through and replace these colors by Material NEXT colors.
-        ensureThemeOnChildren();
+        ensureThemeOnChildren(mWrappedView);
 
         if (needsInversion(resolveBackgroundColor(), mWrappedView)) {
             invertViewLuminosity(mWrappedView);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index 34bc537..eb79e3c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -67,8 +67,6 @@
     private ImageView mWorkProfileImage;
     private View mAudiblyAlertedIcon;
     private View mFeedbackIcon;
-    private View mLeftIcon;
-    private View mRightIcon;
 
     private boolean mIsLowPriority;
     private boolean mTransformLowPriorityTitle;
@@ -113,8 +111,6 @@
         mExpandButton = mView.findViewById(com.android.internal.R.id.expand_button);
         mAltExpandTarget = mView.findViewById(com.android.internal.R.id.alternate_expand_target);
         mIconContainer = mView.findViewById(com.android.internal.R.id.conversation_icon_container);
-        mLeftIcon = mView.findViewById(com.android.internal.R.id.left_icon);
-        mRightIcon = mView.findViewById(com.android.internal.R.id.right_icon);
         mWorkProfileImage = mView.findViewById(com.android.internal.R.id.profile_badge);
         mNotificationHeader = mView.findViewById(com.android.internal.R.id.notification_header);
         mNotificationTopLine = mView.findViewById(com.android.internal.R.id.notification_top_line);
@@ -160,12 +156,6 @@
         updateCropToPaddingForImageViews();
         Notification notification = row.getEntry().getSbn().getNotification();
         mIcon.setTag(ImageTransformState.ICON_TAG, notification.getSmallIcon());
-        if (mLeftIcon != null) {
-            mLeftIcon.setClipToOutline(true);
-        }
-        if (mRightIcon != null) {
-            mRightIcon.setClipToOutline(true);
-        }
 
         // We need to reset all views that are no longer transforming in case a view was previously
         // transformed, but now we decided to transform its container instead.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index 5fff8c8..89babf0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -36,12 +36,12 @@
 import android.view.ViewGroup;
 import android.widget.TextView;
 
-import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.graphics.ColorUtils;
 import com.android.internal.util.ContrastColorUtil;
 import com.android.internal.widget.CachingIconView;
 import com.android.settingslib.Utils;
+import com.android.systemui.R;
 import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.statusbar.TransformableView;
 import com.android.systemui.statusbar.notification.TransformState;
@@ -58,9 +58,11 @@
     private final Rect mTmpRect = new Rect();
 
     protected int mBackgroundColor = 0;
-    private int mLightTextColor;
-    private int mDarkTextColor;
-    private int mDefaultTextColor;
+    private int mMaterialTextColorPrimary;
+    private int mMaterialTextColorSecondary;
+    private int mThemedTextColorPrimary;
+    private int mThemedTextColorSecondary;
+    private boolean mAdjustTheme;
 
     public static NotificationViewWrapper wrap(Context ctx, View v, ExpandableNotificationRow row) {
         if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) {
@@ -97,6 +99,8 @@
         mView = view;
         mRow = row;
         onReinflated();
+        mAdjustTheme = ctx.getResources().getBoolean(
+                R.bool.config_adjustThemeOnNotificationCustomViews);
     }
 
     /**
@@ -121,15 +125,22 @@
             mBackgroundColor = backgroundColor;
             mView.setBackground(new ColorDrawable(Color.TRANSPARENT));
         }
-        mLightTextColor = mView.getContext().getColor(
-                com.android.internal.R.color.notification_primary_text_color_light);
-        mDarkTextColor = mView.getContext().getColor(
-                R.color.notification_primary_text_color_dark);
+
+        Context materialTitleContext = new ContextThemeWrapper(mView.getContext(),
+                com.android.internal.R.style.TextAppearance_Material_Notification_Title);
+        mMaterialTextColorPrimary = Utils.getColorAttr(materialTitleContext,
+                com.android.internal.R.attr.textColor).getDefaultColor();
+        Context materialContext = new ContextThemeWrapper(mView.getContext(),
+                com.android.internal.R.style.TextAppearance_Material_Notification);
+        mMaterialTextColorSecondary = Utils.getColorAttr(materialContext,
+                com.android.internal.R.attr.textColor).getDefaultColor();
 
         Context themedContext = new ContextThemeWrapper(mView.getContext(),
-                R.style.Theme_DeviceDefault_DayNight);
-        mDefaultTextColor = Utils.getColorAttr(themedContext, R.attr.textColorPrimary)
-                .getDefaultColor();
+                com.android.internal.R.style.Theme_DeviceDefault_DayNight);
+        mThemedTextColorPrimary = Utils.getColorAttr(themedContext,
+                com.android.internal.R.attr.textColorPrimary).getDefaultColor();
+        mThemedTextColorSecondary = Utils.getColorAttr(themedContext,
+                com.android.internal.R.attr.textColorSecondary).getDefaultColor();
     }
 
     protected boolean needsInversion(int defaultBackgroundColor, View view) {
@@ -207,38 +218,35 @@
         return false;
     }
 
-    protected void ensureThemeOnChildren() {
-        if (mView == null) {
+    protected void ensureThemeOnChildren(View rootView) {
+        if (!mAdjustTheme || mView == null || rootView == null) {
             return;
         }
 
         // Notifications with custom backgrounds should not be adjusted
         if (mBackgroundColor != Color.TRANSPARENT
-                || getBackgroundColor(mView) != Color.TRANSPARENT) {
+                || getBackgroundColor(mView) != Color.TRANSPARENT
+                || getBackgroundColor(rootView) != Color.TRANSPARENT) {
             return;
         }
 
         // Now let's check if there's unprotected text somewhere, and apply the theme if we find it.
-        if (!(mView instanceof ViewGroup)) {
-            return;
-        }
-        processChildrenTextColor((ViewGroup) mView);
+        processTextColorRecursive(rootView);
     }
 
-    private void processChildrenTextColor(ViewGroup viewGroup) {
-        if (viewGroup == null) {
-            return;
-        }
-
-        for (int i = 0; i < viewGroup.getChildCount(); i++) {
-            View child = viewGroup.getChildAt(i);
-            if (child instanceof TextView) {
-                int foreground = ((TextView) child).getCurrentTextColor();
-                if (foreground == mLightTextColor || foreground == mDarkTextColor) {
-                    ((TextView) child).setTextColor(mDefaultTextColor);
-                }
-            } else if (child instanceof ViewGroup) {
-                processChildrenTextColor((ViewGroup) child);
+    private void processTextColorRecursive(View view) {
+        if (view instanceof TextView) {
+            TextView textView = (TextView) view;
+            int foreground = textView.getCurrentTextColor();
+            if (foreground == mMaterialTextColorPrimary) {
+                textView.setTextColor(mThemedTextColorPrimary);
+            } else if (foreground == mMaterialTextColorSecondary) {
+                textView.setTextColor(mThemedTextColorSecondary);
+            }
+        } else if (view instanceof ViewGroup) {
+            ViewGroup viewGroup = (ViewGroup) view;
+            for (int i = 0; i < viewGroup.getChildCount(); i++) {
+                processTextColorRecursive(viewGroup.getChildAt(i));
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 2c7c5cc..417ff5e 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
@@ -21,6 +21,7 @@
 import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT;
 import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_SWIPE;
 import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
+import static com.android.systemui.util.Utils.shouldUseSplitNotificationShade;
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
@@ -83,6 +84,7 @@
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.DragDownHelper.DragDownCallback;
 import com.android.systemui.statusbar.EmptyShadeView;
+import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.NotificationShelfController;
@@ -453,6 +455,7 @@
     private NotificationEntry mTopHeadsUpEntry;
     private long mNumHeadsUp;
     private NotificationStackScrollLayoutController.TouchHandler mTouchHandler;
+    private final FeatureFlags mFeatureFlags;
 
     private final ExpandableView.OnHeightChangedListener mOnChildHeightChangedListener =
             new ExpandableView.OnHeightChangedListener() {
@@ -492,8 +495,8 @@
             GroupMembershipManager groupMembershipManager,
             GroupExpansionManager groupExpansionManager,
             SysuiStatusBarStateController statusbarStateController,
-            AmbientState ambientState
-    ) {
+            AmbientState ambientState,
+            FeatureFlags featureFlags) {
         super(context, attrs, 0, 0);
         Resources res = getResources();
         mSectionsManager = notificationSectionsManager;
@@ -530,6 +533,7 @@
         mGroupMembershipManager = groupMembershipManager;
         mGroupExpansionManager = groupExpansionManager;
         mStatusbarStateController = statusbarStateController;
+        mFeatureFlags = featureFlags;
     }
 
     void initializeForegroundServiceSection(ForegroundServiceDungeonView fgsSectionView) {
@@ -622,7 +626,12 @@
         mBgColor = Utils.getColorAttr(mContext, android.R.attr.colorBackgroundFloating)
                 .getDefaultColor();
         updateBackgroundDimming();
-        mShelf.onUiModeChanged();
+        for (int i = 0; i < getChildCount(); i++) {
+            View child = getChildAt(i);
+            if (child instanceof ActivatableNotificationView) {
+                ((ActivatableNotificationView) child).updateBackgroundColors();
+            }
+        }
     }
 
     @ShadeViewRefactor(RefactorComponent.DECORATOR)
@@ -1156,8 +1165,13 @@
                 if (stackStartPosition <= stackEndPosition) {
                     stackHeight = stackEndPosition;
                 } else {
-                    stackHeight = (int) NotificationUtils.interpolate(stackStartPosition,
-                            stackEndPosition, mQsExpansionFraction);
+                    if (shouldUseSplitNotificationShade(mFeatureFlags, getResources())) {
+                        // This prevents notifications from being collapsed when QS is expanded.
+                        stackHeight = (int) height;
+                    } else {
+                        stackHeight = (int) NotificationUtils.interpolate(stackStartPosition,
+                                stackEndPosition, mQsExpansionFraction);
+                    }
                 }
             } else {
                 stackHeight = (int) height;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index a516742..3997028 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -223,6 +223,7 @@
             updateShowEmptyShadeView();
             mView.updateCornerRadius();
             mView.updateBgColor();
+            mView.updateDecorViews();
             mView.reinflateViews();
         }
 
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 8cdaa63..f4830fb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -134,7 +134,7 @@
         mStackScrollerController = stackScrollerController;
         mNotificationPanelViewController = notificationPanelViewController;
         notificationPanelViewController.addTrackingHeadsUpListener(mSetTrackingHeadsUp);
-        notificationPanelViewController.addVerticalTranslationListener(mUpdatePanelTranslation);
+        notificationPanelViewController.setVerticalTranslationListener(mUpdatePanelTranslation);
         notificationPanelViewController.setHeadsUpAppearanceController(this);
         mStackScrollerController.addOnExpandedHeightChangedListener(mSetExpandedHeight);
         mStackScrollerController.addOnLayoutChangeListener(mStackScrollLayoutChangeListener);
@@ -171,7 +171,7 @@
         mHeadsUpStatusBarView.setOnDrawingRectChangedListener(null);
         mWakeUpCoordinator.removeListener(this);
         mNotificationPanelViewController.removeTrackingHeadsUpListener(mSetTrackingHeadsUp);
-        mNotificationPanelViewController.removeVerticalTranslationListener(mUpdatePanelTranslation);
+        mNotificationPanelViewController.setVerticalTranslationListener(null);
         mNotificationPanelViewController.setHeadsUpAppearanceController(null);
         mStackScrollerController.removeOnExpandedHeightChangedListener(mSetExpandedHeight);
         mStackScrollerController.removeOnLayoutChangeListener(mStackScrollLayoutChangeListener);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index a6daed5..d638019 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -89,7 +89,8 @@
     private int mNotificationStackHeight;
 
     /**
-     * Minimum top margin to avoid overlap with status bar.
+     * Minimum top margin to avoid overlap with status bar, lock icon, or multi-user switcher
+     * avatar.
      */
     private int mMinTopMargin;
 
@@ -186,15 +187,15 @@
     /**
      * Sets up algorithm values.
      */
-    public void setup(int statusBarMinHeight, int maxShadeBottom, int notificationStackHeight,
-            float panelExpansion, int parentHeight, int keyguardStatusHeight,
-            int userSwitchHeight, int clockPreferredY, int userSwitchPreferredY,
-            boolean hasCustomClock, boolean hasVisibleNotifs, float dark, float emptyDragAmount,
-            boolean bypassEnabled, int unlockedStackScrollerPadding, boolean showLockIcon,
-            float qsExpansion, int cutoutTopInset) {
-        mMinTopMargin = statusBarMinHeight + (showLockIcon
-                ? mContainerTopPaddingWithLockIcon : mContainerTopPaddingWithoutLockIcon)
-                + userSwitchHeight;
+    public void setup(int keyguardStatusBarHeaderHeight, int maxShadeBottom,
+            int notificationStackHeight, float panelExpansion, int parentHeight,
+            int keyguardStatusHeight, int userSwitchHeight, int clockPreferredY,
+            int userSwitchPreferredY, boolean hasCustomClock, boolean hasVisibleNotifs, float dark,
+            float emptyDragAmount, boolean bypassEnabled, int unlockedStackScrollerPadding,
+            boolean showLockIcon, float qsExpansion, int cutoutTopInset) {
+        mMinTopMargin = keyguardStatusBarHeaderHeight + Math.max(showLockIcon
+                        ? mContainerTopPaddingWithLockIcon : mContainerTopPaddingWithoutLockIcon,
+                userSwitchHeight);
         mMaxShadeBottom = maxShadeBottom;
         mNotificationStackHeight = notificationStackHeight;
         mPanelExpansion = panelExpansion;
@@ -344,8 +345,11 @@
     }
 
     private float burnInPreventionOffsetX() {
-        return getBurnInOffset(mBurnInPreventionOffsetX * 2, true /* xAxis */)
-                - mBurnInPreventionOffsetX;
+        if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL) {
+            return getBurnInOffset(mBurnInPreventionOffsetX * 2, true /* xAxis */)
+                    - mBurnInPreventionOffsetX;
+        }
+        return getBurnInOffset(mBurnInPreventionOffsetX, true /* xAxis */);
     }
 
     public static class Result {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
deleted file mode 100644
index 377fb92..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.phone;
-
-import com.android.keyguard.CarrierTextController;
-import com.android.systemui.util.ViewController;
-
-import javax.inject.Inject;
-
-/** View Controller for {@link com.android.systemui.statusbar.phone.KeyguardStatusBarView}. */
-public class KeyguardStatusBarViewController extends ViewController<KeyguardStatusBarView> {
-    private final CarrierTextController mCarrierTextController;
-
-    @Inject
-    public KeyguardStatusBarViewController(
-            KeyguardStatusBarView view, CarrierTextController carrierTextController) {
-        super(view);
-        mCarrierTextController = carrierTextController;
-    }
-
-    @Override
-    protected void onInit() {
-        super.onInit();
-        mCarrierTextController.init();
-    }
-
-    @Override
-    protected void onViewAttached() {
-    }
-
-    @Override
-    protected void onViewDetached() {
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 2f9fa9e..83c347b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -83,7 +83,6 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
-import com.android.keyguard.dagger.KeyguardStatusBarViewComponent;
 import com.android.keyguard.dagger.KeyguardStatusViewComponent;
 import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
 import com.android.systemui.DejankUtils;
@@ -197,7 +196,8 @@
             new MyOnHeadsUpChangedListener();
     private final HeightListener mHeightListener = new HeightListener();
     private final ConfigurationListener mConfigurationListener = new ConfigurationListener();
-    private final StatusBarStateListener mStatusBarStateListener = new StatusBarStateListener();
+    @VisibleForTesting final StatusBarStateListener mStatusBarStateListener =
+            new StatusBarStateListener();
     private final ExpansionCallback mExpansionCallback = new ExpansionCallback();
     private final BiometricUnlockController mBiometricUnlockController;
     private final NotificationPanelView mView;
@@ -281,37 +281,12 @@
 
                 @Override
                 public void onKeyguardVisibilityChanged(boolean showing) {
-                    if (mDisabledUdfpsController == null
-                            && mAuthController.getUdfpsRegion() != null
-                            && mAuthController.isUdfpsEnrolled(
-                                   KeyguardUpdateMonitor.getCurrentUser())) {
-                        mLayoutInflater.inflate(R.layout.disabled_udfps_view, mView);
-                        mDisabledUdfpsController = new DisabledUdfpsController(
-                                mView.findViewById(R.id.disabled_udfps_view),
-                                mStatusBarStateController,
-                                mUpdateMonitor,
-                                mAuthController,
-                                mStatusBarKeyguardViewManager);
-                        mDisabledUdfpsController.init();
+                    if (showing) {
+                        updateDisabledUdfpsController();
                     }
                 }
     };
 
-    final KeyguardUserSwitcherController.KeyguardUserSwitcherListener
-            mKeyguardUserSwitcherListener =
-            new KeyguardUserSwitcherController.KeyguardUserSwitcherListener() {
-                @Override
-                public void onKeyguardUserSwitcherChanged(boolean open) {
-                    if (mKeyguardUserSwitcherController == null) {
-                        updateUserSwitcherVisibility(false);
-                    } else if (!mKeyguardUserSwitcherController.isSimpleUserSwitcher()) {
-                        updateUserSwitcherVisibility(open
-                                && mKeyguardStateController.isShowing()
-                                && !mKeyguardStateController.isKeyguardFadingAway());
-                    }
-                }
-            };
-
     private final LayoutInflater mLayoutInflater;
     private final PowerManager mPowerManager;
     private final AccessibilityManager mAccessibilityManager;
@@ -326,7 +301,6 @@
     private final KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
     private final KeyguardQsUserSwitchComponent.Factory mKeyguardQsUserSwitchComponentFactory;
     private final KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory;
-    private final KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory;
     private final QSDetailDisplayer mQSDetailDisplayer;
     private final FeatureFlags mFeatureFlags;
     private final ScrimController mScrimController;
@@ -340,10 +314,8 @@
 
     private KeyguardAffordanceHelper mAffordanceHelper;
     private KeyguardQsUserSwitchController mKeyguardQsUserSwitchController;
-    private boolean mKeyguardUserSwitcherIsShowing;
     private KeyguardUserSwitcherController mKeyguardUserSwitcherController;
     private KeyguardStatusBarView mKeyguardStatusBar;
-    private KeyguardStatusBarViewController mKeyguarStatusBarViewController;
     private ViewGroup mBigClockContainer;
     private QS mQs;
     private FrameLayout mQsFrame;
@@ -386,6 +358,7 @@
     private ValueAnimator mQsExpansionAnimator;
     private FlingAnimationUtils mFlingAnimationUtils;
     private int mStatusBarMinHeight;
+    private int mStatusBarHeaderHeightKeyguard;
     private int mNotificationsHeaderCollideDistance;
     private float mEmptyDragAmount;
     private float mDownX;
@@ -476,7 +449,7 @@
     private ArrayList<Consumer<ExpandableNotificationRow>>
             mTrackingHeadsUpListeners =
             new ArrayList<>();
-    private ArrayList<Runnable> mVerticalTranslationListener = new ArrayList<>();
+    private Runnable mVerticalTranslationListener;
     private HeadsUpAppearanceController mHeadsUpAppearanceController;
 
     private int mPanelAlpha;
@@ -597,7 +570,6 @@
             KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory,
             KeyguardQsUserSwitchComponent.Factory keyguardQsUserSwitchComponentFactory,
             KeyguardUserSwitcherComponent.Factory keyguardUserSwitcherComponentFactory,
-            KeyguardStatusBarViewComponent.Factory keyguardStatusBarViewComponentFactory,
             QSDetailDisplayer qsDetailDisplayer,
             NotificationGroupManagerLegacy groupManager,
             NotificationIconAreaController notificationIconAreaController,
@@ -624,7 +596,6 @@
         mGroupManager = groupManager;
         mNotificationIconAreaController = notificationIconAreaController;
         mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory;
-        mKeyguardStatusBarViewComponentFactory = keyguardStatusBarViewComponentFactory;
         mFeatureFlags = featureFlags;
         mKeyguardQsUserSwitchComponentFactory = keyguardQsUserSwitchComponentFactory;
         mKeyguardUserSwitcherComponentFactory = keyguardUserSwitcherComponentFactory;
@@ -634,6 +605,7 @@
         mKeyguardQsUserSwitchEnabled =
                 mKeyguardUserSwitcherEnabled && mResources.getBoolean(
                         R.bool.config_keyguard_user_switch_opens_qs_details);
+        keyguardUpdateMonitor.setKeyguardQsUserSwitchEnabled(mKeyguardQsUserSwitchEnabled);
         mView.setWillNotDraw(!DEBUG);
         mLayoutInflater = layoutInflater;
         mFalsingManager = falsingManager;
@@ -728,9 +700,7 @@
         }
 
         updateViewControllers(mView.findViewById(R.id.keyguard_status_view),
-                userAvatarView,
-                mKeyguardStatusBar,
-                keyguardUserSwitcherView);
+                userAvatarView, keyguardUserSwitcherView);
         mNotificationContainerParent = mView.findViewById(R.id.notification_container_parent);
         NotificationStackScrollLayout stackScrollLayout = mView.findViewById(
                 R.id.notification_stack_scroller);
@@ -788,6 +758,8 @@
                 .setMaxLengthSeconds(0.4f).build();
         mStatusBarMinHeight = mResources.getDimensionPixelSize(
                 com.android.internal.R.dimen.status_bar_height);
+        mStatusBarHeaderHeightKeyguard = mResources.getDimensionPixelSize(
+                R.dimen.status_bar_header_height_keyguard);
         mQsPeekHeight = mResources.getDimensionPixelSize(R.dimen.qs_peek_height);
         mNotificationsHeaderCollideDistance = mResources.getDimensionPixelSize(
                 R.dimen.header_notifications_collide_distance);
@@ -808,21 +780,13 @@
     }
 
     private void updateViewControllers(KeyguardStatusView keyguardStatusView,
-            UserAvatarView userAvatarView,
-            KeyguardStatusBarView keyguardStatusBarView,
-            KeyguardUserSwitcherView keyguardUserSwitcherView) {
+            UserAvatarView userAvatarView, KeyguardUserSwitcherView keyguardUserSwitcherView) {
         // Re-associate the KeyguardStatusViewController
         KeyguardStatusViewComponent statusViewComponent =
                 mKeyguardStatusViewComponentFactory.build(keyguardStatusView);
         mKeyguardStatusViewController = statusViewComponent.getKeyguardStatusViewController();
         mKeyguardStatusViewController.init();
 
-        KeyguardStatusBarViewComponent statusBarViewComponent =
-                mKeyguardStatusBarViewComponentFactory.build(keyguardStatusBarView);
-        mKeyguarStatusBarViewController =
-                statusBarViewComponent.getKeyguardStatusBarViewController();
-        mKeyguarStatusBarViewController.init();
-
         // Re-associate the clock container with the keyguard clock switch.
         KeyguardClockSwitchController keyguardClockSwitchController =
                 statusViewComponent.getKeyguardClockSwitchController();
@@ -832,7 +796,6 @@
             // Try to close the switcher so that callbacks are triggered if necessary.
             // Otherwise, NPV can get into a state where some of the views are still hidden
             mKeyguardUserSwitcherController.closeSwitcherIfOpenAndNotSimple(false);
-            mKeyguardUserSwitcherController.removeCallback();
         }
 
         mKeyguardQsUserSwitchController = null;
@@ -852,7 +815,6 @@
                     mKeyguardUserSwitcherComponentFactory.build(keyguardUserSwitcherView);
             mKeyguardUserSwitcherController =
                     userSwitcherComponent.getKeyguardUserSwitcherController();
-            mKeyguardUserSwitcherController.setCallback(mKeyguardUserSwitcherListener);
             mKeyguardUserSwitcherController.init();
             mKeyguardStatusBar.setKeyguardUserSwitcherEnabled(true);
         } else {
@@ -882,25 +844,16 @@
 
     public void updateResources() {
         int qsWidth = mResources.getDimensionPixelSize(R.dimen.qs_panel_width);
-        ViewGroup.LayoutParams lp = mQsFrame.getLayoutParams();
-        if (lp.width != qsWidth) {
-            lp.width = qsWidth;
-            mQsFrame.setLayoutParams(lp);
-        }
-
         int panelWidth = mResources.getDimensionPixelSize(R.dimen.notification_panel_width);
-        lp = mNotificationStackScrollLayoutController.getLayoutParams();
-        if (lp.width != panelWidth) {
-            lp.width = panelWidth;
-            mNotificationStackScrollLayoutController.setLayoutParams(lp);
-        }
 
-        // In order to change the constraints at runtime, all children of the Constraint Layout
-        // must have ids.
+        // To change the constraints at runtime, all children of the ConstraintLayout must have ids
         ensureAllViewsHaveIds(mNotificationContainerParent);
         ConstraintSet constraintSet = new ConstraintSet();
         constraintSet.clone(mNotificationContainerParent);
         if (Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources)) {
+            // width = 0 to take up all available space within constraints
+            qsWidth = 0;
+            panelWidth = 0;
             constraintSet.connect(R.id.qs_frame, END, R.id.qs_edge_guideline, END);
             constraintSet.connect(
                     R.id.notification_stack_scroller, START,
@@ -909,6 +862,8 @@
             constraintSet.connect(R.id.qs_frame, END, PARENT_ID, END);
             constraintSet.connect(R.id.notification_stack_scroller, START, PARENT_ID, START);
         }
+        constraintSet.getConstraint(R.id.notification_stack_scroller).layout.mWidth = panelWidth;
+        constraintSet.getConstraint(R.id.qs_frame).layout.mWidth = qsWidth;
         constraintSet.applyTo(mNotificationContainerParent);
     }
 
@@ -970,8 +925,7 @@
                         showKeyguardUserSwitcher /* enabled */);
 
         mBigClockContainer.removeAllViews();
-        updateViewControllers(
-                keyguardStatusView, userAvatarView, mKeyguardStatusBar, keyguardUserSwitcherView);
+        updateViewControllers(keyguardStatusView, userAvatarView, keyguardUserSwitcherView);
 
         // Update keyguard bottom area
         index = mView.indexOfChild(mKeyguardBottomArea);
@@ -1101,7 +1055,7 @@
             int totalHeight = mView.getHeight();
             int bottomPadding = Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding);
             int clockPreferredY = mKeyguardStatusViewController.getClockPreferredY(totalHeight);
-            int userSwitcherPreferredY = mStatusBarMinHeight;
+            int userSwitcherPreferredY = mStatusBarHeaderHeightKeyguard;
             boolean bypassEnabled = mKeyguardBypassController.getBypassEnabled();
             final boolean hasVisibleNotifications = mNotificationStackScrollLayoutController
                     .getVisibleNotificationCount() != 0 || mMediaDataManager.hasActiveMedia();
@@ -1110,7 +1064,8 @@
                     ? mKeyguardQsUserSwitchController.getUserIconHeight()
                     : (mKeyguardUserSwitcherController != null
                             ? mKeyguardUserSwitcherController.getUserIconHeight() : 0);
-            mClockPositionAlgorithm.setup(mStatusBarMinHeight, totalHeight - bottomPadding,
+            mClockPositionAlgorithm.setup(mStatusBarHeaderHeightKeyguard,
+                    totalHeight - bottomPadding,
                     mNotificationStackScrollLayoutController.getIntrinsicContentHeight(),
                     getExpandedFraction(),
                     totalHeight,
@@ -1868,7 +1823,7 @@
         }
     }
 
-    private void setQsExpanded(boolean expanded) {
+    @VisibleForTesting void setQsExpanded(boolean expanded) {
         boolean changed = mQsExpanded != expanded;
         if (changed) {
             mQsExpanded = expanded;
@@ -1971,8 +1926,10 @@
     private void updateQsState() {
         mNotificationStackScrollLayoutController.setQsExpanded(mQsExpanded);
         mNotificationStackScrollLayoutController.setScrollingEnabled(
-                mBarState != KEYGUARD && (!mQsExpanded
-                        || mQsExpansionFromOverscroll));
+                mBarState != KEYGUARD
+                        && (!mQsExpanded
+                            || mQsExpansionFromOverscroll
+                            || Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources)));
 
         if (mKeyguardUserSwitcherController != null && mQsExpanded
                 && !mStackScrollerOverscrolling) {
@@ -2252,13 +2209,16 @@
 
     @Override
     protected boolean canCollapsePanelOnTouch() {
-        if (!isInSettings()) {
-            return mBarState == KEYGUARD
-                    || mIsPanelCollapseOnQQS
-                    || mNotificationStackScrollLayoutController.isScrolledToBottom();
-        } else {
+        if (!isInSettings() && mBarState == KEYGUARD) {
             return true;
         }
+
+        if (mNotificationStackScrollLayoutController.isScrolledToBottom()) {
+            return true;
+        }
+
+        return !Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources)
+                && (isInSettings() || mIsPanelCollapseOnQQS);
     }
 
     @Override
@@ -2936,7 +2896,8 @@
      * @param x the x-coordinate the touch event
      */
     protected void updateHorizontalPanelPosition(float x) {
-        if (mNotificationStackScrollLayoutController.getWidth() * 1.75f > mView.getWidth()) {
+        if (mNotificationStackScrollLayoutController.getWidth() * 1.75f > mView.getWidth()
+                || Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources)) {
             resetHorizontalPanelPosition();
             return;
         }
@@ -2964,9 +2925,8 @@
     protected void setHorizontalPanelTranslation(float translation) {
         mNotificationStackScrollLayoutController.setTranslationX(translation);
         mQsFrame.setTranslationX(translation);
-        int size = mVerticalTranslationListener.size();
-        for (int i = 0; i < size; i++) {
-            mVerticalTranslationListener.get(i).run();
+        if (mVerticalTranslationListener != null) {
+            mVerticalTranslationListener.run();
         }
     }
 
@@ -3259,12 +3219,8 @@
         mTrackingHeadsUpListeners.remove(listener);
     }
 
-    public void addVerticalTranslationListener(Runnable verticalTranslationListener) {
-        mVerticalTranslationListener.add(verticalTranslationListener);
-    }
-
-    public void removeVerticalTranslationListener(Runnable verticalTranslationListener) {
-        mVerticalTranslationListener.remove(verticalTranslationListener);
+    public void setVerticalTranslationListener(Runnable verticalTranslationListener) {
+        mVerticalTranslationListener = verticalTranslationListener;
     }
 
     public void setHeadsUpAppearanceController(
@@ -3554,31 +3510,22 @@
         return false;
     }
 
-    private void updateUserSwitcherVisibility(boolean open) {
-        // Do not update if previously called with the same state.
-        if (mKeyguardUserSwitcherIsShowing == open) {
-            return;
-        }
-        mKeyguardUserSwitcherIsShowing = open;
-
-        if (open) {
-            animateKeyguardStatusBarOut();
-            mKeyguardStatusViewController.setKeyguardStatusViewVisibility(
-                    mBarState,
-                    true /* keyguardFadingAway */,
-                    true /* goingToFullShade */,
-                    mBarState);
-            setKeyguardBottomAreaVisibility(mBarState, true);
-            mNotificationContainerParent.setVisibility(View.GONE);
-        } else {
-            animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-            mKeyguardStatusViewController.setKeyguardStatusViewVisibility(
-                    StatusBarState.KEYGUARD,
-                    false,
-                    false,
-                    StatusBarState.SHADE_LOCKED);
-            setKeyguardBottomAreaVisibility(mBarState, false);
-            mNotificationContainerParent.setVisibility(View.VISIBLE);
+    private void updateDisabledUdfpsController() {
+        final boolean udfpsEnrolled = mAuthController.getUdfpsRegion() != null
+                && mAuthController.isUdfpsEnrolled(
+                KeyguardUpdateMonitor.getCurrentUser());
+        if (mDisabledUdfpsController == null && udfpsEnrolled) {
+            mLayoutInflater.inflate(R.layout.disabled_udfps_view, mView);
+            mDisabledUdfpsController = new DisabledUdfpsController(
+                    mView.findViewById(R.id.disabled_udfps_view),
+                    mStatusBarStateController,
+                    mUpdateMonitor,
+                    mAuthController,
+                    mStatusBarKeyguardViewManager);
+            mDisabledUdfpsController.init();
+        } else if (mDisabledUdfpsController != null && !udfpsEnrolled) {
+            mDisabledUdfpsController.destroy();
+            mDisabledUdfpsController = null;
         }
     }
 
@@ -3631,6 +3578,10 @@
             NotificationStackScrollLayout.OnOverscrollTopChangedListener {
         @Override
         public void onOverscrollTopChanged(float amount, boolean isRubberbanded) {
+            // When in split shade, overscroll shouldn't carry through to QS
+            if (Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources)) {
+                return;
+            }
             cancelQsAnimation();
             if (!mQsExpansionEnabled) {
                 amount = 0f;
@@ -3997,6 +3948,7 @@
             FragmentHostManager.get(mView).addTagListener(QS.TAG, mFragmentListener);
             mStatusBarStateController.addCallback(mStatusBarStateListener);
             mConfigurationController.addCallback(mConfigurationListener);
+            updateDisabledUdfpsController();
             mUpdateMonitor.registerCallback(mKeyguardUpdateCallback);
             // Theme might have changed between inflating this view and attaching it to the
             // window, so
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
index e394ebc..0c9ed66 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
@@ -18,14 +18,12 @@
 
 import android.app.Fragment;
 import android.content.Context;
-import android.content.res.Configuration;
 import android.graphics.Canvas;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.WindowInsets;
 import android.widget.FrameLayout;
 
-import androidx.annotation.DimenRes;
 import androidx.constraintlayout.widget.ConstraintLayout;
 
 import com.android.systemui.R;
@@ -83,22 +81,6 @@
     }
 
     @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        reloadWidth(mQsFrame, R.dimen.qs_panel_width);
-        reloadWidth(mStackScroller, R.dimen.notification_panel_width);
-    }
-
-    /**
-     * Loads the given width resource and sets it on the given View.
-     */
-    private void reloadWidth(View view, @DimenRes int width) {
-        LayoutParams params = (LayoutParams) view.getLayoutParams();
-        params.width = getResources().getDimensionPixelSize(width);
-        view.setLayoutParams(params);
-    }
-
-    @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
         mBottomPadding = insets.getStableInsetBottom();
         setPadding(0, 0, 0, mBottomPadding);
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 041a97e..b25fced 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -78,6 +78,7 @@
 import android.metrics.LogMaker;
 import android.net.Uri;
 import android.os.AsyncTask;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -276,7 +277,8 @@
     public static final boolean DEBUG = false;
     public static final boolean SPEW = false;
     public static final boolean DUMPTRUCK = true; // extra dumpsys info
-    public static final boolean DEBUG_GESTURES = false;
+    public static final boolean DEBUG_GESTURES = Build.IS_DEBUGGABLE; // TODO(b/178277858)
+    public static final boolean DEBUG_GESTURES_VERBOSE = true;
     public static final boolean DEBUG_MEDIA_FAKE_ARTWORK = false;
     public static final boolean DEBUG_CAMERA_LIFT = false;
 
@@ -456,9 +458,7 @@
     private final DisplayMetrics mDisplayMetrics;
 
     // XXX: gesture research
-    private final GestureRecorder mGestureRec = DEBUG_GESTURES
-        ? new GestureRecorder("/sdcard/statusbar_gestures.dat")
-        : null;
+    private GestureRecorder mGestureRec = null;
 
     private final ScreenPinningRequest mScreenPinningRequest;
 
@@ -856,6 +856,10 @@
 
         mActivityIntentHelper = new ActivityIntentHelper(mContext);
         DateTimeView.setReceiverHandler(timeTickHandler);
+
+        if (DEBUG_GESTURES) {
+            mGestureRec = new GestureRecorder(mContext.getCacheDir() + "/statusbar_gestures.dat");
+        }
     }
 
     @Override
@@ -2267,7 +2271,7 @@
 
     public boolean interceptTouchEvent(MotionEvent event) {
         if (DEBUG_GESTURES) {
-            if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
+            if (DEBUG_GESTURES_VERBOSE || event.getActionMasked() != MotionEvent.ACTION_MOVE) {
                 EventLog.writeEvent(EventLogTags.SYSUI_STATUSBAR_TOUCH,
                         event.getActionMasked(), (int) event.getX(), (int) event.getY(),
                         mDisabled1, mDisabled2);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index 7bc1bb3..9ee7b09 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -27,6 +27,8 @@
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators;
+import com.android.systemui.statusbar.policy.NetworkController.WifiIndicators;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl;
 import com.android.systemui.statusbar.policy.SecurityController;
 import com.android.systemui.tuner.TunerService;
@@ -40,7 +42,7 @@
 public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallback,
         SecurityController.SecurityControllerCallback, Tunable {
     private static final String TAG = "StatusBarSignalPolicy";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.INFO);
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private final String mSlotAirplane;
     private final String mSlotMobile;
@@ -143,24 +145,14 @@
     }
 
     @Override
-    public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
-            boolean activityIn, boolean activityOut, String description, boolean isTransient,
-            String statusLabel) {
+    public void setWifiIndicators(WifiIndicators indicators) {
         if (DEBUG) {
-            Log.d(TAG, "setWifiIndicators: "
-                    + "enabled = " + enabled + ","
-                    + "statusIcon = " + (statusIcon == null ? "" : statusIcon.toString()) + ","
-                    + "qsIcon = " + (qsIcon == null ? "" : qsIcon.toString()) + ","
-                    + "activityIn = " + activityIn + ","
-                    + "activityOut = " + activityOut + ","
-                    + "description = " + description + ","
-                    + "isTransient = " + isTransient + ","
-                    + "statusLabel = " + statusLabel);
+            Log.d(TAG, "setWifiIndicators: " + indicators);
         }
-        boolean visible = statusIcon.visible && !mHideWifi;
-        boolean in = activityIn && mActivityEnabled && visible;
-        boolean out = activityOut && mActivityEnabled && visible;
-        mIsWifiEnabled = enabled;
+        boolean visible = indicators.statusIcon.visible && !mHideWifi;
+        boolean in = indicators.activityIn && mActivityEnabled && visible;
+        boolean out = indicators.activityOut && mActivityEnabled && visible;
+        mIsWifiEnabled = indicators.enabled;
 
         WifiIconState newState = mWifiIconState.copy();
 
@@ -174,10 +166,10 @@
             newState.resId = R.drawable.ic_qs_no_internet_available;
         } else {
             newState.visible = visible;
-            newState.resId = statusIcon.icon;
+            newState.resId = indicators.statusIcon.icon;
             newState.activityIn = in;
             newState.activityOut = out;
-            newState.contentDescription = statusIcon.contentDescription;
+            newState.contentDescription = indicators.statusIcon.contentDescription;
             MobileIconState first = getFirstMobileState();
             newState.signalSpacerVisible = first != null && first.typeId != 0;
         }
@@ -225,44 +217,28 @@
     }
 
     @Override
-    public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
-            int qsType, boolean activityIn, boolean activityOut,
-            CharSequence typeContentDescription,
-            CharSequence typeContentDescriptionHtml, CharSequence description,
-            boolean isWide, int subId, boolean roaming, boolean showTriangle) {
+    public void setMobileDataIndicators(MobileDataIndicators indicators) {
         if (DEBUG) {
-            Log.d(TAG, "setMobileDataIndicators: "
-                    + "statusIcon = " + (statusIcon == null ? "" : statusIcon.toString()) + ","
-                    + "qsIcon = " + (qsIcon == null ? "" : qsIcon.toString()) + ","
-                    + "statusType = " + statusType + ","
-                    + "qsType = " + qsType + ","
-                    + "activityIn = " + activityIn + ","
-                    + "activityOut = " + activityOut + ","
-                    + "typeContentDescription = " + typeContentDescription + ","
-                    + "typeContentDescriptionHtml = " + typeContentDescriptionHtml + ","
-                    + "description = " + description + ","
-                    + "isWide = " + isWide + ","
-                    + "subId = " + subId + ","
-                    + "roaming = " + roaming + ","
-                    + "showTriangle = " + showTriangle);
+            Log.d(TAG, "setMobileDataIndicators: " + indicators);
         }
-        MobileIconState state = getState(subId);
+        MobileIconState state = getState(indicators.subId);
         if (state == null) {
             return;
         }
 
         // Visibility of the data type indicator changed
-        boolean typeChanged = statusType != state.typeId && (statusType == 0 || state.typeId == 0);
+        boolean typeChanged = indicators.statusType != state.typeId
+                && (indicators.statusType == 0 || state.typeId == 0);
 
-        state.visible = statusIcon.visible && !mHideMobile;
-        state.strengthId = statusIcon.icon;
-        state.typeId = statusType;
-        state.contentDescription = statusIcon.contentDescription;
-        state.typeContentDescription = typeContentDescription;
-        state.showTriangle = showTriangle;
-        state.roaming = roaming;
-        state.activityIn = activityIn && mActivityEnabled;
-        state.activityOut = activityOut && mActivityEnabled;
+        state.visible = indicators.statusIcon.visible && !mHideMobile;
+        state.strengthId = indicators.statusIcon.icon;
+        state.typeId = indicators.statusType;
+        state.contentDescription = indicators.statusIcon.contentDescription;
+        state.typeContentDescription = indicators.typeContentDescription;
+        state.showTriangle = indicators.showTriangle;
+        state.roaming = indicators.roaming;
+        state.activityIn = indicators.activityIn && mActivityEnabled;
+        state.activityOut = indicators.activityOut && mActivityEnabled;
 
         if (DEBUG) {
             Log.d(TAG, "MobileIconStates: "
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
index 5ff8970..b96cb5e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
@@ -23,7 +23,9 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
+import com.android.systemui.statusbar.policy.NetworkController.WifiIndicators;
 
 import java.io.PrintWriter;
 import java.text.SimpleDateFormat;
@@ -56,6 +58,7 @@
     private final String[] mHistory = new String[HISTORY_SIZE];
     // Where to copy the next state into.
     private int mHistoryIndex;
+    private String mLastCallback;
 
     public CallbackHandler() {
         super(Looper.getMainLooper());
@@ -118,63 +121,29 @@
     }
 
     @Override
-    public void setWifiIndicators(final boolean enabled, final IconState statusIcon,
-            final IconState qsIcon, final boolean activityIn, final boolean activityOut,
-            final String description, boolean isTransient, String secondaryLabel) {
+    public void setWifiIndicators(final WifiIndicators indicators) {
         String log = new StringBuilder()
                 .append(SSDF.format(System.currentTimeMillis())).append(",")
-                .append("setWifiIndicators: ")
-                .append("enabled=").append(enabled).append(",")
-                .append("statusIcon=").append(statusIcon).append(",")
-                .append("qsIcon=").append(qsIcon).append(",")
-                .append("activityIn=").append(activityIn).append(",")
-                .append("activityOut=").append(activityOut).append(",")
-                .append("description=").append(description).append(",")
-                .append("isTransient=").append(isTransient).append(",")
-                .append("secondaryLabel=").append(secondaryLabel)
+                .append(indicators)
                 .toString();
         recordLastCallback(log);
         post(() -> {
             for (SignalCallback callback : mSignalCallbacks) {
-                callback.setWifiIndicators(enabled, statusIcon, qsIcon, activityIn, activityOut,
-                        description, isTransient, secondaryLabel);
+                callback.setWifiIndicators(indicators);
             }
         });
-
-
     }
 
     @Override
-    public void setMobileDataIndicators(final IconState statusIcon, final IconState qsIcon,
-            final int statusType, final int qsType, final boolean activityIn,
-            final boolean activityOut, final CharSequence typeContentDescription,
-            CharSequence typeContentDescriptionHtml, final CharSequence description,
-            final boolean isWide, final int subId, boolean roaming, boolean showTriangle) {
+    public void setMobileDataIndicators(final MobileDataIndicators indicators) {
         String log = new StringBuilder()
                 .append(SSDF.format(System.currentTimeMillis())).append(",")
-                .append("setMobileDataIndicators: ")
-                .append("statusIcon=").append(statusIcon).append(",")
-                .append("qsIcon=").append(qsIcon).append(",")
-                .append("statusType=").append(statusType).append(",")
-                .append("qsType=").append(qsType).append(",")
-                .append("activityIn=").append(activityIn).append(",")
-                .append("activityOut=").append(activityOut).append(",")
-                .append("typeContentDescription=").append(typeContentDescription).append(",")
-                .append("typeContentDescriptionHtml=").append(typeContentDescriptionHtml)
-                .append(",")
-                .append("description=").append(description).append(",")
-                .append("isWide=").append(isWide).append(",")
-                .append("subId=").append(subId).append(",")
-                .append("roaming=").append(roaming).append(",")
-                .append("showTriangle=").append(showTriangle)
+                .append(indicators)
                 .toString();
         recordLastCallback(log);
         post(() -> {
             for (SignalCallback signalCluster : mSignalCallbacks) {
-                signalCluster.setMobileDataIndicators(statusIcon, qsIcon, statusType, qsType,
-                        activityIn, activityOut, typeContentDescription,
-                        typeContentDescriptionHtml, description, isWide, subId, roaming,
-                        showTriangle);
+                signalCluster.setMobileDataIndicators(indicators);
             }
         });
     }
@@ -182,14 +151,20 @@
     @Override
     public void setConnectivityStatus(boolean noDefaultNetwork, boolean noValidatedNetwork,
                 boolean noNetworksAvailable) {
-        String log = new StringBuilder()
-                .append(SSDF.format(System.currentTimeMillis())).append(",")
+        String currentCallback = new StringBuilder()
                 .append("setConnectivityStatus: ")
                 .append("noDefaultNetwork=").append(noDefaultNetwork).append(",")
                 .append("noValidatedNetwork=").append(noValidatedNetwork).append(",")
                 .append("noNetworksAvailable=").append(noNetworksAvailable)
                 .toString();
-        recordLastCallback(log);
+        if (!currentCallback.equals(mLastCallback)) {
+            mLastCallback = currentCallback;
+            String log = new StringBuilder()
+                    .append(SSDF.format(System.currentTimeMillis())).append(",")
+                    .append(currentCallback).append(",")
+                    .toString();
+            recordLastCallback(log);
+        }
         post(() -> {
             for (SignalCallback signalCluster : mSignalCallbacks) {
                 signalCluster.setConnectivityStatus(
@@ -200,13 +175,19 @@
 
     @Override
     public void setCallIndicator(IconState statusIcon, int subId) {
-        String log = new StringBuilder()
-                .append(SSDF.format(System.currentTimeMillis())).append(",")
+        String currentCallback = new StringBuilder()
                 .append("setCallIndicator: ")
                 .append("statusIcon=").append(statusIcon).append(",")
                 .append("subId=").append(subId)
                 .toString();
-        recordLastCallback(log);
+        if (!currentCallback.equals(mLastCallback)) {
+            mLastCallback = currentCallback;
+            String log = new StringBuilder()
+                    .append(SSDF.format(System.currentTimeMillis())).append(",")
+                    .append(currentCallback).append(",")
+                    .toString();
+            recordLastCallback(log);
+        }
         post(() -> {
             for (SignalCallback signalCluster : mSignalCallbacks) {
                 signalCluster.setCallIndicator(statusIcon, subId);
@@ -216,12 +197,18 @@
 
     @Override
     public void setSubs(List<SubscriptionInfo> subs) {
-        String log = new StringBuilder()
-                .append(SSDF.format(System.currentTimeMillis())).append(",")
+        String currentCallback = new StringBuilder()
                 .append("setSubs: ")
                 .append("subs=").append(subs == null ? "" : subs.toString())
                 .toString();
-        recordLastCallback(log);
+        if (!currentCallback.equals(mLastCallback)) {
+            mLastCallback = currentCallback;
+            String log = new StringBuilder()
+                    .append(SSDF.format(System.currentTimeMillis())).append(",")
+                    .append(currentCallback).append(",")
+                    .toString();
+            recordLastCallback(log);
+        }
         obtainMessage(MSG_SUBS_CHANGED, subs).sendToTarget();
     }
 
@@ -253,12 +240,18 @@
 
     @Override
     public void setIsAirplaneMode(IconState icon) {
-        String log = new StringBuilder()
-                .append(SSDF.format(System.currentTimeMillis())).append(",")
+        String currentCallback = new StringBuilder()
                 .append("setIsAirplaneMode: ")
                 .append("icon=").append(icon)
                 .toString();
-        recordLastCallback(log);
+        if (!currentCallback.equals(mLastCallback)) {
+            mLastCallback = currentCallback;
+            String log = new StringBuilder()
+                    .append(SSDF.format(System.currentTimeMillis())).append(",")
+                    .append(currentCallback).append(",")
+                    .toString();
+            recordLastCallback(log);
+        }
         obtainMessage(MSG_AIRPLANE_MODE_CHANGED, icon).sendToTarget();;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java
index a76d08a..7f935d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java
@@ -16,17 +16,17 @@
 
 package com.android.systemui.statusbar.policy;
 
-import android.hardware.SensorPrivacyManager.IndividualSensor;
+import android.hardware.SensorPrivacyManager.Sensors.Sensor;
 
 public interface IndividualSensorPrivacyController extends
         CallbackController<IndividualSensorPrivacyController.Callback> {
     void init();
 
-    boolean isSensorBlocked(@IndividualSensor int sensor);
+    boolean isSensorBlocked(@Sensor int sensor);
 
-    void setSensorBlocked(@IndividualSensor int sensor, boolean blocked);
+    void setSensorBlocked(@Sensor int sensor, boolean blocked);
 
     interface Callback {
-        void onSensorBlockedChanged(@IndividualSensor int sensor, boolean blocked);
+        void onSensorBlockedChanged(@Sensor int sensor, boolean blocked);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java
index 32d15ed..295df05 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java
@@ -16,11 +16,11 @@
 
 package com.android.systemui.statusbar.policy;
 
-import static android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_CAMERA;
-import static android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE;
+import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
+import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
 
 import android.hardware.SensorPrivacyManager;
-import android.hardware.SensorPrivacyManager.IndividualSensor;
+import android.hardware.SensorPrivacyManager.Sensors.Sensor;
 import android.util.ArraySet;
 import android.util.SparseBooleanArray;
 
@@ -30,8 +30,7 @@
 
 public class IndividualSensorPrivacyControllerImpl implements IndividualSensorPrivacyController {
 
-    private static final int[] SENSORS = new int[] {INDIVIDUAL_SENSOR_CAMERA,
-            INDIVIDUAL_SENSOR_MICROPHONE};
+    private static final int[] SENSORS = new int[] {CAMERA, MICROPHONE};
 
     private final @NonNull SensorPrivacyManager mSensorPrivacyManager;
     private final SparseBooleanArray mState = new SparseBooleanArray();
@@ -48,18 +47,18 @@
             mSensorPrivacyManager.addSensorPrivacyListener(sensor,
                     (enabled) -> onSensorPrivacyChanged(sensor, enabled));
 
-            mState.put(sensor, mSensorPrivacyManager.isIndividualSensorPrivacyEnabled(sensor));
+            mState.put(sensor, mSensorPrivacyManager.isSensorPrivacyEnabled(sensor));
         }
     }
 
     @Override
-    public boolean isSensorBlocked(@IndividualSensor int sensor) {
+    public boolean isSensorBlocked(@Sensor int sensor) {
         return mState.get(sensor, false);
     }
 
     @Override
-    public void setSensorBlocked(@IndividualSensor int sensor, boolean blocked) {
-        mSensorPrivacyManager.setIndividualSensorPrivacyForProfileGroup(sensor, blocked);
+    public void setSensorBlocked(@Sensor int sensor, boolean blocked) {
+        mSensorPrivacyManager.setSensorPrivacyForProfileGroup(sensor, blocked);
     }
 
     @Override
@@ -72,7 +71,7 @@
         mCallbacks.remove(listener);
     }
 
-    private void onSensorPrivacyChanged(@IndividualSensor int sensor, boolean blocked) {
+    private void onSensorPrivacyChanged(@Sensor int sensor, boolean blocked) {
         mState.put(sensor, blocked);
 
         for (Callback callback : mCallbacks) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java
deleted file mode 100644
index cbc8405..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.policy;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.Notification;
-import android.widget.Button;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Holder for inflated smart replies and actions. These objects should be inflated on a background
- * thread, to later be accessed and modified on the (performance critical) UI thread.
- */
-public class InflatedSmartReplies {
-    @Nullable private final SmartReplyView mSmartReplyView;
-    @Nullable private final List<Button> mSmartSuggestionButtons;
-    @NonNull private final SmartRepliesAndActions mSmartRepliesAndActions;
-
-    public InflatedSmartReplies(
-            @Nullable SmartReplyView smartReplyView,
-            @Nullable List<Button> smartSuggestionButtons,
-            @NonNull SmartRepliesAndActions smartRepliesAndActions) {
-        mSmartReplyView = smartReplyView;
-        mSmartSuggestionButtons = smartSuggestionButtons;
-        mSmartRepliesAndActions = smartRepliesAndActions;
-    }
-
-    @Nullable public SmartReplyView getSmartReplyView() {
-        return mSmartReplyView;
-    }
-
-    @Nullable public List<Button> getSmartSuggestionButtons() {
-        return mSmartSuggestionButtons;
-    }
-
-    @NonNull public SmartRepliesAndActions getSmartRepliesAndActions() {
-        return mSmartRepliesAndActions;
-    }
-
-    /**
-     * A storage for smart replies and smart action.
-     */
-    public static class SmartRepliesAndActions {
-        @Nullable public final SmartReplyView.SmartReplies smartReplies;
-        @Nullable public final SmartReplyView.SmartActions smartActions;
-
-        SmartRepliesAndActions(
-                @Nullable SmartReplyView.SmartReplies smartReplies,
-                @Nullable SmartReplyView.SmartActions smartActions) {
-            this.smartReplies = smartReplies;
-            this.smartActions = smartActions;
-        }
-
-        @NonNull public List<CharSequence> getSmartReplies() {
-            return smartReplies == null ? Collections.emptyList() : smartReplies.choices;
-        }
-
-        @NonNull public List<Notification.Action> getSmartActions() {
-            return smartActions == null ? Collections.emptyList() : smartActions.actions;
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplyState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplyState.kt
new file mode 100644
index 0000000..1f8b84f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplyState.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.policy
+
+import android.app.Notification
+import com.android.systemui.statusbar.policy.SmartReplyView.SmartActions
+import com.android.systemui.statusbar.policy.SmartReplyView.SmartReplies
+
+/**
+ * A storage for smart replies, smart actions, and related state
+ */
+class InflatedSmartReplyState internal constructor(
+    val smartReplies: SmartReplies?,
+    val smartActions: SmartActions?,
+    val suppressedActions: SuppressedActions?,
+    val hasPhishingAction: Boolean
+) {
+    val smartRepliesList: List<CharSequence>
+        get() = smartReplies?.choices ?: emptyList()
+    val smartActionsList: List<Notification.Action>
+        get() = smartActions?.actions ?: emptyList()
+    val suppressedActionIndices: List<Int>
+        get() = suppressedActions?.suppressedActionIndices ?: emptyList()
+
+    /**
+     * Data class for standard actions suppressed by the smart actions.
+     */
+    class SuppressedActions(val suppressedActionIndices: List<Int>)
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplyViewHolder.kt
similarity index 60%
copy from packages/SystemUI/src/com/android/keyguard/clock/ClockModule.java
copy to packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplyViewHolder.kt
index c4be1ba535..4e5c461 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplyViewHolder.kt
@@ -13,21 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.systemui.statusbar.policy
 
-package com.android.keyguard.clock;
+import android.widget.Button
 
-import java.util.List;
-
-import dagger.Module;
-import dagger.Provides;
-
-/** Dagger Module for clock package. */
-@Module
-public abstract class ClockModule {
-
-    /** */
-    @Provides
-    public static List<ClockInfo> provideClockInfoList(ClockManager clockManager) {
-        return clockManager.getClockInfos();
-    }
-}
+/**
+ * Holder for inflated smart replies and actions. These objects should be inflated on a background
+ * thread, to later be accessed and modified on the (performance critical) UI thread.
+ */
+class InflatedSmartReplyViewHolder(
+    val smartReplyView: SmartReplyView?,
+    val smartSuggestionButtons: List<Button>?
+)
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
index b76e451..8845a05 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
@@ -19,9 +19,13 @@
 import static com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_DISABLED_ALPHA;
 import static com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_ENABLED_ALPHA;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.content.res.Resources;
 import android.database.DataSetObserver;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LayerDrawable;
 import android.os.UserHandle;
@@ -50,7 +54,6 @@
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.util.ViewController;
 
-import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 
 import javax.inject.Inject;
@@ -73,9 +76,10 @@
     private final KeyguardUserAdapter mAdapter;
     private final KeyguardStateController mKeyguardStateController;
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-    private WeakReference<KeyguardUserSwitcherListener> mKeyguardUserSwitcherCallback;
     protected final SysuiStatusBarStateController mStatusBarStateController;
     private final KeyguardVisibilityHelper mKeyguardVisibilityHelper;
+    private ObjectAnimator mBgAnimator;
+    private final KeyguardUserSwitcherScrim mBackground;
 
     // Child views of KeyguardUserSwitcherView
     private KeyguardUserSwitcherListView mListView;
@@ -171,6 +175,7 @@
                 mUserSwitcherController, this);
         mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView,
                 keyguardStateController, dozeParameters);
+        mBackground = new KeyguardUserSwitcherScrim(context);
     }
 
     @Override
@@ -204,6 +209,9 @@
         mKeyguardUpdateMonitor.registerCallback(mInfoCallback);
         mStatusBarStateController.addCallback(mStatusBarStateListener);
         mScreenLifecycle.addObserver(mScreenObserver);
+        mView.addOnLayoutChangeListener(mBackground);
+        mView.setBackground(mBackground);
+        mBackground.setAlpha(0);
     }
 
     @Override
@@ -217,6 +225,9 @@
         mKeyguardUpdateMonitor.removeCallback(mInfoCallback);
         mStatusBarStateController.removeCallback(mStatusBarStateListener);
         mScreenLifecycle.removeObserver(mScreenObserver);
+        mView.removeOnLayoutChangeListener(mBackground);
+        mView.setBackground(null);
+        mBackground.setAlpha(0);
     }
 
     /**
@@ -338,6 +349,13 @@
                 animate);
         PropertyAnimator.setProperty(mListView, AnimatableProperty.TRANSLATION_X, -Math.abs(x),
                 ANIMATION_PROPERTIES, animate);
+
+        Rect r = new Rect();
+        mListView.getDrawingRect(r);
+        mView.offsetDescendantRectToMyCoords(mListView, r);
+        mBackground.setGradientCenter(
+                (int) (mListView.getTranslationX() + r.left + r.width() / 2),
+                (int) (mListView.getTranslationY() + r.top + r.height() / 2));
     }
 
     /**
@@ -372,49 +390,52 @@
     }
 
     /**
-     * Remove the callback if it exists.
-     */
-    public void removeCallback() {
-        if (DEBUG) Log.d(TAG, "removeCallback");
-        mKeyguardUserSwitcherCallback = null;
-    }
-
-    /**
-     * Register to receive notifications about keyguard user switcher state
-     * (see {@link KeyguardUserSwitcherListener}.
-     *
-     * Only one callback can be used at a time.
-     *
-     * @param callback The callback to register
-     */
-    public void setCallback(KeyguardUserSwitcherListener callback) {
-        if (DEBUG) Log.d(TAG, "setCallback");
-        mKeyguardUserSwitcherCallback = new WeakReference<>(callback);
-    }
-
-    /**
-     * If user switcher state changes, notifies all {@link KeyguardUserSwitcherListener}.
-     * Switcher state is updatd before animations finish.
+     * NOTE: switcher state is updated before animations finish.
      *
      * @param animate true to animate transition. The user switcher state (i.e.
      *                {@link #isUserSwitcherOpen()}) is updated before animation is finished.
      */
     private void setUserSwitcherOpened(boolean open, boolean animate) {
-        boolean wasOpen = mUserSwitcherOpen;
         if (DEBUG) {
-            Log.d(TAG, String.format("setUserSwitcherOpened: %b -> %b (animate=%b)", wasOpen,
-                    open, animate));
+            Log.d(TAG,
+                    String.format("setUserSwitcherOpened: %b -> %b (animate=%b)",
+                            mUserSwitcherOpen, open, animate));
         }
         mUserSwitcherOpen = open;
-        if (mUserSwitcherOpen != wasOpen) {
-            notifyUserSwitcherStateChanged();
-        }
         updateVisibilities(animate);
     }
 
     private void updateVisibilities(boolean animate) {
         if (DEBUG) Log.d(TAG, String.format("updateVisibilities: animate=%b", animate));
         mEndGuestButton.animate().cancel();
+        if (mBgAnimator != null) {
+            mBgAnimator.cancel();
+        }
+
+        if (mUserSwitcherOpen) {
+            mBgAnimator = ObjectAnimator.ofInt(mBackground, "alpha", 0, 255);
+            mBgAnimator.setDuration(400);
+            mBgAnimator.setInterpolator(Interpolators.ALPHA_IN);
+            mBgAnimator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    mBgAnimator = null;
+                }
+            });
+            mBgAnimator.start();
+        } else {
+            mBgAnimator = ObjectAnimator.ofInt(mBackground, "alpha", 255, 0);
+            mBgAnimator.setDuration(400);
+            mBgAnimator.setInterpolator(Interpolators.ALPHA_OUT);
+            mBgAnimator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    mBgAnimator = null;
+                }
+            });
+            mBgAnimator.start();
+        }
+
         if (mUserSwitcherOpen && mCurrentUserIsGuest) {
             // Show the "End guest session" button
             mEndGuestButton.setVisibility(View.VISIBLE);
@@ -459,34 +480,6 @@
         return mUserSwitcherOpen;
     }
 
-    private void notifyUserSwitcherStateChanged() {
-        if (DEBUG) {
-            Log.d(TAG, String.format("notifyUserSwitcherStateChanged: mUserSwitcherOpen=%b",
-                    mUserSwitcherOpen));
-        }
-        if (mKeyguardUserSwitcherCallback != null) {
-            KeyguardUserSwitcherListener cb = mKeyguardUserSwitcherCallback.get();
-            if (cb != null) {
-                cb.onKeyguardUserSwitcherChanged(mUserSwitcherOpen);
-            }
-        }
-    }
-
-    /**
-     * Callback for keyguard user switcher state information
-     */
-    public interface KeyguardUserSwitcherListener {
-
-        /**
-         * Called when the keyguard enters or leaves user switcher mode. This will be called
-         * before the animations are finished.
-         *
-         * @param open if true, keyguard is showing the user switcher or transitioning from/to user
-         *             switcher mode.
-         */
-        void onKeyguardUserSwitcherChanged(boolean open);
-    }
-
     static class KeyguardUserAdapter extends
             UserSwitcherController.BaseUserAdapter implements View.OnClickListener {
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java
index 49f5bcd..1d9d33d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java
@@ -26,7 +26,6 @@
 import android.graphics.Rect;
 import android.graphics.Shader;
 import android.graphics.drawable.Drawable;
-import android.util.LayoutDirection;
 import android.view.View;
 
 import com.android.systemui.R;
@@ -38,13 +37,14 @@
         implements View.OnLayoutChangeListener {
 
     private static final float OUTER_EXTENT = 2.5f;
-    private static final float INNER_EXTENT = 0.75f;
+    private static final float INNER_EXTENT = 0.25f;
 
     private int mDarkColor;
-    private int mTop;
     private int mAlpha = 255;
     private Paint mRadialGradientPaint = new Paint();
-    private int mLayoutWidth;
+    private int mCircleX;
+    private int mCircleY;
+    private int mSize;
 
     public KeyguardUserSwitcherScrim(Context context) {
         mDarkColor = context.getColor(
@@ -53,14 +53,11 @@
 
     @Override
     public void draw(Canvas canvas) {
-        boolean isLtr = getLayoutDirection() == LayoutDirection.LTR;
+        if (mAlpha == 0) {
+            return;
+        }
         Rect bounds = getBounds();
-        float width = bounds.width() * OUTER_EXTENT;
-        float height = (mTop + bounds.height()) * OUTER_EXTENT;
-        canvas.translate(0, -mTop);
-        canvas.scale(1, height / width);
-        canvas.drawRect(isLtr ? bounds.right - width : 0, 0,
-                isLtr ? bounds.right : bounds.left + width, width, mRadialGradientPaint);
+        canvas.drawRect(bounds.left, bounds.top, bounds.right, bounds.bottom, mRadialGradientPaint);
     }
 
     @Override
@@ -88,24 +85,36 @@
     public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
             int oldTop, int oldRight, int oldBottom) {
         if (left != oldLeft || top != oldTop || right != oldRight || bottom != oldBottom) {
-            mLayoutWidth = right - left;
-            mTop = top;
+            int width = right - left;
+            int height = bottom - top;
+            mSize = Math.max(width, height);
             updatePaint();
         }
     }
 
     private void updatePaint() {
-        if (mLayoutWidth == 0) {
+        if (mSize == 0) {
             return;
         }
-        float radius = mLayoutWidth * OUTER_EXTENT;
-        boolean isLtr = getLayoutDirection() == LayoutDirection.LTR;
+        float outerRadius = mSize * OUTER_EXTENT;
         mRadialGradientPaint.setShader(
-                new RadialGradient(isLtr ? mLayoutWidth : 0, 0, radius,
+                new RadialGradient(mCircleX, mCircleY, outerRadius,
                         new int[] { Color.argb(
                                         (int) (Color.alpha(mDarkColor) * mAlpha / 255f), 0, 0, 0),
                                 Color.TRANSPARENT },
-                        new float[] { Math.max(0f, mLayoutWidth * INNER_EXTENT / radius), 1f },
+                        new float[] { Math.max(0f, INNER_EXTENT / OUTER_EXTENT), 1f },
                         Shader.TileMode.CLAMP));
     }
+
+    /**
+     * Sets the center of the radial gradient used as a background
+     *
+     * @param x
+     * @param y
+     */
+    public void setGradientCenter(int x, int y) {
+        mCircleX = x;
+        mCircleY = y;
+        updatePaint();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 1ab7652..6c097bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -59,6 +59,7 @@
 import com.android.settingslib.net.SignalStrengthUtil;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 
 import java.io.PrintWriter;
@@ -402,10 +403,12 @@
             showDataIcon |= mCurrentState.roaming;
             IconState statusIcon = new IconState(showDataIcon && !mCurrentState.airplaneMode,
                     getCurrentIconId(), contentDescription);
-            callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
+            MobileDataIndicators mobileDataIndicators = new MobileDataIndicators(
+                    statusIcon, qsIcon, typeIcon, qsTypeIcon,
                     activityIn, activityOut, dataContentDescription, dataContentDescriptionHtml,
                     description, icons.isWide, mSubscriptionInfo.getSubscriptionId(),
                     mCurrentState.roaming, showTriangle);
+            callback.setMobileDataIndicators(mobileDataIndicators);
         } else {
             boolean showDataIcon = mCurrentState.dataConnected || dataDisabled;
             IconState statusIcon = new IconState(
@@ -432,10 +435,12 @@
             showDataIcon &= mCurrentState.isDefault || dataDisabled;
             int typeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.dataType : 0;
             boolean showTriangle = mCurrentState.enabled && !mCurrentState.airplaneMode;
-            callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
+            MobileDataIndicators mobileDataIndicators = new MobileDataIndicators(
+                    statusIcon, qsIcon, typeIcon, qsTypeIcon,
                     activityIn, activityOut, dataContentDescription, dataContentDescriptionHtml,
                     description, icons.isWide, mSubscriptionInfo.getSubscriptionId(),
                     mCurrentState.roaming, showTriangle);
+            callback.setMobileDataIndicators(mobileDataIndicators);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 0a9fead..ef2ca98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -46,34 +46,117 @@
 
     boolean isRadioOn();
 
+    /**
+     * Wrapper class for all the WiFi signals used for WiFi indicators.
+     */
+    final class WifiIndicators {
+        public boolean enabled;
+        public IconState statusIcon;
+        public IconState qsIcon;
+        public boolean activityIn;
+        public boolean activityOut;
+        public String description;
+        public boolean isTransient;
+        public String statusLabel;
+
+        public WifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
+                boolean activityIn, boolean activityOut, String description,
+                boolean isTransient, String statusLabel) {
+            this.enabled = enabled;
+            this.statusIcon = statusIcon;
+            this.qsIcon = qsIcon;
+            this.activityIn = activityIn;
+            this.activityOut = activityOut;
+            this.description = description;
+            this.isTransient = isTransient;
+            this.statusLabel = statusLabel;
+        }
+
+        @Override
+        public String toString() {
+            return new StringBuilder("WifiIndicators[")
+                .append("enabled=").append(enabled)
+                .append(",statusIcon=").append(statusIcon == null ? "" : statusIcon.toString())
+                .append(",qsIcon=").append(qsIcon == null ? "" : qsIcon.toString())
+                .append(",activityIn=").append(activityIn)
+                .append(",activityOut=").append(activityOut)
+                .append(",description=").append(description)
+                .append(",isTransient=").append(isTransient)
+                .append(",statusLabel=").append(statusLabel)
+                .append(']').toString();
+        }
+    }
+
+    /**
+     * Wrapper class for all the mobile signals used for mobile data indicators.
+     */
+    final class MobileDataIndicators {
+        public IconState statusIcon;
+        public IconState qsIcon;
+        public int statusType;
+        public int qsType;
+        public boolean activityIn;
+        public boolean activityOut;
+        public CharSequence typeContentDescription;
+        public CharSequence typeContentDescriptionHtml;
+        public CharSequence description;
+        public boolean isWide;
+        public int subId;
+        public boolean roaming;
+        public boolean showTriangle;
+
+        public MobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
+                int qsType, boolean activityIn, boolean activityOut,
+                CharSequence typeContentDescription, CharSequence typeContentDescriptionHtml,
+                CharSequence description, boolean isWide, int subId, boolean roaming,
+                boolean showTriangle) {
+            this.statusIcon = statusIcon;
+            this.qsIcon = qsIcon;
+            this.statusType = statusType;
+            this.qsType = qsType;
+            this.activityIn = activityIn;
+            this.activityOut = activityOut;
+            this.typeContentDescription = typeContentDescription;
+            this.typeContentDescriptionHtml = typeContentDescriptionHtml;
+            this.description = description;
+            this.isWide = isWide;
+            this.subId = subId;
+            this.roaming = roaming;
+            this.showTriangle = showTriangle;
+        }
+
+        @Override
+        public String toString() {
+            return new StringBuilder("MobileDataIndicators[")
+                .append("statusIcon=").append(statusIcon == null ? "" :  statusIcon.toString())
+                .append(",qsIcon=").append(qsIcon == null ? "" : qsIcon.toString())
+                .append(",statusType=").append(statusType)
+                .append(",qsType=").append(qsType)
+                .append(",activityIn=").append(activityIn)
+                .append(",activityOut=").append(activityOut)
+                .append(",typeContentDescription=").append(typeContentDescription)
+                .append(",typeContentDescriptionHtml=").append(typeContentDescriptionHtml)
+                .append(",description=").append(description)
+                .append(",isWide=").append(isWide)
+                .append(",subId=").append(subId)
+                .append(",roaming=").append(roaming)
+                .append(",showTriangle=").append(showTriangle)
+                .append(']').toString();
+        }
+    }
+
     public interface SignalCallback {
-        default void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
-                boolean activityIn, boolean activityOut, String description, boolean isTransient,
-                String statusLabel) {}
+        /**
+         * Callback for listeners to be able to update the state of any UI tracking connectivity of
+         * WiFi networks.
+         */
+        default void setWifiIndicators(WifiIndicators wifiIndicators) {}
 
         /**
          * Callback for listeners to be able to update the state of any UI tracking connectivity
-         * @param statusIcon the icon that should be shown in the status bar
-         * @param qsIcon the icon to show in Quick Settings
-         * @param statusType the resId of the data type icon (e.g. LTE) to show in the status bar
-         * @param qsType similar to above, the resId of the data type icon to show in Quick Settings
-         * @param activityIn indicates whether there is inbound activity
-         * @param activityOut indicates outbound activity
-         * @param typeContentDescription the contentDescription of the data type
-         * @param typeContentDescriptionHtml the (possibly HTML-styled) contentDescription of the
-         *                                   data type. Suitable for display
-         * @param description description of the network (usually just the network name)
-         * @param isWide //TODO: unused?
-         * @param subId subscription ID for which to update the UI
-         * @param roaming indicates roaming
-         * @param showTriangle whether to show the mobile triangle the in status bar
+         * of Mobile networks.
          */
-        default void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
-                int qsType, boolean activityIn, boolean activityOut,
-                CharSequence typeContentDescription,
-                CharSequence typeContentDescriptionHtml, CharSequence description,
-                boolean isWide, int subId, boolean roaming, boolean showTriangle) {
-        }
+        default void setMobileDataIndicators(MobileDataIndicators mobileDataIndicators) {}
 
         default void setSubs(List<SubscriptionInfo> subs) {}
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 9f92142..8eb1e64 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -165,7 +165,7 @@
     private int mCurrentUserId;
 
     private OnSubscriptionsChangedListener mSubscriptionListener;
-
+    private NetworkCapabilities mLastDefaultNetworkCapabilities;
     // Handler that all broadcasts are received on.
     private final Handler mReceiverHandler;
     // Handler that all callbacks are made on.
@@ -315,6 +315,7 @@
             public void onLost(Network network) {
                 mLastNetwork = null;
                 mLastNetworkCapabilities = null;
+                mLastDefaultNetworkCapabilities = null;
                 String callback = new StringBuilder()
                         .append(SSDF.format(System.currentTimeMillis())).append(",")
                         .append("onLost: ")
@@ -341,6 +342,7 @@
                 }
                 mLastNetwork = network;
                 mLastNetworkCapabilities = networkCapabilities;
+                mLastDefaultNetworkCapabilities = networkCapabilities;
                 String callback = new StringBuilder()
                         .append(SSDF.format(System.currentTimeMillis())).append(",")
                         .append("onCapabilitiesChanged: ")
@@ -959,18 +961,17 @@
     private void updateConnectivity() {
         mConnectedTransports.clear();
         mValidatedTransports.clear();
-        for (NetworkCapabilities nc :
-                mConnectivityManager.getDefaultNetworkCapabilitiesForUser(mCurrentUserId)) {
-            for (int transportType : nc.getTransportTypes()) {
+        if (mLastDefaultNetworkCapabilities != null) {
+            for (int transportType : mLastDefaultNetworkCapabilities.getTransportTypes()) {
                 if (transportType == NetworkCapabilities.TRANSPORT_CELLULAR
-                        && Utils.tryGetWifiInfoForVcn(nc) != null) {
+                        && Utils.tryGetWifiInfoForVcn(mLastDefaultNetworkCapabilities) != null) {
                     mConnectedTransports.set(NetworkCapabilities.TRANSPORT_WIFI);
-                    if (nc.hasCapability(NET_CAPABILITY_VALIDATED)) {
+                    if (mLastDefaultNetworkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
                         mValidatedTransports.set(NetworkCapabilities.TRANSPORT_WIFI);
                     }
                 } else {
                     mConnectedTransports.set(transportType);
-                    if (nc.hasCapability(NET_CAPABILITY_VALIDATED)) {
+                    if (mLastDefaultNetworkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
                         mValidatedTransports.set(transportType);
                     }
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 8e833c0..320b00a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -561,6 +561,11 @@
         super.onVisibilityChanged(changedView, visibility);
         if (changedView == this && mOnVisibilityChangedListener != null) {
             mOnVisibilityChangedListener.accept(visibility == VISIBLE);
+            // Hide soft-keyboard when the input view became invisible
+            // (i.e. The notification shade collapsed by pressing the home key)
+            if (visibility != VISIBLE && !mEditText.isVisibleToUser()) {
+                mEditText.hideIme();
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartRepliesAndActionsInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt
similarity index 83%
rename from packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartRepliesAndActionsInflater.kt
rename to packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt
index ea80325..0bf2d50 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartRepliesAndActionsInflater.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt
@@ -44,7 +44,7 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.logging.NotificationLogger
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil
-import com.android.systemui.statusbar.policy.InflatedSmartReplies.SmartRepliesAndActions
+import com.android.systemui.statusbar.policy.InflatedSmartReplyState.SuppressedActions
 import com.android.systemui.statusbar.policy.SmartReplyView.SmartActions
 import com.android.systemui.statusbar.policy.SmartReplyView.SmartButtonType
 import com.android.systemui.statusbar.policy.SmartReplyView.SmartReplies
@@ -53,10 +53,10 @@
 /** Returns whether we should show the smart reply view and its smart suggestions. */
 fun shouldShowSmartReplyView(
     entry: NotificationEntry,
-    smartRepliesAndActions: SmartRepliesAndActions
+    smartReplyState: InflatedSmartReplyState
 ): Boolean {
-    if (smartRepliesAndActions.smartReplies == null
-            && smartRepliesAndActions.smartActions == null) {
+    if (smartReplyState.smartReplies == null &&
+            smartReplyState.smartActions == null) {
         // There are no smart replies and no smart actions.
         return false
     }
@@ -71,58 +71,65 @@
             .getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false)
 }
 
-/** Determines if two [SmartRepliesAndActions] are visually similar. */
+/** Determines if two [InflatedSmartReplyState] are visually similar. */
 fun areSuggestionsSimilar(
-    left: SmartRepliesAndActions?,
-    right: SmartRepliesAndActions?
+    left: InflatedSmartReplyState?,
+    right: InflatedSmartReplyState?
 ): Boolean = when {
     left === right -> true
     left == null || right == null -> false
-    left.getSmartReplies() != right.getSmartReplies() -> false
-    else -> !NotificationUiAdjustment.areDifferent(left.getSmartActions(), right.getSmartActions())
+    left.hasPhishingAction != right.hasPhishingAction -> false
+    left.smartRepliesList != right.smartRepliesList -> false
+    left.suppressedActionIndices != right.suppressedActionIndices -> false
+    else -> !NotificationUiAdjustment.areDifferent(left.smartActionsList, right.smartActionsList)
 }
 
-interface SmartRepliesAndActionsInflater {
-    fun inflateSmartReplies(
+interface SmartReplyStateInflater {
+    fun inflateSmartReplyState(entry: NotificationEntry): InflatedSmartReplyState
+
+    fun inflateSmartReplyViewHolder(
         sysuiContext: Context,
         notifPackageContext: Context,
         entry: NotificationEntry,
-        existingRepliesAndAction: SmartRepliesAndActions?
-    ): InflatedSmartReplies
+        existingSmartReplyState: InflatedSmartReplyState?,
+        newSmartReplyState: InflatedSmartReplyState
+    ): InflatedSmartReplyViewHolder
 }
 
-/*internal*/ class SmartRepliesAndActionsInflaterImpl @Inject constructor(
+/*internal*/ class SmartReplyStateInflaterImpl @Inject constructor(
     private val constants: SmartReplyConstants,
     private val activityManagerWrapper: ActivityManagerWrapper,
     private val packageManagerWrapper: PackageManagerWrapper,
     private val devicePolicyManagerWrapper: DevicePolicyManagerWrapper,
     private val smartRepliesInflater: SmartReplyInflater,
     private val smartActionsInflater: SmartActionInflater
-) : SmartRepliesAndActionsInflater {
+) : SmartReplyStateInflater {
 
-    override fun inflateSmartReplies(
+    override fun inflateSmartReplyState(entry: NotificationEntry): InflatedSmartReplyState =
+            chooseSmartRepliesAndActions(entry)
+
+    override fun inflateSmartReplyViewHolder(
         sysuiContext: Context,
         notifPackageContext: Context,
         entry: NotificationEntry,
-        existingRepliesAndAction: SmartRepliesAndActions?
-    ): InflatedSmartReplies {
-        val newRepliesAndActions = chooseSmartRepliesAndActions(entry)
-        if (!shouldShowSmartReplyView(entry, newRepliesAndActions)) {
-            return InflatedSmartReplies(
+        existingSmartReplyState: InflatedSmartReplyState?,
+        newSmartReplyState: InflatedSmartReplyState
+    ): InflatedSmartReplyViewHolder {
+        if (!shouldShowSmartReplyView(entry, newSmartReplyState)) {
+            return InflatedSmartReplyViewHolder(
                     null /* smartReplyView */,
-                    null /* smartSuggestionButtons */,
-                    newRepliesAndActions)
+                    null /* smartSuggestionButtons */)
         }
 
         // Only block clicks if the smart buttons are different from the previous set - to avoid
         // scenarios where a user incorrectly cannot click smart buttons because the
         // notification is updated.
         val delayOnClickListener =
-                !areSuggestionsSimilar(existingRepliesAndAction, newRepliesAndActions)
+                !areSuggestionsSimilar(existingSmartReplyState, newSmartReplyState)
 
         val smartReplyView = SmartReplyView.inflate(sysuiContext, constants)
 
-        val smartReplies = newRepliesAndActions.smartReplies
+        val smartReplies = newSmartReplyState.smartReplies
         smartReplyView.setSmartRepliesGeneratedByAssistant(smartReplies?.fromAssistant ?: false)
         val smartReplyButtons = smartReplies?.let {
             smartReplies.choices.asSequence().mapIndexed { index, choice ->
@@ -136,7 +143,7 @@
             }
         } ?: emptySequence()
 
-        val smartActionButtons = newRepliesAndActions.smartActions?.let { smartActions ->
+        val smartActionButtons = newSmartReplyState.smartActions?.let { smartActions ->
             val themedPackageContext =
                     ContextThemeWrapper(notifPackageContext, sysuiContext.theme)
             smartActions.actions.asSequence()
@@ -153,10 +160,9 @@
                     }
         } ?: emptySequence()
 
-        return InflatedSmartReplies(
+        return InflatedSmartReplyViewHolder(
                 smartReplyView,
-                (smartReplyButtons + smartActionButtons).toList(),
-                newRepliesAndActions)
+                (smartReplyButtons + smartActionButtons).toList())
     }
 
     /**
@@ -165,23 +171,23 @@
      * replies or actions generated by the NotificationAssistantService (NAS), and if the app
      * provides any smart actions we also don't show any NAS-generated replies or actions.
      */
-    fun chooseSmartRepliesAndActions(entry: NotificationEntry): SmartRepliesAndActions {
+    fun chooseSmartRepliesAndActions(entry: NotificationEntry): InflatedSmartReplyState {
         val notification = entry.sbn.notification
         val remoteInputActionPair = notification.findRemoteInputActionPair(false /* freeform */)
         val freeformRemoteInputActionPair =
                 notification.findRemoteInputActionPair(true /* freeform */)
         if (!constants.isEnabled) {
             if (DEBUG) {
-                Log.d(TAG, "Smart suggestions not enabled, not adding suggestions for "
-                        + entry.sbn.key)
+                Log.d(TAG, "Smart suggestions not enabled, not adding suggestions for " +
+                        entry.sbn.key)
             }
-            return SmartRepliesAndActions(null, null)
+            return InflatedSmartReplyState(null, null, null, false)
         }
         // Only use smart replies from the app if they target P or above. We have this check because
         // the smart reply API has been used for other things (Wearables) in the past. The API to
         // add smart actions is new in Q so it doesn't require a target-sdk check.
-        val enableAppGeneratedSmartReplies = (!constants.requiresTargetingP()
-                || entry.targetSdk >= Build.VERSION_CODES.P)
+        val enableAppGeneratedSmartReplies = (!constants.requiresTargetingP() ||
+                entry.targetSdk >= Build.VERSION_CODES.P)
         val appGeneratedSmartActions = notification.contextualActions
 
         var smartReplies: SmartReplies? = when {
@@ -207,18 +213,18 @@
         if (smartReplies == null && smartActions == null) {
             val entryReplies = entry.smartReplies
             val entryActions = entry.smartActions
-            if (entryReplies.isNotEmpty()
-                    && freeformRemoteInputActionPair != null
-                    && freeformRemoteInputActionPair.second.allowGeneratedReplies
-                    && freeformRemoteInputActionPair.second.actionIntent != null) {
+            if (entryReplies.isNotEmpty() &&
+                    freeformRemoteInputActionPair != null &&
+                    freeformRemoteInputActionPair.second.allowGeneratedReplies &&
+                    freeformRemoteInputActionPair.second.actionIntent != null) {
                 smartReplies = SmartReplies(
                         entryReplies,
                         freeformRemoteInputActionPair.first,
                         freeformRemoteInputActionPair.second.actionIntent,
                         true /* fromAssistant */)
             }
-            if (entryActions.isNotEmpty()
-                    && notification.allowSystemGeneratedContextualActions) {
+            if (entryActions.isNotEmpty() &&
+                    notification.allowSystemGeneratedContextualActions) {
                 val systemGeneratedActions: List<Notification.Action> = when {
                     activityManagerWrapper.isLockTaskKioskModeActive ->
                         // Filter actions if we're in kiosk-mode - we don't care about screen
@@ -229,7 +235,21 @@
                 smartActions = SmartActions(systemGeneratedActions, true /* fromAssistant */)
             }
         }
-        return SmartRepliesAndActions(smartReplies, smartActions)
+        val hasPhishingAction = smartActions?.actions?.any {
+            it.isContextual && it.semanticAction ==
+                    Notification.Action.SEMANTIC_ACTION_CONVERSATION_IS_PHISHING
+        } ?: false
+        var suppressedActions: SuppressedActions? = null
+        if (hasPhishingAction) {
+            // If there is a phishing action, calculate the indices of the actions with RemoteInput
+            //  as those need to be hidden from the view.
+            val suppressedActionIndices = notification.actions.mapIndexedNotNull { index, action ->
+                if (action.remoteInputs?.isNotEmpty() == true) index else null
+            }
+            suppressedActions = SuppressedActions(suppressedActionIndices)
+        }
+        return InflatedSmartReplyState(smartReplies, smartActions, suppressedActions,
+                hasPhishingAction)
     }
 
     /**
@@ -311,8 +331,8 @@
         actionIndex: Int,
         action: Notification.Action
     ) =
-        if (smartActions.fromAssistant
-            && SEMANTIC_ACTION_MARK_CONVERSATION_AS_PRIORITY == action.semanticAction) {
+        if (smartActions.fromAssistant &&
+            SEMANTIC_ACTION_MARK_CONVERSATION_AS_PRIORITY == action.semanticAction) {
             entry.row.doSmartActionClick(entry.row.x.toInt() / 2,
                 entry.row.y.toInt() / 2, SEMANTIC_ACTION_MARK_CONVERSATION_AS_PRIORITY)
             smartReplyController
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index 34c7881..ad4fa64 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -794,8 +794,8 @@
         public final List<CharSequence> choices;
         public final boolean fromAssistant;
 
-        public SmartReplies(List<CharSequence> choices, RemoteInput remoteInput,
-                PendingIntent pendingIntent, boolean fromAssistant) {
+        public SmartReplies(@NonNull List<CharSequence> choices, @NonNull RemoteInput remoteInput,
+                @NonNull PendingIntent pendingIntent, boolean fromAssistant) {
             this.choices = choices;
             this.remoteInput = remoteInput;
             this.pendingIntent = pendingIntent;
@@ -812,7 +812,7 @@
         public final List<Notification.Action> actions;
         public final boolean fromAssistant;
 
-        public SmartActions(List<Notification.Action> actions, boolean fromAssistant) {
+        public SmartActions(@NonNull List<Notification.Action> actions, boolean fromAssistant) {
             this.actions = actions;
             this.fromAssistant = fromAssistant;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index 16998d7..8d72c9c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -38,7 +38,9 @@
 import com.android.settingslib.wifi.WifiStatusTracker;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
+import com.android.systemui.statusbar.policy.NetworkController.WifiIndicators;
 
 import java.io.PrintWriter;
 import java.util.Objects;
@@ -113,18 +115,24 @@
                         mWifiTracker.isCaptivePortal ? R.drawable.ic_qs_wifi_disconnected
                                 : getQsCurrentIconId(), contentDescription);
             }
-            callback.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,
+            WifiIndicators wifiIndicators = new WifiIndicators(
+                    mCurrentState.enabled, statusIcon, qsIcon,
                     ssidPresent && mCurrentState.activityIn,
                     ssidPresent && mCurrentState.activityOut,
-                    wifiDesc, mCurrentState.isTransient, mCurrentState.statusLabel);
+                    wifiDesc, mCurrentState.isTransient, mCurrentState.statusLabel
+            );
+            callback.setWifiIndicators(wifiIndicators);
         } else {
             IconState qsIcon = new IconState(mCurrentState.connected,
                     mWifiTracker.isCaptivePortal ? R.drawable.ic_qs_wifi_disconnected
                             : getQsCurrentIconId(), contentDescription);
-            callback.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,
+            WifiIndicators wifiIndicators = new WifiIndicators(
+                    mCurrentState.enabled, statusIcon, qsIcon,
                     ssidPresent && mCurrentState.activityIn,
                     ssidPresent && mCurrentState.activityOut,
-                    wifiDesc, mCurrentState.isTransient, mCurrentState.statusLabel);
+                    wifiDesc, mCurrentState.isTransient, mCurrentState.statusLabel
+            );
+            callback.setWifiIndicators(wifiIndicators);
         }
     }
 
@@ -149,10 +157,13 @@
                 mCurrentState.connected, getQsCurrentIconIdForCarrierWifi(), contentDescription);
         CharSequence description =
                 mNetworkController.getNetworkNameForCarrierWiFi(mCurrentState.subId);
-        callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
+        MobileDataIndicators mobileDataIndicators = new MobileDataIndicators(
+                statusIcon, qsIcon, typeIcon, qsTypeIcon,
                 mCurrentState.activityIn, mCurrentState.activityOut, dataContentDescription,
                 dataContentDescriptionHtml, description, icons.isWide,
-                mCurrentState.subId, /* roaming= */ false, /* showTriangle= */ true);
+                mCurrentState.subId, /* roaming= */ false, /* showTriangle= */ true
+        );
+        callback.setMobileDataIndicators(mobileDataIndicators);
     }
 
     private int getCurrentIconIdForCarrierWifi() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/SmartRepliesInflationModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/SmartRepliesInflationModule.kt
index 803d26e..ce4a927 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/SmartRepliesInflationModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/SmartRepliesInflationModule.kt
@@ -17,10 +17,10 @@
 
 import com.android.systemui.statusbar.policy.SmartActionInflater
 import com.android.systemui.statusbar.policy.SmartActionInflaterImpl
-import com.android.systemui.statusbar.policy.SmartRepliesAndActionsInflater
-import com.android.systemui.statusbar.policy.SmartRepliesAndActionsInflaterImpl
 import com.android.systemui.statusbar.policy.SmartReplyInflater
 import com.android.systemui.statusbar.policy.SmartReplyInflaterImpl
+import com.android.systemui.statusbar.policy.SmartReplyStateInflater
+import com.android.systemui.statusbar.policy.SmartReplyStateInflaterImpl
 import dagger.Binds
 import dagger.Module
 
@@ -29,6 +29,6 @@
     @Binds fun bindSmartActionsInflater(impl: SmartActionInflaterImpl): SmartActionInflater
     @Binds fun bindSmartReplyInflater(impl: SmartReplyInflaterImpl): SmartReplyInflater
     @Binds fun bindsInflatedSmartRepliesProvider(
-        impl: SmartRepliesAndActionsInflaterImpl
-    ): SmartRepliesAndActionsInflater
+        impl: SmartReplyStateInflaterImpl
+    ): SmartReplyStateInflater
 }
\ No newline at end of file
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 bdf2b0c..37a763b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -22,12 +22,10 @@
 import android.os.ServiceManager;
 
 import com.android.internal.statusbar.IStatusBarService;
-import com.android.systemui.R;
 import com.android.systemui.SystemUI;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.tv.micdisclosure.AudioRecordingDisclosureBar;
 
 import javax.inject.Inject;
 
@@ -36,11 +34,6 @@
 /**
  * Status bar implementation for "large screen" products that mostly present no on-screen nav.
  * Serves as a collection of UI components, rather than showing its own UI.
- * The following is the list of elements that constitute the TV-specific status bar:
- * <ul>
- * <li> {@link AudioRecordingDisclosureBar} - shown whenever applications are conducting audio
- * recording, discloses the responsible applications </li>
- * </ul>
  */
 @SysUISingleton
 public class TvStatusBar extends SystemUI implements CommandQueue.Callbacks {
@@ -66,11 +59,6 @@
         } catch (RemoteException ex) {
             // If the system process isn't there we're doomed anyway.
         }
-
-        if (mContext.getResources().getBoolean(R.bool.audio_recording_disclosure_enabled)) {
-            // Creating AudioRecordingDisclosureBar and just letting it run
-            new AudioRecordingDisclosureBar(mContext);
-        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioActivityObserver.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioActivityObserver.java
deleted file mode 100644
index bbab625..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioActivityObserver.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.tv.micdisclosure;
-
-import android.content.Context;
-
-import java.util.Set;
-
-/**
- * A base class for implementing observers for different kinds of activities related to audio
- * recording. These observers are to be initialized by {@link AudioRecordingDisclosureBar} and to
- * report back to it.
- */
-abstract class AudioActivityObserver {
-
-    interface OnAudioActivityStateChangeListener {
-        void onAudioActivityStateChange(boolean active, String packageName);
-    }
-
-    final Context mContext;
-
-    final OnAudioActivityStateChangeListener mListener;
-
-    AudioActivityObserver(Context context, OnAudioActivityStateChangeListener listener) {
-        mContext = context;
-        mListener = listener;
-    }
-
-    abstract void start();
-
-    abstract void stop();
-
-    abstract Set<String> getActivePackages();
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
deleted file mode 100644
index c9d1b71..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.tv.micdisclosure;
-
-import static android.provider.DeviceConfig.NAMESPACE_PRIVACY;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.annotation.IntDef;
-import android.annotation.UiThread;
-import android.content.Context;
-import android.graphics.PixelFormat;
-import android.provider.DeviceConfig;
-import android.text.TextUtils;
-import android.util.ArraySet;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewTreeObserver;
-import android.view.WindowManager;
-
-import com.android.systemui.R;
-import com.android.systemui.statusbar.tv.TvStatusBar;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-
-/**
- * A component of {@link TvStatusBar} responsible for notifying the user whenever an application is
- * recording audio.
- *
- * @see TvStatusBar
- */
-public class AudioRecordingDisclosureBar implements
-        AudioActivityObserver.OnAudioActivityStateChangeListener {
-    private static final String TAG = "AudioRecordingDisclosure";
-    static final boolean DEBUG = false;
-
-    // This title is used to test the microphone disclosure indicator in
-    // CtsSystemUiHostTestCases:TvMicrophoneCaptureIndicatorTest
-    private static final String LAYOUT_PARAMS_TITLE = "MicrophoneCaptureIndicator";
-
-    private static final String ENABLED_FLAG = "mic_disclosure_enabled";
-    private static final String EXEMPT_PACKAGES_LIST = "mic_disclosure_exempt_packages";
-    private static final String FORCED_PACKAGES_LIST = "mic_disclosure_forced_packages";
-
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = {"STATE_"}, value = {
-            STATE_STOPPED,
-            STATE_NOT_SHOWN,
-            STATE_APPEARING,
-            STATE_SHOWN,
-            STATE_DISAPPEARING
-    })
-    public @interface State {}
-
-    private static final int STATE_STOPPED = -1;
-    private static final int STATE_NOT_SHOWN = 0;
-    private static final int STATE_APPEARING = 1;
-    private static final int STATE_SHOWN = 2;
-    private static final int STATE_DISAPPEARING = 3;
-
-    private static final int ANIMATION_DURATION_MS = 200;
-
-    private final Context mContext;
-    private boolean mIsEnabled;
-
-    private View mIndicatorView;
-    private boolean mViewAndWindowAdded;
-    private ObjectAnimator mAnimator;
-
-    @State private int mState = STATE_STOPPED;
-
-    /**
-     * Array of the observers that monitor different aspects of the system, such as AppOps and
-     * microphone foreground services
-     */
-    private AudioActivityObserver[] mAudioActivityObservers;
-    /**
-     * Set of applications for which we make an exception and do not show the indicator. This gets
-     * populated once - in {@link #AudioRecordingDisclosureBar(Context)}.
-     */
-    private final Set<String> mExemptPackages = new ArraySet<>();
-
-    public AudioRecordingDisclosureBar(Context context) {
-        mContext = context;
-
-        // Load configs
-        reloadExemptPackages();
-
-        mIsEnabled = DeviceConfig.getBoolean(NAMESPACE_PRIVACY, ENABLED_FLAG, true);
-        // Start if enabled
-        if (mIsEnabled) {
-            start();
-        }
-
-        // Set up a config change listener
-        DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_PRIVACY, mContext.getMainExecutor(),
-                mConfigChangeListener);
-    }
-
-    private void reloadExemptPackages() {
-        mExemptPackages.clear();
-        mExemptPackages.addAll(Arrays.asList(mContext.getResources().getStringArray(
-                R.array.audio_recording_disclosure_exempt_apps)));
-        mExemptPackages.addAll(
-                splitByComma(
-                        DeviceConfig.getString(NAMESPACE_PRIVACY, EXEMPT_PACKAGES_LIST, null)));
-        mExemptPackages.removeAll(
-                splitByComma(
-                        DeviceConfig.getString(NAMESPACE_PRIVACY, FORCED_PACKAGES_LIST, null)));
-    }
-
-    @UiThread
-    private void start() {
-        if (mState != STATE_STOPPED) {
-            return;
-        }
-        mState = STATE_NOT_SHOWN;
-
-        if (mAudioActivityObservers == null) {
-            mAudioActivityObservers = new AudioActivityObserver[]{
-                    new RecordAudioAppOpObserver(mContext, this),
-                    new MicrophoneForegroundServicesObserver(mContext, this),
-            };
-        }
-
-        for (int i = mAudioActivityObservers.length - 1; i >= 0; i--) {
-            mAudioActivityObservers[i].start();
-        }
-    }
-
-    @UiThread
-    private void stop() {
-        if (mState == STATE_STOPPED) {
-            return;
-        }
-        mState = STATE_STOPPED;
-
-        for (int i = mAudioActivityObservers.length - 1; i >= 0; i--) {
-            mAudioActivityObservers[i].stop();
-        }
-
-        // Remove the view if shown.
-        if (mState != STATE_NOT_SHOWN) {
-            removeIndicatorView();
-        }
-    }
-
-    @UiThread
-    @Override
-    public void onAudioActivityStateChange(boolean active, String packageName) {
-        if (DEBUG) {
-            Log.d(TAG,
-                    "onAudioActivityStateChange, packageName=" + packageName + ", active="
-                            + active);
-        }
-
-        if (mExemptPackages.contains(packageName)) {
-            if (DEBUG) Log.d(TAG, "   - exempt package: ignoring");
-            return;
-        }
-
-        if (active) {
-            showIfNeeded();
-        } else {
-            hideIndicatorIfNeeded();
-        }
-    }
-
-    @UiThread
-    private void hideIndicatorIfNeeded() {
-        // If STOPPED, NOT_SHOWN or DISAPPEARING - nothing else for us to do here.
-        if (mState != STATE_SHOWN && mState != STATE_APPEARING) return;
-
-        if (hasActiveRecorders()) {
-            return;
-        }
-
-        if (mViewAndWindowAdded) {
-            mState = STATE_DISAPPEARING;
-            animateDisappearance();
-        } else {
-            // Appearing animation has not started yet, as we were still waiting for the View to be
-            // laid out.
-            mState = STATE_NOT_SHOWN;
-            removeIndicatorView();
-        }
-    }
-
-    @UiThread
-    private void showIfNeeded() {
-        // If STOPPED, SHOWN or APPEARING - nothing else for us to do here.
-        if (mState != STATE_NOT_SHOWN && mState != STATE_DISAPPEARING) return;
-
-        if (DEBUG) Log.d(TAG, "Showing indicator");
-
-        final int prevState = mState;
-        mState = STATE_APPEARING;
-
-        if (prevState == STATE_DISAPPEARING) {
-            animateAppearance();
-            return;
-        }
-
-        // Inflate the indicator view
-        mIndicatorView = LayoutInflater.from(mContext).inflate(
-                R.layout.tv_audio_recording_indicator, null);
-
-        // 1. Set alpha to 0.
-        // 2. Wait until the window is shown and the view is laid out.
-        // 3. Start a "fade in" (alpha) animation.
-        mIndicatorView.setAlpha(0f);
-        mIndicatorView
-                .getViewTreeObserver()
-                .addOnGlobalLayoutListener(
-                        new ViewTreeObserver.OnGlobalLayoutListener() {
-                            @Override
-                            public void onGlobalLayout() {
-                                // State could have changed to NOT_SHOWN (if all the recorders are
-                                // already gone) to STOPPED (if the indicator was disabled)
-                                if (mState != STATE_APPEARING) return;
-
-                                mViewAndWindowAdded = true;
-                                // Remove the observer
-                                mIndicatorView.getViewTreeObserver().removeOnGlobalLayoutListener(
-                                        this);
-
-                                animateAppearance();
-                            }
-                        });
-
-        final boolean isLtr = mContext.getResources().getConfiguration().getLayoutDirection()
-                == View.LAYOUT_DIRECTION_LTR;
-        final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
-                WRAP_CONTENT,
-                WRAP_CONTENT,
-                WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
-                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
-                PixelFormat.TRANSLUCENT);
-        layoutParams.gravity = Gravity.TOP | (isLtr ? Gravity.RIGHT : Gravity.LEFT);
-        layoutParams.setTitle(LAYOUT_PARAMS_TITLE);
-        layoutParams.packageName = mContext.getPackageName();
-        final WindowManager windowManager = (WindowManager) mContext.getSystemService(
-                Context.WINDOW_SERVICE);
-        windowManager.addView(mIndicatorView, layoutParams);
-    }
-
-
-    private void animateAppearance() {
-        animateAlphaTo(1f);
-    }
-
-    private void animateDisappearance() {
-        animateAlphaTo(0f);
-    }
-
-    private void animateAlphaTo(final float endValue) {
-        if (mAnimator == null) {
-            if (DEBUG) Log.d(TAG, "set up animator");
-
-            mAnimator = new ObjectAnimator();
-            mAnimator.setTarget(mIndicatorView);
-            mAnimator.setProperty(View.ALPHA);
-            mAnimator.addListener(new AnimatorListenerAdapter() {
-                boolean mCancelled;
-
-                @Override
-                public void onAnimationStart(Animator animation, boolean isReverse) {
-                    if (DEBUG) Log.d(TAG, "AnimatorListenerAdapter#onAnimationStart");
-                    mCancelled = false;
-                }
-
-                @Override
-                public void onAnimationCancel(Animator animation) {
-                    if (DEBUG) Log.d(TAG, "AnimatorListenerAdapter#onAnimationCancel");
-                    mCancelled = true;
-                }
-
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    if (DEBUG) Log.d(TAG, "AnimatorListenerAdapter#onAnimationEnd");
-                    // When ValueAnimator#cancel() is called it always calls onAnimationCancel(...)
-                    // and then onAnimationEnd(...). We, however, only want to proceed here if the
-                    // animation ended "naturally".
-                    if (!mCancelled) {
-                        onAnimationFinished();
-                    }
-                }
-            });
-        } else if (mAnimator.isRunning()) {
-            if (DEBUG) Log.d(TAG, "cancel running animation");
-            mAnimator.cancel();
-        }
-
-        final float currentValue = mIndicatorView.getAlpha();
-        if (DEBUG) Log.d(TAG, "animate alpha to " + endValue + " from " + currentValue);
-
-        mAnimator.setDuration((int) (Math.abs(currentValue - endValue) * ANIMATION_DURATION_MS));
-        mAnimator.setFloatValues(endValue);
-        mAnimator.start();
-    }
-
-    private void onAnimationFinished() {
-        if (DEBUG) Log.d(TAG, "onAnimationFinished");
-
-        if (mState == STATE_APPEARING) {
-            mState = STATE_SHOWN;
-        } else if (mState == STATE_DISAPPEARING) {
-            removeIndicatorView();
-            mState = STATE_NOT_SHOWN;
-        }
-    }
-
-    private boolean hasActiveRecorders() {
-        for (int index = mAudioActivityObservers.length - 1; index >= 0; index--) {
-            for (String activePackage : mAudioActivityObservers[index].getActivePackages()) {
-                if (mExemptPackages.contains(activePackage)) continue;
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private void removeIndicatorView() {
-        if (DEBUG) Log.d(TAG, "removeIndicatorView");
-
-        final WindowManager windowManager = (WindowManager) mContext.getSystemService(
-                Context.WINDOW_SERVICE);
-        windowManager.removeView(mIndicatorView);
-
-        mIndicatorView = null;
-        mAnimator = null;
-
-        mViewAndWindowAdded = false;
-    }
-
-    private static List<String> splitByComma(String string) {
-        return TextUtils.isEmpty(string) ? Collections.emptyList() : Arrays.asList(
-                string.split(","));
-    }
-
-    private final DeviceConfig.OnPropertiesChangedListener mConfigChangeListener =
-            new DeviceConfig.OnPropertiesChangedListener() {
-                @Override
-                public void onPropertiesChanged(DeviceConfig.Properties properties) {
-                    reloadExemptPackages();
-
-                    // Check if was enabled/disabled
-                    if (mIsEnabled != properties.getBoolean(ENABLED_FLAG, true)) {
-                        mIsEnabled = !mIsEnabled;
-                        if (mIsEnabled) {
-                            start();
-                        } else {
-                            stop();
-                        }
-                    }
-                }
-            };
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/MicrophoneForegroundServicesObserver.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/MicrophoneForegroundServicesObserver.java
deleted file mode 100644
index 8caf95f..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/MicrophoneForegroundServicesObserver.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.tv.micdisclosure;
-
-import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE;
-
-import static com.android.systemui.statusbar.tv.micdisclosure.AudioRecordingDisclosureBar.DEBUG;
-
-import android.annotation.UiThread;
-import android.app.ActivityManager;
-import android.app.IActivityManager;
-import android.app.IProcessObserver;
-import android.content.Context;
-import android.os.RemoteException;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.util.SparseArray;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * The purpose of these class is to detect packages that are running foreground services of type
- * 'microphone' and to report back to {@link AudioRecordingDisclosureBar}.
- */
-class MicrophoneForegroundServicesObserver extends AudioActivityObserver {
-    private static final String TAG = "MicrophoneForegroundServicesObserver";
-
-    private IActivityManager mActivityManager;
-    /**
-     * A dictionary that maps PIDs to the package names. We only keep track of the PIDs that are
-     * "active" (those that are running FGS with FOREGROUND_SERVICE_TYPE_MICROPHONE flag).
-     */
-    private final SparseArray<String[]> mPidToPackages = new SparseArray<>();
-    /**
-     * A dictionary that maps "active" packages to the number of the "active" processes associated
-     * with those packages. We really only need this in case when one application is running in
-     * multiple processes, so that we don't lose track of the package when one of its "active"
-     * processes ceases, while others remain "active".
-     */
-    private final Map<String, Integer> mPackageToProcessCount = new ArrayMap<>();
-
-    MicrophoneForegroundServicesObserver(Context context,
-            OnAudioActivityStateChangeListener listener) {
-        super(context, listener);
-    }
-
-    @Override
-    void start() {
-        mActivityManager = ActivityManager.getService();
-        try {
-            mActivityManager.registerProcessObserver(mProcessObserver);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Couldn't register process observer", e);
-        }
-    }
-
-    @Override
-    void stop() {
-        try {
-            mActivityManager.unregisterProcessObserver(mProcessObserver);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Couldn't unregister process observer", e);
-        }
-        mActivityManager = null;
-        mPackageToProcessCount.clear();
-    }
-
-    @Override
-    Set<String> getActivePackages() {
-        return mPackageToProcessCount.keySet();
-    }
-
-    @UiThread
-    private void onProcessForegroundServicesChanged(int pid, boolean hasMicFgs) {
-        final String[] changedPackages;
-        if (hasMicFgs) {
-            if (mPidToPackages.contains(pid)) {
-                // We are already tracking this pid - ignore.
-                changedPackages = null;
-            } else {
-                changedPackages = getPackageNames(pid);
-                mPidToPackages.append(pid, changedPackages);
-            }
-        } else {
-            changedPackages = mPidToPackages.removeReturnOld(pid);
-        }
-
-        if (changedPackages == null) {
-            return;
-        }
-
-        for (int index = changedPackages.length - 1; index >= 0; index--) {
-            final String packageName = changedPackages[index];
-            int processCount = mPackageToProcessCount.getOrDefault(packageName, 0);
-            final boolean shouldNotify;
-            if (hasMicFgs) {
-                processCount++;
-                shouldNotify = processCount == 1;
-            } else {
-                processCount--;
-                shouldNotify = processCount == 0;
-            }
-            if (processCount > 0) {
-                mPackageToProcessCount.put(packageName, processCount);
-            } else {
-                mPackageToProcessCount.remove(packageName);
-            }
-            if (shouldNotify) notifyPackageStateChanged(packageName, hasMicFgs);
-        }
-    }
-
-    @UiThread
-    private void onProcessDied(int pid) {
-        final String[] packages = mPidToPackages.removeReturnOld(pid);
-        if (packages == null) {
-            // This PID was not active - ignore.
-            return;
-        }
-
-        for (int index = packages.length - 1; index >= 0; index--) {
-            final String packageName = packages[index];
-            int processCount = mPackageToProcessCount.getOrDefault(packageName, 0);
-            if (processCount <= 0) {
-                Log.e(TAG, "Bookkeeping error, process count for " + packageName + " is "
-                        + processCount);
-                continue;
-            }
-            processCount--;
-            if (processCount > 0) {
-                mPackageToProcessCount.put(packageName, processCount);
-            } else {
-                mPackageToProcessCount.remove(packageName);
-                notifyPackageStateChanged(packageName, false);
-            }
-        }
-    }
-
-    @UiThread
-    private void notifyPackageStateChanged(String packageName, boolean active) {
-        if (DEBUG) {
-            Log.d(TAG, (active ? "New microphone fgs detected" : "Microphone fgs is gone")
-                    + ", package=" + packageName);
-        }
-
-        mListener.onAudioActivityStateChange(active, packageName);
-    }
-
-    @UiThread
-    private String[] getPackageNames(int pid) {
-        final List<ActivityManager.RunningAppProcessInfo> runningApps;
-        try {
-            runningApps = mActivityManager.getRunningAppProcesses();
-        } catch (RemoteException e) {
-            Log.d(TAG, "Couldn't get package name for pid=" + pid);
-            return null;
-        }
-        if (runningApps == null) {
-            Log.wtf(TAG, "No running apps reported");
-        }
-        for (ActivityManager.RunningAppProcessInfo app : runningApps) {
-            if (app.pid == pid) {
-                return app.pkgList;
-            }
-        }
-        return null;
-    }
-
-    private final IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
-        @Override
-        public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {}
-
-        @Override
-        public void onForegroundServicesChanged(int pid, int uid, int serviceTypes) {
-            mContext.getMainExecutor().execute(() -> onProcessForegroundServicesChanged(pid,
-                    (serviceTypes & FOREGROUND_SERVICE_TYPE_MICROPHONE) != 0));
-        }
-
-        @Override
-        public void onProcessDied(int pid, int uid) {
-            mContext.getMainExecutor().execute(
-                    () -> MicrophoneForegroundServicesObserver.this.onProcessDied(pid));
-        }
-    };
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/RecordAudioAppOpObserver.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/RecordAudioAppOpObserver.java
deleted file mode 100644
index 9a2b4a9..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/RecordAudioAppOpObserver.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.tv.micdisclosure;
-
-import static com.android.systemui.statusbar.tv.micdisclosure.AudioRecordingDisclosureBar.DEBUG;
-
-import android.annotation.UiThread;
-import android.app.AppOpsManager;
-import android.content.Context;
-import android.util.ArraySet;
-import android.util.Log;
-
-import java.util.Set;
-
-/**
- * The purpose of these class is to detect packages that are conducting audio recording (according
- * to {@link AppOpsManager}) and report this to {@link AudioRecordingDisclosureBar}.
- */
-class RecordAudioAppOpObserver extends AudioActivityObserver implements
-        AppOpsManager.OnOpActiveChangedListener {
-    private static final String TAG = "RecordAudioAppOpObserver";
-
-    /**
-     * Set of the applications that currently are conducting audio recording according to {@link
-     * AppOpsManager}.
-     */
-    private final Set<String> mActiveAudioRecordingPackages = new ArraySet<>();
-
-    RecordAudioAppOpObserver(Context context, OnAudioActivityStateChangeListener listener) {
-        super(context, listener);
-    }
-
-    @Override
-    void start() {
-        if (DEBUG) {
-            Log.d(TAG, "Start");
-        }
-
-        // Register AppOpsManager callback
-        mContext.getSystemService(AppOpsManager.class)
-                .startWatchingActive(
-                        new String[]{AppOpsManager.OPSTR_RECORD_AUDIO},
-                        mContext.getMainExecutor(),
-                        this);
-    }
-
-    @Override
-    void stop() {
-        if (DEBUG) {
-            Log.d(TAG, "Stop");
-        }
-
-        // Unregister AppOpsManager callback
-        mContext.getSystemService(AppOpsManager.class).stopWatchingActive(this);
-
-        // Clean up state
-        mActiveAudioRecordingPackages.clear();
-    }
-
-    @UiThread
-    @Override
-    Set<String> getActivePackages() {
-        return mActiveAudioRecordingPackages;
-    }
-
-    @UiThread
-    @Override
-    public void onOpActiveChanged(String op, int uid, String packageName, boolean active) {
-        if (DEBUG) {
-            Log.d(TAG,
-                    "OP_RECORD_AUDIO active change, active=" + active + ", package="
-                            + packageName);
-        }
-
-        if (active) {
-            if (mActiveAudioRecordingPackages.add(packageName)) {
-                mListener.onAudioActivityStateChange(true, packageName);
-            }
-        } else {
-            if (mActiveAudioRecordingPackages.remove(packageName)) {
-                mListener.onAudioActivityStateChange(false, packageName);
-            }
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
index 0a3e833..bbb2f1a 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
@@ -94,6 +94,7 @@
      */
     static final List<String> THEME_CATEGORIES = Lists.newArrayList(
             OVERLAY_CATEGORY_SYSTEM_PALETTE,
+            OVERLAY_CATEGORY_NEUTRAL_PALETTE,
             OVERLAY_CATEGORY_ICON_LAUNCHER,
             OVERLAY_CATEGORY_SHAPE,
             OVERLAY_CATEGORY_FONT,
@@ -107,6 +108,7 @@
     @VisibleForTesting
     static final Set<String> SYSTEM_USER_CATEGORIES = Sets.newHashSet(
             OVERLAY_CATEGORY_SYSTEM_PALETTE,
+            OVERLAY_CATEGORY_NEUTRAL_PALETTE,
             OVERLAY_CATEGORY_ACCENT_COLOR,
             OVERLAY_CATEGORY_FONT,
             OVERLAY_CATEGORY_SHAPE,
@@ -129,8 +131,9 @@
         mLauncherPackage = launcherPackage;
         mThemePickerPackage = themePickerPackage;
         mTargetPackageToCategories.put(ANDROID_PACKAGE, Sets.newHashSet(
-                OVERLAY_CATEGORY_SYSTEM_PALETTE, OVERLAY_CATEGORY_ACCENT_COLOR,
-                OVERLAY_CATEGORY_FONT, OVERLAY_CATEGORY_SHAPE, OVERLAY_CATEGORY_ICON_ANDROID));
+                OVERLAY_CATEGORY_SYSTEM_PALETTE, OVERLAY_CATEGORY_NEUTRAL_PALETTE,
+                OVERLAY_CATEGORY_ACCENT_COLOR, OVERLAY_CATEGORY_FONT, OVERLAY_CATEGORY_SHAPE,
+                OVERLAY_CATEGORY_ICON_ANDROID));
         mTargetPackageToCategories.put(SYSUI_PACKAGE,
                 Sets.newHashSet(OVERLAY_CATEGORY_ICON_SYSUI));
         mTargetPackageToCategories.put(SETTINGS_PACKAGE,
@@ -158,10 +161,10 @@
     void applyCurrentUserOverlays(
             Map<String, OverlayIdentifier> categoryToPackage,
             FabricatedOverlay[] pendingCreation,
-            Set<UserHandle> userHandles) {
+            int currentUser,
+            Set<UserHandle> managedProfiles) {
         // Disable all overlays that have not been specified in the user setting.
         final Set<String> overlayCategoriesToDisable = new HashSet<>(THEME_CATEGORIES);
-        overlayCategoriesToDisable.removeAll(categoryToPackage.keySet());
         final Set<String> targetPackagesToQuery = overlayCategoriesToDisable.stream()
                 .map(category -> mCategoryToTargetPackage.get(category))
                 .collect(Collectors.toSet());
@@ -172,6 +175,7 @@
                 .filter(o ->
                         mTargetPackageToCategories.get(o.targetPackageName).contains(o.category))
                 .filter(o -> overlayCategoriesToDisable.contains(o.category))
+                .filter(o -> !categoryToPackage.containsValue(new OverlayIdentifier(o.packageName)))
                 .filter(o -> o.isEnabled())
                 .map(o -> new Pair<>(o.category, o.packageName))
                 .collect(Collectors.toList());
@@ -183,17 +187,18 @@
             }
         }
 
-        // Toggle overlays in the order of THEME_CATEGORIES.
+        for (Pair<String, String> packageToDisable : overlaysToDisable) {
+            OverlayIdentifier overlayInfo = new OverlayIdentifier(packageToDisable.second);
+            setEnabled(transaction, overlayInfo, packageToDisable.first, currentUser,
+                    managedProfiles, false);
+        }
+
         for (String category : THEME_CATEGORIES) {
             if (categoryToPackage.containsKey(category)) {
                 OverlayIdentifier overlayInfo = categoryToPackage.get(category);
-                setEnabled(transaction, overlayInfo, category, userHandles, true);
+                setEnabled(transaction, overlayInfo, category, currentUser, managedProfiles, true);
             }
         }
-        for (Pair<String, String> packageToDisable : overlaysToDisable) {
-            OverlayIdentifier overlayInfo = new OverlayIdentifier(packageToDisable.second);
-            setEnabled(transaction, overlayInfo, packageToDisable.first, userHandles, false);
-        }
 
         mExecutor.execute(() -> {
             try {
@@ -210,18 +215,30 @@
     }
 
     private void setEnabled(OverlayManagerTransaction.Builder transaction,
-            OverlayIdentifier identifier, String category, Set<UserHandle> handles,
-            boolean enabled) {
+            OverlayIdentifier identifier, String category, int currentUser,
+            Set<UserHandle> managedProfiles, boolean enabled) {
         if (DEBUG) {
             Log.d(TAG, "setEnabled: " + identifier.getPackageName() + " category: "
                     + category + ": " + enabled);
         }
-        for (UserHandle userHandle : handles) {
-            transaction.setEnabled(identifier, enabled, userHandle.getIdentifier());
-        }
-        if (!handles.contains(UserHandle.SYSTEM) && SYSTEM_USER_CATEGORIES.contains(category)) {
+
+        transaction.setEnabled(identifier, enabled, currentUser);
+        if (currentUser != UserHandle.SYSTEM.getIdentifier()
+                && SYSTEM_USER_CATEGORIES.contains(category)) {
             transaction.setEnabled(identifier, enabled, UserHandle.SYSTEM.getIdentifier());
         }
+
+        // Do not apply Launcher or Theme picker overlays to managed users. Apps are not
+        // installed in there.
+        OverlayInfo overlayInfo = mOverlayManager.getOverlayInfo(identifier, UserHandle.SYSTEM);
+        if (overlayInfo == null || overlayInfo.targetPackageName.equals(mLauncherPackage)
+                || overlayInfo.targetPackageName.equals(mThemePickerPackage)) {
+            return;
+        }
+
+        for (UserHandle userHandle : managedProfiles) {
+            transaction.setEnabled(identifier, enabled, userHandle.getIdentifier());
+        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index 1f222d8..5d02845 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -55,14 +55,13 @@
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.settings.SecureSettings;
 
-import com.google.android.collect.Sets;
-
 import org.json.JSONException;
 import org.json.JSONObject;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.Collection;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.Executor;
@@ -86,7 +85,7 @@
 
     protected static final int PRIMARY = 0;
     protected static final int SECONDARY = 1;
-    protected static final int NEUTRAL = 1;
+    protected static final int NEUTRAL = 2;
 
     // If lock screen wallpaper colors should also be considered when selecting the theme.
     // Doing this has performance impact, given that overlays would need to be swapped when
@@ -151,7 +150,7 @@
             @Override
             public void onReceive(Context context, Intent intent) {
                 if (DEBUG) Log.d(TAG, "Updating overlays for user switch / profile added.");
-                updateThemeOverlays();
+                reevaluateSystemTheme(true /* forceReload */);
             }
         }, filter, mBgExecutor, UserHandle.ALL);
         mSecureSettings.registerContentObserverForUser(
@@ -163,7 +162,7 @@
                             int userId) {
                         if (DEBUG) Log.d(TAG, "Overlay changed for user: " + userId);
                         if (ActivityManager.getCurrentUser() == userId) {
-                            updateThemeOverlays();
+                            reevaluateSystemTheme(true /* forceReload */);
                         }
                     }
                 },
@@ -180,7 +179,7 @@
                     mLockColors = lockColors;
                 }
                 mSystemColors = systemColor;
-                reevaluateSystemTheme();
+                reevaluateSystemTheme(false /* forceReload */);
             });
         });
         if (USE_LOCK_SCREEN_WALLPAPER) {
@@ -192,7 +191,7 @@
                     }
                     // It's possible that the user has a lock screen wallpaper. On this case we'll
                     // end up with different colors after unlocking.
-                    reevaluateSystemTheme();
+                    reevaluateSystemTheme(false /* forceReload */);
                 }
             });
         }
@@ -209,11 +208,11 @@
                     Log.d(TAG, "got new lock colors: " + wallpaperColors + " where: " + which);
                 }
             }
-            reevaluateSystemTheme();
+            reevaluateSystemTheme(false /* forceReload */);
         }, null, UserHandle.USER_ALL);
     }
 
-    private void reevaluateSystemTheme() {
+    private void reevaluateSystemTheme(boolean forceReload) {
         WallpaperColors currentColors =
                 mKeyguardStateController.isShowing() && mLockColors != null
                         ? mLockColors : mSystemColors;
@@ -228,7 +227,8 @@
             accentCandidate = getAccentColor(currentColors);
         }
 
-        if (mMainWallpaperColor == mainColor && mWallpaperAccentColor == accentCandidate) {
+        if (mMainWallpaperColor == mainColor && mWallpaperAccentColor == accentCandidate
+                && !forceReload) {
             return;
         }
 
@@ -309,6 +309,16 @@
             } catch (NumberFormatException e) {
                 Log.w(TAG, "Invalid color definition: " + systemPalette.getPackageName());
             }
+        } else if (!mIsMonetEnabled && systemPalette != null) {
+            try {
+                // It's possible that we flipped the flag off and still have a @ColorInt in the
+                // setting. We need to sanitize the input, otherwise the overlay transaction will
+                // fail.
+                Integer.parseInt(systemPalette.getPackageName().toLowerCase(), 16);
+                categoryToPackage.remove(OVERLAY_CATEGORY_SYSTEM_PALETTE);
+            } catch (NumberFormatException e) {
+                // This is a package name. All good, let's continue
+            }
         }
 
         // Same for accent color.
@@ -322,6 +332,13 @@
             } catch (NumberFormatException e) {
                 Log.w(TAG, "Invalid color definition: " + accentPalette.getPackageName());
             }
+        } else if (!mIsMonetEnabled && accentPalette != null) {
+            try {
+                Integer.parseInt(accentPalette.getPackageName().toLowerCase(), 16);
+                categoryToPackage.remove(OVERLAY_CATEGORY_ACCENT_COLOR);
+            } catch (NumberFormatException e) {
+                // This is a package name. All good, let's continue
+            }
         }
 
         // Compatibility with legacy themes, where full packages were defined, instead of just
@@ -337,10 +354,10 @@
             categoryToPackage.put(OVERLAY_CATEGORY_ACCENT_COLOR, mSecondaryOverlay.getIdentifier());
         }
 
-        Set<UserHandle> userHandles = Sets.newHashSet(UserHandle.of(currentUser));
+        Set<UserHandle> managedProfiles = new HashSet<>();
         for (UserInfo userInfo : mUserManager.getEnabledProfiles(currentUser)) {
             if (userInfo.isManagedProfile()) {
-                userHandles.add(userInfo.getUserHandle());
+                managedProfiles.add(userInfo.getUserHandle());
             }
         }
         if (DEBUG) {
@@ -352,9 +369,10 @@
             mNeedsOverlayCreation = false;
             mThemeManager.applyCurrentUserOverlays(categoryToPackage, new FabricatedOverlay[] {
                     mPrimaryOverlay, mSecondaryOverlay, mNeutralOverlay
-            }, userHandles);
+            }, currentUser, managedProfiles);
         } else {
-            mThemeManager.applyCurrentUserOverlays(categoryToPackage, null, userHandles);
+            mThemeManager.applyCurrentUserOverlays(categoryToPackage, null, currentUser,
+                    managedProfiles);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java b/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java
index 365cd2a..fab1655 100644
--- a/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java
+++ b/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java
@@ -187,10 +187,7 @@
             mPluginToast.onOrientationChange(orientation);
         }
 
-        mDefaultY = mContext.getResources().getDimensionPixelSize(
-                mToastStyleEnabled
-                        ? com.android.systemui.R.dimen.toast_y_offset
-                        : R.dimen.toast_y_offset);
+        mDefaultY = mContext.getResources().getDimensionPixelSize(R.dimen.toast_y_offset);
         mDefaultGravity =
                 mContext.getResources().getInteger(R.integer.config_toastDefaultGravity);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
index 78341ed..5b66216 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
@@ -43,11 +43,13 @@
     private static final String TAG_TUNER = "tuner";
 
     private final DemoModeController mDemoModeController;
+    private final TunerService mTunerService;
 
     @Inject
-    TunerActivity(DemoModeController demoModeController) {
+    TunerActivity(DemoModeController demoModeController, TunerService tunerService) {
         super();
         mDemoModeController = demoModeController;
+        mTunerService = tunerService;
     }
 
     protected void onCreate(Bundle savedInstanceState) {
@@ -67,7 +69,7 @@
                     "com.android.settings.action.DEMO_MODE");
             final PreferenceFragment fragment = showDemoMode
                     ? new DemoModeFragment(mDemoModeController)
-                    : new TunerFragment();
+                    : new TunerFragment(mTunerService);
             getFragmentManager().beginTransaction().replace(R.id.content_frame,
                     fragment, TAG_TUNER).commit();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index 4c724ae..989462a 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -15,7 +15,7 @@
  */
 package com.android.systemui.tuner;
 
-import android.app.ActivityManager;
+import android.annotation.SuppressLint;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
@@ -23,7 +23,6 @@
 import android.hardware.display.AmbientDisplayConfiguration;
 import android.os.Build;
 import android.os.Bundle;
-import android.os.UserHandle;
 import android.provider.Settings;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -56,6 +55,15 @@
 
     private static final int MENU_REMOVE = Menu.FIRST + 1;
 
+    private final TunerService mTunerService;
+
+    // We are the only ones who ever call this constructor, so don't worry about the warning
+    @SuppressLint("ValidFragment")
+    public TunerFragment(TunerService tunerService) {
+        super();
+        mTunerService = tunerService;
+    }
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -124,13 +132,9 @@
                 getActivity().finish();
                 return true;
             case MENU_REMOVE:
-                UserHandle user = new UserHandle(ActivityManager.getCurrentUser());
-                TunerService.showResetRequest(getContext(), user, new Runnable() {
-                    @Override
-                    public void run() {
-                        if (getActivity() != null) {
-                            getActivity().finish();
-                        }
+                mTunerService.showResetRequest(() -> {
+                    if (getActivity() != null) {
+                        getActivity().finish();
                     }
                 });
                 return true;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
index b67574d..5d09e06 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -15,19 +15,10 @@
 package com.android.systemui.tuner;
 
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
 import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
 import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.UserHandle;
-import android.provider.Settings;
 
 import com.android.systemui.Dependency;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.SystemUIDialog;
 
 public abstract class TunerService {
 
@@ -47,6 +38,16 @@
     public abstract void addTunable(Tunable tunable, String... keys);
     public abstract void removeTunable(Tunable tunable);
 
+    /**
+     * Sets the state of the {@link TunerActivity} component for the current user
+     */
+    public abstract void setTunerEnabled(boolean enabled);
+
+    /**
+     * Returns true if the tuner is enabled for the current user.
+     */
+    public abstract boolean isTunerEnabled();
+
     public interface Tunable {
         void onTuningChanged(String key, String newValue);
     }
@@ -55,38 +56,6 @@
         mContext = context;
     }
 
-    private static Context userContext(Context context, UserHandle user) {
-        try {
-            return context.createPackageContextAsUser(context.getPackageName(), 0, user);
-        } catch (NameNotFoundException e) {
-            return context;
-        }
-    }
-
-    /** Enables or disables the tuner for the supplied user. */
-    public void setTunerEnabled(UserHandle user, boolean enabled) {
-        setTunerEnabled(mContext, user, enabled);
-    }
-
-    public static final void setTunerEnabled(Context context, UserHandle user, boolean enabled) {
-        userContext(context, user).getPackageManager().setComponentEnabledSetting(
-                new ComponentName(context, TunerActivity.class),
-                enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
-                        : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
-                PackageManager.DONT_KILL_APP);
-    }
-
-    /** Returns true if the tuner is enabled for the supplied user. */
-    public boolean isTunerEnabled(UserHandle user) {
-        return isTunerEnabled(mContext, user);
-    }
-
-    public static final boolean isTunerEnabled(Context context, UserHandle user) {
-        return userContext(context, user).getPackageManager().getComponentEnabledSetting(
-                new ComponentName(context, TunerActivity.class))
-                == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
-    }
-
     public static class ClearReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -97,35 +66,7 @@
     }
 
     /** */
-    public void showResetRequest(UserHandle user, final Runnable onDisabled) {
-        showResetRequest(mContext, user, onDisabled);
-    }
-
-    public static final void showResetRequest(final Context context, UserHandle user,
-            final Runnable onDisabled) {
-        SystemUIDialog dialog = new SystemUIDialog(context);
-        dialog.setShowForAllUsers(true);
-        dialog.setMessage(R.string.remove_from_settings_prompt);
-        dialog.setButton(DialogInterface.BUTTON_NEGATIVE, context.getString(R.string.cancel),
-                (OnClickListener) null);
-        dialog.setButton(DialogInterface.BUTTON_POSITIVE,
-                context.getString(R.string.guest_exit_guest_dialog_remove), new OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int which) {
-                        // Tell the tuner (in main SysUI process) to clear all its settings.
-                        context.sendBroadcast(new Intent(TunerService.ACTION_CLEAR));
-                        // Disable access to tuner.
-                        TunerService.setTunerEnabled(context, user, false);
-                        // Make them sit through the warning dialog again.
-                        Settings.Secure.putInt(context.getContentResolver(),
-                                TunerFragment.SETTING_SEEN_TUNER_WARNING, 0);
-                        if (onDisabled != null) {
-                            onDisabled.run();
-                        }
-                    }
-                });
-        dialog.show();
-    }
+    public abstract void showResetRequest(Runnable onDisabled);
 
     public static boolean parseIntegerSwitch(String value, boolean defaultValue) {
         try {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index 027c282b..e9e4380 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -15,8 +15,12 @@
  */
 package com.android.systemui.tuner;
 
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.database.ContentObserver;
 import android.net.Uri;
@@ -32,13 +36,14 @@
 
 import com.android.internal.util.ArrayUtils;
 import com.android.systemui.DejankUtils;
-import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.demomode.DemoModeController;
 import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.util.leak.LeakDetector;
 
 import java.util.HashSet;
@@ -83,6 +88,7 @@
     private int mCurrentUser;
     private UserTracker.Callback mCurrentUserTracker;
     private UserTracker mUserTracker;
+    private final ComponentName mTunerComponent;
 
     /**
      */
@@ -92,7 +98,6 @@
             @Main Handler mainHandler,
             LeakDetector leakDetector,
             DemoModeController demoModeController,
-            BroadcastDispatcher broadcastDispatcher,
             UserTracker userTracker) {
         super(context);
         mContext = context;
@@ -100,6 +105,7 @@
         mLeakDetector = leakDetector;
         mDemoModeController = demoModeController;
         mUserTracker = userTracker;
+        mTunerComponent = new ComponentName(mContext, TunerActivity.class);
 
         for (UserInfo user : UserManager.get(mContext).getUsers()) {
             mCurrentUser = user.getUserHandle().getIdentifier();
@@ -142,7 +148,7 @@
             }
         }
         if (oldVersion < 2) {
-            setTunerEnabled(mContext, mUserTracker.getUserHandle(), false);
+            setTunerEnabled(false);
         }
         // 3 Removed because of a revert.
         if (oldVersion < 4) {
@@ -269,6 +275,46 @@
         }
     }
 
+
+    @Override
+    public void setTunerEnabled(boolean enabled) {
+        mUserTracker.getUserContext().getPackageManager().setComponentEnabledSetting(
+                mTunerComponent,
+                enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+                        : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                PackageManager.DONT_KILL_APP
+        );
+    }
+
+    @Override
+    public boolean isTunerEnabled() {
+        return mUserTracker.getUserContext().getPackageManager().getComponentEnabledSetting(
+                mTunerComponent) == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+    }
+
+    @Override
+    public void showResetRequest(Runnable onDisabled) {
+        SystemUIDialog dialog = new SystemUIDialog(mContext);
+        dialog.setShowForAllUsers(true);
+        dialog.setMessage(R.string.remove_from_settings_prompt);
+        dialog.setButton(DialogInterface.BUTTON_NEGATIVE, mContext.getString(R.string.cancel),
+                (DialogInterface.OnClickListener) null);
+        dialog.setButton(DialogInterface.BUTTON_POSITIVE,
+                mContext.getString(R.string.guest_exit_guest_dialog_remove), (d, which) -> {
+                    // Tell the tuner (in main SysUI process) to clear all its settings.
+                    mContext.sendBroadcast(new Intent(TunerService.ACTION_CLEAR));
+                    // Disable access to tuner.
+                    setTunerEnabled(false);
+                    // Make them sit through the warning dialog again.
+                    Secure.putInt(mContext.getContentResolver(),
+                            TunerFragment.SETTING_SEEN_TUNER_WARNING, 0);
+                    if (onDisabled != null) {
+                        onDisabled.run();
+                    }
+                });
+        dialog.show();
+    }
+
     private class Observer extends ContentObserver {
         public Observer() {
             super(new Handler(Looper.getMainLooper()));
diff --git a/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java b/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java
index 79a197d..a22793b 100644
--- a/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java
@@ -16,15 +16,18 @@
 
 package com.android.systemui.util;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
 import android.graphics.drawable.DrawableWrapper;
+import android.graphics.drawable.InsetDrawable;
 import android.util.AttributeSet;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 import com.android.systemui.R;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -45,13 +48,18 @@
  * @attr ref R.styleable#AlphaTintDrawableWrapper_tint
  * @attr ref R.styleable#AlphaTintDrawableWrapper_alpha
  */
-public class AlphaTintDrawableWrapper extends DrawableWrapper {
+public class AlphaTintDrawableWrapper extends InsetDrawable {
     private ColorStateList mTint;
     private int[] mThemeAttrs;
 
     /** No-arg constructor used by drawable inflation. */
     public AlphaTintDrawableWrapper() {
-        super(null);
+        super(null, 0);
+    }
+
+    AlphaTintDrawableWrapper(Drawable drawable, int[] themeAttrs) {
+        super(drawable, 0);
+        mThemeAttrs = themeAttrs;
     }
 
     @Override
@@ -74,7 +82,7 @@
     public void applyTheme(Theme t) {
         super.applyTheme(t);
 
-        if (mThemeAttrs != null) {
+        if (mThemeAttrs != null && t != null) {
             final TypedArray a = t.resolveAttributes(mThemeAttrs,
                     R.styleable.AlphaTintDrawableWrapper);
             updateStateFromTypedArray(a);
@@ -92,9 +100,6 @@
     }
 
     private void updateStateFromTypedArray(@NonNull TypedArray a) {
-        if (a.hasValue(R.styleable.AlphaTintDrawableWrapper_android_drawable)) {
-            setDrawable(a.getDrawable(R.styleable.AlphaTintDrawableWrapper_android_drawable));
-        }
         if (a.hasValue(R.styleable.AlphaTintDrawableWrapper_android_tint)) {
             mTint = a.getColorStateList(R.styleable.AlphaTintDrawableWrapper_android_tint);
         }
@@ -109,4 +114,57 @@
             getDrawable().mutate().setTintList(mTint);
         }
     }
+
+    @Nullable
+    @Override
+    public ConstantState getConstantState() {
+        return new AlphaTintState(super.getConstantState(), mThemeAttrs, getAlpha(), mTint);
+    }
+
+    static class AlphaTintState extends Drawable.ConstantState {
+
+        private ConstantState mWrappedState;
+        private int[] mThemeAttrs;
+        private int mAlpha;
+        private ColorStateList mColorStateList;
+
+        AlphaTintState(
+                ConstantState wrappedState,
+                int[] themeAttrs,
+                int alpha,
+                ColorStateList colorStateList
+        ) {
+            mWrappedState = wrappedState;
+            mThemeAttrs = themeAttrs;
+            mAlpha = alpha;
+            mColorStateList = colorStateList;
+        }
+
+        @NonNull
+        @Override
+        public Drawable newDrawable() {
+            return newDrawable(null, null);
+        }
+
+        @NonNull
+        @Override
+        public Drawable newDrawable(Resources res, Theme theme) {
+            DrawableWrapper wrapper = (DrawableWrapper) mWrappedState.newDrawable(res, theme);
+            AlphaTintDrawableWrapper alphaTintDrawableWrapper =
+                    new AlphaTintDrawableWrapper(wrapper.getDrawable(), mThemeAttrs);
+            alphaTintDrawableWrapper.setTintList(mColorStateList);
+            alphaTintDrawableWrapper.setAlpha(mAlpha);
+            return alphaTintDrawableWrapper;
+        }
+
+        @Override
+        public boolean canApplyTheme() {
+            return true;
+        }
+
+        @Override
+        public int getChangingConfigurations() {
+            return mWrappedState.getChangingConfigurations();
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/util/RoundedCornerProgressDrawable.kt b/packages/SystemUI/src/com/android/systemui/util/RoundedCornerProgressDrawable.kt
index 1af2c9f..6aadd10 100644
--- a/packages/SystemUI/src/com/android/systemui/util/RoundedCornerProgressDrawable.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/RoundedCornerProgressDrawable.kt
@@ -17,15 +17,12 @@
 package com.android.systemui.util
 
 import android.content.res.Resources
-import android.content.res.TypedArray
 import android.graphics.Canvas
 import android.graphics.Path
 import android.graphics.Rect
 import android.graphics.drawable.Drawable
 import android.graphics.drawable.DrawableWrapper
-import android.util.AttributeSet
-import com.android.systemui.R
-import org.xmlpull.v1.XmlPullParser
+import android.graphics.drawable.InsetDrawable
 
 /**
  * [DrawableWrapper] to use in the progress of a slider.
@@ -38,9 +35,9 @@
  * is meant to be smaller than the rounded corner. The background should have rounded corners that
  * are half of the height.
  */
-class RoundedCornerProgressDrawable(drawable: Drawable?) : DrawableWrapper(drawable) {
-
-    constructor() : this(null)
+class RoundedCornerProgressDrawable @JvmOverloads constructor(
+    drawable: Drawable? = null
+) : InsetDrawable(drawable, 0) {
 
     companion object {
         private const val MAX_LEVEL = 10000 // Taken from Drawable
@@ -52,35 +49,11 @@
         setClipPath(Rect())
     }
 
-    override fun inflate(
-        r: Resources,
-        parser: XmlPullParser,
-        attrs: AttributeSet,
-        theme: Resources.Theme?
-    ) {
-        val a = obtainAttributes(r, theme, attrs, R.styleable.RoundedCornerProgressDrawable)
-
-        // Inflation will advance the XmlPullParser and AttributeSet.
-        super.inflate(r, parser, attrs, theme)
-
-        updateStateFromTypedArray(a)
-        if (drawable == null) {
-            throw IllegalStateException("${this::class.java.simpleName} needs a drawable")
-        }
-        a.recycle()
-    }
-
     override fun onLayoutDirectionChanged(layoutDirection: Int): Boolean {
         onLevelChange(level)
         return super.onLayoutDirectionChanged(layoutDirection)
     }
 
-    private fun updateStateFromTypedArray(a: TypedArray) {
-        if (a.hasValue(R.styleable.RoundedCornerProgressDrawable_android_drawable)) {
-            setDrawable(a.getDrawable(R.styleable.RoundedCornerProgressDrawable_android_drawable))
-        }
-    }
-
     override fun onBoundsChange(bounds: Rect) {
         setClipPath(bounds)
         super.onBoundsChange(bounds)
@@ -115,4 +88,24 @@
         super.draw(canvas)
         canvas.restore()
     }
+
+    override fun getConstantState(): ConstantState? {
+        // This should not be null as it was created with a state in the constructor.
+        return RoundedCornerState(super.getConstantState()!!)
+    }
+
+    private class RoundedCornerState(private val wrappedState: ConstantState) : ConstantState() {
+        override fun newDrawable(): Drawable {
+            return newDrawable(null, null)
+        }
+
+        override fun newDrawable(res: Resources?, theme: Resources.Theme?): Drawable {
+            val wrapper = wrappedState.newDrawable(res, theme) as DrawableWrapper
+            return RoundedCornerProgressDrawable(wrapper.drawable)
+        }
+
+        override fun getChangingConfigurations(): Int {
+            return wrappedState.changingConfigurations
+        }
+    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
index 06806d0..6a648bd 100644
--- a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
@@ -347,6 +347,7 @@
         public void check(long timeoutMs, Consumer<Boolean> callback) {
             if (!mSensor.isLoaded()) {
                 callback.accept(null);
+                return;
             }
             mCallbacks.add(callback);
             if (!mRegistered.getAndSet(true)) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index df54eab..25345d5 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -33,7 +33,11 @@
 
 import static com.android.systemui.volume.Events.DISMISS_REASON_SETTINGS_CLICKED;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ArgbEvaluator;
 import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
 import android.annotation.SuppressLint;
 import android.app.ActivityManager;
 import android.app.Dialog;
@@ -51,6 +55,9 @@
 import android.graphics.PixelFormat;
 import android.graphics.Region;
 import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.graphics.drawable.RotateDrawable;
 import android.media.AudioManager;
 import android.media.AudioSystem;
 import android.os.Debug;
@@ -81,6 +88,8 @@
 import android.view.animation.DecelerateInterpolator;
 import android.widget.FrameLayout;
 import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
 import android.widget.SeekBar;
 import android.widget.SeekBar.OnSeekBarChangeListener;
 import android.widget.TextView;
@@ -88,6 +97,7 @@
 
 import com.android.settingslib.Utils;
 import com.android.systemui.Dependency;
+import com.android.systemui.Interpolators;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.media.dialog.MediaOutputDialogFactory;
@@ -99,6 +109,8 @@
 import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.util.AlphaTintDrawableWrapper;
+import com.android.systemui.util.RoundedCornerProgressDrawable;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -124,8 +136,14 @@
     static final int DIALOG_ODI_CAPTIONS_TOOLTIP_TIMEOUT_MILLIS = 5000;
     static final int DIALOG_HOVERING_TIMEOUT_MILLIS = 16000;
 
+    private static final int DRAWER_ANIMATION_DURATION_SHORT = 175;
+    private static final int DRAWER_ANIMATION_DURATION = 250;
+
     private final int mDialogShowAnimationDurationMs;
     private final int mDialogHideAnimationDurationMs;
+    private final int mRingerDrawerItemSize;
+    private final boolean mShowVibrate;
+    private final int mRingerCount;
     private final boolean mShowLowMediaVolumeIcon;
     private final boolean mChangeVolumeRowTintWhenInactive;
 
@@ -140,6 +158,30 @@
     private ViewGroup mDialogView;
     private ViewGroup mDialogRowsView;
     private ViewGroup mRinger;
+
+    private ViewGroup mSelectedRingerContainer;
+    private ImageView mSelectedRingerIcon;
+
+    private ViewGroup mRingerDrawerContainer;
+    private ViewGroup mRingerDrawerMute;
+    private ViewGroup mRingerDrawerVibrate;
+    private ViewGroup mRingerDrawerNormal;
+    private ImageView mRingerDrawerMuteIcon;
+    private ImageView mRingerDrawerVibrateIcon;
+    private ImageView mRingerDrawerNormalIcon;
+
+    /**
+     * View that draws the 'selected' background behind one of the three ringer choices in the
+     * drawer.
+     */
+    private ViewGroup mRingerDrawerNewSelectionBg;
+
+    private final ValueAnimator mRingerDrawerIconColorAnimator = ValueAnimator.ofFloat(0f, 1f);
+    private ImageView mRingerDrawerIconAnimatingSelected;
+    private ImageView mRingerDrawerIconAnimatingDeselected;
+
+    private boolean mIsRingerDrawerOpen = false;
+
     private ImageButton mRingerIcon;
     private ViewGroup mODICaptionsView;
     private CaptionsToggleImageButton mODICaptionsIcon;
@@ -191,6 +233,12 @@
             mContext.getResources().getInteger(R.integer.config_dialogShowAnimationDurationMs);
         mDialogHideAnimationDurationMs =
             mContext.getResources().getInteger(R.integer.config_dialogHideAnimationDurationMs);
+        mRingerDrawerItemSize = mContext.getResources().getDimensionPixelSize(
+                R.dimen.volume_ringer_drawer_item_size);
+        mShowVibrate = mController.hasVibrator();
+
+        // Normal, mute, and possibly vibrate.
+        mRingerCount = mShowVibrate ? 3 : 2;
     }
 
     @Override
@@ -314,6 +362,20 @@
             mZenIcon = mRinger.findViewById(R.id.dnd_icon);
         }
 
+        mSelectedRingerIcon = mDialog.findViewById(R.id.volume_new_ringer_active_icon);
+        mSelectedRingerContainer = mDialog.findViewById(
+                R.id.volume_new_ringer_active_icon_container);
+
+        mRingerDrawerMute = mDialog.findViewById(R.id.volume_drawer_mute);
+        mRingerDrawerNormal = mDialog.findViewById(R.id.volume_drawer_normal);
+        mRingerDrawerVibrate = mDialog.findViewById(R.id.volume_drawer_vibrate);
+        mRingerDrawerMuteIcon = mDialog.findViewById(R.id.volume_drawer_mute_icon);
+        mRingerDrawerVibrateIcon = mDialog.findViewById(R.id.volume_drawer_vibrate_icon);
+        mRingerDrawerNormalIcon = mDialog.findViewById(R.id.volume_drawer_normal_icon);
+        mRingerDrawerNewSelectionBg = mDialog.findViewById(R.id.volume_drawer_selection_background);
+
+        setupRingerDrawer();
+
         mODICaptionsView = mDialog.findViewById(R.id.odi_captions);
         if (mODICaptionsView != null) {
             mODICaptionsIcon = mODICaptionsView.findViewById(R.id.odi_captions_icon);
@@ -475,40 +537,275 @@
 
         row.anim = null;
 
+        final LayerDrawable seekbarDrawable =
+                (LayerDrawable) mContext.getDrawable(R.drawable.volume_row_seekbar);
+
+        final LayerDrawable seekbarBgDrawable =
+                (LayerDrawable) seekbarDrawable.findDrawableByLayerId(android.R.id.background);
+
+        row.sliderBgSolid = seekbarBgDrawable.findDrawableByLayerId(
+                R.id.volume_seekbar_background_solid);
+
+        row.sliderBgIcon = (AlphaTintDrawableWrapper)
+                ((RotateDrawable) seekbarBgDrawable.findDrawableByLayerId(
+                        R.id.volume_seekbar_background_icon)).getDrawable();
+
+        final LayerDrawable seekbarProgressDrawable = (LayerDrawable)
+                ((RoundedCornerProgressDrawable) seekbarDrawable.findDrawableByLayerId(
+                        android.R.id.progress)).getDrawable();
+
+        row.sliderProgressSolid = seekbarProgressDrawable.findDrawableByLayerId(
+                R.id.volume_seekbar_progress_solid);
+
+        row.sliderProgressIcon = (AlphaTintDrawableWrapper)
+                ((RotateDrawable) seekbarProgressDrawable.findDrawableByLayerId(
+                        R.id.volume_seekbar_progress_icon)).getDrawable();
+
+        row.slider.setProgressDrawable(seekbarDrawable);
+        row.slider.setThumb(null);
+
         row.icon = row.view.findViewById(R.id.volume_row_icon);
-        row.icon.setImageResource(iconRes);
-        if (row.stream != AudioSystem.STREAM_ACCESSIBILITY) {
-            row.icon.setOnClickListener(v -> {
-                Events.writeEvent(Events.EVENT_ICON_CLICK, row.stream, row.iconState);
-                mController.setActiveStream(row.stream);
-                if (row.stream == AudioManager.STREAM_RING) {
-                    final boolean hasVibrator = mController.hasVibrator();
-                    if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
-                        if (hasVibrator) {
-                            mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false);
+
+        row.setIcon(iconRes, mContext.getTheme());
+
+        if (row.icon != null) {
+            if (row.stream != AudioSystem.STREAM_ACCESSIBILITY) {
+                row.icon.setOnClickListener(v -> {
+                    Events.writeEvent(Events.EVENT_ICON_CLICK, row.stream, row.iconState);
+                    mController.setActiveStream(row.stream);
+                    if (row.stream == AudioManager.STREAM_RING) {
+                        final boolean hasVibrator = mController.hasVibrator();
+                        if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
+                            if (hasVibrator) {
+                                mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false);
+                            } else {
+                                final boolean wasZero = row.ss.level == 0;
+                                mController.setStreamVolume(stream,
+                                        wasZero ? row.lastAudibleLevel : 0);
+                            }
                         } else {
-                            final boolean wasZero = row.ss.level == 0;
-                            mController.setStreamVolume(stream,
-                                    wasZero ? row.lastAudibleLevel : 0);
+                            mController.setRingerMode(
+                                    AudioManager.RINGER_MODE_NORMAL, false);
+                            if (row.ss.level == 0) {
+                                mController.setStreamVolume(stream, 1);
+                            }
                         }
                     } else {
-                        mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false);
-                        if (row.ss.level == 0) {
-                            mController.setStreamVolume(stream, 1);
-                        }
+                        final boolean vmute = row.ss.level == row.ss.levelMin;
+                        mController.setStreamVolume(stream,
+                                vmute ? row.lastAudibleLevel : row.ss.levelMin);
                     }
-                } else {
-                    final boolean vmute = row.ss.level == row.ss.levelMin;
-                    mController.setStreamVolume(stream,
-                            vmute ? row.lastAudibleLevel : row.ss.levelMin);
-                }
-                row.userAttempt = 0;  // reset the grace period, slider updates immediately
-            });
-        } else {
-            row.icon.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+                    row.userAttempt = 0;  // reset the grace period, slider updates immediately
+                });
+            } else {
+                row.icon.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+            }
         }
     }
 
+    private void setRingerMode(int newRingerMode) {
+        Events.writeEvent(Events.EVENT_RINGER_TOGGLE, newRingerMode);
+        incrementManualToggleCount();
+        updateRingerH();
+        provideTouchFeedbackH(newRingerMode);
+        mController.setRingerMode(newRingerMode, false);
+        maybeShowToastH(newRingerMode);
+    }
+
+    private void setupRingerDrawer() {
+        mRingerDrawerContainer = mDialog.findViewById(R.id.volume_drawer_container);
+
+        if (mRingerDrawerContainer == null) {
+            return;
+        }
+
+        if (!mShowVibrate) {
+            mRingerDrawerVibrate.setVisibility(GONE);
+        }
+
+        // In portrait, add padding to the bottom to account for the height of the open ringer
+        // drawer.
+        if (!isLandscape()) {
+            mDialogView.setPadding(
+                    mDialogView.getPaddingLeft(),
+                    mDialogView.getPaddingTop(),
+                    mDialogView.getPaddingRight(),
+                    mDialogView.getPaddingBottom() + (mRingerCount - 1) * mRingerDrawerItemSize);
+        } else {
+            mDialogView.setPadding(
+                    mDialogView.getPaddingLeft() + (mRingerCount - 1) * mRingerDrawerItemSize,
+                    mDialogView.getPaddingTop(),
+                    mDialogView.getPaddingRight(),
+                    mDialogView.getPaddingBottom());
+        }
+
+        ((LinearLayout) mRingerDrawerContainer.findViewById(R.id.volume_drawer_options))
+                .setOrientation(isLandscape() ? LinearLayout.HORIZONTAL : LinearLayout.VERTICAL);
+
+        mSelectedRingerContainer.setOnClickListener(view -> {
+            if (mIsRingerDrawerOpen) {
+                hideRingerDrawer();
+            } else {
+                showRingerDrawer();
+            }
+        });
+
+        mRingerDrawerVibrate.setOnClickListener(
+                new RingerDrawerItemClickListener(RINGER_MODE_VIBRATE));
+        mRingerDrawerMute.setOnClickListener(
+                new RingerDrawerItemClickListener(RINGER_MODE_SILENT));
+        mRingerDrawerNormal.setOnClickListener(
+                new RingerDrawerItemClickListener(RINGER_MODE_NORMAL));
+
+        final int unselectedColor = Utils.getColorAccentDefaultColor(mContext);
+        final int selectedColor = Utils.getColorAttrDefaultColor(
+                mContext, android.R.attr.colorBackgroundFloating);
+
+        // Add an update listener that animates the deselected icon to the unselected color, and the
+        // selected icon to the selected color.
+        mRingerDrawerIconColorAnimator.addUpdateListener(
+                anim -> {
+                    final float currentValue = (float) anim.getAnimatedValue();
+                    final int curUnselectedColor = (int) ArgbEvaluator.getInstance().evaluate(
+                            currentValue, selectedColor, unselectedColor);
+                    final int curSelectedColor = (int) ArgbEvaluator.getInstance().evaluate(
+                            currentValue, unselectedColor, selectedColor);
+
+                    mRingerDrawerIconAnimatingDeselected.setColorFilter(curUnselectedColor);
+                    mRingerDrawerIconAnimatingSelected.setColorFilter(curSelectedColor);
+                });
+        mRingerDrawerIconColorAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mRingerDrawerIconAnimatingDeselected.clearColorFilter();
+                mRingerDrawerIconAnimatingSelected.clearColorFilter();
+            }
+        });
+        mRingerDrawerIconColorAnimator.setDuration(DRAWER_ANIMATION_DURATION_SHORT);
+    }
+
+    private ImageView getDrawerIconViewForMode(int mode) {
+        if (mode == RINGER_MODE_VIBRATE) {
+            return mRingerDrawerVibrateIcon;
+        } else if (mode == RINGER_MODE_SILENT) {
+            return mRingerDrawerMuteIcon;
+        } else {
+            return mRingerDrawerNormalIcon;
+        }
+    }
+
+    /**
+     * Translation to apply form the origin (either top or left) to overlap the selection background
+     * with the given mode in the drawer.
+     */
+    private float getTranslationInDrawerForRingerMode(int mode) {
+        return mode == RINGER_MODE_VIBRATE
+                ? -mRingerDrawerItemSize * 2
+                : mode == RINGER_MODE_SILENT
+                        ? -mRingerDrawerItemSize
+                        : 0;
+    }
+
+    /** Animates in the ringer drawer. */
+    private void showRingerDrawer() {
+        // Show all ringer icons except the currently selected one, since we're going to animate the
+        // ringer button to that position.
+        mRingerDrawerVibrateIcon.setVisibility(
+                mState.ringerModeInternal == RINGER_MODE_VIBRATE ? INVISIBLE : VISIBLE);
+        mRingerDrawerMuteIcon.setVisibility(
+                mState.ringerModeInternal == RINGER_MODE_SILENT ? INVISIBLE : VISIBLE);
+        mRingerDrawerNormalIcon.setVisibility(
+                mState.ringerModeInternal == RINGER_MODE_NORMAL ? INVISIBLE : VISIBLE);
+
+        // Hide the selection background - we use this to show a selection when one is
+        // tapped, so it should be invisible until that happens. However, position it below
+        // the currently selected ringer so that it's ready to animate.
+        mRingerDrawerNewSelectionBg.setAlpha(0f);
+
+        if (!isLandscape()) {
+            mRingerDrawerNewSelectionBg.setTranslationY(
+                    getTranslationInDrawerForRingerMode(mState.ringerModeInternal));
+        } else {
+            mRingerDrawerNewSelectionBg.setTranslationX(
+                    getTranslationInDrawerForRingerMode(mState.ringerModeInternal));
+        }
+
+        // Move the drawer so that the top/rightmost ringer choice overlaps with the selected ringer
+        // icon.
+        if (!isLandscape()) {
+            mRingerDrawerContainer.setTranslationY(mRingerDrawerItemSize * (mRingerCount - 1));
+        } else {
+            mRingerDrawerContainer.setTranslationX(mRingerDrawerItemSize * (mRingerCount - 1));
+        }
+        mRingerDrawerContainer.setAlpha(0f);
+        mRingerDrawerContainer.setVisibility(VISIBLE);
+
+        // Animate the drawer up and visible.
+        mRingerDrawerContainer.animate()
+                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+                // Vibrate is way farther up, so give the selected ringer icon a head start if
+                // vibrate is selected.
+                .setDuration(mState.ringerModeInternal == RINGER_MODE_VIBRATE
+                        ? DRAWER_ANIMATION_DURATION_SHORT
+                        : DRAWER_ANIMATION_DURATION)
+                .setStartDelay(mState.ringerModeInternal == RINGER_MODE_VIBRATE
+                        ? DRAWER_ANIMATION_DURATION - DRAWER_ANIMATION_DURATION_SHORT
+                        : 0)
+                .alpha(1f)
+                .translationX(0f)
+                .translationY(0f)
+                .start();
+
+        // Animate the selected ringer view up to that ringer's position in the drawer.
+        mSelectedRingerContainer.animate()
+                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+                .setDuration(DRAWER_ANIMATION_DURATION)
+                .withEndAction(() ->
+                        getDrawerIconViewForMode(mState.ringerModeInternal).setVisibility(VISIBLE));
+
+        if (!isLandscape()) {
+            mSelectedRingerContainer.animate()
+                    .translationY(getTranslationInDrawerForRingerMode(mState.ringerModeInternal))
+                    .start();
+        } else {
+            mSelectedRingerContainer.animate()
+                    .translationX(getTranslationInDrawerForRingerMode(mState.ringerModeInternal))
+                    .start();
+        }
+
+        mIsRingerDrawerOpen = true;
+    }
+
+    /** Animates away the ringer drawer. */
+    private void hideRingerDrawer() {
+        // Hide the drawer icon for the selected ringer - it's visible in the ringer button and we
+        // don't want to be able to see it while it animates away.
+        getDrawerIconViewForMode(mState.ringerModeInternal).setVisibility(INVISIBLE);
+
+        mRingerDrawerContainer.animate()
+                .alpha(0f)
+                .setDuration(DRAWER_ANIMATION_DURATION)
+                .setStartDelay(0)
+                .withEndAction(() -> mRingerDrawerContainer.setVisibility(INVISIBLE));
+
+        if (!isLandscape()) {
+            mRingerDrawerContainer.animate()
+                    .translationY(mRingerDrawerItemSize * 2)
+                    .start();
+        } else {
+            mRingerDrawerContainer.animate()
+                    .translationX(mRingerDrawerItemSize * 2)
+                    .start();
+        }
+
+        mSelectedRingerContainer.animate()
+                .translationX(0f)
+                .translationY(0f)
+                .start();
+
+        mIsRingerDrawerOpen = false;
+    }
+
     public void initSettingsH() {
         if (mSettingsView != null) {
             mSettingsView.setVisibility(
@@ -555,12 +852,8 @@
                         mController.setStreamVolume(AudioManager.STREAM_RING, 1);
                     }
                 }
-                Events.writeEvent(Events.EVENT_RINGER_TOGGLE, newRingerMode);
-                incrementManualToggleCount();
-                updateRingerH();
-                provideTouchFeedbackH(newRingerMode);
-                mController.setRingerMode(newRingerMode, false);
-                maybeShowToastH(newRingerMode);
+
+                setRingerMode(newRingerMode);
             });
         }
         updateRingerH();
@@ -809,6 +1102,8 @@
                     mDialog.dismiss();
                     tryToRemoveCaptionsTooltip();
                     mIsAnimatingDismiss = false;
+
+                    hideRingerDrawer();
                 }, 50));
         if (!isLandscape()) animator.translationX(mDialogView.getWidth() / 2.0f);
         animator.start();
@@ -889,12 +1184,14 @@
             switch (mState.ringerModeInternal) {
                 case AudioManager.RINGER_MODE_VIBRATE:
                     mRingerIcon.setImageResource(R.drawable.ic_volume_ringer_vibrate);
+                    mSelectedRingerIcon.setImageResource(R.drawable.ic_volume_ringer_vibrate);
                     addAccessibilityDescription(mRingerIcon, RINGER_MODE_VIBRATE,
                             mContext.getString(R.string.volume_ringer_hint_mute));
                     mRingerIcon.setTag(Events.ICON_STATE_VIBRATE);
                     break;
                 case AudioManager.RINGER_MODE_SILENT:
                     mRingerIcon.setImageResource(R.drawable.ic_volume_ringer_mute);
+                    mSelectedRingerIcon.setImageResource(R.drawable.ic_volume_ringer_mute);
                     mRingerIcon.setTag(Events.ICON_STATE_MUTE);
                     addAccessibilityDescription(mRingerIcon, RINGER_MODE_SILENT,
                             mContext.getString(R.string.volume_ringer_hint_unmute));
@@ -904,11 +1201,13 @@
                     boolean muted = (mAutomute && ss.level == 0) || ss.muted;
                     if (!isZenMuted && muted) {
                         mRingerIcon.setImageResource(R.drawable.ic_volume_ringer_mute);
+                        mSelectedRingerIcon.setImageResource(R.drawable.ic_volume_ringer_mute);
                         addAccessibilityDescription(mRingerIcon, RINGER_MODE_NORMAL,
                                 mContext.getString(R.string.volume_ringer_hint_unmute));
                         mRingerIcon.setTag(Events.ICON_STATE_MUTE);
                     } else {
                         mRingerIcon.setImageResource(R.drawable.ic_volume_ringer);
+                        mSelectedRingerIcon.setImageResource(R.drawable.ic_volume_ringer);
                         if (mController.hasVibrator()) {
                             addAccessibilityDescription(mRingerIcon, RINGER_MODE_NORMAL,
                                     mContext.getString(R.string.volume_ringer_hint_vibrate));
@@ -1075,8 +1374,6 @@
 
         // update icon
         final boolean iconEnabled = (mAutomute || ss.muteSupported) && !zenMuted;
-        row.icon.setEnabled(iconEnabled);
-        row.icon.setAlpha(iconEnabled ? 1 : 0.5f);
         final int iconRes;
         if (isRingVibrate) {
             iconRes = R.drawable.ic_volume_ringer_vibrate;
@@ -1092,7 +1389,7 @@
                       ? R.drawable.ic_volume_media_low : row.iconRes;
         }
 
-        row.icon.setImageResource(iconRes);
+        row.setIcon(iconRes, mContext.getTheme());
         row.iconState =
                 iconRes == R.drawable.ic_volume_ringer_vibrate ? Events.ICON_STATE_VIBRATE
                 : (iconRes == R.drawable.ic_volume_media_bt_mute || iconRes == row.iconMuteRes)
@@ -1101,18 +1398,35 @@
                         || iconRes == R.drawable.ic_volume_media_low)
                         ? Events.ICON_STATE_UNMUTE
                 : Events.ICON_STATE_UNKNOWN;
-        if (iconEnabled) {
-            if (isRingStream) {
-                if (isRingVibrate) {
-                    row.icon.setContentDescription(mContext.getString(
-                            R.string.volume_stream_content_description_unmute,
-                            getStreamLabelH(ss)));
-                } else {
-                    if (mController.hasVibrator()) {
+
+        if (row.icon != null) {
+            if (iconEnabled) {
+                if (isRingStream) {
+                    if (isRingVibrate) {
                         row.icon.setContentDescription(mContext.getString(
-                                mShowA11yStream
-                                        ? R.string.volume_stream_content_description_vibrate_a11y
-                                        : R.string.volume_stream_content_description_vibrate,
+                                R.string.volume_stream_content_description_unmute,
+                                getStreamLabelH(ss)));
+                    } else {
+                        if (mController.hasVibrator()) {
+                            row.icon.setContentDescription(mContext.getString(
+                                    mShowA11yStream
+                                            ? R.string.volume_stream_content_description_vibrate_a11y
+                                            : R.string.volume_stream_content_description_vibrate,
+                                    getStreamLabelH(ss)));
+                        } else {
+                            row.icon.setContentDescription(mContext.getString(
+                                    mShowA11yStream
+                                            ? R.string.volume_stream_content_description_mute_a11y
+                                            : R.string.volume_stream_content_description_mute,
+                                    getStreamLabelH(ss)));
+                        }
+                    }
+                } else if (isA11yStream) {
+                    row.icon.setContentDescription(getStreamLabelH(ss));
+                } else {
+                    if (ss.muted || mAutomute && ss.level == 0) {
+                        row.icon.setContentDescription(mContext.getString(
+                                R.string.volume_stream_content_description_unmute,
                                 getStreamLabelH(ss)));
                     } else {
                         row.icon.setContentDescription(mContext.getString(
@@ -1122,23 +1436,9 @@
                                 getStreamLabelH(ss)));
                     }
                 }
-            } else if (isA11yStream) {
-                row.icon.setContentDescription(getStreamLabelH(ss));
             } else {
-                if (ss.muted || mAutomute && ss.level == 0) {
-                   row.icon.setContentDescription(mContext.getString(
-                           R.string.volume_stream_content_description_unmute,
-                           getStreamLabelH(ss)));
-                } else {
-                    row.icon.setContentDescription(mContext.getString(
-                            mShowA11yStream
-                                    ? R.string.volume_stream_content_description_mute_a11y
-                                    : R.string.volume_stream_content_description_mute,
-                            getStreamLabelH(ss)));
-                }
+                row.icon.setContentDescription(getStreamLabelH(ss));
             }
-        } else {
-            row.icon.setContentDescription(getStreamLabelH(ss));
         }
 
         // ensure tracking is disabled if zenMuted
@@ -1167,22 +1467,29 @@
         if (!useActiveColoring && !mChangeVolumeRowTintWhenInactive) {
             return;
         }
-        final ColorStateList tint = useActiveColoring
+        final ColorStateList colorTint = useActiveColoring
                 ? Utils.getColorAccent(mContext)
                 : Utils.getColorAttr(mContext, android.R.attr.colorForeground);
         final int alpha = useActiveColoring
-                ? Color.alpha(tint.getDefaultColor())
+                ? Color.alpha(colorTint.getDefaultColor())
                 : getAlphaAttr(android.R.attr.secondaryContentAlpha);
-        if (tint == row.cachedTint) return;
-        row.slider.setProgressTintList(tint);
-        row.slider.setThumbTintList(tint);
-        row.slider.setProgressBackgroundTintList(tint);
-        row.slider.setAlpha(((float) alpha) / 255);
-        row.icon.setImageTintList(tint);
-        row.icon.setImageAlpha(alpha);
-        row.cachedTint = tint;
+
+        final ColorStateList bgTint = Utils.getColorAttr(
+                mContext, android.R.attr.colorBackgroundFloating);
+
+        row.sliderProgressSolid.setTintList(colorTint);
+        row.sliderBgIcon.setTintList(colorTint);
+
+        row.sliderBgSolid.setTintList(bgTint);
+        row.sliderProgressIcon.setTintList(bgTint);
+
+        if (row.icon != null) {
+            row.icon.setImageTintList(colorTint);
+            row.icon.setImageAlpha(alpha);
+        }
+
         if (row.number != null) {
-            row.number.setTextColor(tint);
+            row.number.setTextColor(colorTint);
             row.number.setAlpha(alpha);
         }
     }
@@ -1538,6 +1845,10 @@
         private View view;
         private TextView header;
         private ImageButton icon;
+        private Drawable sliderBgSolid;
+        private AlphaTintDrawableWrapper sliderBgIcon;
+        private Drawable sliderProgressSolid;
+        private AlphaTintDrawableWrapper sliderProgressIcon;
         private SeekBar slider;
         private TextView number;
         private int stream;
@@ -1555,5 +1866,69 @@
         private int animTargetProgress;
         private int lastAudibleLevel = 1;
         private FrameLayout dndIcon;
+
+        void setIcon(int iconRes, Resources.Theme theme) {
+            if (icon != null) {
+                icon.setImageResource(iconRes);
+            }
+
+            sliderProgressIcon.setDrawable(view.getResources().getDrawable(iconRes, theme));
+            sliderBgIcon.setDrawable(view.getResources().getDrawable(iconRes, theme));
+        }
+    }
+
+    /**
+     * Click listener added to each ringer option in the drawer. This will initiate the animation to
+     * select and then close the ringer drawer, and actually change the ringer mode.
+     */
+    private class RingerDrawerItemClickListener implements View.OnClickListener {
+        private final int mClickedRingerMode;
+
+        RingerDrawerItemClickListener(int clickedRingerMode) {
+            mClickedRingerMode = clickedRingerMode;
+        }
+
+        @Override
+        public void onClick(View view) {
+            setRingerMode(mClickedRingerMode);
+
+            mRingerDrawerIconAnimatingSelected = getDrawerIconViewForMode(mClickedRingerMode);
+            mRingerDrawerIconAnimatingDeselected = getDrawerIconViewForMode(
+                    mState.ringerModeInternal);
+
+            // Begin switching the selected icon and deselected icon colors since the background is
+            // going to animate behind the new selection.
+            mRingerDrawerIconColorAnimator.start();
+
+            mSelectedRingerContainer.setVisibility(View.INVISIBLE);
+            mRingerDrawerNewSelectionBg.setAlpha(1f);
+            mRingerDrawerNewSelectionBg.animate()
+                    .setInterpolator(Interpolators.ACCELERATE_DECELERATE)
+                    .setDuration(DRAWER_ANIMATION_DURATION_SHORT)
+                    .withEndAction(() -> {
+                        mRingerDrawerNewSelectionBg.setAlpha(0f);
+
+                        if (!isLandscape()) {
+                            mSelectedRingerContainer.setTranslationY(
+                                    getTranslationInDrawerForRingerMode(mClickedRingerMode));
+                        } else {
+                            mSelectedRingerContainer.setTranslationX(
+                                    getTranslationInDrawerForRingerMode(mClickedRingerMode));
+                        }
+
+                        mSelectedRingerContainer.setVisibility(VISIBLE);
+                        hideRingerDrawer();
+                    });
+
+            if (!isLandscape()) {
+                mRingerDrawerNewSelectionBg.animate()
+                        .translationY(getTranslationInDrawerForRingerMode(mClickedRingerMode))
+                        .start();
+            } else {
+                mRingerDrawerNewSelectionBg.animate()
+                        .translationX(getTranslationInDrawerForRingerMode(mClickedRingerMode))
+                        .start();
+            }
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index 8505703..4eb75eb 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -287,6 +287,13 @@
 
             @Override
             public void onKeyguardVisibilityChanged(boolean showing) {
+                if (showing) {
+                    // When keyguard shown, temperory lock OHM disabled to avoid mis-trigger.
+                    oneHanded.setLockedDisabled(true /* locked */, false /* enabled */);
+                } else {
+                    // Reset locked.
+                    oneHanded.setLockedDisabled(false /* locked */, false /* enabled */);
+                }
                 oneHanded.stopOneHanded();
             }
         };
@@ -315,6 +322,13 @@
                 }
             }
         });
+
+        mConfigurationController.addCallback(new ConfigurationController.ConfigurationListener() {
+            @Override
+            public void onConfigChanged(Configuration newConfig) {
+                oneHanded.onConfigChanged(newConfig);
+            }
+        });
     }
 
     @VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index fba0b00..8d3a040 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -31,6 +31,7 @@
 import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
 import com.android.internal.logging.UiEventLogger;
 import com.android.internal.statusbar.IStatusBarService;
+import com.android.systemui.R;
 import com.android.systemui.dagger.WMComponent;
 import com.android.systemui.dagger.WMSingleton;
 import com.android.systemui.dagger.qualifiers.Main;
@@ -76,6 +77,8 @@
 import com.android.wm.shell.sizecompatui.SizeCompatUIController;
 import com.android.wm.shell.splitscreen.SplitScreen;
 import com.android.wm.shell.splitscreen.SplitScreenController;
+import com.android.wm.shell.startingsurface.StartingSurface;
+import com.android.wm.shell.startingsurface.StartingWindowController;
 import com.android.wm.shell.transition.RemoteTransitions;
 import com.android.wm.shell.transition.Transitions;
 
@@ -97,7 +100,12 @@
 @Module
 public abstract class WMShellBaseModule {
 
-    private static final boolean ENABLE_SHELL_MAIN_THREAD = false;
+    /**
+     * Returns whether to enable a separate shell thread for the shell features.
+     */
+    private static boolean enableShellMainThread(Context context) {
+        return context.getResources().getBoolean(R.bool.config_enableShellMainThread);
+    }
 
     //
     // Shell Concurrency - Components used for managing threading in the Shell and SysUI
@@ -120,8 +128,8 @@
     @WMSingleton
     @Provides
     @ShellMainThread
-    public static Handler provideShellMainHandler(@Main Handler sysuiMainHandler) {
-        if (ENABLE_SHELL_MAIN_THREAD) {
+    public static Handler provideShellMainHandler(Context context, @Main Handler sysuiMainHandler) {
+        if (enableShellMainThread(context)) {
              HandlerThread mainThread = new HandlerThread("wmshell.main");
              mainThread.start();
              return mainThread.getThreadHandler();
@@ -135,9 +143,9 @@
     @WMSingleton
     @Provides
     @ShellMainThread
-    public static ShellExecutor provideShellMainExecutor(@ShellMainThread Handler mainHandler,
-            @Main ShellExecutor sysuiMainExecutor) {
-        if (ENABLE_SHELL_MAIN_THREAD) {
+    public static ShellExecutor provideShellMainExecutor(Context context,
+            @ShellMainThread Handler mainHandler, @Main ShellExecutor sysuiMainExecutor) {
+        if (enableShellMainThread(context)) {
             return new HandlerExecutor(mainHandler);
         }
         return sysuiMainExecutor;
@@ -380,9 +388,9 @@
     @WMSingleton
     @Provides
     static Transitions provideTransitions(ShellTaskOrganizer organizer, TransactionPool pool,
-            @ShellMainThread ShellExecutor mainExecutor,
+            Context context, @ShellMainThread ShellExecutor mainExecutor,
             @ShellAnimationThread ShellExecutor animExecutor) {
-        return new Transitions(organizer, pool, mainExecutor, animExecutor);
+        return new Transitions(organizer, pool, context, mainExecutor, animExecutor);
     }
 
     //
@@ -409,10 +417,11 @@
             ShellTaskOrganizer shellTaskOrganizer,
             SyncTransactionQueue syncQueue, Context context,
             RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
-            @ShellMainThread ShellExecutor mainExecutor) {
+            @ShellMainThread ShellExecutor mainExecutor,
+            DisplayImeController displayImeController) {
         if (ActivityTaskManager.supportsSplitScreenMultiWindow(context)) {
             return Optional.of(new SplitScreenController(shellTaskOrganizer, syncQueue, context,
-                    rootTaskDisplayAreaOrganizer, mainExecutor));
+                    rootTaskDisplayAreaOrganizer, mainExecutor, displayImeController));
         } else {
             return Optional.empty();
         }
@@ -441,6 +450,22 @@
     @BindsOptionalOf
     abstract AppPairsController optionalAppPairs();
 
+    // Starting window
+
+    @WMSingleton
+    @Provides
+    static Optional<StartingSurface> provideStartingSurface(
+            StartingWindowController startingWindowController) {
+        return Optional.of(startingWindowController.asStartingSurface());
+    }
+
+    @WMSingleton
+    @Provides
+    static StartingWindowController provideStartingWindowController(Context context,
+            @ShellMainThread ShellExecutor mainExecutor) {
+        return new StartingWindowController(context, mainExecutor);
+    }
+
     //
     // Task view factory
     //
@@ -472,6 +497,7 @@
             Optional<LegacySplitScreenController> legacySplitScreenOptional,
             Optional<SplitScreenController> splitScreenOptional,
             Optional<AppPairsController> appPairsOptional,
+            Optional<StartingSurface> startingSurface,
             FullscreenTaskListener fullscreenTaskListener,
             Transitions transitions,
             @ShellMainThread ShellExecutor mainExecutor) {
@@ -481,6 +507,7 @@
                 legacySplitScreenOptional,
                 splitScreenOptional,
                 appPairsOptional,
+                startingSurface,
                 fullscreenTaskListener,
                 transitions,
                 mainExecutor);
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
index 997b488..754b6a6 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
@@ -104,9 +104,10 @@
     @Provides
     static AppPairsController provideAppPairs(ShellTaskOrganizer shellTaskOrganizer,
             SyncTransactionQueue syncQueue, DisplayController displayController,
-            @ShellMainThread ShellExecutor mainExecutor) {
+            @ShellMainThread ShellExecutor mainExecutor,
+            DisplayImeController displayImeController) {
         return new AppPairsController(shellTaskOrganizer, syncQueue, displayController,
-                mainExecutor);
+                mainExecutor, displayImeController);
     }
 
     //
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
similarity index 79%
rename from packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
rename to packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
index d3f9d641..aa4122f 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
@@ -54,6 +54,7 @@
 import android.testing.TestableLooper;
 import android.text.TextUtils;
 
+import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
@@ -73,7 +74,7 @@
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
-public class CarrierTextManagerTest extends SysuiTestCase {
+public class CarrierTextControllerTest extends SysuiTestCase {
 
     private static final CharSequence SEPARATOR = " \u2014 ";
     private static final CharSequence INVALID_CARD_TEXT = "Invalid card";
@@ -94,9 +95,7 @@
     @Mock
     private WifiManager mWifiManager;
     @Mock
-    private WakefulnessLifecycle mWakefulnessLifecycle;
-    @Mock
-    private CarrierTextManager.CarrierTextCallback mCarrierTextCallback;
+    private CarrierTextController.CarrierTextCallback mCarrierTextCallback;
     @Mock
     private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     @Mock
@@ -105,14 +104,13 @@
     private TelephonyManager mTelephonyManager;
     @Mock
     private SubscriptionManager mSubscriptionManager;
-    private CarrierTextManager.CarrierTextCallbackInfo mCarrierTextCallbackInfo;
+    private CarrierTextController.CarrierTextCallbackInfo mCarrierTextCallbackInfo;
 
-    private CarrierTextManager mCarrierTextManager;
+    private CarrierTextController mCarrierTextController;
     private TestableLooper mTestableLooper;
-    private Handler mMainHandler;
 
     private Void checkMainThread(InvocationOnMock inv) {
-        Looper mainLooper = mMainHandler.getLooper();
+        Looper mainLooper = Dependency.get(Dependency.MAIN_HANDLER).getLooper();
         if (!mainLooper.isCurrentThread()) {
             fail("This call should be done from the main thread");
         }
@@ -124,33 +122,35 @@
         MockitoAnnotations.initMocks(this);
         mTestableLooper = TestableLooper.get(this);
 
-        mMainHandler = new Handler(mTestableLooper.getLooper());
+        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(
                 R.string.keyguard_sim_error_message_short, INVALID_CARD_TEXT);
         mContext.getOrCreateTestableResources().addOverride(
                 R.string.airplane_mode, AIRPLANE_MODE_TEXT);
+        mDependency.injectMockDependency(WakefulnessLifecycle.class);
+        mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
+                new Handler(mTestableLooper.getLooper()));
+        mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
+        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 CarrierTextManager.CarrierTextCallbackInfo("",
+        mCarrierTextCallbackInfo = new CarrierTextController.CarrierTextCallbackInfo("",
                 new CharSequence[]{}, false, new int[]{});
         when(mTelephonyManager.getSupportedModemCount()).thenReturn(3);
         when(mTelephonyManager.getActiveModemCount()).thenReturn(3);
 
-        mCarrierTextManager = new CarrierTextManager.Builder(
-                mContext, mContext.getResources(), mWifiManager, mConnectivityManager,
-                mTelephonyManager, mWakefulnessLifecycle, new Handler(mTestableLooper.getLooper()),
-                mMainHandler, mKeyguardUpdateMonitor)
-                .setShowAirplaneMode(true)
-                .setShowMissingSim(true)
-                .build();
+        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
-        mCarrierTextManager.setListening(mCarrierTextCallback);
+        mCarrierTextController.setListening(mCarrierTextCallback);
         mTestableLooper.processAllMessages();
     }
 
@@ -165,8 +165,8 @@
         TestableLooper testableLooper = new TestableLooper(thread.getLooper());
         Handler h = new Handler(testableLooper.getLooper());
         h.post(() -> {
-            mCarrierTextManager.setListening(null);
-            mCarrierTextManager.setListening(mCarrierTextCallback);
+            mCarrierTextController.setListening(null);
+            mCarrierTextController.setListening(mCarrierTextCallback);
         });
         testableLooper.processAllMessages();
         mTestableLooper.processAllMessages();
@@ -183,11 +183,11 @@
         when(mKeyguardUpdateMonitor.getSimState(0)).thenReturn(TelephonyManager.SIM_STATE_READY);
         mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
 
-        mCarrierTextManager.updateCarrierText();
+        mCarrierTextController.updateCarrierText();
 
-        ArgumentCaptor<CarrierTextManager.CarrierTextCallbackInfo> captor =
+        ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
                 ArgumentCaptor.forClass(
-                        CarrierTextManager.CarrierTextCallbackInfo.class);
+                        CarrierTextController.CarrierTextCallbackInfo.class);
 
         mTestableLooper.processAllMessages();
         verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
@@ -205,12 +205,12 @@
                 TelephonyManager.SIM_STATE_CARD_IO_ERROR);
         mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
 
-        mCarrierTextManager.mCallback.onSimStateChanged(3, 1,
+        mCarrierTextController.mCallback.onSimStateChanged(3, 1,
                 TelephonyManager.SIM_STATE_CARD_IO_ERROR);
 
-        ArgumentCaptor<CarrierTextManager.CarrierTextCallbackInfo> captor =
+        ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
                 ArgumentCaptor.forClass(
-                        CarrierTextManager.CarrierTextCallbackInfo.class);
+                        CarrierTextController.CarrierTextCallbackInfo.class);
 
         mTestableLooper.processAllMessages();
         verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
@@ -223,7 +223,7 @@
         reset(mCarrierTextCallback);
         when(mTelephonyManager.getActiveModemCount()).thenReturn(1);
         // Update carrier text. It should ignore error state of subId 3 in inactive slotId.
-        mCarrierTextManager.updateCarrierText();
+        mCarrierTextController.updateCarrierText();
         mTestableLooper.processAllMessages();
         verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
         assertEquals("TEST_CARRIER", captor.getValue().carrierText);
@@ -237,9 +237,9 @@
         when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(
                 TelephonyManager.SIM_STATE_CARD_IO_ERROR);
         // This should not produce an out of bounds error, even though there are no subscriptions
-        mCarrierTextManager.mCallback.onSimStateChanged(0, -3,
+        mCarrierTextController.mCallback.onSimStateChanged(0, -3,
                 TelephonyManager.SIM_STATE_CARD_IO_ERROR);
-        mCarrierTextManager.mCallback.onSimStateChanged(0, 3, TelephonyManager.SIM_STATE_READY);
+        mCarrierTextController.mCallback.onSimStateChanged(0, 3, TelephonyManager.SIM_STATE_READY);
         verify(mCarrierTextCallback, never()).updateCarrierInfo(any());
     }
 
@@ -257,23 +257,23 @@
         when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(
                 TelephonyManager.SIM_STATE_CARD_IO_ERROR);
         // This should not produce an out of bounds error, even though there are no subscriptions
-        mCarrierTextManager.mCallback.onSimStateChanged(0, 1,
+        mCarrierTextController.mCallback.onSimStateChanged(0, 1,
                 TelephonyManager.SIM_STATE_CARD_IO_ERROR);
 
         mTestableLooper.processAllMessages();
         verify(mCarrierTextCallback).updateCarrierInfo(
-                any(CarrierTextManager.CarrierTextCallbackInfo.class));
+                any(CarrierTextController.CarrierTextCallbackInfo.class));
     }
 
     @Test
     public void testCallback() {
         reset(mCarrierTextCallback);
-        mCarrierTextManager.postToCallback(mCarrierTextCallbackInfo);
+        mCarrierTextController.postToCallback(mCarrierTextCallbackInfo);
         mTestableLooper.processAllMessages();
 
-        ArgumentCaptor<CarrierTextManager.CarrierTextCallbackInfo> captor =
+        ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
                 ArgumentCaptor.forClass(
-                        CarrierTextManager.CarrierTextCallbackInfo.class);
+                        CarrierTextController.CarrierTextCallbackInfo.class);
         verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
         assertEquals(mCarrierTextCallbackInfo, captor.getValue());
     }
@@ -282,8 +282,8 @@
     public void testNullingCallback() {
         reset(mCarrierTextCallback);
 
-        mCarrierTextManager.postToCallback(mCarrierTextCallbackInfo);
-        mCarrierTextManager.setListening(null);
+        mCarrierTextController.postToCallback(mCarrierTextCallbackInfo);
+        mCarrierTextController.setListening(null);
 
         // This shouldn't produce NPE
         mTestableLooper.processAllMessages();
@@ -301,15 +301,15 @@
 
         mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
 
-        ArgumentCaptor<CarrierTextManager.CarrierTextCallbackInfo> captor =
+        ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
                 ArgumentCaptor.forClass(
-                        CarrierTextManager.CarrierTextCallbackInfo.class);
+                        CarrierTextController.CarrierTextCallbackInfo.class);
 
-        mCarrierTextManager.updateCarrierText();
+        mCarrierTextController.updateCarrierText();
         mTestableLooper.processAllMessages();
         verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
 
-        CarrierTextManager.CarrierTextCallbackInfo info = captor.getValue();
+        CarrierTextController.CarrierTextCallbackInfo info = captor.getValue();
         assertEquals(1, info.listOfCarriers.length);
         assertEquals(TEST_CARRIER, info.listOfCarriers[0]);
         assertEquals(1, info.subscriptionIds.length);
@@ -326,15 +326,15 @@
 
         mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
 
-        ArgumentCaptor<CarrierTextManager.CarrierTextCallbackInfo> captor =
+        ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
                 ArgumentCaptor.forClass(
-                        CarrierTextManager.CarrierTextCallbackInfo.class);
+                        CarrierTextController.CarrierTextCallbackInfo.class);
 
-        mCarrierTextManager.updateCarrierText();
+        mCarrierTextController.updateCarrierText();
         mTestableLooper.processAllMessages();
         verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
 
-        CarrierTextManager.CarrierTextCallbackInfo info = captor.getValue();
+        CarrierTextController.CarrierTextCallbackInfo info = captor.getValue();
         assertEquals(1, info.listOfCarriers.length);
         assertTrue(info.listOfCarriers[0].toString().contains(TEST_CARRIER));
         assertEquals(1, info.subscriptionIds.length);
@@ -346,16 +346,16 @@
         List<SubscriptionInfo> list = new ArrayList<>();
         list.add(TEST_SUBSCRIPTION_NULL);
         when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(
-                TelephonyManager.SIM_STATE_READY);
+            TelephonyManager.SIM_STATE_READY);
         when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(anyBoolean())).thenReturn(list);
 
         mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
 
-        ArgumentCaptor<CarrierTextManager.CarrierTextCallbackInfo> captor =
+        ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
                 ArgumentCaptor.forClass(
-                        CarrierTextManager.CarrierTextCallbackInfo.class);
+                        CarrierTextController.CarrierTextCallbackInfo.class);
 
-        mCarrierTextManager.updateCarrierText();
+        mCarrierTextController.updateCarrierText();
         mTestableLooper.processAllMessages();
         verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
 
@@ -380,11 +380,11 @@
         when(ss.getDataRegistrationState()).thenReturn(ServiceState.STATE_IN_SERVICE);
         mKeyguardUpdateMonitor.mServiceStates.put(TEST_SUBSCRIPTION_NULL.getSubscriptionId(), ss);
 
-        ArgumentCaptor<CarrierTextManager.CarrierTextCallbackInfo> captor =
+        ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
                 ArgumentCaptor.forClass(
-                        CarrierTextManager.CarrierTextCallbackInfo.class);
+                        CarrierTextController.CarrierTextCallbackInfo.class);
 
-        mCarrierTextManager.updateCarrierText();
+        mCarrierTextController.updateCarrierText();
         mTestableLooper.processAllMessages();
         verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
 
@@ -407,15 +407,15 @@
         when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(anyBoolean())).thenReturn(
                 new ArrayList<>());
 
-        ArgumentCaptor<CarrierTextManager.CarrierTextCallbackInfo> captor =
+        ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
                 ArgumentCaptor.forClass(
-                        CarrierTextManager.CarrierTextCallbackInfo.class);
+                        CarrierTextController.CarrierTextCallbackInfo.class);
 
-        mCarrierTextManager.updateCarrierText();
+        mCarrierTextController.updateCarrierText();
         mTestableLooper.processAllMessages();
         verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
 
-        CarrierTextManager.CarrierTextCallbackInfo info = captor.getValue();
+        CarrierTextController.CarrierTextCallbackInfo info = captor.getValue();
         assertEquals(0, info.listOfCarriers.length);
         assertEquals(0, info.subscriptionIds.length);
 
@@ -428,16 +428,16 @@
         list.add(TEST_SUBSCRIPTION);
         list.add(TEST_SUBSCRIPTION);
         when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(
-                TelephonyManager.SIM_STATE_READY);
+            TelephonyManager.SIM_STATE_READY);
         when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(anyBoolean())).thenReturn(list);
 
         mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
 
-        ArgumentCaptor<CarrierTextManager.CarrierTextCallbackInfo> captor =
+        ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
                 ArgumentCaptor.forClass(
-                        CarrierTextManager.CarrierTextCallbackInfo.class);
+                        CarrierTextController.CarrierTextCallbackInfo.class);
 
-        mCarrierTextManager.updateCarrierText();
+        mCarrierTextController.updateCarrierText();
         mTestableLooper.processAllMessages();
         verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
 
@@ -458,11 +458,11 @@
 
         mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
 
-        ArgumentCaptor<CarrierTextManager.CarrierTextCallbackInfo> captor =
+        ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
                 ArgumentCaptor.forClass(
-                        CarrierTextManager.CarrierTextCallbackInfo.class);
+                        CarrierTextController.CarrierTextCallbackInfo.class);
 
-        mCarrierTextManager.updateCarrierText();
+        mCarrierTextController.updateCarrierText();
         mTestableLooper.processAllMessages();
         verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
 
@@ -483,11 +483,11 @@
 
         mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
 
-        ArgumentCaptor<CarrierTextManager.CarrierTextCallbackInfo> captor =
+        ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
                 ArgumentCaptor.forClass(
-                        CarrierTextManager.CarrierTextCallbackInfo.class);
+                        CarrierTextController.CarrierTextCallbackInfo.class);
 
-        mCarrierTextManager.updateCarrierText();
+        mCarrierTextController.updateCarrierText();
         mTestableLooper.processAllMessages();
         verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
 
@@ -509,11 +509,11 @@
         when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(anyBoolean())).thenReturn(list);
         mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
 
-        ArgumentCaptor<CarrierTextManager.CarrierTextCallbackInfo> captor =
+        ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
                 ArgumentCaptor.forClass(
-                        CarrierTextManager.CarrierTextCallbackInfo.class);
+                        CarrierTextController.CarrierTextCallbackInfo.class);
 
-        mCarrierTextManager.updateCarrierText();
+        mCarrierTextController.updateCarrierText();
         mTestableLooper.processAllMessages();
         verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
 
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java
index d67fe6d..c2ade81 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java
@@ -69,8 +69,6 @@
     private KeyguardMessageAreaController mKeyguardMessageAreaController;
     @Mock
     private LatencyTracker mLatencyTracker;
-    @Mock
-    private EmergencyButtonController mEmergencyButtonController;
 
     private KeyguardAbsKeyInputViewController mKeyguardAbsKeyInputViewController;
 
@@ -86,8 +84,7 @@
                 .thenReturn(mKeyguardMessageArea);
         mKeyguardAbsKeyInputViewController = new KeyguardAbsKeyInputViewController(mAbsKeyInputView,
                 mKeyguardUpdateMonitor, mSecurityMode, mLockPatternUtils, mKeyguardSecurityCallback,
-                mKeyguardMessageAreaControllerFactory, mLatencyTracker,
-                mEmergencyButtonController) {
+                mKeyguardMessageAreaControllerFactory, mLatencyTracker) {
             @Override
             void resetState() {
             }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardDisplayManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardDisplayManagerTest.java
index 4beec57..826be2b 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardDisplayManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardDisplayManagerTest.java
@@ -54,11 +54,11 @@
 public class KeyguardDisplayManagerTest extends SysuiTestCase {
 
     @Mock
-    private NavigationBarController mNavigationBarController;
-    @Mock
     private KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
+
     @Mock
     private DisplayManager mDisplayManager;
+
     @Mock
     private KeyguardDisplayManager.KeyguardPresentation mKeyguardPresentation;
 
@@ -76,8 +76,9 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext.addMockSystemService(DisplayManager.class, mDisplayManager);
-        mManager = spy(new KeyguardDisplayManager(mContext, () -> mNavigationBarController,
-                mKeyguardStatusViewComponentFactory, mBackgroundExecutor));
+        mDependency.injectMockDependency(NavigationBarController.class);
+        mManager = spy(new KeyguardDisplayManager(mContext, mKeyguardStatusViewComponentFactory,
+                mBackgroundExecutor));
         doReturn(mKeyguardPresentation).when(mManager).createPresentation(any());
 
         mDefaultDisplay = new Display(DisplayManagerGlobal.getInstance(), Display.DEFAULT_DISPLAY,
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
index 6d0c640..c69ec1a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
@@ -49,8 +49,6 @@
     @Mock
     private lateinit var mLatencyTracker: LatencyTracker
     @Mock
-    private lateinit var mEmergencyButtonController: EmergencyButtonController
-    @Mock
     private lateinit
     var mKeyguardMessageAreaControllerFactory: KeyguardMessageAreaController.Factory
     @Mock
@@ -74,8 +72,7 @@
                 .thenReturn(mKeyguardMessageAreaController)
         mKeyguardPatternViewController = KeyguardPatternViewController(mKeyguardPatternView,
         mKeyguardUpdateMonitor, mSecurityMode, mLockPatternUtils, mKeyguardSecurityCallback,
-                mLatencyTracker, mEmergencyButtonController,
-                mKeyguardMessageAreaControllerFactory)
+                mLatencyTracker, mKeyguardMessageAreaControllerFactory)
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java
index 8d1e1a4..31cc7bb 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java
@@ -67,8 +67,6 @@
     private LatencyTracker mLatencyTracker;
     @Mock
     private LiftToActivateListener mLiftToactivateListener;
-    @Mock
-    private EmergencyButtonController mEmergencyButtonController;
     private FalsingCollector mFalsingCollector = new FalsingCollectorFake();
     @Mock
     private View mDeleteButton;
@@ -94,7 +92,7 @@
         mKeyguardPinViewController = new KeyguardPinBasedInputViewController(mPinBasedInputView,
                 mKeyguardUpdateMonitor, mSecurityMode, mLockPatternUtils, mKeyguardSecurityCallback,
                 mKeyguardMessageAreaControllerFactory, mLatencyTracker, mLiftToactivateListener,
-                mEmergencyButtonController, mFalsingCollector) {
+                mFalsingCollector) {
             @Override
             public void onResume(int reason) {
                 super.onResume(reason);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java
index 9296d3d..3b7f4b8 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java
@@ -59,10 +59,6 @@
     @Mock
     private KeyguardInputViewController.Factory mKeyguardSecurityViewControllerFactory;
     @Mock
-    private EmergencyButtonController.Factory mEmergencyButtonControllerFactory;
-    @Mock
-    private EmergencyButtonController mEmergencyButtonController;
-    @Mock
     private KeyguardInputViewController mKeyguardInputViewController;
     @Mock
     private KeyguardInputView mInputView;
@@ -80,12 +76,9 @@
                 any(KeyguardSecurityCallback.class)))
                 .thenReturn(mKeyguardInputViewController);
         when(mView.getWindowInsetsController()).thenReturn(mWindowInsetsController);
-        when(mEmergencyButtonControllerFactory.create(any(EmergencyButton.class)))
-                .thenReturn(mEmergencyButtonController);
 
         mKeyguardSecurityViewFlipperController = new KeyguardSecurityViewFlipperController(mView,
-                mLayoutInflater, mKeyguardSecurityViewControllerFactory,
-                mEmergencyButtonControllerFactory);
+                mLayoutInflater, mKeyguardSecurityViewControllerFactory);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 6e2398c..eb95d16 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -56,6 +56,7 @@
 import android.hardware.face.FaceSensorPropertiesInternal;
 import android.hardware.fingerprint.FingerprintManager;
 import android.media.AudioManager;
+import android.nfc.NfcAdapter;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IRemoteCallback;
@@ -851,6 +852,17 @@
         assertThat(mKeyguardUpdateMonitor.shouldListenForUdfps()).isEqualTo(false);
     }
 
+    @Test
+    public void testRequireUnlockForNfc_Broadcast() {
+        KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class);
+        mKeyguardUpdateMonitor.registerCallback(callback);
+        Intent intent = new Intent(NfcAdapter.ACTION_REQUIRE_UNLOCK_FOR_NFC);
+        mKeyguardUpdateMonitor.mBroadcastAllReceiver.onReceive(getContext(), intent);
+        mTestableLooper.processAllMessages();
+
+        verify(callback, atLeastOnce()).onRequireUnlockForNfc();
+    }
+
     private void setKeyguardBouncerVisibility(boolean isVisible) {
         mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(isVisible);
         mTestableLooper.processAllMessages();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
index 6c3b37e..ba21afd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
@@ -309,17 +309,6 @@
     }
 
     @Test
-    public void testOverlayPredicate() {
-        StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, "com.example.app1",
-                5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
-        StatusBarNotification sbn_user1_overlay = makeMockSBN(USERID_ONE, "android",
-                0, "AlertWindowNotification", Notification.FLAG_NO_CLEAR);
-
-        assertTrue(mFsc.isSystemAlertNotification(sbn_user1_overlay));
-        assertFalse(mFsc.isSystemAlertNotification(sbn_user1_app1));
-    }
-
-    @Test
     public void testNoNotifsNorAppOps_noSystemAlertWarningRequired() {
         // no notifications nor app op signals that this package/userId requires system alert
         // warning
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java b/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
index 0c69ffd..e1ddaad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
@@ -43,6 +43,7 @@
 import com.android.systemui.glwallpaper.ImageWallpaperRenderer;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -53,6 +54,7 @@
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
+@Ignore
 public class ImageWallpaperTest extends SysuiTestCase {
     private static final int LOW_BMP_WIDTH = 128;
     private static final int LOW_BMP_HEIGHT = 128;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
index bc322f7..2526990 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
@@ -16,8 +16,8 @@
 
 package com.android.systemui.appops;
 
-import static android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_CAMERA;
-import static android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE;
+import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
+import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
 
 import static junit.framework.TestCase.assertFalse;
 
@@ -69,6 +69,7 @@
 @TestableLooper.RunWithLooper
 public class AppOpsControllerTest extends SysuiTestCase {
     private static final String TEST_PACKAGE_NAME = "test";
+    private static final String TEST_ATTRIBUTION_NAME = "attribution";
     private static final int TEST_UID = UserHandle.getUid(0, 0);
     private static final int TEST_UID_OTHER = UserHandle.getUid(1, 0);
     private static final int TEST_UID_NON_USER_SENSITIVE = UserHandle.getUid(2, 0);
@@ -124,9 +125,9 @@
         when(mAudioManager.getActiveRecordingConfigurations())
                 .thenReturn(List.of(mPausedMockRecording));
 
-        when(mSensorPrivacyController.isSensorBlocked(INDIVIDUAL_SENSOR_CAMERA))
+        when(mSensorPrivacyController.isSensorBlocked(CAMERA))
                 .thenReturn(false);
-        when(mSensorPrivacyController.isSensorBlocked(INDIVIDUAL_SENSOR_CAMERA))
+        when(mSensorPrivacyController.isSensorBlocked(CAMERA))
                 .thenReturn(false);
 
         mController = new AppOpsControllerImpl(
@@ -164,7 +165,7 @@
         mController.onOpActiveChanged(
                 AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+                TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
         mTestableLooper.processAllMessages();
         verify(mCallback).onActiveStateChanged(AppOpsManager.OP_RECORD_AUDIO,
                 TEST_UID, TEST_PACKAGE_NAME, true);
@@ -218,8 +219,8 @@
         mController.onOpActiveChanged(AppOpsManager.OP_CAMERA,
                 TEST_UID, TEST_PACKAGE_NAME, true);
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION,
-                TEST_UID, TEST_PACKAGE_NAME, AppOpsManager.OP_FLAG_SELF,
-                AppOpsManager.MODE_ALLOWED);
+                TEST_UID, TEST_PACKAGE_NAME, TEST_ATTRIBUTION_NAME,
+                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
         assertEquals(3, mController.getActiveAppOps().size());
     }
 
@@ -230,8 +231,8 @@
         mController.onOpActiveChanged(AppOpsManager.OP_CAMERA,
                 TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION,
-                TEST_UID, TEST_PACKAGE_NAME, AppOpsManager.OP_FLAG_SELF,
-                AppOpsManager.MODE_ALLOWED);
+                TEST_UID, TEST_PACKAGE_NAME, TEST_ATTRIBUTION_NAME,
+                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
         assertEquals(2,
                 mController.getActiveAppOpsForUser(UserHandle.getUserId(TEST_UID)).size());
         assertEquals(1,
@@ -262,7 +263,7 @@
     public void opNotedScheduledForRemoval() {
         mController.setBGHandler(mMockHandler);
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+                TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
         verify(mMockHandler).scheduleRemoval(any(AppOpItem.class), anyLong());
     }
 
@@ -274,7 +275,7 @@
         mController.onOpActiveChanged(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
                 true);
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+                TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
         assertFalse(mController.getActiveAppOps().isEmpty());
 
         mController.setListening(false);
@@ -288,9 +289,9 @@
         mController.setBGHandler(mMockHandler);
 
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+                TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+                TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
 
         // Only one post to notify subscribers
         verify(mMockHandler, times(1)).post(any());
@@ -304,9 +305,9 @@
         mController.setBGHandler(mMockHandler);
 
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+                TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+                TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
 
         // Only one post to notify subscribers
         verify(mMockHandler, times(2)).scheduleRemoval(any(), anyLong());
@@ -324,7 +325,7 @@
                 AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
 
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+                TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
 
         // Check that we "scheduled" the removal. Don't actually schedule until we are ready to
         // process messages at a later time.
@@ -353,7 +354,7 @@
         mController.addCallback(new int[]{AppOpsManager.OP_FINE_LOCATION}, mCallback);
 
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+                TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
 
         mController.onOpActiveChanged(
                 AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
@@ -382,7 +383,7 @@
         mController.addCallback(new int[]{AppOpsManager.OP_FINE_LOCATION}, mCallback);
 
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+                TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
 
         mController.onOpActiveChanged(
                 AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
@@ -400,7 +401,7 @@
                 AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
 
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+                TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
 
         mTestableLooper.processAllMessages();
         verify(mCallback).onActiveStateChanged(
@@ -504,7 +505,7 @@
         assertFalse(list.get(0).isDisabled());
 
         // Add a camera op, and disable the microphone. The camera op should be the only op returned
-        mController.onSensorBlockedChanged(INDIVIDUAL_SENSOR_MICROPHONE, true);
+        mController.onSensorBlockedChanged(MICROPHONE, true);
         mController.onOpActiveChanged(
                 AppOpsManager.OP_CAMERA, TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
         mTestableLooper.processAllMessages();
@@ -514,7 +515,7 @@
 
 
         // Re enable the microphone, and verify the op returns
-        mController.onSensorBlockedChanged(INDIVIDUAL_SENSOR_MICROPHONE, false);
+        mController.onSensorBlockedChanged(MICROPHONE, false);
         mTestableLooper.processAllMessages();
 
         list = mController.getActiveAppOps();
@@ -537,7 +538,7 @@
         assertFalse(list.get(0).isDisabled());
 
         // Add an audio op, and disable the camera. The audio op should be the only op returned
-        mController.onSensorBlockedChanged(INDIVIDUAL_SENSOR_CAMERA, true);
+        mController.onSensorBlockedChanged(CAMERA, true);
         mController.onOpActiveChanged(
                 AppOpsManager.OP_RECORD_AUDIO, TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
         mTestableLooper.processAllMessages();
@@ -546,7 +547,7 @@
         assertEquals(AppOpsManager.OP_RECORD_AUDIO, list.get(0).getCode());
 
         // Re enable the camera, and verify the op returns
-        mController.onSensorBlockedChanged(INDIVIDUAL_SENSOR_CAMERA, false);
+        mController.onSensorBlockedChanged(CAMERA, false);
         mTestableLooper.processAllMessages();
 
         list = mController.getActiveAppOps();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index 3e873d1..700f101 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -150,7 +150,10 @@
     }
 
     @Test
-    public void dozeTimeTick() {
+    public void dozeTimeTick() throws RemoteException {
+        mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
+        mFgExecutor.runAllReady();
         mUdfpsController.dozeTimeTick();
         verify(mUdfpsView).dozeTimeTick();
     }
@@ -240,7 +243,8 @@
 
     @Test
     public void registersViewForCallbacks() throws RemoteException {
-        verify(mStatusBarStateController).addCallback(mUdfpsView);
-        verify(mStatusBar).addExpansionChangedListener(mUdfpsView);
+        verify(mStatusBarStateController).addCallback(mUdfpsController.mStatusBarStateListener);
+        verify(mStatusBar).addExpansionChangedListener(
+                mUdfpsController.mStatusBarExpansionListener);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java
index 6d8c372..afe5c0b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java
@@ -41,7 +41,9 @@
 
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.tuner.TunerService;
 import com.android.systemui.util.wakelock.WakeLockFake;
 
 import org.junit.After;
@@ -67,10 +69,14 @@
     private DozeHost mHost;
     @Mock
     private DozeLog mDozeLog;
+    @Mock
+    private TunerService mTunerService;
     private WakeLockFake mWakeLock;
     private Handler mHandler;
     private HandlerThread mHandlerThread;
     private DozeUi mDozeUi;
+    @Mock
+    private StatusBarStateController mStatusBarStateController;
 
     @Before
     public void setUp() throws Exception {
@@ -82,7 +88,8 @@
         mHandler = mHandlerThread.getThreadHandler();
 
         mDozeUi = new DozeUi(mContext, mAlarmManager, mWakeLock, mHost, mHandler,
-                mDozeParameters, mKeyguardUpdateMonitor, mDozeLog);
+                mDozeParameters, mKeyguardUpdateMonitor, mDozeLog, mTunerService,
+                () -> mStatusBarStateController);
         mDozeUi.setDozeMachine(mMachine);
     }
 
@@ -138,7 +145,8 @@
         reset(mHost);
         when(mDozeParameters.getDisplayNeedsBlanking()).thenReturn(true);
         mDozeUi = new DozeUi(mContext, mAlarmManager, mWakeLock, mHost, mHandler,
-                mDozeParameters, mKeyguardUpdateMonitor, mDozeLog);
+                mDozeParameters, mKeyguardUpdateMonitor, mDozeLog, mTunerService,
+                () -> mStatusBarStateController);
         mDozeUi.setDozeMachine(mMachine);
 
         // Never animate if display doesn't support it.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagReaderTest.java b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagReaderTest.java
index c79037b..223714c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagReaderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagReaderTest.java
@@ -18,7 +18,6 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
@@ -27,59 +26,44 @@
 import static org.mockito.Mockito.when;
 
 import android.content.res.Resources;
-import android.provider.DeviceConfig;
 
 import androidx.annotation.BoolRes;
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.assist.DeviceConfigHelper;
 import com.android.systemui.util.wrapper.BuildInfo;
 
 import org.junit.Before;
 import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.Executor;
-
 @SmallTest
 public class FeatureFlagReaderTest extends SysuiTestCase {
     @Mock private Resources mResources;
     @Mock private BuildInfo mBuildInfo;
-    @Mock private DeviceConfigHelper mDeviceConfig;
-    @Mock private Executor mBackgroundExecutor;
+    @Mock private SystemPropertiesHelper mSystemPropertiesHelper;
 
     private FeatureFlagReader mReader;
 
-    @Captor private ArgumentCaptor<DeviceConfig.OnPropertiesChangedListener> mListenerCaptor;
-    private DeviceConfig.OnPropertiesChangedListener mPropChangeListener;
-
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
-        when(mDeviceConfig.getBoolean(anyString(), anyBoolean()))
+        when(mSystemPropertiesHelper.getBoolean(anyString(), anyBoolean()))
                 .thenAnswer(invocation -> invocation.getArgument(1));
 
         defineFlag(FLAG_RESID_0, false);
         defineFlag(FLAG_RESID_1, true);
 
         initialize(true, true);
-
-        verify(mDeviceConfig).addOnPropertiesChangedListener(any(), mListenerCaptor.capture());
-        mPropChangeListener = mListenerCaptor.getValue();
     }
 
     private void initialize(boolean isDebuggable, boolean isOverrideable) {
         when(mBuildInfo.isDebuggable()).thenReturn(isDebuggable);
         when(mResources.getBoolean(R.bool.are_flags_overrideable)).thenReturn(isOverrideable);
-        mReader = new FeatureFlagReader(mResources, mBuildInfo, mDeviceConfig, mBackgroundExecutor);
+        mReader = new FeatureFlagReader(mResources, mBuildInfo, mSystemPropertiesHelper);
     }
 
     @Test
@@ -136,24 +120,8 @@
 
         // THEN the underlying resource and override are only queried once
         verify(mResources, times(1)).getBoolean(FLAG_RESID_0);
-        verify(mDeviceConfig, times(1)).getBoolean(fakeStorageKey(FLAG_RESID_0), false);
-    }
-
-    @Test
-    public void testCachesAreClearedAfterPropsChange() {
-        // GIVEN a flag whose value has already been queried
-        assertFalse(mReader.isEnabled(FLAG_RESID_0));
-
-        // WHEN the value of the flag changes
-        overrideFlag(FLAG_RESID_0, true);
-        Map<String, String> changedMap = new HashMap<>();
-        changedMap.put(fakeStorageKey(FLAG_RESID_0), "true");
-        DeviceConfig.Properties properties =
-                new DeviceConfig.Properties("systemui", changedMap);
-        mPropChangeListener.onPropertiesChanged(properties);
-
-        // THEN the new value is provided
-        assertTrue(mReader.isEnabled(FLAG_RESID_0));
+        verify(mSystemPropertiesHelper, times(1))
+                .getBoolean(fakeStorageKey(FLAG_RESID_0), false);
     }
 
     private void defineFlag(int resId, boolean value) {
@@ -162,12 +130,12 @@
     }
 
     private void overrideFlag(int resId, boolean value) {
-        when(mDeviceConfig.getBoolean(eq(fakeStorageKey(resId)), anyBoolean()))
+        when(mSystemPropertiesHelper.getBoolean(eq(fakeStorageKey(resId)), anyBoolean()))
                 .thenReturn(value);
     }
 
     private String fakeStorageKey(@BoolRes int resId) {
-        return "flag_testname_" + resId;
+        return "persist.systemui.flag_testname_" + resId;
     }
 
     private static final int FLAG_RESID_0 = 47;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/EglHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/EglHelperTest.java
index e23507b..a3221b5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/EglHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/EglHelperTest.java
@@ -50,6 +50,7 @@
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
+@Ignore
 public class EglHelperTest extends SysuiTestCase {
 
     @Spy
diff --git a/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/ImageWallpaperRendererTest.java b/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/ImageWallpaperRendererTest.java
index 24f3eb2..510b907 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/ImageWallpaperRendererTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/ImageWallpaperRendererTest.java
@@ -33,6 +33,7 @@
 import com.android.systemui.SysuiTestCase;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -43,6 +44,7 @@
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
+@Ignore
 public class ImageWallpaperRendererTest extends SysuiTestCase {
 
     private WallpaperManager mWpmSpy;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NearestTouchFrameTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NearestTouchFrameTest.java
index 0320103..c8f223b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NearestTouchFrameTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NearestTouchFrameTest.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.navigationbar.buttons;
 
+import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
@@ -25,6 +26,7 @@
 import static org.mockito.Mockito.when;
 
 import android.content.res.Configuration;
+import android.graphics.Rect;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.MotionEvent;
@@ -39,6 +41,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Map;
+
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
 @SmallTest
@@ -51,6 +55,7 @@
         Configuration c = new Configuration(mContext.getResources().getConfiguration());
         c.smallestScreenWidthDp = 500;
         mNearestTouchFrame = new NearestTouchFrame(mContext, null, c);
+        mNearestTouchFrame.layout(0, 0, 100, 100);
     }
 
     @Test
@@ -64,7 +69,7 @@
 
         mNearestTouchFrame.addView(left);
         mNearestTouchFrame.addView(right);
-        mNearestTouchFrame.onMeasure(0, 0);
+        mNearestTouchFrame.layout(0, 0, 30, 30);
 
         MotionEvent ev = MotionEvent.obtain(0, 0, 0,
                 12 /* x */, 5 /* y */, 0);
@@ -81,7 +86,7 @@
 
         mNearestTouchFrame.addView(left);
         mNearestTouchFrame.addView(right);
-        mNearestTouchFrame.onMeasure(0, 0);
+        mNearestTouchFrame.layout(0, 0, 30, 30);
 
         MotionEvent ev = MotionEvent.obtain(0, 0, 0,
                 12 /* x */, 5 /* y */, 0);
@@ -100,7 +105,7 @@
 
         mNearestTouchFrame.addView(left);
         mNearestTouchFrame.addView(right);
-        mNearestTouchFrame.onMeasure(0, 0);
+        mNearestTouchFrame.layout(0, 0, 30, 30);
 
         // Would go to left view if attached, but goes to right instead as left should be detached.
         MotionEvent ev = MotionEvent.obtain(0, 0, 0,
@@ -117,7 +122,7 @@
 
         mNearestTouchFrame.addView(left);
         mNearestTouchFrame.addView(right);
-        mNearestTouchFrame.onMeasure(0, 0);
+        mNearestTouchFrame.layout(0, 0, 30, 30);
 
         MotionEvent ev = MotionEvent.obtain(0, 0, 0,
                 12 /* x */, 5 /* y */, 0);
@@ -133,7 +138,7 @@
 
         mNearestTouchFrame.addView(left);
         mNearestTouchFrame.addView(right);
-        mNearestTouchFrame.onMeasure(0, 0);
+        mNearestTouchFrame.layout(0, 0, 30, 30);
 
         MotionEvent ev = MotionEvent.obtain(0, 0, 0,
                 18 /* x */, 5 /* y */, 0);
@@ -146,10 +151,10 @@
     public void testVerticalSelection_Top() {
         View top = mockViewAt(0, 0, 10, 10);
         View bottom = mockViewAt(0, 20, 10, 10);
-
+        mNearestTouchFrame.setIsVertical(true);
         mNearestTouchFrame.addView(top);
         mNearestTouchFrame.addView(bottom);
-        mNearestTouchFrame.onMeasure(0, 0);
+        mNearestTouchFrame.layout(0, 0, 30, 30);
 
         MotionEvent ev = MotionEvent.obtain(0, 0, 0,
                 5 /* x */, 12 /* y */, 0);
@@ -162,10 +167,10 @@
     public void testVerticalSelection_Bottom() {
         View top = mockViewAt(0, 0, 10, 10);
         View bottom = mockViewAt(0, 20, 10, 10);
-
+        mNearestTouchFrame.setIsVertical(true);
         mNearestTouchFrame.addView(top);
         mNearestTouchFrame.addView(bottom);
-        mNearestTouchFrame.onMeasure(0, 0);
+        mNearestTouchFrame.layout(0, 0, 30, 30);
 
         MotionEvent ev = MotionEvent.obtain(0, 0, 0,
                 5 /* x */, 18 /* y */, 0);
@@ -179,7 +184,7 @@
         View view = mockViewAt(0, 20, 10, 10);
         when(view.isAttachedToWindow()).thenReturn(false);
         mNearestTouchFrame.addView(view);
-        mNearestTouchFrame.onMeasure(0, 0);
+        mNearestTouchFrame.layout(0, 0, 30, 30);
 
         MotionEvent ev = MotionEvent.obtain(0, 0, 0, 5 /* x */, 18 /* y */, 0);
         mNearestTouchFrame.onTouchEvent(ev);
@@ -187,6 +192,56 @@
         ev.recycle();
     }
 
+    @Test
+    public void testViewMiddleChildNotAttachedCrash() {
+        View view1 = mockViewAt(0, 20, 10, 10);
+        View view2 = mockViewAt(11, 20, 10, 10);
+        View view3 = mockViewAt(21, 20, 10, 10);
+        when(view2.isAttachedToWindow()).thenReturn(false);
+        mNearestTouchFrame.addView(view1);
+        mNearestTouchFrame.addView(view2);
+        mNearestTouchFrame.addView(view3);
+        mNearestTouchFrame.layout(0, 0, 30, 30);
+
+        MotionEvent ev = MotionEvent.obtain(0, 0, 0, 5 /* x */, 18 /* y */, 0);
+        mNearestTouchFrame.onTouchEvent(ev);
+        verify(view2, never()).onTouchEvent(eq(ev));
+        ev.recycle();
+    }
+
+    @Test
+    public void testCachedRegionsSplit_horizontal() {
+        View left = mockViewAt(0, 0, 5, 20);
+        View right = mockViewAt(15, 0, 5, 20);
+        mNearestTouchFrame.addView(left);
+        mNearestTouchFrame.addView(right);
+        mNearestTouchFrame.layout(0, 0, 20, 20);
+
+        Map<View, Rect> childRegions = mNearestTouchFrame.getFullTouchableChildRegions();
+        assertEquals(2, childRegions.size());
+        Rect leftRegion = childRegions.get(left);
+        Rect rightRegion = childRegions.get(right);
+        assertEquals(new Rect(0, 0, 9, 20), leftRegion);
+        assertEquals(new Rect(10, 0, 20, 20), rightRegion);
+    }
+
+    @Test
+    public void testCachedRegionsSplit_vertical() {
+        View top = mockViewAt(0, 0, 20, 5);
+        View bottom = mockViewAt(0, 15, 20, 5);
+        mNearestTouchFrame.addView(top);
+        mNearestTouchFrame.addView(bottom);
+        mNearestTouchFrame.setIsVertical(true);
+        mNearestTouchFrame.layout(0, 0, 20, 20);
+
+        Map<View, Rect> childRegions = mNearestTouchFrame.getFullTouchableChildRegions();
+        assertEquals(2, childRegions.size());
+        Rect topRegion = childRegions.get(top);
+        Rect bottomRegion = childRegions.get(bottom);
+        assertEquals(new Rect(0, 0, 20, 9), topRegion);
+        assertEquals(new Rect(0, 10, 20, 20), bottomRegion);
+    }
+
     private View mockViewAt(int x, int y, int width, int height) {
         View v = spy(new View(mContext));
         doAnswer(invocation -> {
@@ -197,6 +252,8 @@
         }).when(v).getLocationInWindow(any());
         when(v.isClickable()).thenReturn(true);
         when(v.isAttachedToWindow()).thenReturn(true);
+        when(v.getWidth()).thenReturn(width);
+        when(v.getHeight()).thenReturn(height);
 
         // Stupid final methods.
         v.setLeft(0);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
index d79155c..2a4b41c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.people;
 
+import static android.app.Notification.CATEGORY_MISSED_CALL;
 import static android.app.people.ConversationStatus.ACTIVITY_BIRTHDAY;
 import static android.app.people.ConversationStatus.ACTIVITY_GAME;
 import static android.app.people.ConversationStatus.ACTIVITY_NEW_STORY;
@@ -113,6 +114,7 @@
     private static final Uri URI = Uri.parse("fake_uri");
     private static final Icon ICON = Icon.createWithResource("package", R.drawable.ic_android);
     private static final String GAME_DESCRIPTION = "Playing a game!";
+    private static final CharSequence MISSED_CALL = "Custom missed call message";
     private static final String NAME = "username";
     private static final Person PERSON = new Person.Builder()
             .setName("name")
@@ -346,7 +348,7 @@
                 .build();
 
         Notification.MessagingStyle.Message lastMessage =
-                PeopleSpaceUtils.getLastMessagingStyleMessage(sbn);
+                PeopleSpaceUtils.getLastMessagingStyleMessage(sbn.getNotification());
 
         assertThat(lastMessage).isNull();
     }
@@ -447,7 +449,7 @@
                 .build();
 
         Notification.MessagingStyle.Message lastMessage =
-                PeopleSpaceUtils.getLastMessagingStyleMessage(sbn);
+                PeopleSpaceUtils.getLastMessagingStyleMessage(sbn.getNotification());
 
         assertThat(lastMessage.getText().toString()).isEqualTo(NOTIFICATION_TEXT_2);
     }
@@ -462,10 +464,10 @@
                 new PeopleSpaceTile
                         .Builder(SHORTCUT_ID_1, "userName", ICON, new Intent())
                         .setPackageName(PACKAGE_NAME)
-                        .setUid(0)
+                        .setUserHandle(new UserHandle(0))
                         .build();
         PeopleSpaceTile actual = PeopleSpaceUtils
-                .augmentTileFromNotification(tile, sbn);
+                .augmentTileFromNotification(mContext, tile, sbn);
 
         assertThat(actual.getNotificationContent().toString()).isEqualTo(NOTIFICATION_TEXT_2);
     }
@@ -480,12 +482,11 @@
                 new PeopleSpaceTile
                         .Builder(SHORTCUT_ID_3, "userName", ICON, new Intent())
                         .setPackageName(PACKAGE_NAME)
-                        .setUid(0)
+                        .setUserHandle(new UserHandle(0))
                         .build();
         PeopleSpaceTile actual = PeopleSpaceUtils
-                .augmentTileFromNotification(tile, sbn);
+                .augmentTileFromNotification(mContext, tile, sbn);
 
-        assertThat(actual.getNotificationKey()).isEqualTo(null);
         assertThat(actual.getNotificationContent()).isEqualTo(null);
     }
 
@@ -495,10 +496,10 @@
                 new PeopleSpaceTile
                         .Builder(SHORTCUT_ID_1, "userName", ICON, new Intent())
                         .setPackageName(PACKAGE_NAME)
-                        .setUid(0)
+                        .setUserHandle(new UserHandle(0))
                         .build();
         PeopleSpaceTile actual = PeopleSpaceUtils
-                .augmentTileFromVisibleNotifications(tile,
+                .augmentTileFromVisibleNotifications(mContext, tile,
                         Map.of(PeopleSpaceUtils.getKey(mNotificationEntry1), mNotificationEntry1));
 
         assertThat(actual.getNotificationContent().toString()).isEqualTo(NOTIFICATION_TEXT_2);
@@ -510,10 +511,10 @@
                 new PeopleSpaceTile
                         .Builder(SHORTCUT_ID_4, "userName", ICON, new Intent())
                         .setPackageName(PACKAGE_NAME)
-                        .setUid(0)
+                        .setUserHandle(new UserHandle(0))
                         .build();
         PeopleSpaceTile actual = PeopleSpaceUtils
-                .augmentTileFromVisibleNotifications(tile,
+                .augmentTileFromVisibleNotifications(mContext, tile,
                         Map.of(PeopleSpaceUtils.getKey(mNotificationEntry1), mNotificationEntry1));
 
         assertThat(actual.getNotificationContent()).isEqualTo(null);
@@ -525,10 +526,11 @@
                 new PeopleSpaceTile
                         .Builder(SHORTCUT_ID_1, "userName", ICON, new Intent())
                         .setPackageName(PACKAGE_NAME)
-                        .setUid(0)
+                        .setUserHandle(new UserHandle(0))
                         .build();
         List<PeopleSpaceTile> actualList = PeopleSpaceUtils
-                .augmentTilesFromVisibleNotifications(List.of(tile), mNotificationEntryManager);
+                .augmentTilesFromVisibleNotifications(
+                        mContext, List.of(tile), mNotificationEntryManager);
 
         assertThat(actualList.size()).isEqualTo(1);
         assertThat(actualList.get(0).getNotificationContent().toString())
@@ -543,16 +545,16 @@
                 new PeopleSpaceTile
                         .Builder(SHORTCUT_ID_1, "userName", ICON, new Intent())
                         .setPackageName(PACKAGE_NAME)
-                        .setUid(1)
+                        .setUserHandle(new UserHandle(0))
                         .build();
         PeopleSpaceTile tile2 =
                 new PeopleSpaceTile
                         .Builder(SHORTCUT_ID_2, "userName2", ICON, new Intent())
                         .setPackageName(PACKAGE_NAME)
-                        .setUid(0)
+                        .setUserHandle(new UserHandle(0))
                         .build();
         List<PeopleSpaceTile> actualList = PeopleSpaceUtils
-                .augmentTilesFromVisibleNotifications(List.of(tile1, tile2),
+                .augmentTilesFromVisibleNotifications(mContext, List.of(tile1, tile2),
                         mNotificationEntryManager);
 
         assertThat(actualList.size()).isEqualTo(2);
@@ -763,6 +765,33 @@
     }
 
     @Test
+    public void testCreateRemoteViewsWithMissedCallNotification() {
+        PeopleSpaceTile tileWithMissedCallNotification = PERSON_TILE.toBuilder()
+                .setNotificationDataUri(null)
+                .setNotificationCategory(CATEGORY_MISSED_CALL)
+                .setNotificationContent(MISSED_CALL)
+                .build();
+        RemoteViews views = PeopleSpaceUtils.createRemoteViews(mContext,
+                tileWithMissedCallNotification, 0);
+        View result = views.apply(mContext, null);
+
+        TextView name = (TextView) result.findViewById(R.id.name);
+        assertEquals(name.getText(), NAME);
+        // Has availability.
+        View availability = result.findViewById(R.id.availability);
+        assertEquals(View.GONE, availability.getVisibility());
+        // Has new story.
+        View personIcon = result.findViewById(R.id.person_icon_only);
+        View personIconWithStory = result.findViewById(R.id.person_icon_with_story);
+        assertEquals(View.VISIBLE, personIcon.getVisibility());
+        assertEquals(View.GONE, personIconWithStory.getVisibility());
+        // Has status.
+        TextView statusContent = (TextView) result.findViewById(R.id.status);
+        assertEquals(statusContent.getText(), MISSED_CALL);
+    }
+
+
+    @Test
     public void testCreateRemoteViewsWithNotificationTemplate() {
         PeopleSpaceTile tileWithStatusAndNotification = PERSON_TILE.toBuilder()
                 .setNotificationDataUri(null)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
index 9470141..800d859 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.people.widget;
 
+import static android.app.Notification.CATEGORY_MISSED_CALL;
 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
 import static android.app.NotificationManager.IMPORTANCE_HIGH;
 
@@ -108,7 +109,7 @@
             new PeopleSpaceTile
                     .Builder(SHORTCUT_ID, "username", ICON, new Intent())
                     .setPackageName(TEST_PACKAGE_A)
-                    .setUid(0)
+                    .setUserHandle(new UserHandle(1))
                     .setNotificationKey(NOTIFICATION_KEY + "1")
                     .setNotificationContent(NOTIFICATION_CONTENT)
                     .setNotificationDataUri(URI)
@@ -167,7 +168,8 @@
         int[] widgetIdsArray = {};
         when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
 
-        StatusBarNotification sbn = createConversationNotification(OTHER_SHORTCUT_ID);
+        StatusBarNotification sbn = createNotification(
+                OTHER_SHORTCUT_ID, /* isMessagingStyle = */ false, /* isMissedCall = */ false);
         NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
                 .setSbn(sbn)
                 .setId(1));
@@ -207,7 +209,8 @@
         when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
 
         StatusBarNotification sbnWithoutPackageName = new SbnBuilder()
-                .setNotification(createMessagingStyleNotification(SHORTCUT_ID))
+                .setNotification(createMessagingStyleNotification(
+                        SHORTCUT_ID, /* isMessagingStyle = */ false, /* isMissedCall = */ false))
                 .build();
         NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
                 .setSbn(sbnWithoutPackageName)
@@ -256,7 +259,8 @@
         int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
         when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
 
-        StatusBarNotification sbn = createConversationNotification(OTHER_SHORTCUT_ID);
+        StatusBarNotification sbn = createNotification(
+                OTHER_SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ false);
         NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
                 .setSbn(sbn)
                 .setId(1));
@@ -276,7 +280,8 @@
         when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
 
         StatusBarNotification sbnWithDifferentPackageName = new SbnBuilder()
-                .setNotification(createMessagingStyleNotification(SHORTCUT_ID))
+                .setNotification(createMessagingStyleNotification(
+                        SHORTCUT_ID, /* isMessagingStyle = */ false, /* isMissedCall = */ false))
                 .setPkg(TEST_PACKAGE_B)
                 .build();
         NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
@@ -295,7 +300,8 @@
         int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
         when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
 
-        StatusBarNotification sbn = createConversationNotification(OTHER_SHORTCUT_ID);
+        StatusBarNotification sbn = createNotification(
+                OTHER_SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ false);
         NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
                 .setSbn(sbn)
                 .setId(1));
@@ -315,7 +321,8 @@
         when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
 
         StatusBarNotification sbnWithDifferentPackageName = new SbnBuilder()
-                .setNotification(createMessagingStyleNotification(SHORTCUT_ID))
+                .setNotification(createMessagingStyleNotification(
+                        SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ false))
                 .setPkg(TEST_PACKAGE_B)
                 .build();
         NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
@@ -337,7 +344,8 @@
         when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
 
         NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
-                .setSbn(createConversationNotification(SHORTCUT_ID))
+                .setSbn(createNotification(
+                        SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ false))
                 .setId(1));
         mClock.advanceTime(MIN_LINGER_DURATION);
 
@@ -367,7 +375,8 @@
         when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
 
         NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
-                .setSbn(createConversationNotification(SHORTCUT_ID))
+                .setSbn(createNotification(
+                        SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ false))
                 .setId(1));
         mClock.advanceTime(MIN_LINGER_DURATION);
 
@@ -400,7 +409,8 @@
 
         PeopleSpaceUtils.removeStorageForTile(mContext, SECOND_WIDGET_ID_WITH_SHORTCUT);
         NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
-                .setSbn(createConversationNotification(SHORTCUT_ID))
+                .setSbn(createNotification(
+                        SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ false))
                 .setId(1));
         mClock.advanceTime(MIN_LINGER_DURATION);
 
@@ -417,33 +427,52 @@
     }
 
     @Test
-    public void testDoNotUpdateNotificationPostedWithoutMessagesIfExistingTile()
+    public void testUpdateMissedCallNotificationWithoutContentPostedIfExistingTile()
             throws Exception {
         int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
         when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
         setStorageForTile(SHORTCUT_ID, TEST_PACKAGE_A, WIDGET_ID_WITH_SHORTCUT);
 
-        Notification notificationWithoutMessagingStyle = new Notification.Builder(mContext)
-                .setContentTitle("TEST_TITLE")
-                .setContentText("TEST_TEXT")
-                .setShortcutId(SHORTCUT_ID)
-                .build();
-        StatusBarNotification sbn = new SbnBuilder()
-                .setNotification(notificationWithoutMessagingStyle)
-                .setPkg(TEST_PACKAGE_A)
-                .setUid(0)
-                .build();
         NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
-                .setSbn(sbn)
+                .setSbn(createNotification(
+                        SHORTCUT_ID, /* isMessagingStyle = */ false, /* isMissedCall = */ true))
                 .setId(1));
         mClock.advanceTime(MIN_LINGER_DURATION);
 
         verify(mAppWidgetManager, times(1))
                 .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
                         mBundleArgumentCaptor.capture());
-        Bundle options = requireNonNull(mBundleArgumentCaptor.getValue());
-        assertThat((PeopleSpaceTile) options.getParcelable(OPTIONS_PEOPLE_SPACE_TILE))
-                .isEqualTo(PERSON_TILE);
+        Bundle bundle = requireNonNull(mBundleArgumentCaptor.getValue());
+
+        PeopleSpaceTile tile = bundle.getParcelable(OPTIONS_PEOPLE_SPACE_TILE);
+        assertThat(tile.getNotificationKey()).isEqualTo(NOTIFICATION_KEY);
+        assertThat(tile.getNotificationContent())
+                .isEqualTo(mContext.getString(R.string.missed_call));
+        verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
+                any());
+    }
+
+    @Test
+    public void testUpdateMissedCallNotificationWithContentPostedIfExistingTile()
+            throws Exception {
+        int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
+        when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+        setStorageForTile(SHORTCUT_ID, TEST_PACKAGE_A, WIDGET_ID_WITH_SHORTCUT);
+
+        NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
+                .setSbn(createNotification(
+                        SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ true))
+                .setId(1));
+        mClock.advanceTime(MIN_LINGER_DURATION);
+
+        verify(mAppWidgetManager, times(1))
+                .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
+                        mBundleArgumentCaptor.capture());
+        Bundle bundle = requireNonNull(mBundleArgumentCaptor.getValue());
+
+        PeopleSpaceTile tile = bundle.getParcelable(OPTIONS_PEOPLE_SPACE_TILE);
+        assertThat(tile.getNotificationKey()).isEqualTo(NOTIFICATION_KEY);
+        assertThat(tile.getNotificationContent()).isEqualTo(NOTIFICATION_CONTENT);
         verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
                 any());
     }
@@ -453,7 +482,8 @@
         int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
         when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
 
-        StatusBarNotification sbn = createConversationNotification(SHORTCUT_ID);
+        StatusBarNotification sbn = createNotification(
+                SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ false);
         NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
                 .setSbn(sbn)
                 .setId(1));
@@ -483,21 +513,29 @@
         return convo;
     }
 
-    private Notification createMessagingStyleNotification(String shortcutId) {
-        return new Notification.Builder(mContext)
+    private Notification createMessagingStyleNotification(String shortcutId,
+            boolean isMessagingStyle, boolean isMissedCall) {
+        Notification.Builder builder = new Notification.Builder(mContext)
                 .setContentTitle("TEST_TITLE")
                 .setContentText("TEST_TEXT")
-                .setShortcutId(shortcutId)
-                .setStyle(new Notification.MessagingStyle(PERSON)
-                        .addMessage(
-                                new Notification.MessagingStyle.Message(NOTIFICATION_CONTENT, 10,
-                                        PERSON))
-                )
-                .build();
+                .setShortcutId(shortcutId);
+        if (isMessagingStyle) {
+            builder.setStyle(new Notification.MessagingStyle(PERSON)
+                    .addMessage(
+                            new Notification.MessagingStyle.Message(NOTIFICATION_CONTENT, 10,
+                                    PERSON))
+            );
+        }
+        if (isMissedCall) {
+            builder.setCategory(CATEGORY_MISSED_CALL);
+        }
+        return builder.build();
     }
 
-    private StatusBarNotification createConversationNotification(String shortcutId) {
-        Notification notification = createMessagingStyleNotification(shortcutId);
+    private StatusBarNotification createNotification(String shortcutId,
+            boolean isMessagingStyle, boolean isMissedCall) {
+        Notification notification = createMessagingStyleNotification(
+                shortcutId, isMessagingStyle, isMissedCall);
         return new SbnBuilder()
                 .setNotification(notification)
                 .setPkg(TEST_PACKAGE_A)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java
index 2dfd388..d40e6a4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java
@@ -89,6 +89,8 @@
     private View mEdit;
     @Mock
     private MultiUserSwitch mMultiUserSwitch;
+    @Mock
+    private View mPowerMenuLiteView;
 
     private QSFooterViewController mController;
 
@@ -111,11 +113,12 @@
         when(mView.findViewById(R.id.build)).thenReturn(mBuildText);
         when(mView.findViewById(android.R.id.edit)).thenReturn(mEdit);
         when(mView.findViewById(R.id.multi_user_switch)).thenReturn(mMultiUserSwitch);
+        when(mView.findViewById(R.id.pm_lite)).thenReturn(mPowerMenuLiteView);
 
         mController = new QSFooterViewController(mView, mUserManager, mUserInfoController,
                 mActivityStarter, mDeviceProvisionedController, mUserTracker, mQSPanelController,
                 new QSDetailDisplayer(), mQuickQSPanelController, mFakeTunerService,
-                mMetricsLogger);
+                mMetricsLogger, false);
 
         mController.init();
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
index 0dfebab..a2a179e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
@@ -121,7 +121,6 @@
                 mQSTileHost, mQSCustomizerController, true, mMediaHost,
                 mQSTileRevealControllerFactory, mDumpManager, mMetricsLogger, mUiEventLogger,
                 mQSLogger, mBrightnessControllerFactory, mToggleSliderViewControllerFactory,
-                /* labelsFlag */ false,
                 mFeatureFlags
         );
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
index 5870200..cb380d5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
@@ -87,7 +87,6 @@
                 uiEventLogger,
                 qsLogger,
                 dumpManager,
-                false,
                 featureFlags
         )
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java
index e855834..5a1bd5f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java
@@ -33,9 +33,10 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.keyguard.CarrierTextManager;
+import com.android.keyguard.CarrierTextController;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators;
 import com.android.systemui.utils.leaks.LeakCheckedTest;
 import com.android.systemui.utils.os.FakeHandler;
 
@@ -54,7 +55,7 @@
 
     private QSCarrierGroupController mQSCarrierGroupController;
     private NetworkController.SignalCallback mSignalCallback;
-    private CarrierTextManager.CarrierTextCallback mCallback;
+    private CarrierTextController.CarrierTextCallback mCallback;
     @Mock
     private QSCarrierGroup mQSCarrierGroup;
     @Mock
@@ -62,9 +63,9 @@
     @Mock
     private NetworkController mNetworkController;
     @Mock
-    private CarrierTextManager.Builder mCarrierTextControllerBuilder;
+    private CarrierTextController.Builder mCarrierTextControllerBuilder;
     @Mock
-    private CarrierTextManager mCarrierTextManager;
+    private CarrierTextController mCarrierTextController;
     private TestableLooper mTestableLooper;
 
     @Before
@@ -83,11 +84,11 @@
                 .thenReturn(mCarrierTextControllerBuilder);
         when(mCarrierTextControllerBuilder.setShowMissingSim(anyBoolean()))
                 .thenReturn(mCarrierTextControllerBuilder);
-        when(mCarrierTextControllerBuilder.build()).thenReturn(mCarrierTextManager);
+        when(mCarrierTextControllerBuilder.build()).thenReturn(mCarrierTextController);
 
         doAnswer(invocation -> mCallback = invocation.getArgument(0))
-                .when(mCarrierTextManager)
-                .setListening(any(CarrierTextManager.CarrierTextCallback.class));
+                .when(mCarrierTextController)
+                .setListening(any(CarrierTextController.CarrierTextCallback.class));
 
         when(mQSCarrierGroup.getNoSimTextView()).thenReturn(new TextView(mContext));
         when(mQSCarrierGroup.getCarrier1View()).thenReturn(mock(QSCarrier.class));
@@ -113,8 +114,8 @@
                 (Answer<Integer>) invocationOnMock -> invocationOnMock.getArgument(0));
 
         // listOfCarriers length 1, subscriptionIds length 1, anySims false
-        CarrierTextManager.CarrierTextCallbackInfo
-                c1 = new CarrierTextManager.CarrierTextCallbackInfo(
+        CarrierTextController.CarrierTextCallbackInfo
+                c1 = new CarrierTextController.CarrierTextCallbackInfo(
                 "",
                 new CharSequence[]{""},
                 false,
@@ -122,8 +123,8 @@
         mCallback.updateCarrierInfo(c1);
 
         // listOfCarriers length 1, subscriptionIds length 1, anySims true
-        CarrierTextManager.CarrierTextCallbackInfo
-                c2 = new CarrierTextManager.CarrierTextCallbackInfo(
+        CarrierTextController.CarrierTextCallbackInfo
+                c2 = new CarrierTextController.CarrierTextCallbackInfo(
                 "",
                 new CharSequence[]{""},
                 true,
@@ -131,8 +132,8 @@
         mCallback.updateCarrierInfo(c2);
 
         // listOfCarriers length 2, subscriptionIds length 2, anySims false
-        CarrierTextManager.CarrierTextCallbackInfo
-                c3 = new CarrierTextManager.CarrierTextCallbackInfo(
+        CarrierTextController.CarrierTextCallbackInfo
+                c3 = new CarrierTextController.CarrierTextCallbackInfo(
                 "",
                 new CharSequence[]{"", ""},
                 false,
@@ -140,8 +141,8 @@
         mCallback.updateCarrierInfo(c3);
 
         // listOfCarriers length 2, subscriptionIds length 2, anySims true
-        CarrierTextManager.CarrierTextCallbackInfo
-                c4 = new CarrierTextManager.CarrierTextCallbackInfo(
+        CarrierTextController.CarrierTextCallbackInfo
+                c4 = new CarrierTextController.CarrierTextCallbackInfo(
                 "",
                 new CharSequence[]{"", ""},
                 true,
@@ -159,8 +160,8 @@
                 (Answer<Integer>) invocationOnMock -> invocationOnMock.getArgument(0));
 
         // listOfCarriers length 2, subscriptionIds length 1, anySims false
-        CarrierTextManager.CarrierTextCallbackInfo
-                c1 = new CarrierTextManager.CarrierTextCallbackInfo(
+        CarrierTextController.CarrierTextCallbackInfo
+                c1 = new CarrierTextController.CarrierTextCallbackInfo(
                 "",
                 new CharSequence[]{"", ""},
                 false,
@@ -168,8 +169,8 @@
         mCallback.updateCarrierInfo(c1);
 
         // listOfCarriers length 2, subscriptionIds length 1, anySims true
-        CarrierTextManager.CarrierTextCallbackInfo
-                c2 = new CarrierTextManager.CarrierTextCallbackInfo(
+        CarrierTextController.CarrierTextCallbackInfo
+                c2 = new CarrierTextController.CarrierTextCallbackInfo(
                 "",
                 new CharSequence[]{"", ""},
                 true,
@@ -177,8 +178,8 @@
         mCallback.updateCarrierInfo(c2);
 
         // listOfCarriers length 1, subscriptionIds length 2, anySims false
-        CarrierTextManager.CarrierTextCallbackInfo
-                c3 = new CarrierTextManager.CarrierTextCallbackInfo(
+        CarrierTextController.CarrierTextCallbackInfo
+                c3 = new CarrierTextController.CarrierTextCallbackInfo(
                 "",
                 new CharSequence[]{""},
                 false,
@@ -186,8 +187,8 @@
         mCallback.updateCarrierInfo(c3);
 
         // listOfCarriers length 1, subscriptionIds length 2, anySims true
-        CarrierTextManager.CarrierTextCallbackInfo
-                c4 = new CarrierTextManager.CarrierTextCallbackInfo(
+        CarrierTextController.CarrierTextCallbackInfo
+                c4 = new CarrierTextController.CarrierTextCallbackInfo(
                 "",
                 new CharSequence[]{""},
                 true,
@@ -203,8 +204,8 @@
         when(spiedCarrierGroupController.getSlotIndex(anyInt())).thenReturn(
                 SubscriptionManager.INVALID_SIM_SLOT_INDEX);
 
-        CarrierTextManager.CarrierTextCallbackInfo
-                c4 = new CarrierTextManager.CarrierTextCallbackInfo(
+        CarrierTextController.CarrierTextCallbackInfo
+                c4 = new CarrierTextController.CarrierTextCallbackInfo(
                 "",
                 new CharSequence[]{"", ""},
                 true,
@@ -215,16 +216,17 @@
 
     @Test // throws no Exception
     public void testSetMobileDataIndicators_invalidSim() {
-        mSignalCallback.setMobileDataIndicators(
+        MobileDataIndicators indicators = new MobileDataIndicators(
                 mock(NetworkController.IconState.class),
                 mock(NetworkController.IconState.class),
                 0, 0, true, true, "", "", "", true, 0, true, true);
+        mSignalCallback.setMobileDataIndicators(indicators);
     }
 
     @Test
     public void testNoEmptyVisibleView_airplaneMode() {
-        CarrierTextManager.CarrierTextCallbackInfo
-                info = new CarrierTextManager.CarrierTextCallbackInfo(
+        CarrierTextController.CarrierTextCallbackInfo
+                info = new CarrierTextController.CarrierTextCallbackInfo(
                 "",
                 new CharSequence[]{""},
                 true,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
index faf43a2..1c29a81 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
@@ -46,6 +46,7 @@
 import com.android.systemui.statusbar.policy.HotspotController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.NetworkController.WifiIndicators;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -134,9 +135,11 @@
     public void testStateUnavailable_wifiDisabled() {
         NetworkController.IconState qsIcon =
                 new NetworkController.IconState(false, 0, "");
-        mSignalCallback.setWifiIndicators(false, mock(NetworkController.IconState.class),
+        WifiIndicators indicators = new WifiIndicators(
+                false, mock(NetworkController.IconState.class),
                 qsIcon, false,false, "",
                 false, "");
+        mSignalCallback.setWifiIndicators(indicators);
         mTestableLooper.processAllMessages();
 
         assertEquals(Tile.STATE_UNAVAILABLE, mCastTile.getState().state);
@@ -146,9 +149,11 @@
     public void testStateUnavailable_wifiNotConnected() {
         NetworkController.IconState qsIcon =
                 new NetworkController.IconState(false, 0, "");
-        mSignalCallback.setWifiIndicators(true, mock(NetworkController.IconState.class),
+        WifiIndicators indicators = new WifiIndicators(
+                true, mock(NetworkController.IconState.class),
                 qsIcon, false,false, "",
                 false, "");
+        mSignalCallback.setWifiIndicators(indicators);
         mTestableLooper.processAllMessages();
 
         assertEquals(Tile.STATE_UNAVAILABLE, mCastTile.getState().state);
@@ -157,9 +162,11 @@
     private void enableWifiAndProcessMessages() {
         NetworkController.IconState qsIcon =
                 new NetworkController.IconState(true, 0, "");
-        mSignalCallback.setWifiIndicators(true, mock(NetworkController.IconState.class),
+        WifiIndicators indicators = new WifiIndicators(
+                true, mock(NetworkController.IconState.class),
                 qsIcon, false,false, "",
                 false, "");
+        mSignalCallback.setWifiIndicators(indicators);
         mTestableLooper.processAllMessages();
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
index d3dbe2b..ccd9548 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
@@ -25,7 +25,6 @@
 import androidx.test.filters.SmallTest
 import com.android.internal.logging.MetricsLogger
 import com.android.internal.logging.UiEventLogger
-import com.android.internal.widget.LockPatternUtils
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.controls.ControlsServiceInfo
 import com.android.systemui.controls.controller.ControlsController
@@ -37,9 +36,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.qs.QSHost
 import com.android.systemui.qs.logging.QSLogger
-import com.android.systemui.settings.UserTracker
 import com.android.systemui.statusbar.FeatureFlags
-import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.capture
 import com.android.systemui.util.settings.FakeSettings
@@ -49,7 +46,6 @@
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.mockito.Answers
 import org.mockito.ArgumentCaptor
 import org.mockito.Captor
 import org.mockito.Mock
@@ -57,6 +53,7 @@
 import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
+import java.util.Optional
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
@@ -73,6 +70,7 @@
     private lateinit var activityStarter: ActivityStarter
     @Mock
     private lateinit var qsLogger: QSLogger
+    @Mock
     private lateinit var controlsComponent: ControlsComponent
     @Mock
     private lateinit var controlsUiController: ControlsUiController
@@ -96,54 +94,64 @@
     private lateinit var testableLooper: TestableLooper
     private lateinit var tile: DeviceControlsTile
 
-    @Mock
-    private lateinit var keyguardStateController: KeyguardStateController
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private lateinit var userTracker: UserTracker
-    @Mock
-    private lateinit var lockPatternUtils: LockPatternUtils
-    @Mock
     private lateinit var secureSettings: SecureSettings
+    private var featureEnabled = true
 
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
         testableLooper = TestableLooper.get(this)
+        secureSettings = FakeSettings()
 
         `when`(qsHost.context).thenReturn(mContext)
         `when`(qsHost.uiEventLogger).thenReturn(uiEventLogger)
+        `when`(controlsController.available).thenReturn(true)
+        `when`(controlsComponent.isEnabled()).thenReturn(true)
+        secureSettings.putInt(Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT, 1)
 
-        controlsComponent = ControlsComponent(
-                true,
-                mContext,
-                { controlsController },
-                { controlsUiController },
-                { controlsListingController },
-                lockPatternUtils,
-                keyguardStateController,
-                userTracker,
-                secureSettings
-        )
+        setupControlsComponent()
 
         globalSettings = FakeSettings()
 
         globalSettings.putInt(DeviceControlsTile.SETTINGS_FLAG, 1)
         `when`(featureFlags.isKeyguardLayoutEnabled).thenReturn(true)
 
-        `when`(userTracker.userHandle.identifier).thenReturn(0)
-
         tile = createTile()
     }
 
+    private fun setupControlsComponent() {
+        `when`(controlsComponent.getControlsController()).thenAnswer {
+            if (featureEnabled) {
+                Optional.of(controlsController)
+            } else {
+                Optional.empty()
+            }
+        }
+
+        `when`(controlsComponent.getControlsListingController()).thenAnswer {
+            if (featureEnabled) {
+                Optional.of(controlsListingController)
+            } else {
+                Optional.empty()
+            }
+        }
+
+        `when`(controlsComponent.getControlsUiController()).thenAnswer {
+            if (featureEnabled) {
+                Optional.of(controlsUiController)
+            } else {
+                Optional.empty()
+            }
+        }
+    }
+
     @Test
     fun testAvailable() {
-        `when`(controlsController.available).thenReturn(true)
         assertThat(tile.isAvailable).isTrue()
     }
 
     @Test
     fun testNotAvailableFeature() {
-        `when`(controlsController.available).thenReturn(true)
         `when`(featureFlags.isKeyguardLayoutEnabled).thenReturn(false)
 
         assertThat(tile.isAvailable).isFalse()
@@ -151,24 +159,22 @@
 
     @Test
     fun testNotAvailableControls() {
-        controlsComponent = ControlsComponent(
-                false,
-                mContext,
-                { controlsController },
-                { controlsUiController },
-                { controlsListingController },
-                lockPatternUtils,
-                keyguardStateController,
-                userTracker,
-                secureSettings
-        )
+        featureEnabled = false
         tile = createTile()
 
         assertThat(tile.isAvailable).isFalse()
     }
 
     @Test
-    fun testNotAvailableFlag() {
+    fun testAvailableControlsSettingOff() {
+        `when`(controlsController.available).thenReturn(false)
+
+        tile = createTile()
+        assertThat(tile.isAvailable).isTrue()
+    }
+
+    @Test
+    fun testNotAvailableControlsLockscreenFlag() {
         globalSettings.putInt(DeviceControlsTile.SETTINGS_FLAG, 0)
         tile = createTile()
 
@@ -207,11 +213,26 @@
     }
 
     @Test
+    fun testStateUnavailableIfNotEnabled() {
+        verify(controlsListingController).observe(
+            any(LifecycleOwner::class.java),
+            capture(listingCallbackCaptor)
+        )
+        `when`(controlsComponent.isEnabled()).thenReturn(false)
+
+        listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))
+        testableLooper.processAllMessages()
+
+        assertThat(tile.state.state).isEqualTo(Tile.STATE_UNAVAILABLE)
+    }
+
+    @Test
     fun testStateAvailableIfListings() {
         verify(controlsListingController).observe(
                 any(LifecycleOwner::class.java),
                 capture(listingCallbackCaptor)
         )
+        `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE)
 
         listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))
         testableLooper.processAllMessages()
@@ -220,6 +241,21 @@
     }
 
     @Test
+    fun testStateInactiveIfLocked() {
+        verify(controlsListingController).observe(
+            any(LifecycleOwner::class.java),
+            capture(listingCallbackCaptor)
+        )
+        `when`(controlsComponent.getVisibility())
+            .thenReturn(ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK)
+
+        listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))
+        testableLooper.processAllMessages()
+
+        assertThat(tile.state.state).isEqualTo(Tile.STATE_INACTIVE)
+    }
+
+    @Test
     fun testMoveBetweenStates() {
         verify(controlsListingController).observe(
                 any(LifecycleOwner::class.java),
@@ -249,6 +285,7 @@
                 any(LifecycleOwner::class.java),
                 capture(listingCallbackCaptor)
         )
+        `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE)
 
         listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))
         testableLooper.processAllMessages()
@@ -260,6 +297,24 @@
     }
 
     @Test
+    fun testNoDialogWhenInactive() {
+        verify(controlsListingController).observe(
+            any(LifecycleOwner::class.java),
+            capture(listingCallbackCaptor)
+        )
+        `when`(controlsComponent.getVisibility())
+            .thenReturn(ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK)
+
+        listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))
+        testableLooper.processAllMessages()
+
+        tile.click()
+        testableLooper.processAllMessages()
+
+        verify(controlsDialog, never()).show(any(ControlsUiController::class.java))
+    }
+
+    @Test
     fun testDialogDismissedOnDestroy() {
         verify(controlsListingController).observe(
                 any(LifecycleOwner::class.java),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/FakeScrollCaptureConnection.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/FakeScrollCaptureConnection.java
index a75c39c..9e62a62 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/FakeScrollCaptureConnection.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/FakeScrollCaptureConnection.java
@@ -24,6 +24,7 @@
 import android.graphics.RecordingCanvas;
 import android.graphics.Rect;
 import android.graphics.RenderNode;
+import android.os.ICancellationSignal;
 import android.os.RemoteException;
 import android.view.IScrollCaptureCallbacks;
 import android.view.IScrollCaptureConnection;
@@ -46,7 +47,7 @@
     }
 
     @Override
-    public void startCapture(Surface surface) {
+    public ICancellationSignal startCapture(Surface surface) {
         mSurface = surface;
         mHwuiContext = new HwuiContext(false, surface);
         mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
@@ -56,27 +57,28 @@
         } catch (RemoteException e) {
             e.rethrowAsRuntimeException();
         }
+        return null;
     }
 
     @Override
-    public void requestImage(Rect rect) {
+    public ICancellationSignal requestImage(Rect rect) {
         Canvas canvas = mHwuiContext.lockCanvas(rect.width(), rect.height());
         mPaint.setColor(mColors[mNextColor]);
         canvas.drawRect(rect, mPaint);
         mNextColor = (mNextColor++) % mColors.length;
-        long frameNumber = mSurface.getNextFrameNumber();
         mHwuiContext.unlockAndPost(canvas);
         try {
-            mCallbacks.onCaptureBufferSent(frameNumber, rect);
+            mCallbacks.onImageRequestCompleted(0, rect);
         } catch (RemoteException e) {
             e.rethrowAsRuntimeException();
         }
+        return null;
     }
 
     @Override
-    public void endCapture() {
+    public ICancellationSignal endCapture() {
         try {
-            mCallbacks.onConnectionClosed();
+            mCallbacks.onCaptureEnded();
         } catch (RemoteException e) {
             e.rethrowAsRuntimeException();
         } finally {
@@ -84,6 +86,12 @@
             mSurface = null;
             mCallbacks = null;
         }
+        return null;
+    }
+
+    @Override
+    public void close() throws RemoteException {
+
     }
 
     // From android.view.Surface, but issues render requests synchronously with waitForPresent(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureClientTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureClientTest.java
index 580f800..802b462 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureClientTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureClientTest.java
@@ -29,7 +29,6 @@
 import static java.util.Objects.requireNonNull;
 
 import android.content.Context;
-import android.graphics.Point;
 import android.graphics.Rect;
 import android.hardware.display.DisplayManager;
 import android.os.RemoteException;
@@ -37,6 +36,7 @@
 import android.view.Display;
 import android.view.IScrollCaptureCallbacks;
 import android.view.IWindowManager;
+import android.view.ScrollCaptureResponse;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
@@ -82,10 +82,11 @@
     public void testBasicClientFlow() throws RemoteException {
         doAnswer((Answer<Void>) invocation -> {
             IScrollCaptureCallbacks cb = invocation.getArgument(3);
-            cb.onConnected(
-                    new FakeScrollCaptureConnection(cb),
-                    /* scrollBounds */ new Rect(0, 0, 100, 100),
-                    /* positionInWindow */ new Point(0, 0));
+            cb.onScrollCaptureResponse(new ScrollCaptureResponse.Builder()
+                    .setBoundsInWindow(new Rect(0, 0, 100, 100))
+                    .setWindowBounds(new Rect(0, 0, 100, 100))
+                    .setConnection(new FakeScrollCaptureConnection(cb))
+                    .build());
             return null;
         }).when(mWm).requestScrollCapture(/* displayId */ anyInt(), /* token */  isNull(),
                 /* taskId */ anyInt(), any(IScrollCaptureCallbacks.class));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureTest.java
index 2b3ca7c..6564d58 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureTest.java
@@ -19,15 +19,14 @@
 import static org.junit.Assert.fail;
 
 import android.content.Intent;
-import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.RemoteException;
 import android.testing.AndroidTestingRunner;
 import android.util.Log;
 import android.view.Display;
 import android.view.IScrollCaptureCallbacks;
-import android.view.IScrollCaptureConnection;
 import android.view.IWindowManager;
+import android.view.ScrollCaptureResponse;
 import android.view.WindowManagerGlobal;
 
 import androidx.test.filters.SmallTest;
@@ -67,31 +66,27 @@
             wms.requestScrollCapture(Display.DEFAULT_DISPLAY, null, -1,
                     new IScrollCaptureCallbacks.Stub() {
                         @Override
-                        public void onConnected(
-                                IScrollCaptureConnection connection, Rect scrollBounds,
-                                Point positionInWindow) {
-                            Log.d(TAG,
-                                    "client connected: " + connection + "[scrollBounds= "
-                                            + scrollBounds + ", "
-                                            + "positionInWindow=" + positionInWindow + "]");
+                        public void onScrollCaptureResponse(ScrollCaptureResponse response)
+                                throws RemoteException {
+                            Log.d(TAG, "onScrollCaptureResponse: " + response);
                             latch.countDown();
                         }
 
                         @Override
-                        public void onUnavailable() {
-                        }
-
-                        @Override
                         public void onCaptureStarted() {
                         }
 
                         @Override
-                        public void onCaptureBufferSent(long frameNumber, Rect capturedArea) {
+                        public void onImageRequestCompleted(int i, Rect rect)
+                                throws RemoteException {
+
                         }
 
                         @Override
-                        public void onConnectionClosed() {
+                        public void onCaptureEnded() throws RemoteException {
+
                         }
+
                     });
         } catch (RemoteException e) {
             Log.e(TAG, "request failed", e);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 0cae6742..7ff056e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar;
 
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT;
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
 import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE;
 
 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_DISCLOSURE;
@@ -40,6 +42,7 @@
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.TrustManager;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.UserInfo;
@@ -94,8 +97,12 @@
 
     private static final String ORGANIZATION_NAME = "organization";
 
+    private static final ComponentName DEVICE_OWNER_COMPONENT = new ComponentName("com.android.foo",
+            "bar");
+
     private String mDisclosureWithOrganization;
     private String mDisclosureGeneric;
+    private String mFinancedDisclosureWithOrganization;
 
     @Mock
     private DevicePolicyManager mDevicePolicyManager;
@@ -156,6 +163,8 @@
         mDisclosureWithOrganization = mContext.getString(R.string.do_disclosure_with_name,
                 ORGANIZATION_NAME);
         mDisclosureGeneric = mContext.getString(R.string.do_disclosure_generic);
+        mFinancedDisclosureWithOrganization = mContext.getString(
+                R.string.do_financed_disclosure_with_name, ORGANIZATION_NAME);
 
         when(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
         when(mKeyguardUpdateMonitor.isScreenOn()).thenReturn(true);
@@ -165,6 +174,11 @@
                 .thenReturn(mIndicationAreaBottom);
         when(mIndicationArea.findViewById(R.id.keyguard_indication_text)).thenReturn(mTextView);
 
+        when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser())
+                .thenReturn(DEVICE_OWNER_COMPONENT);
+        when(mDevicePolicyManager.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
+                .thenReturn(DEVICE_OWNER_TYPE_DEFAULT);
+
         mWakeLock = new WakeLockFake();
         mWakeLockBuilder = new WakeLockFake.Builder(mContext);
         mWakeLockBuilder.setWakeLock(mWakeLock);
@@ -372,6 +386,22 @@
     }
 
     @Test
+    public void disclosure_deviceOwner_financedDeviceWithOrganizationName() {
+        createController();
+
+        when(mDevicePolicyManager.isDeviceManaged()).thenReturn(true);
+        when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn(ORGANIZATION_NAME);
+        when(mDevicePolicyManager.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
+                .thenReturn(DEVICE_OWNER_TYPE_FINANCED);
+        sendUpdateDisclosureBroadcast();
+
+        verify(mRotateTextViewController).updateIndication(eq(INDICATION_TYPE_DISCLOSURE),
+                mKeyguardIndicationCaptor.capture(), eq(false));
+        assertThat(mKeyguardIndicationCaptor.getValue().getMessage())
+                .isEqualTo(mFinancedDisclosureWithOrganization);
+    }
+
+    @Test
     public void transientIndication_holdsWakeLock_whenDozing() {
         createController();
 
@@ -609,6 +639,16 @@
         assertThat(mTextView.getText()).isEqualTo(percentage);
     }
 
+    @Test
+    public void onRequireUnlockForNfc_showsRequireUnlockForNfcIndication() {
+        createController();
+        String message = mContext.getString(R.string.require_unlock_for_nfc);
+        mController.getKeyguardCallback().onRequireUnlockForNfc();
+        mController.setVisible(true);
+
+        assertThat(mTextView.getText()).isEqualTo(message);
+    }
+
     private void sendUpdateDisclosureBroadcast() {
         mBroadcastReceiver.onReceive(mContext, new Intent());
     }
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 05cf33a..b493b9a 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
@@ -171,62 +171,10 @@
     }
 
     @Test
-    public void testSuppressSystemAlertNotification() {
-        when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(false);
-        when(mFsc.isSystemAlertNotification(any())).thenReturn(true);
-        StatusBarNotification sbn = mRow.getEntry().getSbn();
-        Bundle bundle = new Bundle();
-        bundle.putStringArray(Notification.EXTRA_FOREGROUND_APPS, new String[]{"something"});
-        sbn.getNotification().extras = bundle;
-
-        assertTrue(mNotificationFilter.shouldFilterOut(mRow.getEntry()));
-    }
-
-    @Test
-    public void testDoNotSuppressSystemAlertNotification() {
-        StatusBarNotification sbn = mRow.getEntry().getSbn();
-        Bundle bundle = new Bundle();
-        bundle.putStringArray(Notification.EXTRA_FOREGROUND_APPS, new String[]{"something"});
-        sbn.getNotification().extras = bundle;
-
-        when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(true);
-        when(mFsc.isSystemAlertNotification(any())).thenReturn(true);
-
-        assertFalse(mNotificationFilter.shouldFilterOut(mRow.getEntry()));
-
-        when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(true);
-        when(mFsc.isSystemAlertNotification(any())).thenReturn(false);
-
-        assertFalse(mNotificationFilter.shouldFilterOut(mRow.getEntry()));
-
-        when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(false);
-        when(mFsc.isSystemAlertNotification(any())).thenReturn(false);
-
-        assertFalse(mNotificationFilter.shouldFilterOut(mRow.getEntry()));
-    }
-
-    @Test
-    public void testDoNotSuppressMalformedSystemAlertNotification() {
-        when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(true);
-
-        // missing extra
-        assertFalse(mNotificationFilter.shouldFilterOut(mRow.getEntry()));
-
-        StatusBarNotification sbn = mRow.getEntry().getSbn();
-        Bundle bundle = new Bundle();
-        bundle.putStringArray(Notification.EXTRA_FOREGROUND_APPS, new String[]{});
-        sbn.getNotification().extras = bundle;
-
-        // extra missing values
-        assertFalse(mNotificationFilter.shouldFilterOut(mRow.getEntry()));
-    }
-
-    @Test
     public void testShouldFilterHiddenNotifications() {
         initStatusBarNotification(false);
         // setup
         when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(false);
-        when(mFsc.isSystemAlertNotification(any())).thenReturn(false);
 
         // test should filter out hidden notifications:
         // hidden
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
index ce0f122..9a5482c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
@@ -377,8 +377,6 @@
         // THEN we send the dismissal to system server
         verify(mStatusBarService).onNotificationClear(
                 notif2.sbn.getPackageName(),
-                notif2.sbn.getTag(),
-                88,
                 notif2.sbn.getUser().getIdentifier(),
                 notif2.sbn.getKey(),
                 stats.dismissalSurface,
@@ -528,8 +526,6 @@
         // THEN we never send the dismissal to system server
         verify(mStatusBarService, never()).onNotificationClear(
                 notif.sbn.getPackageName(),
-                notif.sbn.getTag(),
-                47,
                 notif.sbn.getUser().getIdentifier(),
                 notif.sbn.getKey(),
                 stats.dismissalSurface,
@@ -566,8 +562,6 @@
         // THEN the notification is never sent to system server to dismiss
         verify(mStatusBarService, never()).onNotificationClear(
                 eq(notif.sbn.getPackageName()),
-                eq(notif.sbn.getTag()),
-                eq(47),
                 eq(notif.sbn.getUser().getIdentifier()),
                 eq(notif.sbn.getKey()),
                 anyInt(),
@@ -596,8 +590,6 @@
         // THEN we send the dismissal to system server
         verify(mStatusBarService).onNotificationClear(
                 eq(notif.sbn.getPackageName()),
-                eq(notif.sbn.getTag()),
-                eq(47),
                 eq(notif.sbn.getUser().getIdentifier()),
                 eq(notif.sbn.getKey()),
                 anyInt(),
@@ -1125,8 +1117,6 @@
         // THEN we send the dismissals to system server
         verify(mStatusBarService).onNotificationClear(
                 notif1.sbn.getPackageName(),
-                notif1.sbn.getTag(),
-                47,
                 notif1.sbn.getUser().getIdentifier(),
                 notif1.sbn.getKey(),
                 stats1.dismissalSurface,
@@ -1135,8 +1125,6 @@
 
         verify(mStatusBarService).onNotificationClear(
                 notif2.sbn.getPackageName(),
-                notif2.sbn.getTag(),
-                88,
                 notif2.sbn.getUser().getIdentifier(),
                 notif2.sbn.getKey(),
                 stats2.dismissalSurface,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java
index 0954621..2784568 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java
@@ -115,41 +115,6 @@
     }
 
     @Test
-    public void filterTest_systemAlertNotificationUnnecessary() {
-        // GIVEN the alert notification isn't needed for this user
-        final Bundle extras = new Bundle();
-        extras.putStringArray(Notification.EXTRA_FOREGROUND_APPS,
-                new String[]{TEST_PKG});
-        mEntryBuilder.modifyNotification(mContext)
-                .setExtras(extras);
-        NotificationEntry entry = mEntryBuilder.build();
-        StatusBarNotification sbn = entry.getSbn();
-        when(mForegroundServiceController.isSystemAlertWarningNeeded(sbn.getUserId(), TEST_PKG))
-                .thenReturn(false);
-
-        // GIVEN the notification is a system alert notification + not a disclosure notification
-        when(mForegroundServiceController.isSystemAlertNotification(sbn)).thenReturn(true);
-        when(mForegroundServiceController.isDisclosureNotification(sbn)).thenReturn(false);
-
-
-        // THEN filter out the notification
-        assertTrue(mForegroundFilter.shouldFilterOut(entry, 0));
-    }
-
-    @Test
-    public void filterTest_doNotFilter() {
-        NotificationEntry entry = mEntryBuilder.build();
-        StatusBarNotification sbn = entry.getSbn();
-
-        // GIVEN the notification isn't a system alert notification nor a disclosure notification
-        when(mForegroundServiceController.isSystemAlertNotification(sbn)).thenReturn(false);
-        when(mForegroundServiceController.isDisclosureNotification(sbn)).thenReturn(false);
-
-        // THEN don't filter out the notification
-        assertFalse(mForegroundFilter.shouldFilterOut(entry, 0));
-    }
-
-    @Test
     public void testIncludeFGSInSection_importanceDefault() {
         // GIVEN the notification represents a colorized foreground service with > min importance
         mEntryBuilder
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 2e2945e..8375e7c 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
@@ -58,8 +58,9 @@
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.BindParams;
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationCallback;
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
-import com.android.systemui.statusbar.policy.InflatedSmartReplies;
-import com.android.systemui.statusbar.policy.SmartRepliesAndActionsInflater;
+import com.android.systemui.statusbar.policy.InflatedSmartReplyState;
+import com.android.systemui.statusbar.policy.InflatedSmartReplyViewHolder;
+import com.android.systemui.statusbar.policy.SmartReplyStateInflater;
 import com.android.systemui.tests.R;
 
 import org.junit.Assert;
@@ -87,11 +88,24 @@
 
     @Mock private NotifRemoteViewCache mCache;
     @Mock private ConversationNotificationProcessor mConversationNotificationProcessor;
-    @Mock private InflatedSmartReplies mInflatedSmartReplies;
+    @Mock private InflatedSmartReplyState mInflatedSmartReplyState;
+    @Mock private InflatedSmartReplyViewHolder mInflatedSmartReplies;
 
-    private final SmartRepliesAndActionsInflater mSmartRepliesAndActionsInflater =
-            (sysuiContext, notifPackageContext, entry, existingRepliesAndAction) ->
-                    mInflatedSmartReplies;
+    private final SmartReplyStateInflater mSmartReplyStateInflater =
+            new SmartReplyStateInflater() {
+                @Override
+                public InflatedSmartReplyViewHolder inflateSmartReplyViewHolder(
+                        Context sysuiContext, Context notifPackageContext, NotificationEntry entry,
+                        InflatedSmartReplyState existingSmartReplyState,
+                        InflatedSmartReplyState newSmartReplyState) {
+                    return mInflatedSmartReplies;
+                }
+
+                @Override
+                public InflatedSmartReplyState inflateSmartReplyState(NotificationEntry entry) {
+                    return mInflatedSmartReplyState;
+                }
+            };
 
     @Before
     public void setUp() throws Exception {
@@ -114,7 +128,7 @@
                 mConversationNotificationProcessor,
                 mock(MediaFeatureFlag.class),
                 mock(Executor.class),
-                mSmartRepliesAndActionsInflater);
+                mSmartReplyStateInflater);
     }
 
     @Test
@@ -130,7 +144,7 @@
                 FLAG_CONTENT_VIEW_ALL,
                 builder,
                 mContext,
-                mSmartRepliesAndActionsInflater);
+                mSmartReplyStateInflater);
         verify(builder).createHeadsUpContentView(true);
     }
 
@@ -147,7 +161,7 @@
                 FLAG_CONTENT_VIEW_ALL,
                 builder,
                 mContext,
-                mSmartRepliesAndActionsInflater);
+                mSmartReplyStateInflater);
         verify(builder).createContentView(true);
     }
 
@@ -386,7 +400,7 @@
 
         @Override
         public CancellationSignal applyAsync(Context context, ViewGroup parent, Executor executor,
-                OnViewAppliedListener listener, OnClickHandler handler) {
+                OnViewAppliedListener listener, InteractionHandler handler) {
             mHandler.post(() -> listener.onError(new RuntimeException("Failed to inflate async")));
             return new CancellationSignal();
         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
index ababebd..97313ba 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
@@ -29,6 +29,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.Notification;
+import android.content.Context;
 import android.content.pm.LauncherApps;
 import android.os.Handler;
 import android.service.notification.NotificationListenerService;
@@ -80,7 +81,9 @@
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
-import com.android.systemui.statusbar.policy.InflatedSmartReplies;
+import com.android.systemui.statusbar.policy.InflatedSmartReplyState;
+import com.android.systemui.statusbar.policy.InflatedSmartReplyViewHolder;
+import com.android.systemui.statusbar.policy.SmartReplyStateInflater;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.leak.LeakDetector;
 import com.android.systemui.util.time.FakeSystemClock;
@@ -140,7 +143,8 @@
     @Mock private ActivatableNotificationViewController mActivatableNotificationViewController;
     @Mock private NotificationRowComponent.Builder mNotificationRowComponentBuilder;
     @Mock private PeopleNotificationIdentifier mPeopleNotificationIdentifier;
-    @Mock private InflatedSmartReplies mInflatedSmartReplies;
+    @Mock private InflatedSmartReplyState mInflatedSmartReplyState;
+    @Mock private InflatedSmartReplyViewHolder mInflatedSmartReplies;
 
     private StatusBarNotification mSbn;
     private NotificationListenerService.RankingMap mRankingMap;
@@ -206,8 +210,21 @@
                 mock(ConversationNotificationProcessor.class),
                 mock(MediaFeatureFlag.class),
                 mBgExecutor,
-                (sysuiContext, notifPackageContext, entry, existingRepliesAndAction) ->
-                        mInflatedSmartReplies);
+                new SmartReplyStateInflater() {
+                    @Override
+                    public InflatedSmartReplyState inflateSmartReplyState(NotificationEntry entry) {
+                        return mInflatedSmartReplyState;
+                    }
+
+                    @Override
+                    public InflatedSmartReplyViewHolder inflateSmartReplyViewHolder(
+                            Context sysuiContext, Context notifPackageContext,
+                            NotificationEntry entry,
+                            InflatedSmartReplyState existingSmartReplyState,
+                            InflatedSmartReplyState newSmartReplyState) {
+                        return mInflatedSmartReplies;
+                    }
+                });
         mRowContentBindStage = new RowContentBindStage(
                 binder,
                 mock(NotifInflationErrorManager.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index 64a7bee..f3813fc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -66,7 +66,9 @@
 import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
 import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.policy.InflatedSmartReplies;
+import com.android.systemui.statusbar.policy.InflatedSmartReplyState;
+import com.android.systemui.statusbar.policy.InflatedSmartReplyViewHolder;
+import com.android.systemui.statusbar.policy.SmartReplyStateInflater;
 import com.android.systemui.tests.R;
 import com.android.systemui.wmshell.BubblesManager;
 import com.android.systemui.wmshell.BubblesTestActivity;
@@ -139,8 +141,7 @@
                 mock(ConversationNotificationProcessor.class),
                 mock(MediaFeatureFlag.class),
                 mock(Executor.class),
-                (sysuiContext, notifPackageContext, entry, existingRepliesAndAction) ->
-                        mock(InflatedSmartReplies.class));
+                new MockSmartReplyInflater());
         contentBinder.setInflateSynchronously(true);
         mBindStage = new RowContentBindStage(contentBinder,
                 mock(NotifInflationErrorManager.class),
@@ -464,4 +465,19 @@
                 .setDesiredHeight(314)
                 .build();
     }
+
+    private static class MockSmartReplyInflater implements SmartReplyStateInflater {
+        @Override
+        public InflatedSmartReplyState inflateSmartReplyState(NotificationEntry entry) {
+            return mock(InflatedSmartReplyState.class);
+        }
+
+        @Override
+        public InflatedSmartReplyViewHolder inflateSmartReplyViewHolder(Context sysuiContext,
+                Context notifPackageContext, NotificationEntry entry,
+                InflatedSmartReplyState existingSmartReplyState,
+                InflatedSmartReplyState newSmartReplyState) {
+            return mock(InflatedSmartReplyViewHolder.class);
+        }
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 461f64e..84fb368 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
@@ -21,6 +21,8 @@
 import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
 import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE;
 
+import static com.google.common.truth.Truth.assertWithMessage;
+
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertNotNull;
 
@@ -49,6 +51,7 @@
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.EmptyShadeView;
+import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.NotificationShelfController;
@@ -101,6 +104,7 @@
     @Mock private SysuiStatusBarStateController mStatusBarStateController;
     @Mock private NotificationSwipeHelper mNotificationSwipeHelper;
     @Mock private NotificationStackScrollLayoutController mStackScrollLayoutController;
+    @Mock private FeatureFlags mFeatureFlags;
 
     @Before
     @UiThreadTest
@@ -139,8 +143,8 @@
                 mGroupMembershipManger,
                 mGroupExpansionManager,
                 mStatusBarStateController,
-                mAmbientState
-        );
+                mAmbientState,
+                mFeatureFlags);
         mStackScrollerInternal.initView(getContext(), mKeyguardBypassEnabledProvider,
                 mNotificationSwipeHelper);
         mStackScroller = spy(mStackScrollerInternal);
@@ -205,8 +209,8 @@
     @Test
     @UiThreadTest
     public void testSetExpandedHeight_blockingHelperManagerReceivedCallbacks() {
-        final float expectedHeight[] = {0f};
-        final float expectedAppear[] = {0f};
+        final float[] expectedHeight = {0f};
+        final float[] expectedAppear = {0f};
 
         mStackScroller.addOnExpandedHeightChangedListener((height, appear) -> {
             Assert.assertEquals(expectedHeight[0], height, 0);
@@ -222,6 +226,29 @@
     }
 
     @Test
+    @UiThreadTest
+    public void testSetExpandedHeight_withSplitShade_doesntInterpolateStackHeight() {
+        when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true);
+        final int[] expectedStackHeight = {0};
+
+        mStackScroller.addOnExpandedHeightChangedListener((expandedHeight, appear) -> {
+            assertWithMessage("Given shade enabled: %s",
+                    mFeatureFlags.isTwoColumnNotificationShadeEnabled())
+                    .that(mStackScroller.getHeight())
+                    .isEqualTo(expectedStackHeight[0]);
+        });
+
+        when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(false);
+        expectedStackHeight[0] = 0;
+        mStackScroller.setExpandedHeight(100f);
+
+        when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true);
+        expectedStackHeight[0] = 100;
+        mStackScroller.setExpandedHeight(100f);
+    }
+
+
+    @Test
     public void manageNotifications_visible() {
         FooterView view = mock(FooterView.class);
         mStackScroller.setFooterView(view);
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 8dea84c..6e0cbd9 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
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.phone;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
@@ -197,9 +198,9 @@
         mHeadsUpAppearanceController.destroy();
         verify(mHeadsUpManager).removeListener(any());
         verify(mDarkIconDispatcher).removeDarkReceiver((DarkIconDispatcher.DarkReceiver) any());
-        verify(mPanelView).removeVerticalTranslationListener(any());
+        verify(mPanelView).setVerticalTranslationListener(isNull());
         verify(mPanelView).removeTrackingHeadsUpListener(any());
-        verify(mPanelView).setHeadsUpAppearanceController(any());
+        verify(mPanelView).setHeadsUpAppearanceController(isNull());
         verify(mStackScrollerController).removeOnExpandedHeightChangedListener(any());
         verify(mStackScrollerController).removeOnLayoutChangeListener(any());
     }
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 d69d2db..dd31f52 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
@@ -18,19 +18,22 @@
 
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 
+import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
+import static com.android.systemui.statusbar.StatusBarState.SHADE;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.annotation.IdRes;
 import android.app.ActivityManager;
 import android.app.StatusBarManager;
 import android.content.res.Configuration;
@@ -45,6 +48,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewPropertyAnimator;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
 
@@ -53,6 +57,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
 import com.android.internal.logging.testing.UiEventLoggerFake;
 import com.android.internal.util.LatencyTracker;
 import com.android.keyguard.KeyguardClockSwitch;
@@ -61,7 +66,6 @@
 import com.android.keyguard.KeyguardStatusViewController;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
-import com.android.keyguard.dagger.KeyguardStatusBarViewComponent;
 import com.android.keyguard.dagger.KeyguardStatusViewComponent;
 import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
 import com.android.systemui.R;
@@ -101,7 +105,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
-import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.mockito.stubbing.Answer;
@@ -117,8 +120,6 @@
     @Mock
     private StatusBar mStatusBar;
     @Mock
-    private SysuiStatusBarStateController mStatusBarStateController;
-    @Mock
     private NotificationStackScrollLayout mNotificationStackScrollLayout;
     @Mock
     private KeyguardBottomAreaView mKeyguardBottomArea;
@@ -207,16 +208,10 @@
     @Mock
     private KeyguardStatusViewComponent mKeyguardStatusViewComponent;
     @Mock
-    private KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory;
-    @Mock
-    private KeyguardStatusBarViewComponent mKeyguardStatusBarViewComponent;
-    @Mock
     private KeyguardClockSwitchController mKeyguardClockSwitchController;
     @Mock
     private KeyguardStatusViewController mKeyguardStatusViewController;
     @Mock
-    private KeyguardStatusBarViewController mKeyguardStatusBarViewController;
-    @Mock
     private NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
     @Mock
     private AuthController mAuthController;
@@ -234,7 +229,10 @@
     private AmbientState mAmbientState;
     @Mock
     private UserManager mUserManager;
+    @Mock
+    private UiEventLogger mUiEventLogger;
 
+    private SysuiStatusBarStateController mStatusBarStateController;
     private NotificationPanelViewController mNotificationPanelViewController;
     private View.AccessibilityDelegate mAccessibiltyDelegate;
     private NotificationsQuickSettingsContainer mNotificationContainerParent;
@@ -242,6 +240,8 @@
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
+        mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger);
+
         when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false);
         when(mHeadsUpCallback.getContext()).thenReturn(mContext);
         when(mView.getResources()).thenReturn(mResources);
@@ -265,12 +265,14 @@
         when(mView.findViewById(R.id.keyguard_bottom_area)).thenReturn(mKeyguardBottomArea);
         when(mKeyguardBottomArea.getLeftView()).thenReturn(mock(KeyguardAffordanceView.class));
         when(mKeyguardBottomArea.getRightView()).thenReturn(mock(KeyguardAffordanceView.class));
+        when(mKeyguardBottomArea.animate()).thenReturn(mock(ViewPropertyAnimator.class));
         when(mView.findViewById(R.id.big_clock_container)).thenReturn(mBigClockContainer);
         when(mView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame);
         when(mView.findViewById(R.id.keyguard_status_view))
                 .thenReturn(mock(KeyguardStatusView.class));
-        when(mView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar);
         mNotificationContainerParent = new NotificationsQuickSettingsContainer(getContext(), null);
+        mNotificationContainerParent.addView(newViewWithId(R.id.qs_frame));
+        mNotificationContainerParent.addView(newViewWithId(R.id.notification_stack_scroller));
         when(mView.findViewById(R.id.notification_container_parent))
                 .thenReturn(mNotificationContainerParent);
         FlingAnimationUtils.Builder flingAnimationUtilsBuilder = new FlingAnimationUtils.Builder(
@@ -300,14 +302,6 @@
                 .thenReturn(mKeyguardClockSwitchController);
         when(mKeyguardStatusViewComponent.getKeyguardStatusViewController())
                 .thenReturn(mKeyguardStatusViewController);
-        when(mQsFrame.getLayoutParams()).thenReturn(
-                new ViewGroup.LayoutParams(600, 400));
-        when(mNotificationStackScrollLayoutController.getLayoutParams()).thenReturn(
-                new ViewGroup.LayoutParams(600, 400));
-        when(mKeyguardStatusBarViewComponentFactory.build(any()))
-                .thenReturn(mKeyguardStatusBarViewComponent);
-        when(mKeyguardStatusBarViewComponent.getKeyguardStatusBarViewController())
-                .thenReturn(mKeyguardStatusBarViewController);
 
         mNotificationPanelViewController = new NotificationPanelViewController(mView,
                 mResources,
@@ -326,7 +320,6 @@
                 mKeyguardStatusViewComponentFactory,
                 mKeyguardQsUserSwitchComponentFactory,
                 mKeyguardUserSwitcherComponentFactory,
-                mKeyguardStatusBarViewComponentFactory,
                 mQSDetailDisplayer,
                 mGroupManager,
                 mNotificationAreaController,
@@ -348,17 +341,19 @@
                 ArgumentCaptor.forClass(View.AccessibilityDelegate.class);
         verify(mView).setAccessibilityDelegate(accessibilityDelegateArgumentCaptor.capture());
         mAccessibiltyDelegate = accessibilityDelegateArgumentCaptor.getValue();
+        mNotificationPanelViewController.mStatusBarStateController
+                .addCallback(mNotificationPanelViewController.mStatusBarStateListener);
+        mNotificationPanelViewController
+                .setHeadsUpAppearanceController(mock(HeadsUpAppearanceController.class));
     }
 
     @Test
     public void testSetDozing_notifiesNsslAndStateController() {
-        mNotificationPanelViewController.setDozing(true /* dozing */, true /* animate */,
+        mNotificationPanelViewController.setDozing(true /* dozing */, false /* animate */,
                 null /* touch */);
-        InOrder inOrder = inOrder(
-                mNotificationStackScrollLayoutController, mStatusBarStateController);
-        inOrder.verify(mNotificationStackScrollLayoutController)
-                .setDozing(eq(true), eq(true), eq(null));
-        inOrder.verify(mStatusBarStateController).setDozeAmount(eq(1f), eq(true));
+        verify(mNotificationStackScrollLayoutController)
+                .setDozing(eq(true), eq(false), eq(null));
+        assertThat(mStatusBarStateController.getDozeAmount()).isEqualTo(1f);
     }
 
     @Test
@@ -454,9 +449,8 @@
 
     @Test
     public void testAllChildrenOfNotificationContainer_haveIds() {
-        when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(true);
-        when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true);
-
+        enableSplitShade();
+        mNotificationContainerParent.removeAllViews();
         mNotificationContainerParent.addView(newViewWithId(1));
         mNotificationContainerParent.addView(newViewWithId(View.NO_ID));
 
@@ -469,36 +463,92 @@
     @Test
     public void testSinglePaneShadeLayout_isAlignedToParent() {
         when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(false);
-        mNotificationContainerParent.addView(newViewWithId(R.id.qs_frame));
-        mNotificationContainerParent.addView(newViewWithId(R.id.notification_stack_scroller));
 
         mNotificationPanelViewController.updateResources();
 
-        ConstraintSet constraintSet = new ConstraintSet();
-        constraintSet.clone(mNotificationContainerParent);
-        ConstraintSet.Layout qsFrameLayout = constraintSet.getConstraint(R.id.qs_frame).layout;
-        ConstraintSet.Layout stackScrollerLayout = constraintSet.getConstraint(
-                R.id.notification_stack_scroller).layout;
-        assertThat(qsFrameLayout.endToEnd).isEqualTo(ConstraintSet.PARENT_ID);
-        assertThat(stackScrollerLayout.startToStart).isEqualTo(ConstraintSet.PARENT_ID);
+        assertThat(getConstraintSetLayout(R.id.qs_frame).endToEnd)
+                .isEqualTo(ConstraintSet.PARENT_ID);
+        assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).startToStart)
+                .isEqualTo(ConstraintSet.PARENT_ID);
     }
 
     @Test
     public void testSplitShadeLayout_isAlignedToGuideline() {
-        when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(true);
-        when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true);
-        mNotificationContainerParent.addView(newViewWithId(R.id.qs_frame));
-        mNotificationContainerParent.addView(newViewWithId(R.id.notification_stack_scroller));
+        enableSplitShade();
 
         mNotificationPanelViewController.updateResources();
 
-        ConstraintSet constraintSet = new ConstraintSet();
-        constraintSet.clone(mNotificationContainerParent);
-        ConstraintSet.Layout qsFrameLayout = constraintSet.getConstraint(R.id.qs_frame).layout;
-        ConstraintSet.Layout stackScrollerLayout = constraintSet.getConstraint(
-                R.id.notification_stack_scroller).layout;
-        assertThat(qsFrameLayout.endToEnd).isEqualTo(R.id.qs_edge_guideline);
-        assertThat(stackScrollerLayout.startToStart).isEqualTo(R.id.qs_edge_guideline);
+        assertThat(getConstraintSetLayout(R.id.qs_frame).endToEnd)
+                .isEqualTo(R.id.qs_edge_guideline);
+        assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).startToStart)
+                .isEqualTo(R.id.qs_edge_guideline);
+    }
+
+    @Test
+    public void testSinglePaneShadeLayout_childrenHaveConstantWidth() {
+        when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(false);
+
+        mNotificationPanelViewController.updateResources();
+
+        assertThat(getConstraintSetLayout(R.id.qs_frame).mWidth)
+                .isEqualTo(mResources.getDimensionPixelSize(R.dimen.qs_panel_width));
+        assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).mWidth)
+                .isEqualTo(mResources.getDimensionPixelSize(R.dimen.notification_panel_width));
+    }
+
+    @Test
+    public void testSplitShadeLayout_childrenHaveZeroWidth() {
+        enableSplitShade();
+
+        mNotificationPanelViewController.updateResources();
+
+        assertThat(getConstraintSetLayout(R.id.qs_frame).mWidth).isEqualTo(0);
+        assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).mWidth).isEqualTo(0);
+    }
+
+    @Test
+    public void testOnDragDownEvent_horizontalTranslationIsZeroForSplitShade() {
+        when(mNotificationStackScrollLayoutController.getWidth()).thenReturn(350f);
+        when(mView.getWidth()).thenReturn(800);
+        enableSplitShade();
+
+        onTouchEvent(MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN,
+                200f /* x position */, 0f, 0));
+
+        verify(mQsFrame).setTranslationX(0);
+    }
+
+    @Test
+    public void testCanCollapsePanelOnTouch_trueForKeyGuard() {
+        mStatusBarStateController.setState(KEYGUARD);
+
+        assertThat(mNotificationPanelViewController.canCollapsePanelOnTouch()).isTrue();
+    }
+
+    @Test
+    public void testCanCollapsePanelOnTouch_trueWhenScrolledToBottom() {
+        mStatusBarStateController.setState(SHADE);
+        when(mNotificationStackScrollLayoutController.isScrolledToBottom()).thenReturn(true);
+
+        assertThat(mNotificationPanelViewController.canCollapsePanelOnTouch()).isTrue();
+    }
+
+    @Test
+    public void testCanCollapsePanelOnTouch_trueWhenInSettings() {
+        mStatusBarStateController.setState(SHADE);
+        mNotificationPanelViewController.setQsExpanded(true);
+
+        assertThat(mNotificationPanelViewController.canCollapsePanelOnTouch()).isTrue();
+    }
+
+    @Test
+    public void testCanCollapsePanelOnTouch_falseInDualPaneShade() {
+        mStatusBarStateController.setState(SHADE);
+        when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(true);
+        when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true);
+        mNotificationPanelViewController.setQsExpanded(true);
+
+        assertThat(mNotificationPanelViewController.canCollapsePanelOnTouch()).isFalse();
     }
 
     private View newViewWithId(int id) {
@@ -511,6 +561,17 @@
         return view;
     }
 
+    private ConstraintSet.Layout getConstraintSetLayout(@IdRes int id) {
+        ConstraintSet constraintSet = new ConstraintSet();
+        constraintSet.clone(mNotificationContainerParent);
+        return constraintSet.getConstraint(id).layout;
+    }
+
+    private void enableSplitShade() {
+        when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(true);
+        when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true);
+    }
+
     private void onTouchEvent(MotionEvent ev) {
         mTouchHandler.onTouch(mView, ev);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
index 67c1a08..2418243 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
@@ -30,7 +30,9 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
+import com.android.systemui.statusbar.policy.NetworkController.WifiIndicators;
 import com.android.systemui.tests.R;
 
 import org.junit.Before;
@@ -86,28 +88,24 @@
         boolean out = true;
         String description = "Test";
         String secondaryLabel = "Secondary label";
-        mHandler.setWifiIndicators(enabled, status, qs, in, out, description, true, secondaryLabel);
+        WifiIndicators indicators = new WifiIndicators(
+                enabled, status, qs, in, out, description, true, secondaryLabel);
+        mHandler.setWifiIndicators(indicators);
         waitForCallbacks();
 
-        ArgumentCaptor<Boolean> enableArg = ArgumentCaptor.forClass(Boolean.class);
-        ArgumentCaptor<IconState> statusArg = ArgumentCaptor.forClass(IconState.class);
-        ArgumentCaptor<IconState> qsArg = ArgumentCaptor.forClass(IconState.class);
-        ArgumentCaptor<Boolean> inArg = ArgumentCaptor.forClass(Boolean.class);
-        ArgumentCaptor<Boolean> outArg = ArgumentCaptor.forClass(Boolean.class);
-        ArgumentCaptor<String> descArg = ArgumentCaptor.forClass(String.class);
-        ArgumentCaptor<Boolean> isTransient = ArgumentCaptor.forClass(Boolean.class);
-        ArgumentCaptor<String> secondary = ArgumentCaptor.forClass(String.class);
-        Mockito.verify(mSignalCallback).setWifiIndicators(enableArg.capture(),
-                statusArg.capture(), qsArg.capture(), inArg.capture(), outArg.capture(),
-                descArg.capture(), isTransient.capture(), secondary.capture());
-        assertEquals(enabled, (boolean) enableArg.getValue());
-        assertEquals(status, statusArg.getValue());
-        assertEquals(qs, qsArg.getValue());
-        assertEquals(in, (boolean) inArg.getValue());
-        assertEquals(out, (boolean) outArg.getValue());
-        assertEquals(description, descArg.getValue());
-        assertTrue(isTransient.getValue());
-        assertEquals(secondaryLabel, secondary.getValue());
+        ArgumentCaptor<WifiIndicators> indicatorArg =
+                ArgumentCaptor.forClass(WifiIndicators.class);
+        Mockito.verify(mSignalCallback).setWifiIndicators(indicatorArg.capture());
+        WifiIndicators expected = indicatorArg.getValue();
+
+        assertEquals(enabled, expected.enabled);
+        assertEquals(status, expected.statusIcon);
+        assertEquals(qs, expected.qsIcon);
+        assertEquals(in, expected.activityIn);
+        assertEquals(out, expected.activityOut);
+        assertEquals(description, expected.description);
+        assertTrue(expected.isTransient);
+        assertEquals(secondaryLabel, expected.statusLabel);
     }
 
     @Test
@@ -124,37 +122,30 @@
         boolean wide = true;
         int subId = 5;
         boolean roaming = true;
-        mHandler.setMobileDataIndicators(status, qs, type, qsType, in, out, typeDescription,
+        MobileDataIndicators indicators = new MobileDataIndicators(
+                status, qs, type, qsType, in, out, typeDescription,
                 typeDescriptionHtml, description, wide, subId, roaming, true);
+        mHandler.setMobileDataIndicators(indicators);
         waitForCallbacks();
 
-        ArgumentCaptor<IconState> statusArg = ArgumentCaptor.forClass(IconState.class);
-        ArgumentCaptor<IconState> qsArg = ArgumentCaptor.forClass(IconState.class);
-        ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class);
-        ArgumentCaptor<Integer> qsTypeIconArg = ArgumentCaptor.forClass(Integer.class);
-        ArgumentCaptor<Boolean> inArg = ArgumentCaptor.forClass(Boolean.class);
-        ArgumentCaptor<Boolean> outArg = ArgumentCaptor.forClass(Boolean.class);
-        ArgumentCaptor<CharSequence> typeContentArg = ArgumentCaptor.forClass(CharSequence.class);
-        ArgumentCaptor<CharSequence> typeContentHtmlArg =
-                ArgumentCaptor.forClass(CharSequence.class);
-        ArgumentCaptor<CharSequence> descArg = ArgumentCaptor.forClass(CharSequence.class);
-        ArgumentCaptor<Boolean> wideArg = ArgumentCaptor.forClass(Boolean.class);
-        ArgumentCaptor<Integer> subIdArg = ArgumentCaptor.forClass(Integer.class);
-        Mockito.verify(mSignalCallback).setMobileDataIndicators(statusArg.capture(),
-                qsArg.capture(), typeIconArg.capture(), qsTypeIconArg.capture(), inArg.capture(),
-                outArg.capture(), typeContentArg.capture(), typeContentHtmlArg.capture(),
-                descArg.capture(), wideArg.capture(), subIdArg.capture(), eq(roaming), eq(true));
-        assertEquals(status, statusArg.getValue());
-        assertEquals(qs, qsArg.getValue());
-        assertEquals(type, (int) typeIconArg.getValue());
-        assertEquals(qsType, (int) qsTypeIconArg.getValue());
-        assertEquals(in, (boolean) inArg.getValue());
-        assertEquals(out, (boolean) outArg.getValue());
-        assertEquals(typeDescription, typeContentArg.getValue());
-        assertEquals(typeDescriptionHtml, typeContentHtmlArg.getValue());
-        assertEquals(description, descArg.getValue());
-        assertEquals(wide, (boolean) wideArg.getValue());
-        assertEquals(subId, (int) subIdArg.getValue());
+        ArgumentCaptor<MobileDataIndicators> indicatorArg =
+                ArgumentCaptor.forClass(MobileDataIndicators.class);
+        Mockito.verify(mSignalCallback).setMobileDataIndicators(indicatorArg.capture());
+        MobileDataIndicators expected = indicatorArg.getValue();
+
+        assertEquals(status, expected.statusIcon);
+        assertEquals(qs, expected.qsIcon);
+        assertEquals(type, expected.statusType);
+        assertEquals(qsType, expected.qsType);
+        assertEquals(in, expected.activityIn);
+        assertEquals(out, expected.activityOut);
+        assertEquals(typeDescription, expected.typeContentDescription);
+        assertEquals(typeDescriptionHtml, expected.typeContentDescriptionHtml);
+        assertEquals(description, expected.description);
+        assertEquals(wide, expected.isWide);
+        assertEquals(subId, expected.subId);
+        assertTrue(expected.roaming);
+        assertTrue(expected.showTriangle);
     }
 
     @SuppressWarnings("unchecked")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java
index 32675c9..5e2fa98 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java
@@ -45,7 +45,7 @@
 import com.android.systemui.statusbar.NotificationEntryHelper;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
-import com.android.systemui.statusbar.policy.InflatedSmartReplies.SmartRepliesAndActions;
+import com.android.systemui.statusbar.policy.InflatedSmartReplyState.SuppressedActions;
 import com.android.systemui.statusbar.policy.SmartReplyView.SmartActions;
 import com.android.systemui.statusbar.policy.SmartReplyView.SmartReplies;
 
@@ -74,13 +74,12 @@
     @Mock private ActivityManagerWrapper mActivityManagerWrapper;
     @Mock private PackageManagerWrapper mPackageManagerWrapper;
     @Mock private DevicePolicyManagerWrapper mDevicePolicyManagerWrapper;
-    @Mock private SmartRepliesAndActions mSmartRepliesAndActions;
     @Mock private SmartReplyInflater mSmartReplyInflater;
     @Mock private SmartActionInflater mSmartActionInflater;
 
     private Icon mActionIcon;
     private NotificationEntry mEntry;
-    private SmartRepliesAndActionsInflaterImpl mSmartRepliesInflater;
+    private SmartReplyStateInflaterImpl mSmartReplyStateInflater;
 
     @Before
     @UiThreadTest
@@ -101,7 +100,7 @@
 
         when(mActivityManagerWrapper.isLockTaskKioskModeActive()).thenReturn(false);
 
-        mSmartRepliesInflater = new SmartRepliesAndActionsInflaterImpl(
+        mSmartReplyStateInflater = new SmartReplyStateInflaterImpl(
                 mSmartReplyConstants,
                 mActivityManagerWrapper,
                 mPackageManagerWrapper,
@@ -118,11 +117,13 @@
         setupAppGeneratedSuggestions(smartReplies, smartActions);
         when(mSmartReplyConstants.isEnabled()).thenReturn(false);
 
-        SmartRepliesAndActions repliesAndActions =
-                mSmartRepliesInflater.chooseSmartRepliesAndActions(mEntry);
+        InflatedSmartReplyState smartReplyState =
+                mSmartReplyStateInflater.chooseSmartRepliesAndActions(mEntry);
 
-        assertThat(repliesAndActions.smartReplies).isNull();
-        assertThat(repliesAndActions.smartActions).isNull();
+        assertThat(smartReplyState.getSmartReplies()).isNull();
+        assertThat(smartReplyState.getSmartActions()).isNull();
+        assertThat(smartReplyState.getSuppressedActions()).isNull();
+        assertThat(smartReplyState.getHasPhishingAction()).isFalse();
     }
 
     @Test
@@ -134,11 +135,13 @@
 
         when(mSmartReplyConstants.isEnabled()).thenReturn(false);
 
-        SmartRepliesAndActions repliesAndActions =
-                mSmartRepliesInflater.chooseSmartRepliesAndActions(mEntry);
+        InflatedSmartReplyState smartReplyState =
+                mSmartReplyStateInflater.chooseSmartRepliesAndActions(mEntry);
 
-        assertThat(repliesAndActions.smartReplies).isNull();
-        assertThat(repliesAndActions.smartActions).isNull();
+        assertThat(smartReplyState.getSmartReplies()).isNull();
+        assertThat(smartReplyState.getSmartActions()).isNull();
+        assertThat(smartReplyState.getSuppressedActions()).isNull();
+        assertThat(smartReplyState.getHasPhishingAction()).isFalse();
     }
 
     @Test
@@ -146,12 +149,15 @@
         CharSequence[] smartReplies = new String[] {"Reply1", "Reply2"};
         setupAppGeneratedReplies(smartReplies);
 
-        SmartRepliesAndActions repliesAndActions =
-                mSmartRepliesInflater.chooseSmartRepliesAndActions(mEntry);
+        InflatedSmartReplyState smartReplyState =
+                mSmartReplyStateInflater.chooseSmartRepliesAndActions(mEntry);
 
-        assertThat(repliesAndActions.smartReplies.choices).isEqualTo(Arrays.asList(smartReplies));
-        assertThat(repliesAndActions.smartReplies.fromAssistant).isFalse();
-        assertThat(repliesAndActions.smartActions).isNull();
+        assertThat(smartReplyState.getSmartReplies().choices)
+                .containsExactlyElementsIn(smartReplies).inOrder();
+        assertThat(smartReplyState.getSmartReplies().fromAssistant).isFalse();
+        assertThat(smartReplyState.getSmartActions()).isNull();
+        assertThat(smartReplyState.getSuppressedActions()).isNull();
+        assertThat(smartReplyState.getHasPhishingAction()).isFalse();
     }
 
     @Test
@@ -161,13 +167,17 @@
                 createActions("Test Action 1", "Test Action 2");
         setupAppGeneratedSuggestions(smartReplies, smartActions);
 
-        SmartRepliesAndActions repliesAndActions =
-                mSmartRepliesInflater.chooseSmartRepliesAndActions(mEntry);
+        InflatedSmartReplyState smartReplyState =
+                mSmartReplyStateInflater.chooseSmartRepliesAndActions(mEntry);
 
-        assertThat(repliesAndActions.smartReplies.choices).isEqualTo(Arrays.asList(smartReplies));
-        assertThat(repliesAndActions.smartReplies.fromAssistant).isFalse();
-        assertThat(repliesAndActions.smartActions.actions).isEqualTo(smartActions);
-        assertThat(repliesAndActions.smartActions.fromAssistant).isFalse();
+        assertThat(smartReplyState.getSmartReplies().choices)
+                .containsExactlyElementsIn(smartReplies).inOrder();
+        assertThat(smartReplyState.getSmartReplies().fromAssistant).isFalse();
+        assertThat(smartReplyState.getSmartActions().actions)
+                .containsExactlyElementsIn(smartActions).inOrder();
+        assertThat(smartReplyState.getSmartActions().fromAssistant).isFalse();
+        assertThat(smartReplyState.getSuppressedActions()).isNull();
+        assertThat(smartReplyState.getHasPhishingAction()).isFalse();
     }
 
     @Test
@@ -180,12 +190,15 @@
                 .setSmartReplies(createReplies("Sys Smart Reply 1", "Sys Smart Reply 2"))
                 .build();
 
-        SmartRepliesAndActions repliesAndActions =
-                mSmartRepliesInflater.chooseSmartRepliesAndActions(mEntry);
+        InflatedSmartReplyState smartReplyState =
+                mSmartReplyStateInflater.chooseSmartRepliesAndActions(mEntry);
 
-        assertThat(repliesAndActions.smartReplies.choices).isEqualTo(mEntry.getSmartReplies());
-        assertThat(repliesAndActions.smartReplies.fromAssistant).isTrue();
-        assertThat(repliesAndActions.smartActions).isNull();
+        assertThat(smartReplyState.getSmartReplies().choices)
+                .containsExactlyElementsIn(mEntry.getSmartReplies()).inOrder();
+        assertThat(smartReplyState.getSmartReplies().fromAssistant).isTrue();
+        assertThat(smartReplyState.getSmartActions()).isNull();
+        assertThat(smartReplyState.getSuppressedActions()).isNull();
+        assertThat(smartReplyState.getHasPhishingAction()).isFalse();
     }
 
     @Test
@@ -197,11 +210,13 @@
         NotificationEntryHelper.modifyRanking(mEntry)
                 .setSmartReplies(createReplies("Sys Smart Reply 1", "Sys Smart Reply 2"))
                 .build();
-        SmartRepliesAndActions repliesAndActions =
-                mSmartRepliesInflater.chooseSmartRepliesAndActions(mEntry);
+        InflatedSmartReplyState smartReplyState =
+                mSmartReplyStateInflater.chooseSmartRepliesAndActions(mEntry);
 
-        assertThat(repliesAndActions.smartReplies).isNull();
-        assertThat(repliesAndActions.smartActions).isNull();
+        assertThat(smartReplyState.getSmartReplies()).isNull();
+        assertThat(smartReplyState.getSmartActions()).isNull();
+        assertThat(smartReplyState.getSuppressedActions()).isNull();
+        assertThat(smartReplyState.getHasPhishingAction()).isFalse();
     }
 
     @Test
@@ -214,13 +229,50 @@
                 .setSmartActions(createActions("Sys Smart Action 1", "Sys Smart Action 2"))
                 .build();
 
-        SmartRepliesAndActions repliesAndActions =
-                mSmartRepliesInflater.chooseSmartRepliesAndActions(mEntry);
+        InflatedSmartReplyState smartReplyState =
+                mSmartReplyStateInflater.chooseSmartRepliesAndActions(mEntry);
 
-        assertThat(repliesAndActions.smartReplies).isNull();
-        assertThat(repliesAndActions.smartActions.actions)
-                .isEqualTo(mEntry.getSmartActions());
-        assertThat(repliesAndActions.smartActions.fromAssistant).isTrue();
+        assertThat(smartReplyState.getSmartReplies()).isNull();
+        assertThat(smartReplyState.getSmartActions().actions)
+                .containsExactlyElementsIn(mEntry.getSmartActions()).inOrder();
+        assertThat(smartReplyState.getSmartActions().fromAssistant).isTrue();
+        assertThat(smartReplyState.getSuppressedActions()).isNull();
+        assertThat(smartReplyState.getHasPhishingAction()).isFalse();
+    }
+
+    @Test
+    public void chooseSmartRepliesAndActions_sysGeneratedPhishingSmartAction() {
+        // Pass a null-array as app-generated smart replies, so that we use NAS-generated smart
+        // actions.
+        setupAppGeneratedReplies(null /* smartReplies */);
+
+        mNotification.actions = new Notification.Action[]{
+                createAction("Details"),
+                createActionBuilder("Reply").addRemoteInput(
+                        new RemoteInput.Builder("key").build()).build()
+        };
+
+        modifyRanking(mEntry)
+                .setSmartActions(
+                        createAction("Sys Smart Action 1"),
+                        createActionBuilder("Sys Smart Action 2")
+                                .setContextual(true)
+                                .setSemanticAction(Notification.Action
+                                        .SEMANTIC_ACTION_CONVERSATION_IS_PHISHING)
+                                .build())
+                .build();
+
+        InflatedSmartReplyState smartReplyState =
+                mSmartReplyStateInflater.chooseSmartRepliesAndActions(mEntry);
+
+        assertThat(smartReplyState.getSmartReplies()).isNull();
+        assertThat(smartReplyState.getSmartActions().actions)
+                .containsExactlyElementsIn(mEntry.getSmartActions()).inOrder();
+        assertThat(smartReplyState.getSmartActions().fromAssistant).isTrue();
+        assertThat(smartReplyState.getSuppressedActions()).isNotNull();
+        assertThat(smartReplyState.getSuppressedActions().getSuppressedActionIndices())
+                .containsExactly(1);
+        assertThat(smartReplyState.getHasPhishingAction()).isTrue();
     }
 
     @Test
@@ -237,14 +289,17 @@
                 .setSmartActions(createActions("Sys Smart Action 1", "Sys Smart Action 2"))
                 .build();
 
-        SmartRepliesAndActions repliesAndActions =
-                mSmartRepliesInflater.chooseSmartRepliesAndActions(mEntry);
+        InflatedSmartReplyState smartReplyState =
+                mSmartReplyStateInflater.chooseSmartRepliesAndActions(mEntry);
 
-        assertThat(repliesAndActions.smartReplies.choices)
-                .isEqualTo(Arrays.asList(appGenSmartReplies));
-        assertThat(repliesAndActions.smartReplies.fromAssistant).isFalse();
-        assertThat(repliesAndActions.smartActions.actions).isEqualTo(appGenSmartActions);
-        assertThat(repliesAndActions.smartActions.fromAssistant).isFalse();
+        assertThat(smartReplyState.getSmartReplies().choices)
+                .containsExactlyElementsIn(Arrays.asList(appGenSmartReplies)).inOrder();
+        assertThat(smartReplyState.getSmartReplies().fromAssistant).isFalse();
+        assertThat(smartReplyState.getSmartActions().actions)
+                .containsExactlyElementsIn(appGenSmartActions).inOrder();
+        assertThat(smartReplyState.getSmartActions().fromAssistant).isFalse();
+        assertThat(smartReplyState.getSuppressedActions()).isNull();
+        assertThat(smartReplyState.getHasPhishingAction()).isFalse();
     }
 
     @Test
@@ -259,11 +314,13 @@
                 .setSmartActions(createActions("Sys Smart Action 1", "Sys Smart Action 2"))
                 .build();
 
-        SmartRepliesAndActions repliesAndActions =
-                mSmartRepliesInflater.chooseSmartRepliesAndActions(mEntry);
+        InflatedSmartReplyState smartReplyState =
+                mSmartReplyStateInflater.chooseSmartRepliesAndActions(mEntry);
 
-        assertThat(repliesAndActions.smartActions).isNull();
-        assertThat(repliesAndActions.smartReplies).isNull();
+        assertThat(smartReplyState.getSmartActions()).isNull();
+        assertThat(smartReplyState.getSmartReplies()).isNull();
+        assertThat(smartReplyState.getSuppressedActions()).isNull();
+        assertThat(smartReplyState.getHasPhishingAction()).isFalse();
     }
 
     @Test
@@ -281,13 +338,15 @@
                 .setSmartActions(createActions("Sys Smart Action 1", "Sys Smart Action 2"))
                 .build();
 
-        SmartRepliesAndActions repliesAndActions =
-                mSmartRepliesInflater.chooseSmartRepliesAndActions(mEntry);
+        InflatedSmartReplyState smartReplyState =
+                mSmartReplyStateInflater.chooseSmartRepliesAndActions(mEntry);
 
-        assertThat(repliesAndActions.smartReplies.choices).isEqualTo(
-                mEntry.getSmartReplies());
+        assertThat(smartReplyState.getSmartReplies().choices)
+                .containsExactlyElementsIn(mEntry.getSmartReplies()).inOrder();
         // Since no apps are whitelisted no actions should be shown.
-        assertThat(repliesAndActions.smartActions.actions).isEmpty();
+        assertThat(smartReplyState.getSmartActions().actions).isEmpty();
+        assertThat(smartReplyState.getSuppressedActions()).isNull();
+        assertThat(smartReplyState.getHasPhishingAction()).isFalse();
     }
 
     @Test
@@ -317,13 +376,14 @@
                 .setSmartActions(actions)
                 .build();
 
-        SmartRepliesAndActions repliesAndActions =
-                mSmartRepliesInflater.chooseSmartRepliesAndActions(mEntry);
+        InflatedSmartReplyState smartReplyState =
+                mSmartReplyStateInflater.chooseSmartRepliesAndActions(mEntry);
 
         // Only the action for the whitelisted package should be allowed.
-        assertThat(repliesAndActions.smartActions.actions.size()).isEqualTo(1);
-        assertThat(repliesAndActions.smartActions.actions.get(0)).isEqualTo(
-                mEntry.getSmartActions().get(0));
+        assertThat(smartReplyState.getSmartActions().actions)
+                .containsExactly(mEntry.getSmartActions().get(0));
+        assertThat(smartReplyState.getSuppressedActions()).isNull();
+        assertThat(smartReplyState.getHasPhishingAction()).isFalse();
     }
 
     @Test
@@ -340,14 +400,16 @@
                 .setSmartActions(createActions("Sys Smart Action 1", "Sys Smart Action 2"))
                 .build();
 
-        SmartRepliesAndActions repliesAndActions =
-                mSmartRepliesInflater.chooseSmartRepliesAndActions(mEntry);
+        InflatedSmartReplyState smartReplyState =
+                mSmartReplyStateInflater.chooseSmartRepliesAndActions(mEntry);
 
         // We don't restrict replies or actions in screen pinning mode.
-        assertThat(repliesAndActions.smartReplies.choices).isEqualTo(
-                mEntry.getSmartReplies());
-        assertThat(repliesAndActions.smartActions.actions).isEqualTo(
-                mEntry.getSmartActions());
+        assertThat(smartReplyState.getSmartReplies().choices)
+                .containsExactlyElementsIn(mEntry.getSmartReplies()).inOrder();
+        assertThat(smartReplyState.getSmartActions().actions)
+                .containsExactlyElementsIn(mEntry.getSmartActions()).inOrder();
+        assertThat(smartReplyState.getSuppressedActions()).isNull();
+        assertThat(smartReplyState.getHasPhishingAction()).isFalse();
     }
 
     @Test
@@ -360,17 +422,24 @@
         List<Notification.Action> rightActions = Arrays.asList(
                 createAction("firstAction"),
                 createAction("secondAction"));
+        List<Integer> leftSuppressed = Arrays.asList(1, 2);
+        List<Integer> rightSuppressed = Arrays.asList(1, 2);
+        boolean leftPhishing = true;
+        boolean rightPhishing = true;
 
-        SmartRepliesAndActions leftRepliesAndActions = new SmartRepliesAndActions(
+        InflatedSmartReplyState leftRepliesAndActions = new InflatedSmartReplyState(
                 new SmartReplies(leftReplies, null, null, false /* fromAssistant */),
-                new SmartActions(leftActions, false /* fromAssistant */));
-        SmartRepliesAndActions rightRepliesAndActions = new SmartRepliesAndActions(
+                new SmartActions(leftActions, false /* fromAssistant */),
+                new SuppressedActions(leftSuppressed),
+                leftPhishing);
+        InflatedSmartReplyState rightRepliesAndActions = new InflatedSmartReplyState(
                 new SmartReplies(rightReplies, null, null, false /* fromAssistant */),
-                new SmartActions(rightActions, false /* fromAssistant */));
+                new SmartActions(rightActions, false /* fromAssistant */),
+                new SuppressedActions(rightSuppressed),
+                rightPhishing);
 
-        assertThat(
-                SmartRepliesAndActionsInflaterKt
-                        .areSuggestionsSimilar(leftRepliesAndActions, rightRepliesAndActions))
+        assertThat(SmartReplyStateInflaterKt
+                .areSuggestionsSimilar(leftRepliesAndActions, rightRepliesAndActions))
                 .isTrue();
     }
 
@@ -384,16 +453,25 @@
         List<Notification.Action> rightActions = Arrays.asList(
                 createAction("firstAction"),
                 createAction("secondAction"));
+        List<Integer> leftSuppressed = Arrays.asList(1, 2);
+        List<Integer> rightSuppressed = Arrays.asList(1, 2);
+        boolean leftPhishing = true;
+        boolean rightPhishing = true;
 
-        SmartRepliesAndActions leftRepliesAndActions = new SmartRepliesAndActions(
+        InflatedSmartReplyState leftRepliesAndActions = new InflatedSmartReplyState(
                 new SmartReplies(leftReplies, null, null, false /* fromAssistant */),
-                new SmartActions(leftActions, false /* fromAssistant */));
-        SmartRepliesAndActions rightRepliesAndActions = new SmartRepliesAndActions(
+                new SmartActions(leftActions, false /* fromAssistant */),
+                new SuppressedActions(leftSuppressed),
+                leftPhishing);
+        InflatedSmartReplyState rightRepliesAndActions = new InflatedSmartReplyState(
                 new SmartReplies(rightReplies, null, null, false /* fromAssistant */),
-                new SmartActions(rightActions, false /* fromAssistant */));
+                new SmartActions(rightActions, false /* fromAssistant */),
+                new SuppressedActions(rightSuppressed),
+                rightPhishing);
 
-        assertThat(SmartRepliesAndActionsInflaterKt.areSuggestionsSimilar(
-                leftRepliesAndActions, rightRepliesAndActions)).isFalse();
+        assertThat(SmartReplyStateInflaterKt
+                .areSuggestionsSimilar(leftRepliesAndActions, rightRepliesAndActions))
+                .isFalse();
     }
 
     @Test
@@ -406,16 +484,87 @@
         List<Notification.Action> rightActions = Arrays.asList(
                 createAction("firstAction"),
                 createAction("not secondAction"));
+        List<Integer> leftSuppressed = Arrays.asList(1, 2);
+        List<Integer> rightSuppressed = Arrays.asList(1, 2);
+        boolean leftPhishing = true;
+        boolean rightPhishing = true;
 
-        SmartRepliesAndActions leftRepliesAndActions = new SmartRepliesAndActions(
+        InflatedSmartReplyState leftRepliesAndActions = new InflatedSmartReplyState(
                 new SmartReplies(leftReplies, null, null, false /* fromAssistant */),
-                new SmartActions(leftActions, false /* fromAssistant */));
-        SmartRepliesAndActions rightRepliesAndActions = new SmartRepliesAndActions(
+                new SmartActions(leftActions, false /* fromAssistant */),
+                new SuppressedActions(leftSuppressed),
+                leftPhishing);
+        InflatedSmartReplyState rightRepliesAndActions = new InflatedSmartReplyState(
                 new SmartReplies(rightReplies, null, null, false /* fromAssistant */),
-                new SmartActions(rightActions, false /* fromAssistant */));
+                new SmartActions(rightActions, false /* fromAssistant */),
+                new SuppressedActions(rightSuppressed),
+                rightPhishing);
 
-        assertThat(SmartRepliesAndActionsInflaterKt.areSuggestionsSimilar(
-                leftRepliesAndActions, rightRepliesAndActions)).isFalse();
+        assertThat(SmartReplyStateInflaterKt
+                .areSuggestionsSimilar(leftRepliesAndActions, rightRepliesAndActions))
+                .isFalse();
+    }
+
+    @Test
+    public void areSuggestionsSimilar_falseForDifferentSuppressedActions() {
+        List<CharSequence> leftReplies = createReplies("first reply", "second reply");
+        List<CharSequence> rightReplies = createReplies("first reply", "second reply");
+        List<Notification.Action> leftActions = Arrays.asList(
+                createAction("firstAction"),
+                createAction("secondAction"));
+        List<Notification.Action> rightActions = Arrays.asList(
+                createAction("firstAction"),
+                createAction("secondAction"));
+        List<Integer> leftSuppressed = Arrays.asList(1, 2);
+        List<Integer> rightSuppressed = Arrays.asList(1, 3);
+        boolean leftPhishing = true;
+        boolean rightPhishing = true;
+
+        InflatedSmartReplyState leftRepliesAndActions = new InflatedSmartReplyState(
+                new SmartReplies(leftReplies, null, null, false /* fromAssistant */),
+                new SmartActions(leftActions, false /* fromAssistant */),
+                new SuppressedActions(leftSuppressed),
+                leftPhishing);
+        InflatedSmartReplyState rightRepliesAndActions = new InflatedSmartReplyState(
+                new SmartReplies(rightReplies, null, null, false /* fromAssistant */),
+                new SmartActions(rightActions, false /* fromAssistant */),
+                new SuppressedActions(rightSuppressed),
+                rightPhishing);
+
+        assertThat(SmartReplyStateInflaterKt
+                .areSuggestionsSimilar(leftRepliesAndActions, rightRepliesAndActions))
+                .isFalse();
+    }
+
+    @Test
+    public void areSuggestionsSimilar_falseForDifferentPhishing() {
+        List<CharSequence> leftReplies = createReplies("first reply", "second reply");
+        List<CharSequence> rightReplies = createReplies("first reply", "second reply");
+        List<Notification.Action> leftActions = Arrays.asList(
+                createAction("firstAction"),
+                createAction("secondAction"));
+        List<Notification.Action> rightActions = Arrays.asList(
+                createAction("firstAction"),
+                createAction("secondAction"));
+        List<Integer> leftSuppressed = Arrays.asList(1, 2);
+        List<Integer> rightSuppressed = Arrays.asList(1, 2);
+        boolean leftPhishing = true;
+        boolean rightPhishing = false;
+
+        InflatedSmartReplyState leftRepliesAndActions = new InflatedSmartReplyState(
+                new SmartReplies(leftReplies, null, null, false /* fromAssistant */),
+                new SmartActions(leftActions, false /* fromAssistant */),
+                new SuppressedActions(leftSuppressed),
+                leftPhishing);
+        InflatedSmartReplyState rightRepliesAndActions = new InflatedSmartReplyState(
+                new SmartReplies(rightReplies, null, null, false /* fromAssistant */),
+                new SmartActions(rightActions, false /* fromAssistant */),
+                new SuppressedActions(rightSuppressed),
+                rightPhishing);
+
+        assertThat(SmartReplyStateInflaterKt
+                .areSuggestionsSimilar(leftRepliesAndActions, rightRepliesAndActions))
+                .isFalse();
     }
 
     private void setupAppGeneratedReplies(CharSequence[] smartReplies) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 89cc2b5..e52b926 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -21,9 +21,9 @@
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
 
 import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Matchers.isA;
@@ -76,6 +76,7 @@
 import com.android.systemui.demomode.DemoModeController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 
 import org.junit.After;
@@ -173,8 +174,6 @@
         mMockSubDefaults = mock(SubscriptionDefaults.class);
         mNetCapabilities = new NetworkCapabilities();
         when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(true);
-        when(mMockCm.getDefaultNetworkCapabilitiesForUser(0)).thenReturn(
-                new NetworkCapabilities[] { mNetCapabilities });
         when(mMockTm.createForSubscriptionId(anyInt())).thenReturn(mMockTm);
         doAnswer(invocation -> {
             int rssi = invocation.getArgument(0);
@@ -257,8 +256,11 @@
             ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
         verify(mMockCm, atLeastOnce())
             .registerDefaultNetworkCallback(callbackArg.capture(), isA(Handler.class));
-        mDefaultCallbackInWifiTracker = callbackArg.getAllValues().get(0);
-        mDefaultCallbackInNetworkController = callbackArg.getAllValues().get(1);
+        int captureSize = callbackArg.getAllValues().size();
+        assertTrue(captureSize > 1);
+        assertEquals(captureSize % 2, 0);
+        mDefaultCallbackInWifiTracker = callbackArg.getAllValues().get(captureSize - 2);
+        mDefaultCallbackInNetworkController = callbackArg.getAllValues().get(captureSize - 1);
         assertNotNull(mDefaultCallbackInWifiTracker);
         assertNotNull(mDefaultCallbackInNetworkController);
         verify(mMockCm, atLeastOnce()).registerNetworkCallback(
@@ -307,14 +309,18 @@
         setLevel(DEFAULT_LEVEL);
         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
                 TelephonyManager.NETWORK_TYPE_UMTS);
+        setConnectivityViaCallbackInNetworkController(
+                NetworkCapabilities.TRANSPORT_CELLULAR, true, true, null);
         setConnectivityViaBroadcast(
-            NetworkCapabilities.TRANSPORT_CELLULAR, true, true);
+                NetworkCapabilities.TRANSPORT_CELLULAR, true, true);
     }
 
     public void setConnectivityViaBroadcastForVcn(
             int networkType, boolean validated, boolean isConnected, VcnTransportInfo info) {
         mNetCapabilities.setTransportInfo(info);
         setConnectivityCommon(networkType, validated, isConnected);
+        mDefaultCallbackInNetworkController.onCapabilitiesChanged(
+                mock(Network.class), new NetworkCapabilities(mNetCapabilities));
         Intent i = new Intent(ConnectivityManager.INET_CONDITION_ACTION);
         mNetworkController.onReceive(mContext, i);
     }
@@ -322,6 +328,8 @@
     public void setConnectivityViaBroadcast(
         int networkType, boolean validated, boolean isConnected) {
         setConnectivityCommon(networkType, validated, isConnected);
+        mDefaultCallbackInNetworkController.onCapabilitiesChanged(
+                mock(Network.class), new NetworkCapabilities(mNetCapabilities));
         Intent i = new Intent(ConnectivityManager.INET_CONDITION_ACTION);
         mNetworkController.onReceive(mContext, i);
     }
@@ -487,28 +495,21 @@
 
     protected void verifyLastQsMobileDataIndicators(boolean visible, int icon, int typeIcon,
             boolean dataIn, boolean dataOut) {
-        ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
-        ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class);
-        ArgumentCaptor<Boolean> dataInArg = ArgumentCaptor.forClass(Boolean.class);
-        ArgumentCaptor<Boolean> dataOutArg = ArgumentCaptor.forClass(Boolean.class);
+        ArgumentCaptor<MobileDataIndicators> indicatorsArg =
+                ArgumentCaptor.forClass(MobileDataIndicators.class);
 
         verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators(
-                    any(),
-                    iconArg.capture(),
-                    anyInt(),
-                    typeIconArg.capture(), dataInArg.capture(), dataOutArg.capture(),
-                    any(CharSequence.class), any(CharSequence.class), any(CharSequence.class),
-                    anyBoolean(), anyInt(), anyBoolean(), anyBoolean());
-        IconState iconState = iconArg.getValue();
+                    indicatorsArg.capture());
+        MobileDataIndicators expected = indicatorsArg.getValue();
         int state = SignalDrawable.getState(icon, CellSignalStrength.getNumSignalStrengthLevels(),
                 false);
-        assertEquals("Visibility in, quick settings", visible, iconState.visible);
-        assertEquals("Signal icon in, quick settings", state, iconState.icon);
-        assertEquals("Data icon in, quick settings", typeIcon, (int) typeIconArg.getValue());
+        assertEquals("Visibility in, quick settings", visible, expected.qsIcon.visible);
+        assertEquals("Signal icon in, quick settings", state, expected.qsIcon.icon);
+        assertEquals("Data icon in, quick settings", typeIcon, expected.qsType);
         assertEquals("Data direction in, in quick settings", dataIn,
-                (boolean) dataInArg.getValue());
+                expected.activityIn);
         assertEquals("Data direction out, in quick settings", dataOut,
-                (boolean) dataOutArg.getValue());
+                expected.activityOut);
     }
 
     protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon) {
@@ -522,44 +523,35 @@
 
     protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon,
         boolean roaming, boolean inet) {
-        ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
-        ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class);
+        ArgumentCaptor<MobileDataIndicators> indicatorsArg =
+                ArgumentCaptor.forClass(MobileDataIndicators.class);
 
         // TODO: Verify all fields.
         verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators(
-                iconArg.capture(),
-                any(),
-                typeIconArg.capture(),
-                anyInt(), anyBoolean(), anyBoolean(),
-                any(CharSequence.class), any(CharSequence.class), any(),
-                anyBoolean(), anyInt(), eq(roaming), anyBoolean());
-        IconState iconState = iconArg.getValue();
+                indicatorsArg.capture());
+        MobileDataIndicators expected = indicatorsArg.getValue();
         int state = icon == -1 ? 0
                 : SignalDrawable.getState(icon, CellSignalStrength.getNumSignalStrengthLevels(),
                         !inet);
-        assertEquals("Signal icon in status bar", state, iconState.icon);
-        assertEquals("Data icon in status bar", typeIcon, (int) typeIconArg.getValue());
-        assertEquals("Visibility in status bar", visible, iconState.visible);
+        assertEquals("Signal icon in status bar", state, expected.statusIcon.icon);
+        assertEquals("Data icon in status bar", typeIcon, expected.statusType);
+        assertEquals("Visibility in status bar", visible, expected.statusIcon.visible);
     }
 
     protected void verifyLastMobileDataIndicatorsForVcn(boolean visible, int level, int typeIcon,
             boolean inet) {
-        ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
-        ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class);
+        ArgumentCaptor<MobileDataIndicators> indicatorsArg =
+                ArgumentCaptor.forClass(MobileDataIndicators.class);
 
         verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators(
-                iconArg.capture(),
-                any(),
-                typeIconArg.capture(),
-                anyInt(), anyBoolean(), anyBoolean(),
-                any(CharSequence.class), any(CharSequence.class), any(),
-                anyBoolean(), anyInt(), anyBoolean(), anyBoolean());
-        IconState iconState = iconArg.getValue();
+                indicatorsArg.capture());
+
+        MobileDataIndicators expected = indicatorsArg.getValue();
         int state = SignalDrawable.getState(
                 level, CellSignalStrength.getNumSignalStrengthLevels(), !inet);
-        assertEquals("Signal icon in status bar", state, iconState.icon);
-        assertEquals("Data icon in status bar", typeIcon, (int) typeIconArg.getValue());
-        assertEquals("Visibility in status bar", visible, iconState.visible);
+        assertEquals("Signal icon in status bar", state, expected.statusIcon.icon);
+        assertEquals("Data icon in status bar", typeIcon, expected.statusType);
+        assertEquals("Visibility in status bar", visible, expected.statusIcon.visible);
     }
 
     protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon,
@@ -580,6 +572,8 @@
             boolean qsVisible, int qsIcon, int qsTypeIcon, boolean dataIn, boolean dataOut,
             boolean cutOut, CharSequence typeContentDescription,
             CharSequence typeContentDescriptionHtml) {
+        ArgumentCaptor<MobileDataIndicators> indicatorsArg =
+                ArgumentCaptor.forClass(MobileDataIndicators.class);
         ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
         ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class);
         ArgumentCaptor<IconState> qsIconArg = ArgumentCaptor.forClass(IconState.class);
@@ -592,17 +586,9 @@
                 ArgumentCaptor.forClass(CharSequence.class);
 
         verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators(
-                iconArg.capture(),
-                qsIconArg.capture(),
-                typeIconArg.capture(),
-                qsTypeIconArg.capture(),
-                dataInArg.capture(),
-                dataOutArg.capture(),
-                typeContentDescriptionArg.capture(),
-                typeContentDescriptionHtmlArg.capture(),
-                any(), anyBoolean(), anyInt(), anyBoolean(), anyBoolean());
+                indicatorsArg.capture());
 
-        IconState iconState = iconArg.getValue();
+        MobileDataIndicators expected = indicatorsArg.getValue();
 
         int numSignalStrengthBins = CellSignalStrength.getNumSignalStrengthLevels();
         if (mMobileSignalController.mInflateSignalStrengths) {
@@ -610,29 +596,28 @@
             icon++;
         }
         int state = SignalDrawable.getState(icon, numSignalStrengthBins, cutOut);
-        assertEquals("Data icon in status bar", typeIcon, (int) typeIconArg.getValue());
-        assertEquals("Signal icon in status bar", state, iconState.icon);
-        assertEquals("Visibility in status bar", visible, iconState.visible);
+        assertEquals("Data icon in status bar", typeIcon, expected.statusType);
+        assertEquals("Signal icon in status bar", state, expected.statusIcon.icon);
+        assertEquals("Visibility in status bar", visible, expected.statusIcon.visible);
 
-        iconState = qsIconArg.getValue();
         if (visible) {
-            assertEquals("Visibility in quick settings", qsVisible, iconState.visible);
-            assertEquals("Signal icon in quick settings", state, iconState.icon);
+            assertEquals("Visibility in quick settings", qsVisible, expected.qsIcon.visible);
+            assertEquals("Signal icon in quick settings", state, expected.qsIcon.icon);
         } else {
-            assertEquals("Cellular is not default", null, iconState);
+            assertEquals("Cellular is not default", null, expected.qsIcon);
         }
-        assertEquals("Data icon in quick settings", qsTypeIcon, (int) qsTypeIconArg.getValue());
+        assertEquals("Data icon in quick settings", qsTypeIcon, expected.qsType);
         assertEquals("Data direction in in quick settings", dataIn,
-                (boolean) dataInArg.getValue());
+                expected.activityIn);
         assertEquals("Data direction out in quick settings", dataOut,
-                (boolean) dataOutArg.getValue());
+                expected.activityOut);
         if (typeContentDescription != null) { // Only check if it was provided
             assertEquals("Type content description", typeContentDescription,
-                    typeContentDescriptionArg.getValue());
+                    expected.typeContentDescription);
         }
         if (typeContentDescriptionHtml != null) { // Only check if it was provided
             assertEquals("Type content description (html)", typeContentDescriptionHtml,
-                    typeContentDescriptionHtmlArg.getValue());
+                    expected.typeContentDescriptionHtml);
         }
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
index fc1a08ac..c6812a2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
@@ -3,7 +3,6 @@
 import static junit.framework.Assert.assertEquals;
 
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -21,7 +20,7 @@
 import android.testing.TestableLooper.RunWithLooper;
 
 import com.android.settingslib.mobile.TelephonyIcons;
-import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.WifiIndicators;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -316,44 +315,42 @@
     }
 
     protected void verifyLastQsDataDirection(boolean in, boolean out) {
-        ArgumentCaptor<Boolean> inArg = ArgumentCaptor.forClass(Boolean.class);
-        ArgumentCaptor<Boolean> outArg = ArgumentCaptor.forClass(Boolean.class);
+        ArgumentCaptor<WifiIndicators> indicatorsArg =
+                ArgumentCaptor.forClass(WifiIndicators.class);
 
         Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setWifiIndicators(
-                anyBoolean(), any(), any(), inArg.capture(), outArg.capture(), any(), anyBoolean(),
-                any());
-        assertEquals("WiFi data in, in quick settings", in, (boolean) inArg.getValue());
-        assertEquals("WiFi data out, in quick settings", out, (boolean) outArg.getValue());
+                indicatorsArg.capture());
+        WifiIndicators expected = indicatorsArg.getValue();
+        assertEquals("WiFi data in, in quick settings", in, expected.activityIn);
+        assertEquals("WiFi data out, in quick settings", out, expected.activityOut);
     }
 
     protected void verifyLastQsWifiIcon(boolean enabled, boolean connected, int icon,
             String description) {
-        ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
-        ArgumentCaptor<Boolean> enabledArg = ArgumentCaptor.forClass(Boolean.class);
-        ArgumentCaptor<String> descArg = ArgumentCaptor.forClass(String.class);
+        ArgumentCaptor<WifiIndicators> indicatorsArg =
+                ArgumentCaptor.forClass(WifiIndicators.class);
 
         Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setWifiIndicators(
-                enabledArg.capture(), any(), iconArg.capture(), anyBoolean(),
-                anyBoolean(), descArg.capture(), anyBoolean(), any());
-        IconState iconState = iconArg.getValue();
-        assertEquals("WiFi enabled, in quick settings", enabled, (boolean) enabledArg.getValue());
-        assertEquals("WiFI desc (ssid), in quick settings", description, descArg.getValue());
+                indicatorsArg.capture());
+        WifiIndicators expected = indicatorsArg.getValue();
+        assertEquals("WiFi enabled, in quick settings", enabled, expected.enabled);
+        assertEquals("WiFI desc (ssid), in quick settings", description, expected.description);
         if (enabled && connected) {
-            assertEquals("WiFi connected, in quick settings", connected, iconState.visible);
-            assertEquals("WiFi signal, in quick settings", icon, iconState.icon);
+            assertEquals("WiFi connected, in quick settings", connected, expected.qsIcon.visible);
+            assertEquals("WiFi signal, in quick settings", icon, expected.qsIcon.icon);
         } else {
-            assertEquals("WiFi is not default", null, iconState);
+            assertEquals("WiFi is not default", null, expected.qsIcon);
         }
     }
 
     protected void verifyLastWifiIcon(boolean visible, int icon) {
-        ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
+        ArgumentCaptor<WifiIndicators> indicatorsArg =
+                ArgumentCaptor.forClass(WifiIndicators.class);
 
         Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setWifiIndicators(
-                anyBoolean(), iconArg.capture(), any(), anyBoolean(), anyBoolean(),
-                any(), anyBoolean(), any());
-        IconState iconState = iconArg.getValue();
-        assertEquals("WiFi visible, in status bar", visible, iconState.visible);
-        assertEquals("WiFi signal, in status bar", icon, iconState.icon);
+                indicatorsArg.capture());
+        WifiIndicators expected = indicatorsArg.getValue();
+        assertEquals("WiFi visible, in status bar", visible, expected.statusIcon.visible);
+        assertEquals("WiFi signal, in status bar", icon, expected.statusIcon.icon);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayApplierTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayApplierTest.java
index 45828c3..6067b42 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayApplierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayApplierTest.java
@@ -23,6 +23,7 @@
 import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_ICON_SETTINGS;
 import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_ICON_SYSUI;
 import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_ICON_THEME_PICKER;
+import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_NEUTRAL_PALETTE;
 import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_SHAPE;
 import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_SYSTEM_PALETTE;
 import static com.android.systemui.theme.ThemeOverlayApplier.SETTINGS_PACKAGE;
@@ -31,7 +32,6 @@
 import static com.android.systemui.theme.ThemeOverlayApplier.THEME_CATEGORIES;
 
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.mock;
@@ -87,7 +87,9 @@
     private static final String THEMEPICKER_PACKAGE = "com.android.wallpaper";
     private static final String LAUNCHER_PACKAGE = "com.android.launcher3";
     private static final UserHandle TEST_USER = UserHandle.of(5);
-    private static final Set<UserHandle> TEST_USER_HANDLES = Sets.newHashSet(TEST_USER);
+    private static final UserHandle TEST_USER_MANAGED_PROFILE = UserHandle.of(6);
+    private static final Set<UserHandle> TEST_USER_HANDLES =
+            Sets.newHashSet(TEST_USER_MANAGED_PROFILE);
 
     @Mock
     OverlayManager mOverlayManager;
@@ -114,6 +116,8 @@
                                 ANDROID_PACKAGE, OVERLAY_CATEGORY_ACCENT_COLOR, false),
                         createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_SYSTEM_PALETTE,
                                 ANDROID_PACKAGE, OVERLAY_CATEGORY_SYSTEM_PALETTE, false),
+                        createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_NEUTRAL_PALETTE,
+                                ANDROID_PACKAGE, OVERLAY_CATEGORY_NEUTRAL_PALETTE, false),
                         createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_FONT,
                                 ANDROID_PACKAGE, OVERLAY_CATEGORY_FONT, false),
                         createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_SHAPE,
@@ -124,6 +128,8 @@
                                 ANDROID_PACKAGE, OVERLAY_CATEGORY_ACCENT_COLOR, true),
                         createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_SYSTEM_PALETTE,
                                 ANDROID_PACKAGE, OVERLAY_CATEGORY_SYSTEM_PALETTE, true),
+                        createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_NEUTRAL_PALETTE,
+                                ANDROID_PACKAGE, OVERLAY_CATEGORY_NEUTRAL_PALETTE, true),
                         createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_FONT,
                                 ANDROID_PACKAGE, OVERLAY_CATEGORY_FONT, true),
                         createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_SHAPE,
@@ -154,13 +160,19 @@
                                 THEMEPICKER_PACKAGE, OVERLAY_CATEGORY_ICON_THEME_PICKER, false),
                         createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_ICON_THEME_PICKER,
                                 THEMEPICKER_PACKAGE, OVERLAY_CATEGORY_ICON_THEME_PICKER, true)));
+
+        OverlayInfo launcherTargetInfo = new OverlayInfo("packageName", LAUNCHER_PACKAGE,
+                null, null, "/", 0, 0, 0, false);
+        when(mOverlayManager.getOverlayInfo(any(OverlayIdentifier.class), any()))
+                .thenReturn(launcherTargetInfo);
         clearInvocations(mOverlayManager);
         verify(mDumpManager).registerDumpable(any(), any());
     }
 
     @Test
     public void allCategoriesSpecified_allEnabledExclusively() {
-        mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, TEST_USER_HANDLES);
+        mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, TEST_USER.getIdentifier(),
+                TEST_USER_HANDLES);
         verify(mOverlayManager).commit(any());
 
         for (OverlayIdentifier overlayPackage : ALL_CATEGORIES_MAP.values()) {
@@ -171,7 +183,8 @@
 
     @Test
     public void allCategoriesSpecified_sysuiCategoriesAlsoAppliedToSysuiUser() {
-        mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, TEST_USER_HANDLES);
+        mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, TEST_USER.getIdentifier(),
+                TEST_USER_HANDLES);
 
         for (Map.Entry<String, OverlayIdentifier> entry : ALL_CATEGORIES_MAP.entrySet()) {
             if (SYSTEM_USER_CATEGORIES.contains(entry.getKey())) {
@@ -187,27 +200,25 @@
     @Test
     public void allCategoriesSpecified_enabledForAllUserHandles() {
         Set<UserHandle> userHandles = Sets.newHashSet(TEST_USER_HANDLES);
-        UserHandle newUserHandle = UserHandle.of(10);
-        userHandles.add(newUserHandle);
-        mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, userHandles);
+        mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, TEST_USER.getIdentifier(),
+                userHandles);
 
         for (OverlayIdentifier overlayPackage : ALL_CATEGORIES_MAP.values()) {
             verify(mTransactionBuilder).setEnabled(eq(overlayPackage), eq(true),
                     eq(TEST_USER.getIdentifier()));
-            verify(mTransactionBuilder).setEnabled(eq(overlayPackage), eq(true),
-                    eq(newUserHandle.getIdentifier()));
+            // Not enabled for work profile because the target package is LAUNCHER_PACKAGE
+            verify(mTransactionBuilder, never()).setEnabled(eq(overlayPackage), eq(true),
+                    eq(TEST_USER_MANAGED_PROFILE.getIdentifier()));
         }
     }
 
     @Test
     public void applyCurrentUserOverlays_createsPendingOverlays() {
-        Set<UserHandle> userHandles = Sets.newHashSet(TEST_USER_HANDLES);
-        UserHandle newUserHandle = UserHandle.of(10);
-        userHandles.add(newUserHandle);
-        FabricatedOverlay[] pendingCreation = new FabricatedOverlay[] {
+        FabricatedOverlay[] pendingCreation = new FabricatedOverlay[]{
                 mock(FabricatedOverlay.class)
         };
-        mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, pendingCreation, userHandles);
+        mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, pendingCreation,
+                TEST_USER.getIdentifier(), TEST_USER_HANDLES);
 
         for (FabricatedOverlay overlay : pendingCreation) {
             verify(mTransactionBuilder).registerFabricatedOverlay(eq(overlay));
@@ -215,20 +226,13 @@
     }
 
     @Test
-    public void allCategoriesSpecified_overlayManagerNotQueried() {
-        mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, TEST_USER_HANDLES);
-
-        verify(mOverlayManager, never())
-                .getOverlayInfosForTarget(anyString(), any(UserHandle.class));
-    }
-
-    @Test
     public void someCategoriesSpecified_specifiedEnabled_unspecifiedDisabled() {
         Map<String, OverlayIdentifier> categoryToPackage = new HashMap<>(ALL_CATEGORIES_MAP);
         categoryToPackage.remove(OVERLAY_CATEGORY_ICON_SETTINGS);
         categoryToPackage.remove(OVERLAY_CATEGORY_ICON_ANDROID);
 
-        mManager.applyCurrentUserOverlays(categoryToPackage, null, TEST_USER_HANDLES);
+        mManager.applyCurrentUserOverlays(categoryToPackage, null, TEST_USER.getIdentifier(),
+                TEST_USER_HANDLES);
 
         for (OverlayIdentifier overlayPackage : categoryToPackage.values()) {
             verify(mTransactionBuilder).setEnabled(eq(overlayPackage), eq(true),
@@ -244,7 +248,8 @@
 
     @Test
     public void zeroCategoriesSpecified_allDisabled() {
-        mManager.applyCurrentUserOverlays(Maps.newArrayMap(), null, TEST_USER_HANDLES);
+        mManager.applyCurrentUserOverlays(Maps.newArrayMap(), null, TEST_USER.getIdentifier(),
+                TEST_USER_HANDLES);
 
         for (String category : THEME_CATEGORIES) {
             verify(mTransactionBuilder).setEnabled(
@@ -258,7 +263,8 @@
         Map<String, OverlayIdentifier> categoryToPackage = new HashMap<>(ALL_CATEGORIES_MAP);
         categoryToPackage.put("blah.category", new OverlayIdentifier("com.example.blah.category"));
 
-        mManager.applyCurrentUserOverlays(categoryToPackage, null, TEST_USER_HANDLES);
+        mManager.applyCurrentUserOverlays(categoryToPackage, null, TEST_USER.getIdentifier(),
+                TEST_USER_HANDLES);
 
         verify(mTransactionBuilder, never()).setEnabled(
                 eq(new OverlayIdentifier("com.example.blah.category")), eq(false),
@@ -268,23 +274,6 @@
                 eq(TEST_USER.getIdentifier()));
     }
 
-    @Test
-    public void overlayManagerOnlyQueriedForUnspecifiedPackages() {
-        Map<String, OverlayIdentifier> categoryToPackage = new HashMap<>(ALL_CATEGORIES_MAP);
-        categoryToPackage.remove(OVERLAY_CATEGORY_ICON_SETTINGS);
-
-        mManager.applyCurrentUserOverlays(categoryToPackage, null, TEST_USER_HANDLES);
-
-        verify(mOverlayManager).getOverlayInfosForTarget(SETTINGS_PACKAGE, UserHandle.SYSTEM);
-        verify(mOverlayManager, never()).getOverlayInfosForTarget(ANDROID_PACKAGE,
-                UserHandle.SYSTEM);
-        verify(mOverlayManager, never()).getOverlayInfosForTarget(SYSUI_PACKAGE, UserHandle.SYSTEM);
-        verify(mOverlayManager, never()).getOverlayInfosForTarget(LAUNCHER_PACKAGE,
-                UserHandle.SYSTEM);
-        verify(mOverlayManager, never()).getOverlayInfosForTarget(THEMEPICKER_PACKAGE,
-                UserHandle.SYSTEM);
-    }
-
     private static OverlayInfo createOverlayInfo(String packageName, String targetPackageName,
             String category, boolean enabled) {
         return new OverlayInfo(packageName, null, targetPackageName, null, category, "",
diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
index aa385ef..d80c40f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
@@ -143,7 +143,7 @@
                 ArgumentCaptor.forClass(Map.class);
 
         verify(mThemeOverlayApplier)
-                .applyCurrentUserOverlays(themeOverlays.capture(), any(), any());
+                .applyCurrentUserOverlays(themeOverlays.capture(), any(), anyInt(), any());
 
         // Assert that we received the colors that we were expecting
         assertThat(themeOverlays.getValue().get(OVERLAY_CATEGORY_SYSTEM_PALETTE))
@@ -175,7 +175,7 @@
                 ArgumentCaptor.forClass(Map.class);
 
         verify(mThemeOverlayApplier)
-                .applyCurrentUserOverlays(themeOverlays.capture(), any(), any());
+                .applyCurrentUserOverlays(themeOverlays.capture(), any(), anyInt(), any());
 
         // Assert that we received the colors that we were expecting
         assertThat(themeOverlays.getValue().get(OVERLAY_CATEGORY_SYSTEM_PALETTE))
@@ -198,7 +198,7 @@
                 ArgumentCaptor.forClass(Map.class);
 
         verify(mThemeOverlayApplier)
-                .applyCurrentUserOverlays(themeOverlays.capture(), any(), any());
+                .applyCurrentUserOverlays(themeOverlays.capture(), any(), anyInt(), any());
 
         // Assert that we received the colors that we were expecting
         assertThat(themeOverlays.getValue().get(OVERLAY_CATEGORY_SYSTEM_PALETTE))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java
index c5a197e..242fe9f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.util.sensors;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
@@ -86,6 +88,29 @@
     }
 
     @Test
+    public void testNotLoaded() {
+        mFakeProximitySensor.setSensorAvailable(false);
+
+        assertThat(mTestableCallback.mLastResult).isNull();
+        assertThat(mTestableCallback.mNumCalls).isEqualTo(0);
+
+        mProximityCheck.check(100, mTestableCallback);
+
+        assertThat(mTestableCallback.mLastResult).isNull();
+        assertThat(mTestableCallback.mNumCalls).isEqualTo(1);
+
+        mFakeProximitySensor.setSensorAvailable(true);
+
+        mProximityCheck.check(100, mTestableCallback);
+
+        mFakeProximitySensor.setLastEvent(new ProximitySensor.ThresholdSensorEvent(true, 0));
+        mFakeProximitySensor.alertListeners();
+
+        assertThat(mTestableCallback.mLastResult).isNotNull();
+        assertThat(mTestableCallback.mNumCalls).isEqualTo(2);
+    }
+
+    @Test
     public void testProxDoesntCancelOthers() {
         assertFalse(mFakeProximitySensor.isRegistered());
         // We don't need our "other" listener to do anything. Just ensure our sensor is registered.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java
index 97d4aa7..7d8a288 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java
@@ -14,7 +14,6 @@
 
 package com.android.systemui.utils.leaks;
 
-import android.os.UserHandle;
 import android.testing.LeakCheck;
 
 import com.android.systemui.tuner.TunerService;
@@ -78,12 +77,15 @@
     }
 
     @Override
-    public void setTunerEnabled(UserHandle user, boolean enabled) {
+    public void setTunerEnabled(boolean enabled) {
         mEnabled = enabled;
     }
 
     @Override
-    public boolean isTunerEnabled(UserHandle user) {
+    public boolean isTunerEnabled() {
         return mEnabled;
     }
+
+    @Override
+    public void showResetRequest(Runnable onDisabled) {}
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
index c085689..3cea175 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
@@ -22,6 +22,7 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
 import android.app.KeyguardManager;
@@ -37,6 +38,8 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.systemui.Prefs;
+import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.VolumeDialogController;
 import com.android.systemui.plugins.VolumeDialogController.State;
@@ -58,6 +61,11 @@
 public class VolumeDialogImplTest extends SysuiTestCase {
 
     VolumeDialogImpl mDialog;
+    View mActiveRinger;
+    View mDrawerContainer;
+    View mDrawerVibrate;
+    View mDrawerMute;
+    View mDrawerNormal;
 
     @Mock
     VolumeDialogController mController;
@@ -80,6 +88,17 @@
         mDialog.init(0, null);
         State state = createShellState();
         mDialog.onStateChangedH(state);
+
+        mActiveRinger = mDialog.getDialogView().findViewById(
+                R.id.volume_new_ringer_active_icon_container);
+        mDrawerContainer = mDialog.getDialogView().findViewById(R.id.volume_drawer_container);
+        mDrawerVibrate = mDrawerContainer.findViewById(R.id.volume_drawer_vibrate);
+        mDrawerMute = mDrawerContainer.findViewById(R.id.volume_drawer_mute);
+        mDrawerNormal = mDrawerContainer.findViewById(R.id.volume_drawer_normal);
+
+        Prefs.putInt(mContext,
+                Prefs.Key.SEEN_RINGER_GUIDANCE_COUNT,
+                VolumePrefs.SHOW_RINGER_TOAST_COUNT + 1);
     }
 
     private State createShellState() {
@@ -207,6 +226,48 @@
         verify(mController, never()).vibrate(any());
     }
 
+    @Test
+    public void testSelectVibrateFromDrawer() {
+        final State initialUnsetState = new State();
+        initialUnsetState.ringerModeInternal = AudioManager.RINGER_MODE_NORMAL;
+        mDialog.onStateChangedH(initialUnsetState);
+
+        mActiveRinger.performClick();
+        mDrawerVibrate.performClick();
+
+        // Make sure we've actually changed the ringer mode.
+        verify(mController, times(1)).setRingerMode(
+                AudioManager.RINGER_MODE_VIBRATE, false);
+    }
+
+    @Test
+    public void testSelectMuteFromDrawer() {
+        final State initialUnsetState = new State();
+        initialUnsetState.ringerModeInternal = AudioManager.RINGER_MODE_NORMAL;
+        mDialog.onStateChangedH(initialUnsetState);
+
+        mActiveRinger.performClick();
+        mDrawerMute.performClick();
+
+        // Make sure we've actually changed the ringer mode.
+        verify(mController, times(1)).setRingerMode(
+                AudioManager.RINGER_MODE_SILENT, false);
+    }
+
+    @Test
+    public void testSelectNormalFromDrawer() {
+        final State initialUnsetState = new State();
+        initialUnsetState.ringerModeInternal = AudioManager.RINGER_MODE_VIBRATE;
+        mDialog.onStateChangedH(initialUnsetState);
+
+        mActiveRinger.performClick();
+        mDrawerNormal.performClick();
+
+        // Make sure we've actually changed the ringer mode.
+        verify(mController, times(1)).setRingerMode(
+                AudioManager.RINGER_MODE_NORMAL, false);
+    }
+
 /*
     @Test
     public void testContentDescriptions() {
diff --git a/packages/SystemUI/tools/lint/baseline.xml b/packages/SystemUI/tools/lint/baseline.xml
index 3e49403..9a2e320 100644
--- a/packages/SystemUI/tools/lint/baseline.xml
+++ b/packages/SystemUI/tools/lint/baseline.xml
@@ -1262,17 +1262,6 @@
     <issue
         id="MergeRootFrame"
         message="This `&lt;FrameLayout>` can be replaced with a `&lt;merge>` tag"
-        errorLine1="&lt;FrameLayout"
-        errorLine2="^">
-        <location
-            file="res/layout/pip_menu_activity.xml"
-            line="16"
-            column="1"/>
-    </issue>
-
-    <issue
-        id="MergeRootFrame"
-        message="This `&lt;FrameLayout>` can be replaced with a `&lt;merge>` tag"
         errorLine1="&lt;FrameLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;"
         errorLine2="^">
         <location
diff --git a/packages/VpnDialogs/Android.bp b/packages/VpnDialogs/Android.bp
index 6f2f50c..05135b2 100644
--- a/packages/VpnDialogs/Android.bp
+++ b/packages/VpnDialogs/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "VpnDialogs",
     certificate: "platform",
diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/AlwaysOnDisconnectedDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/AlwaysOnDisconnectedDialog.java
index 6dcad25..3502baa 100644
--- a/packages/VpnDialogs/src/com/android/vpndialogs/AlwaysOnDisconnectedDialog.java
+++ b/packages/VpnDialogs/src/com/android/vpndialogs/AlwaysOnDisconnectedDialog.java
@@ -23,7 +23,7 @@
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.pm.PackageManager;
-import android.net.ConnectivityManager;
+import android.net.VpnManager;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -42,7 +42,7 @@
 
     private static final String TAG = "VpnDisconnected";
 
-    private ConnectivityManager mService;
+    private VpnManager mService;
     private int mUserId;
     private String mVpnPackage;
 
@@ -51,8 +51,8 @@
         super.onCreate(savedInstanceState);
 
         mUserId = UserHandle.myUserId();
-        final ConnectivityManager cm = getSystemService(ConnectivityManager.class);
-        mVpnPackage = cm.getAlwaysOnVpnPackageForUser(mUserId);
+        final VpnManager vm = getSystemService(VpnManager.class);
+        mVpnPackage = vm.getAlwaysOnVpnPackageForUser(mUserId);
         if (mVpnPackage == null) {
             finish();
             return;
diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java
index aab01d0..fb23678 100644
--- a/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java
+++ b/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java
@@ -21,7 +21,6 @@
 import android.content.DialogInterface;
 import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
-import android.net.ConnectivityManager;
 import android.net.VpnManager;
 import android.os.Bundle;
 import android.os.UserHandle;
@@ -45,7 +44,6 @@
 
     private String mPackage;
 
-    private ConnectivityManager mCm;  // TODO: switch entirely to VpnManager once VPN code moves
     private VpnManager mVm;
 
     public ConfirmDialog() {
@@ -60,7 +58,6 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mPackage = getCallingPackage();
-        mCm = getSystemService(ConnectivityManager.class);
         mVm = getSystemService(VpnManager.class);
 
         if (mVm.prepareVpn(mPackage, null, UserHandle.myUserId())) {
@@ -72,7 +69,7 @@
             finish();
             return;
         }
-        final String alwaysOnVpnPackage = mCm.getAlwaysOnVpnPackageForUser(UserHandle.myUserId());
+        final String alwaysOnVpnPackage = mVm.getAlwaysOnVpnPackageForUser(UserHandle.myUserId());
         // Can't prepare new vpn app when another vpn is always-on
         if (alwaysOnVpnPackage != null && !alwaysOnVpnPackage.equals(mPackage)) {
             finish();
diff --git a/packages/WAPPushManager/Android.bp b/packages/WAPPushManager/Android.bp
index 0b62c72..71ec819 100644
--- a/packages/WAPPushManager/Android.bp
+++ b/packages/WAPPushManager/Android.bp
@@ -1,5 +1,24 @@
 // Copyright 2007-2008 The Android Open Source Project
 
+package {
+    default_applicable_licenses: [
+        "frameworks_base_packages_WAPPushManager_license",
+    ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_packages_WAPPushManager_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 android_app {
     name: "WAPPushManager",
     defaults: ["platform_app_defaults"],
diff --git a/packages/WAPPushManager/tests/Android.bp b/packages/WAPPushManager/tests/Android.bp
index 25c6121..0a17938 100644
--- a/packages/WAPPushManager/tests/Android.bp
+++ b/packages/WAPPushManager/tests/Android.bp
@@ -12,6 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_packages_WAPPushManager_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: [
+        "frameworks_base_packages_WAPPushManager_license",
+    ],
+}
+
 android_test {
     name: "WAPPushManagerTests",
     libs: [
diff --git a/packages/WallpaperBackup/Android.bp b/packages/WallpaperBackup/Android.bp
index e52d53e..d142f25 100644
--- a/packages/WallpaperBackup/Android.bp
+++ b/packages/WallpaperBackup/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "WallpaperBackup",
     defaults: ["platform_app_defaults"],
diff --git a/packages/WallpaperCropper/Android.bp b/packages/WallpaperCropper/Android.bp
index df97a3c0..23ec23c 100644
--- a/packages/WallpaperCropper/Android.bp
+++ b/packages/WallpaperCropper/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "WallpaperCropper",
     defaults: ["platform_app_defaults"],
diff --git a/packages/overlays/AccentColorAmethystOverlay/Android.bp b/packages/overlays/AccentColorAmethystOverlay/Android.bp
index 7519b12..186d770 100644
--- a/packages/overlays/AccentColorAmethystOverlay/Android.bp
+++ b/packages/overlays/AccentColorAmethystOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "AccentColorAmethystOverlay",
     theme: "AccentColorAmethyst",
diff --git a/packages/overlays/AccentColorAquamarineOverlay/Android.bp b/packages/overlays/AccentColorAquamarineOverlay/Android.bp
index 4469b36..7fd64f3 100644
--- a/packages/overlays/AccentColorAquamarineOverlay/Android.bp
+++ b/packages/overlays/AccentColorAquamarineOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "AccentColorAquamarineOverlay",
     theme: "AccentColorAquamarine",
diff --git a/packages/overlays/AccentColorBlackOverlay/Android.bp b/packages/overlays/AccentColorBlackOverlay/Android.bp
index bfee26e..ac923eb 100644
--- a/packages/overlays/AccentColorBlackOverlay/Android.bp
+++ b/packages/overlays/AccentColorBlackOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "AccentColorBlackOverlay",
     theme: "AccentColorBlack",
diff --git a/packages/overlays/AccentColorCarbonOverlay/Android.bp b/packages/overlays/AccentColorCarbonOverlay/Android.bp
index 47f66dd..f4f1b8b 100644
--- a/packages/overlays/AccentColorCarbonOverlay/Android.bp
+++ b/packages/overlays/AccentColorCarbonOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "AccentColorCarbonOverlay",
     theme: "AccentColorCarbon",
diff --git a/packages/overlays/AccentColorCinnamonOverlay/Android.bp b/packages/overlays/AccentColorCinnamonOverlay/Android.bp
index 8250315..53899bf 100644
--- a/packages/overlays/AccentColorCinnamonOverlay/Android.bp
+++ b/packages/overlays/AccentColorCinnamonOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "AccentColorCinnamonOverlay",
     theme: "AccentColorCinnamon",
diff --git a/packages/overlays/AccentColorGreenOverlay/Android.bp b/packages/overlays/AccentColorGreenOverlay/Android.bp
index 15b50c7..5b1f744 100644
--- a/packages/overlays/AccentColorGreenOverlay/Android.bp
+++ b/packages/overlays/AccentColorGreenOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "AccentColorGreenOverlay",
     theme: "AccentColorGreen",
diff --git a/packages/overlays/AccentColorOceanOverlay/Android.bp b/packages/overlays/AccentColorOceanOverlay/Android.bp
index 6ad63bc..a8588304 100644
--- a/packages/overlays/AccentColorOceanOverlay/Android.bp
+++ b/packages/overlays/AccentColorOceanOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "AccentColorOceanOverlay",
     theme: "AccentColorOcean",
diff --git a/packages/overlays/AccentColorOrchidOverlay/Android.bp b/packages/overlays/AccentColorOrchidOverlay/Android.bp
index b669333..31ed309 100644
--- a/packages/overlays/AccentColorOrchidOverlay/Android.bp
+++ b/packages/overlays/AccentColorOrchidOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "AccentColorOrchidOverlay",
     theme: "AccentColorOrchid",
diff --git a/packages/overlays/AccentColorPaletteOverlay/Android.bp b/packages/overlays/AccentColorPaletteOverlay/Android.bp
index eeefd16..a6cc1de 100644
--- a/packages/overlays/AccentColorPaletteOverlay/Android.bp
+++ b/packages/overlays/AccentColorPaletteOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "AccentColorPaletteOverlay",
     theme: "AccentColorPalette",
diff --git a/packages/overlays/AccentColorPurpleOverlay/Android.bp b/packages/overlays/AccentColorPurpleOverlay/Android.bp
index ead95df..80e0ab1 100644
--- a/packages/overlays/AccentColorPurpleOverlay/Android.bp
+++ b/packages/overlays/AccentColorPurpleOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "AccentColorPurpleOverlay",
     theme: "AccentColorPurple",
diff --git a/packages/overlays/AccentColorSandOverlay/Android.bp b/packages/overlays/AccentColorSandOverlay/Android.bp
index f70578a..771abca 100644
--- a/packages/overlays/AccentColorSandOverlay/Android.bp
+++ b/packages/overlays/AccentColorSandOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "AccentColorSandOverlay",
     theme: "AccentColorSand",
diff --git a/packages/overlays/AccentColorSpaceOverlay/Android.bp b/packages/overlays/AccentColorSpaceOverlay/Android.bp
index 1d713df..8e4abac 100644
--- a/packages/overlays/AccentColorSpaceOverlay/Android.bp
+++ b/packages/overlays/AccentColorSpaceOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "AccentColorSpaceOverlay",
     theme: "AccentColorSpace",
diff --git a/packages/overlays/AccentColorTangerineOverlay/Android.bp b/packages/overlays/AccentColorTangerineOverlay/Android.bp
index d3b1e54..75c708e 100644
--- a/packages/overlays/AccentColorTangerineOverlay/Android.bp
+++ b/packages/overlays/AccentColorTangerineOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "AccentColorTangerineOverlay",
     theme: "AccentColorTangerine",
diff --git a/packages/overlays/Android.mk b/packages/overlays/Android.mk
index cdc0903..99dfd9e 100644
--- a/packages/overlays/Android.mk
+++ b/packages/overlays/Android.mk
@@ -16,6 +16,9 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := frameworks-base-overlays
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
 LOCAL_REQUIRED_MODULES := \
 	AccentColorBlackOverlay \
 	AccentColorCinnamonOverlay \
@@ -84,6 +87,9 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := frameworks-base-overlays-debug
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
 
 include $(BUILD_PHONY_PACKAGE)
 include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/Android.bp b/packages/overlays/DisplayCutoutEmulationCornerOverlay/Android.bp
index b8def987..8e03809 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/Android.bp
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "DisplayCutoutEmulationCornerOverlay",
     theme: "DisplayCutoutEmulationCorner",
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.bp b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.bp
index b64ddfd..afa5b64 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.bp
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "DisplayCutoutEmulationDoubleOverlay",
     theme: "DisplayCutoutEmulationDouble",
diff --git a/packages/overlays/DisplayCutoutEmulationHoleOverlay/Android.bp b/packages/overlays/DisplayCutoutEmulationHoleOverlay/Android.bp
index 86cfebf..eae907d 100644
--- a/packages/overlays/DisplayCutoutEmulationHoleOverlay/Android.bp
+++ b/packages/overlays/DisplayCutoutEmulationHoleOverlay/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "DisplayCutoutEmulationHoleOverlay",
     theme: "DisplayCutoutEmulationHole",
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/Android.bp b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/Android.bp
index 28ad9db..25bc676 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/Android.bp
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "DisplayCutoutEmulationNarrowOverlay",
     theme: "DisplayCutoutEmulationNarrow",
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/Android.bp b/packages/overlays/DisplayCutoutEmulationTallOverlay/Android.bp
index cd00386..2828612 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/Android.bp
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "DisplayCutoutEmulationTallOverlay",
     theme: "DisplayCutoutEmulationTall",
diff --git a/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/Android.bp b/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/Android.bp
index d5fe683..66be777 100644
--- a/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/Android.bp
+++ b/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "DisplayCutoutEmulationWaterfallOverlay",
     theme: "DisplayCutoutEmulationWaterfall",
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/Android.bp b/packages/overlays/DisplayCutoutEmulationWideOverlay/Android.bp
index 0157ec4..e71cefe 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/Android.bp
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "DisplayCutoutEmulationWideOverlay",
     theme: "DisplayCutoutEmulationWide",
diff --git a/packages/overlays/FontNotoSerifSourceOverlay/Android.bp b/packages/overlays/FontNotoSerifSourceOverlay/Android.bp
index 7fd145b..231295b 100644
--- a/packages/overlays/FontNotoSerifSourceOverlay/Android.bp
+++ b/packages/overlays/FontNotoSerifSourceOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "FontNotoSerifSourceOverlay",
     theme: "FontNotoSerifSource",
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/Android.bp b/packages/overlays/IconPackCircularAndroidOverlay/Android.bp
index cd5829a..7040358 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/Android.bp
+++ b/packages/overlays/IconPackCircularAndroidOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackCircularAndroidOverlay",
     theme: "IconPackCircularAndroid",
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/Android.bp b/packages/overlays/IconPackCircularLauncherOverlay/Android.bp
index 5f2491d..4f8b663 100644
--- a/packages/overlays/IconPackCircularLauncherOverlay/Android.bp
+++ b/packages/overlays/IconPackCircularLauncherOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackCircularLauncherOverlay",
     theme: "IconPackCircularLauncher",
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/Android.bp b/packages/overlays/IconPackCircularSettingsOverlay/Android.bp
index d7bc657..93220c8 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/Android.bp
+++ b/packages/overlays/IconPackCircularSettingsOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackCircularSettingsOverlay",
     theme: "IconPackCircularSettings",
diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/Android.bp b/packages/overlays/IconPackCircularSystemUIOverlay/Android.bp
index 73b8cd8..4eaa420 100644
--- a/packages/overlays/IconPackCircularSystemUIOverlay/Android.bp
+++ b/packages/overlays/IconPackCircularSystemUIOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackCircularSystemUIOverlay",
     theme: "IconPackCircularSystemUI",
diff --git a/packages/overlays/IconPackCircularThemePickerOverlay/Android.bp b/packages/overlays/IconPackCircularThemePickerOverlay/Android.bp
index 5063932..5105b79 100644
--- a/packages/overlays/IconPackCircularThemePickerOverlay/Android.bp
+++ b/packages/overlays/IconPackCircularThemePickerOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackCircularThemePickerOverlay",
     theme: "IconPackCircularThemePicker",
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/Android.bp b/packages/overlays/IconPackFilledAndroidOverlay/Android.bp
index 83f3656..3c4025d 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/Android.bp
+++ b/packages/overlays/IconPackFilledAndroidOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackFilledAndroidOverlay",
     theme: "IconPackFilledAndroid",
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/Android.bp b/packages/overlays/IconPackFilledLauncherOverlay/Android.bp
index 6ca2566..3c5078c 100644
--- a/packages/overlays/IconPackFilledLauncherOverlay/Android.bp
+++ b/packages/overlays/IconPackFilledLauncherOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackFilledLauncherOverlay",
     theme: "IconPackFilledLauncher",
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/Android.bp b/packages/overlays/IconPackFilledSettingsOverlay/Android.bp
index 8551bd5..b5148c2 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/Android.bp
+++ b/packages/overlays/IconPackFilledSettingsOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackFilledSettingsOverlay",
     theme: "IconPackFilledSettings",
diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/Android.bp b/packages/overlays/IconPackFilledSystemUIOverlay/Android.bp
index 684deb4..eb040a5 100644
--- a/packages/overlays/IconPackFilledSystemUIOverlay/Android.bp
+++ b/packages/overlays/IconPackFilledSystemUIOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackFilledSystemUIOverlay",
     theme: "IconPackFilledSystemUI",
diff --git a/packages/overlays/IconPackFilledThemePickerOverlay/Android.bp b/packages/overlays/IconPackFilledThemePickerOverlay/Android.bp
index dae378f..bee4808 100644
--- a/packages/overlays/IconPackFilledThemePickerOverlay/Android.bp
+++ b/packages/overlays/IconPackFilledThemePickerOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackFilledThemePickerOverlay",
     theme: "IconPackFilledThemePicker",
diff --git a/packages/overlays/IconPackKaiAndroidOverlay/Android.bp b/packages/overlays/IconPackKaiAndroidOverlay/Android.bp
index 4161e25..ee588c1 100644
--- a/packages/overlays/IconPackKaiAndroidOverlay/Android.bp
+++ b/packages/overlays/IconPackKaiAndroidOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackKaiAndroidOverlay",
     theme: "IconPackKaiAndroid",
diff --git a/packages/overlays/IconPackKaiLauncherOverlay/Android.bp b/packages/overlays/IconPackKaiLauncherOverlay/Android.bp
index 4bf8f11..dcdad7a 100644
--- a/packages/overlays/IconPackKaiLauncherOverlay/Android.bp
+++ b/packages/overlays/IconPackKaiLauncherOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackKaiLauncherOverlay",
     theme: "IconPackKaiLauncher",
diff --git a/packages/overlays/IconPackKaiSettingsOverlay/Android.bp b/packages/overlays/IconPackKaiSettingsOverlay/Android.bp
index c43f9e5..974bb54 100644
--- a/packages/overlays/IconPackKaiSettingsOverlay/Android.bp
+++ b/packages/overlays/IconPackKaiSettingsOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackKaiSettingsOverlay",
     theme: "IconPackKaiSettings",
diff --git a/packages/overlays/IconPackKaiSystemUIOverlay/Android.bp b/packages/overlays/IconPackKaiSystemUIOverlay/Android.bp
index 22a8c28..b04ca61 100644
--- a/packages/overlays/IconPackKaiSystemUIOverlay/Android.bp
+++ b/packages/overlays/IconPackKaiSystemUIOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackKaiSystemUIOverlay",
     theme: "IconPackKaiSystemUI",
diff --git a/packages/overlays/IconPackKaiThemePickerOverlay/Android.bp b/packages/overlays/IconPackKaiThemePickerOverlay/Android.bp
index 85eb1c4..875cd1d 100644
--- a/packages/overlays/IconPackKaiThemePickerOverlay/Android.bp
+++ b/packages/overlays/IconPackKaiThemePickerOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackKaiThemePickerOverlay",
     theme: "IconPackKaiThemePicker",
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/Android.bp b/packages/overlays/IconPackRoundedAndroidOverlay/Android.bp
index 948f015..cb7b013 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/Android.bp
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackRoundedAndroidOverlay",
     theme: "IconPackRoundedAndroid",
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/Android.bp b/packages/overlays/IconPackRoundedLauncherOverlay/Android.bp
index 5fbe635..8ab6d95 100644
--- a/packages/overlays/IconPackRoundedLauncherOverlay/Android.bp
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackRoundedLauncherOverlay",
     theme: "IconPackRoundedLauncher",
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/Android.bp b/packages/overlays/IconPackRoundedSettingsOverlay/Android.bp
index b1a0713..ee2f98a9 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/Android.bp
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackRoundedSettingsOverlay",
     theme: "IconPackRoundedSettings",
diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/Android.bp b/packages/overlays/IconPackRoundedSystemUIOverlay/Android.bp
index 6432998..ee0220a 100644
--- a/packages/overlays/IconPackRoundedSystemUIOverlay/Android.bp
+++ b/packages/overlays/IconPackRoundedSystemUIOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackRoundedSystemUIOverlay",
     theme: "IconPackRoundedSystemUI",
diff --git a/packages/overlays/IconPackRoundedThemePickerOverlay/Android.bp b/packages/overlays/IconPackRoundedThemePickerOverlay/Android.bp
index 95e1d3a..d74765c 100644
--- a/packages/overlays/IconPackRoundedThemePickerOverlay/Android.bp
+++ b/packages/overlays/IconPackRoundedThemePickerOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackRoundedThemePickerOverlay",
     theme: "IconPackRoundedTheme",
diff --git a/packages/overlays/IconPackSamAndroidOverlay/Android.bp b/packages/overlays/IconPackSamAndroidOverlay/Android.bp
index e8c33b1..2e9dc34 100644
--- a/packages/overlays/IconPackSamAndroidOverlay/Android.bp
+++ b/packages/overlays/IconPackSamAndroidOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackSamAndroidOverlay",
     theme: "IconPackSamAndroid",
diff --git a/packages/overlays/IconPackSamLauncherOverlay/Android.bp b/packages/overlays/IconPackSamLauncherOverlay/Android.bp
index a469646..aa0cf00 100644
--- a/packages/overlays/IconPackSamLauncherOverlay/Android.bp
+++ b/packages/overlays/IconPackSamLauncherOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackSamLauncherOverlay",
     theme: "IconPackSamLauncher",
diff --git a/packages/overlays/IconPackSamSettingsOverlay/Android.bp b/packages/overlays/IconPackSamSettingsOverlay/Android.bp
index bc1fa45..a62037f 100644
--- a/packages/overlays/IconPackSamSettingsOverlay/Android.bp
+++ b/packages/overlays/IconPackSamSettingsOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackSamSettingsOverlay",
     theme: "IconPackSamSettings",
diff --git a/packages/overlays/IconPackSamSystemUIOverlay/Android.bp b/packages/overlays/IconPackSamSystemUIOverlay/Android.bp
index db77352..96ba7a0 100644
--- a/packages/overlays/IconPackSamSystemUIOverlay/Android.bp
+++ b/packages/overlays/IconPackSamSystemUIOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackSamSystemUIOverlay",
     theme: "IconPackSamSystemUI",
diff --git a/packages/overlays/IconPackSamThemePickerOverlay/Android.bp b/packages/overlays/IconPackSamThemePickerOverlay/Android.bp
index c216868..7376f03 100644
--- a/packages/overlays/IconPackSamThemePickerOverlay/Android.bp
+++ b/packages/overlays/IconPackSamThemePickerOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackSamThemePickerOverlay",
     theme: "IconPackSamThemePicker",
diff --git a/packages/overlays/IconPackVictorAndroidOverlay/Android.bp b/packages/overlays/IconPackVictorAndroidOverlay/Android.bp
index de62af1..ee73778 100644
--- a/packages/overlays/IconPackVictorAndroidOverlay/Android.bp
+++ b/packages/overlays/IconPackVictorAndroidOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackVictorAndroidOverlay",
     theme: "IconPackVictorAndroid",
diff --git a/packages/overlays/IconPackVictorLauncherOverlay/Android.bp b/packages/overlays/IconPackVictorLauncherOverlay/Android.bp
index fc4c360..a0cd45a 100644
--- a/packages/overlays/IconPackVictorLauncherOverlay/Android.bp
+++ b/packages/overlays/IconPackVictorLauncherOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackVictorLauncherOverlay",
     theme: "IconPackVictorLauncher",
diff --git a/packages/overlays/IconPackVictorSettingsOverlay/Android.bp b/packages/overlays/IconPackVictorSettingsOverlay/Android.bp
index 046bb3d..7807c6b 100644
--- a/packages/overlays/IconPackVictorSettingsOverlay/Android.bp
+++ b/packages/overlays/IconPackVictorSettingsOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackVictorSettingsOverlay",
     theme: "IconPackVictorSettings",
diff --git a/packages/overlays/IconPackVictorSystemUIOverlay/Android.bp b/packages/overlays/IconPackVictorSystemUIOverlay/Android.bp
index b8a9e77..2deb6cd 100644
--- a/packages/overlays/IconPackVictorSystemUIOverlay/Android.bp
+++ b/packages/overlays/IconPackVictorSystemUIOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackVictorSystemUIOverlay",
     theme: "IconPackVictorSystemUI",
diff --git a/packages/overlays/IconPackVictorThemePickerOverlay/Android.bp b/packages/overlays/IconPackVictorThemePickerOverlay/Android.bp
index 6f0144e..a18ebb3 100644
--- a/packages/overlays/IconPackVictorThemePickerOverlay/Android.bp
+++ b/packages/overlays/IconPackVictorThemePickerOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconPackVictorThemePickerOverlay",
     theme: "IconPackVictorThemePicker",
diff --git a/packages/overlays/IconShapeHeartOverlay/Android.bp b/packages/overlays/IconShapeHeartOverlay/Android.bp
index ec55712..1da8f4f 100644
--- a/packages/overlays/IconShapeHeartOverlay/Android.bp
+++ b/packages/overlays/IconShapeHeartOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconShapeHeartOverlay",
     theme: "IconShapeHeart",
diff --git a/packages/overlays/IconShapePebbleOverlay/Android.bp b/packages/overlays/IconShapePebbleOverlay/Android.bp
index 7dc4fde..fa2a5bb 100644
--- a/packages/overlays/IconShapePebbleOverlay/Android.bp
+++ b/packages/overlays/IconShapePebbleOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconShapePebbleOverlay",
     theme: "IconShapePebble",
diff --git a/packages/overlays/IconShapeRoundedRectOverlay/Android.bp b/packages/overlays/IconShapeRoundedRectOverlay/Android.bp
index b8b8531..5052d08f 100644
--- a/packages/overlays/IconShapeRoundedRectOverlay/Android.bp
+++ b/packages/overlays/IconShapeRoundedRectOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconShapeRoundedRectOverlay",
     theme: "IconShapeRoundedRect",
diff --git a/packages/overlays/IconShapeSquareOverlay/Android.bp b/packages/overlays/IconShapeSquareOverlay/Android.bp
index fdeffee..1176abd 100644
--- a/packages/overlays/IconShapeSquareOverlay/Android.bp
+++ b/packages/overlays/IconShapeSquareOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconShapeSquareOverlay",
     theme: "IconShapeSquare",
diff --git a/packages/overlays/IconShapeSquircleOverlay/Android.bp b/packages/overlays/IconShapeSquircleOverlay/Android.bp
index 468f0f7..8c219f3 100644
--- a/packages/overlays/IconShapeSquircleOverlay/Android.bp
+++ b/packages/overlays/IconShapeSquircleOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconShapeSquircleOverlay",
     theme: "IconShapeSquircle",
diff --git a/packages/overlays/IconShapeTaperedRectOverlay/Android.bp b/packages/overlays/IconShapeTaperedRectOverlay/Android.bp
index 1e48cd1..78855e8 100644
--- a/packages/overlays/IconShapeTaperedRectOverlay/Android.bp
+++ b/packages/overlays/IconShapeTaperedRectOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconShapeTaperedRectOverlay",
     theme: "IconShapeTaperedRect",
diff --git a/packages/overlays/IconShapeTeardropOverlay/Android.bp b/packages/overlays/IconShapeTeardropOverlay/Android.bp
index 017d58ec..dd36f4f 100644
--- a/packages/overlays/IconShapeTeardropOverlay/Android.bp
+++ b/packages/overlays/IconShapeTeardropOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconShapeTeardropOverlay",
     theme: "IconShapeTeardrop",
diff --git a/packages/overlays/IconShapeVesselOverlay/Android.bp b/packages/overlays/IconShapeVesselOverlay/Android.bp
index ba3b309..2e7f8bc 100644
--- a/packages/overlays/IconShapeVesselOverlay/Android.bp
+++ b/packages/overlays/IconShapeVesselOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "IconShapeVesselOverlay",
     theme: "IconShapeVessel",
diff --git a/packages/overlays/NavigationBarMode2ButtonOverlay/Android.bp b/packages/overlays/NavigationBarMode2ButtonOverlay/Android.bp
index e4fcce1..35f671ba 100644
--- a/packages/overlays/NavigationBarMode2ButtonOverlay/Android.bp
+++ b/packages/overlays/NavigationBarMode2ButtonOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "NavigationBarMode2ButtonOverlay",
     theme: "NavigationBarMode2Button",
diff --git a/packages/overlays/NavigationBarMode3ButtonOverlay/Android.bp b/packages/overlays/NavigationBarMode3ButtonOverlay/Android.bp
index 9b6c998..fe9cc81 100644
--- a/packages/overlays/NavigationBarMode3ButtonOverlay/Android.bp
+++ b/packages/overlays/NavigationBarMode3ButtonOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "NavigationBarMode3ButtonOverlay",
     theme: "NavigationBarMode3Button",
diff --git a/packages/overlays/NavigationBarModeGesturalOverlay/Android.bp b/packages/overlays/NavigationBarModeGesturalOverlay/Android.bp
index ba29045..791f420 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlay/Android.bp
+++ b/packages/overlays/NavigationBarModeGesturalOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "NavigationBarModeGesturalOverlay",
     theme: "NavigationBarModeGestural",
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/Android.bp b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/Android.bp
index 0c688a9..28f9f33 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/Android.bp
+++ b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "NavigationBarModeGesturalOverlayExtraWideBack",
     theme: "NavigationBarModeGesturalExtraWideBack",
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/Android.bp b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/Android.bp
index 85d514f..f8a5603 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/Android.bp
+++ b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "NavigationBarModeGesturalOverlayNarrowBack",
     theme: "NavigationBarModeGesturalNarrowBack",
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/Android.bp b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/Android.bp
index 84be626..60ee6d5 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/Android.bp
+++ b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "NavigationBarModeGesturalOverlayWideBack",
     theme: "NavigationBarModeGesturalWideBack",
diff --git a/packages/overlays/OneHandedModeGesturalOverlay/Android.bp b/packages/overlays/OneHandedModeGesturalOverlay/Android.bp
index 9c9d0ef..468069d 100644
--- a/packages/overlays/OneHandedModeGesturalOverlay/Android.bp
+++ b/packages/overlays/OneHandedModeGesturalOverlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 runtime_resource_overlay {
     name: "OneHandedModeGesturalOverlay",
     theme: "OneHandedModeGestural",
diff --git a/packages/overlays/tests/Android.bp b/packages/overlays/tests/Android.bp
index 728ebe2..b781602 100644
--- a/packages/overlays/tests/Android.bp
+++ b/packages/overlays/tests/Android.bp
@@ -11,6 +11,16 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "OverlayTests",
     certificate: "platform",
diff --git a/packages/services/CameraExtensionsProxy/Android.bp b/packages/services/CameraExtensionsProxy/Android.bp
index 54b7453..ea0703e 100644
--- a/packages/services/CameraExtensionsProxy/Android.bp
+++ b/packages/services/CameraExtensionsProxy/Android.bp
@@ -14,10 +14,20 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "CameraExtensionsProxy",
     srcs: ["src/**/*.java"],
     libs: ["androidx.camera.extensions.stub"],
+    optional_uses_libs: ["androidx.camera.extensions.impl"],
     platform_apis: true,
     certificate: "platform",
 }
diff --git a/packages/services/PacProcessor/Android.bp b/packages/services/PacProcessor/Android.bp
index 1fd972c..dd50e25 100644
--- a/packages/services/PacProcessor/Android.bp
+++ b/packages/services/PacProcessor/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "PacProcessor",
     srcs: ["src/**/*.java"],
diff --git a/packages/services/Proxy/Android.bp b/packages/services/Proxy/Android.bp
index d93c9f8..4d76db7 100644
--- a/packages/services/Proxy/Android.bp
+++ b/packages/services/Proxy/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "ProxyHandler",
     srcs: ["src/**/*.java"],
diff --git a/proto/Android.bp b/proto/Android.bp
index 86d8ee3..a5e1335 100644
--- a/proto/Android.bp
+++ b/proto/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library_static {
     name: "framework-protos",
     host_supported: true,
diff --git a/rs/jni/Android.mk b/rs/jni/Android.mk
index 5c3f2d8..e41073b 100644
--- a/rs/jni/Android.mk
+++ b/rs/jni/Android.mk
@@ -28,6 +28,9 @@
 LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
 
 LOCAL_MODULE:= librs_jni
+LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS:= notice
+LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/../../NOTICE
 LOCAL_MODULE_TAGS := optional
 LOCAL_REQUIRED_MODULES := libRS
 
diff --git a/samples/demo/haptic-assessment/Android.bp b/samples/demo/haptic-assessment/Android.bp
index 1c00609..4d54550 100644
--- a/samples/demo/haptic-assessment/Android.bp
+++ b/samples/demo/haptic-assessment/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "HapticAssessment",
     manifest: "AndroidManifest.xml",
@@ -31,4 +40,4 @@
         "res",
     ],
     dxflags: ["--multi-dex"],
-}
\ No newline at end of file
+}
diff --git a/sax/tests/saxtests/Android.bp b/sax/tests/saxtests/Android.bp
index 5889f76..cbd19c3 100644
--- a/sax/tests/saxtests/Android.bp
+++ b/sax/tests/saxtests/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworksSaxTests",
     // Include all test java files.
diff --git a/services/Android.bp b/services/Android.bp
index 3154628..f6bb157 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services-main-sources",
     srcs: ["java/**/*.java"],
@@ -6,7 +15,7 @@
 }
 
 filegroup {
-    name: "services-all-sources",
+    name: "services-non-updatable-sources",
     srcs: [
         ":services.core-sources",
         ":services.core-sources-am-wm",
@@ -38,7 +47,15 @@
         ":services.usb-sources",
         ":services.voiceinteraction-sources",
         ":services.wifi-sources",
-        ":service-media-s-sources", // TODO (b/177640454)
+    ],
+    visibility: ["//visibility:private"],
+}
+
+filegroup {
+    name: "services-all-sources",
+    srcs: [
+        ":services-non-updatable-sources",
+        ":service-media-s-sources",
         ":service-permission-sources",
         ":service-statsd-sources",
     ],
@@ -125,9 +142,8 @@
 // API stub
 // =============================================================
 
-droidstubs {
-    name: "services-stubs.sources",
-    srcs: [":services-all-sources"],
+stubs_defaults {
+    name: "services-stubs-default",
     installable: false,
     args: " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.SYSTEM_SERVER\\)" +
         " --hide-annotation android.annotation.Hide" +
@@ -137,7 +153,13 @@
         " --hide DeprecationMismatch" +
         " --hide HiddenTypedefConstant",
     visibility: ["//visibility:private"],
-    filter_packages: ["com.android."],
+    filter_packages: ["com.android."]
+}
+
+droidstubs {
+    name: "services-stubs.sources",
+    srcs: [":services-all-sources"],
+    defaults: ["services-stubs-default"],
     check_api: {
         current: {
             api_file: "api/current.txt",
@@ -183,3 +205,34 @@
         dir: "apistubs/android/system-server",
     },
 }
+
+droidstubs {
+    name: "services-non-updatable-stubs.sources",
+    srcs: [":services-non-updatable-sources"],
+    defaults: ["services-stubs-default"],
+    check_api: {
+        current: {
+            api_file: "api/non-updatable-current.txt",
+            removed_api_file: "api/non-updatable-removed.txt",
+        },
+        api_lint: {
+            enabled: true,
+            new_since: ":android-non-updatable.api.system-server.latest",
+            baseline_file: "api/non-updatable-lint-baseline.txt",
+        },
+    },
+    dists: [
+        {
+            targets: ["sdk", "win_sdk"],
+            dir: "apistubs/android/system-server/api",
+            dest: "android-non-updatable.txt",
+            tag: ".api.txt"
+        },
+        {
+            targets: ["sdk", "win_sdk"],
+            dir: "apistubs/android/system-server/api",
+            dest: "android-non-updatable-removed.txt",
+            tag: ".removed-api.txt",
+        },
+    ]
+}
\ No newline at end of file
diff --git a/services/accessibility/Android.bp b/services/accessibility/Android.bp
index 65313fc..1698e9a 100644
--- a/services/accessibility/Android.bp
+++ b/services/accessibility/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.accessibility-sources",
     srcs: ["java/**/*.java"],
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index ea1473e..c63c2e1 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -777,6 +777,10 @@
             // performs the current profile parent resolution.
             final int resolvedUserId = mSecurityPolicy
                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
+
+            if (Binder.getCallingPid() == OWN_PROCESS_ID) {
+                return new ArrayList<>(getUserStateLocked(resolvedUserId).mInstalledServices);
+            }
             return getUserStateLocked(resolvedUserId).mInstalledServices;
         }
     }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
index a9e8ea0..6756268 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
@@ -376,7 +376,8 @@
             if (mSecurityPolicy.canPerformGestures(this)) {
                 MotionEventInjector motionEventInjector =
                         mSystemSupport.getMotionEventInjectorForDisplayLocked(displayId);
-                if (mWindowManagerService.isTouchOrFaketouchDevice()) {
+                if (motionEventInjector != null
+                        && mWindowManagerService.isTouchOrFaketouchDevice()) {
                     motionEventInjector.injectEvents(
                             gestureSteps.getList(), mServiceInterface, sequence, displayId);
                 } else {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
index 22efd37..eb30fde 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
@@ -118,6 +118,9 @@
     private int mNonInteractiveUiTimeout = 0;
     private int mInteractiveUiTimeout = 0;
     private int mLastSentClientState = -1;
+
+    /** {@code true} if the device config supports magnification area. */
+    private final boolean mSupportMagnificationArea;
     // The magnification mode of default display.
     private int mMagnificationMode = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
     // The magnification capabilities used to know magnification mode could be switched.
@@ -138,6 +141,10 @@
     private int mSoftKeyboardShowMode = SHOW_MODE_AUTO;
 
     boolean isValidMagnificationModeLocked() {
+        if (!mSupportMagnificationArea
+                && mMagnificationMode == Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) {
+            return false;
+        }
         return (mMagnificationCapabilities & mMagnificationMode) != 0;
     }
 
@@ -156,6 +163,8 @@
                 R.color.accessibility_focus_highlight_color);
         mFocusStrokeWidth = mFocusStrokeWidthDefaultValue;
         mFocusColor = mFocusColorDefaultValue;
+        mSupportMagnificationArea = mContext.getResources().getBoolean(
+                R.bool.config_magnification_area);
     }
 
     boolean isHandlingAccessibilityEventsLocked() {
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/GesturesObserver.java b/services/accessibility/java/com/android/server/accessibility/magnification/GesturesObserver.java
index feed18d..3d8f5173 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/GesturesObserver.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/GesturesObserver.java
@@ -98,8 +98,7 @@
         }
         mProcessMotionEvent = true;
         for (int i = 0; i < mGestureMatchers.size(); i++) {
-            final GestureMatcher matcher =
-                    mGestureMatchers.get(i);
+            final GestureMatcher matcher = mGestureMatchers.get(i);
             matcher.onMotionEvent(event, rawEvent, policyFlags);
             if (matcher.getState() == GestureMatcher.STATE_GESTURE_COMPLETED) {
                 clear();
@@ -128,7 +127,10 @@
             MotionEvent rawEvent, int policyFlags) {
         if (state == GestureMatcher.STATE_GESTURE_COMPLETED) {
             mListener.onGestureCompleted(gestureId, event, rawEvent, policyFlags);
-            //Clear the states in onMotionEvent().
+            // Ideally we clear the states in onMotionEvent(), this case is for hold gestures.
+            // If we clear before processing up event , then MultiTap matcher cancels the gesture
+            // due to incorrect state. It ends up listener#onGestureCancelled is called even
+            // the gesture is detected.
             if (!mProcessMotionEvent) {
                 clear();
             }
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGestureMatcher.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGestureMatcher.java
index 7a4d9e3..570e0ce 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGestureMatcher.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGestureMatcher.java
@@ -33,7 +33,7 @@
 class MagnificationGestureMatcher {
 
     private static final int GESTURE_BASE = 100;
-    public static final int GESTURE_TWO_FINGER_DOWN = GESTURE_BASE + 1;
+    public static final int GESTURE_TWO_FINGERS_DOWN_OR_SWIPE = GESTURE_BASE + 1;
     public static final int GESTURE_SWIPE = GESTURE_BASE + 2;
     public static final int GESTURE_SINGLE_TAP = GESTURE_BASE + 3;
     public static final int GESTURE_SINGLE_TAP_AND_HOLD = GESTURE_BASE + 4;
@@ -41,7 +41,7 @@
     public static final int GESTURE_TRIPLE_TAP_AND_HOLD = GESTURE_BASE + 6;
 
     @IntDef(prefix = {"GESTURE_MAGNIFICATION_"}, value = {
-            GESTURE_TWO_FINGER_DOWN,
+            GESTURE_TWO_FINGERS_DOWN_OR_SWIPE,
             GESTURE_SWIPE
     })
     @Retention(RetentionPolicy.SOURCE)
@@ -57,8 +57,8 @@
         switch (gestureId) {
             case GESTURE_SWIPE:
                 return "GESTURE_SWIPE";
-            case GESTURE_TWO_FINGER_DOWN:
-                return "GESTURE_TWO_FINGER_DOWN";
+            case GESTURE_TWO_FINGERS_DOWN_OR_SWIPE:
+                return "GESTURE_TWO_FINGERS_DOWN_OR_SWIPE";
             case GESTURE_SINGLE_TAP:
                 return "GESTURE_SINGLE_TAP";
             case GESTURE_SINGLE_TAP_AND_HOLD:
@@ -71,6 +71,12 @@
         return "none";
     }
 
+    /**
+     * @param context
+     * @return the duration in milliseconds between the first tap's down event and
+     * the second tap's down event to be considered that the user is going to performing
+     *  panning/scaling gesture.
+     */
     static int getMagnificationMultiTapTimeout(Context context) {
         return ViewConfiguration.getDoubleTapTimeout() + context.getResources().getInteger(
                 R.integer.config_screen_magnification_multi_tap_adjustment);
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGesturesObserver.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGesturesObserver.java
index a209086..085c343 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGesturesObserver.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGesturesObserver.java
@@ -65,7 +65,7 @@
          *                  the last event before timeout.
          *
          * @see MagnificationGestureMatcher#GESTURE_SWIPE
-         * @see MagnificationGestureMatcher#GESTURE_TWO_FINGER_DOWN
+         * @see MagnificationGestureMatcher#GESTURE_TWO_FINGERS_DOWN_OR_SWIPE
          */
         void onGestureCompleted(@GestureId int gestureId, long lastDownEventTime,
                 List<MotionEventInfo> delayedEventQueue, MotionEvent event);
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/SimpleSwipe.java b/services/accessibility/java/com/android/server/accessibility/magnification/SimpleSwipe.java
index cd5061f..fa15ac1 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/SimpleSwipe.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/SimpleSwipe.java
@@ -49,6 +49,11 @@
     }
 
     @Override
+    protected void onPointerDown(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+        cancelGesture(event, rawEvent, policyFlags);
+    }
+
+    @Override
     protected void onMove(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
         if (gestureMatched(event, rawEvent, policyFlags)) {
             completeGesture(event, rawEvent, policyFlags);
@@ -65,7 +70,7 @@
     }
 
     private boolean gestureMatched(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
-        return mLastDown != null && (distance(mLastDown, event) >= mSwipeMinDistance);
+        return mLastDown != null && (distance(mLastDown, event) > mSwipeMinDistance);
     }
 
     @Override
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/TwoFingersDown.java b/services/accessibility/java/com/android/server/accessibility/magnification/TwoFingersDown.java
deleted file mode 100644
index 173a5b8..0000000
--- a/services/accessibility/java/com/android/server/accessibility/magnification/TwoFingersDown.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.accessibility.magnification;
-
-import android.content.Context;
-import android.os.Handler;
-import android.view.MotionEvent;
-
-import com.android.server.accessibility.gestures.GestureMatcher;
-
-/**
- *
- * This class is responsible for matching two fingers down gestures. The gesture matching
- * result is determined in a duration.
- */
-final class TwoFingersDown extends GestureMatcher {
-
-    private MotionEvent mLastDown;
-    private final int mDetectionDurationMillis;
-
-    TwoFingersDown(Context context) {
-        super(MagnificationGestureMatcher.GESTURE_TWO_FINGER_DOWN,
-                new Handler(context.getMainLooper()), null);
-        mDetectionDurationMillis = MagnificationGestureMatcher.getMagnificationMultiTapTimeout(
-                context);
-    }
-
-    @Override
-    protected void onDown(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
-        mLastDown = MotionEvent.obtain(event);
-        cancelAfter(mDetectionDurationMillis, event, rawEvent, policyFlags);
-    }
-
-    @Override
-    protected void onPointerDown(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
-        if (mLastDown == null) {
-            cancelGesture(event, rawEvent, policyFlags);
-        }
-        completeGesture(event, rawEvent, policyFlags);
-    }
-
-    @Override
-    protected void onUp(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
-        cancelGesture(event, rawEvent, policyFlags);
-    }
-
-    @Override
-    public void clear() {
-        if (mLastDown != null) {
-            mLastDown.recycle();
-            mLastDown = null;
-        }
-        super.clear();
-    }
-
-    @Override
-    protected String getGestureName() {
-        return this.getClass().getSimpleName();
-    }
-}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/TwoFingersDownOrSwipe.java b/services/accessibility/java/com/android/server/accessibility/magnification/TwoFingersDownOrSwipe.java
new file mode 100644
index 0000000..1742bd4
--- /dev/null
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/TwoFingersDownOrSwipe.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility.magnification;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.Handler;
+import android.util.MathUtils;
+import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+
+import com.android.server.accessibility.gestures.GestureMatcher;
+
+/**
+ * This class is responsible for detecting that the user is using two fingers to perform
+ * swiping gestures or just stay pressed on the screen. The gesture matching result is determined
+ * in a duration.
+ */
+final class TwoFingersDownOrSwipe extends GestureMatcher {
+
+    private final int mDoubleTapTimeout;
+    private final int mDetectionDurationMillis;
+    private final int mSwipeMinDistance;
+    private MotionEvent mFirstPointerDown;
+    private MotionEvent mSecondPointerDown;
+
+    TwoFingersDownOrSwipe(Context context) {
+        super(MagnificationGestureMatcher.GESTURE_TWO_FINGERS_DOWN_OR_SWIPE,
+                new Handler(context.getMainLooper()), null);
+        mDetectionDurationMillis = MagnificationGestureMatcher.getMagnificationMultiTapTimeout(
+                context);
+        mDoubleTapTimeout = ViewConfiguration.getDoubleTapTimeout();
+        mSwipeMinDistance = ViewConfiguration.get(context).getScaledTouchSlop();
+
+    }
+
+    @Override
+    protected void onDown(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+        mFirstPointerDown = MotionEvent.obtain(event);
+        cancelAfter(mDetectionDurationMillis, event, rawEvent, policyFlags);
+    }
+
+    @Override
+    protected void onPointerDown(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+        if (mFirstPointerDown == null) {
+            cancelGesture(event, rawEvent, policyFlags);
+        }
+        if (event.getPointerCount() == 2) {
+            mSecondPointerDown = MotionEvent.obtain(event);
+            completeAfter(mDoubleTapTimeout, event, rawEvent, policyFlags);
+        } else {
+            cancelGesture(event, rawEvent, policyFlags);
+        }
+    }
+
+    @Override
+    protected void onMove(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+        if (mFirstPointerDown == null || mSecondPointerDown == null) {
+            return;
+        }
+        if (distance(mFirstPointerDown, /* move */ event) > mSwipeMinDistance) {
+            completeGesture(event, rawEvent, policyFlags);
+            return;
+        }
+        if (distance(mSecondPointerDown, /* move */ event) > mSwipeMinDistance) {
+            // The second pointer is swiping.
+            completeGesture(event, rawEvent, policyFlags);
+        }
+    }
+
+    @Override
+    protected void onPointerUp(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+        cancelGesture(event, rawEvent, policyFlags);
+    }
+
+    @Override
+    protected void onUp(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+        cancelGesture(event, rawEvent, policyFlags);
+    }
+
+    @Override
+    public void clear() {
+        if (mFirstPointerDown != null) {
+            mFirstPointerDown.recycle();
+            mFirstPointerDown = null;
+        }
+        if (mSecondPointerDown != null) {
+            mSecondPointerDown.recycle();
+            mSecondPointerDown = null;
+        }
+        super.clear();
+    }
+
+    @Override
+    protected String getGestureName() {
+        return this.getClass().getSimpleName();
+    }
+
+    private static double distance(@NonNull MotionEvent downEvent, @NonNull MotionEvent moveEvent) {
+        final int downActionIndex = downEvent.getActionIndex();
+        final int downPointerId = downEvent.getPointerId(downActionIndex);
+        final int moveActionIndex = moveEvent.findPointerIndex(downPointerId);
+        if (moveActionIndex < 0) {
+            return -1;
+        }
+        return MathUtils.dist(downEvent.getX(downActionIndex), downEvent.getY(downActionIndex),
+                moveEvent.getX(moveActionIndex), moveEvent.getY(moveActionIndex));
+    }
+}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
index 55a911e..fa34062 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
@@ -323,7 +323,7 @@
      * manipulate the window magnifier or want to interact with current UI. The rule of leaving
      * this state is as follows:
      * <ol>
-     *   <li> If {@link MagnificationGestureMatcher#GESTURE_TWO_FINGER_DOWN} is detected,
+     *   <li> If {@link MagnificationGestureMatcher#GESTURE_TWO_FINGERS_DOWN_OR_SWIPE} is detected,
      *   {@link State} will be transited to {@link PanningScalingGestureState}.</li>
      *   <li> If other gesture is detected and the last motion event is neither ACTION_UP nor
      *   ACTION_CANCEL.
@@ -357,7 +357,7 @@
                     new SimpleSwipe(context),
                     multiTap,
                     multiTapAndHold,
-                    new TwoFingersDown(context));
+                    new TwoFingersDownOrSwipe(context));
         }
 
         @Override
@@ -399,7 +399,7 @@
                 Slog.d(mLogTag,
                         "onGestureDetected : delayedEventQueue = " + delayedEventQueue);
             }
-            if (gestureId == MagnificationGestureMatcher.GESTURE_TWO_FINGER_DOWN
+            if (gestureId == MagnificationGestureMatcher.GESTURE_TWO_FINGERS_DOWN_OR_SWIPE
                     && mWindowMagnificationMgr.pointersInWindow(mDisplayId, motionEvent) > 0) {
                 transitionTo(mObservePanningScalingState);
             } else if (gestureId == MagnificationGestureMatcher.GESTURE_TRIPLE_TAP) {
diff --git a/services/api/Android.bp b/services/api/Android.bp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/services/api/Android.bp
diff --git a/services/api/non-updatable-current.txt b/services/api/non-updatable-current.txt
new file mode 100644
index 0000000..3c72d38
--- /dev/null
+++ b/services/api/non-updatable-current.txt
@@ -0,0 +1,55 @@
+// Signature format: 2.0
+package com.android.server {
+
+  public final class LocalManagerRegistry {
+    method public static <T> void addManager(@NonNull Class<T>, @NonNull T);
+    method @Nullable public static <T> T getManager(@NonNull Class<T>);
+  }
+
+  public abstract class SystemService {
+    ctor public SystemService(@NonNull android.content.Context);
+    method @NonNull public final android.content.Context getContext();
+    method public boolean isUserSupported(@NonNull com.android.server.SystemService.TargetUser);
+    method public void onBootPhase(int);
+    method public abstract void onStart();
+    method public void onUserStarting(@NonNull com.android.server.SystemService.TargetUser);
+    method public void onUserStopped(@NonNull com.android.server.SystemService.TargetUser);
+    method public void onUserStopping(@NonNull com.android.server.SystemService.TargetUser);
+    method public void onUserSwitching(@Nullable com.android.server.SystemService.TargetUser, @NonNull com.android.server.SystemService.TargetUser);
+    method public void onUserUnlocked(@NonNull com.android.server.SystemService.TargetUser);
+    method public void onUserUnlocking(@NonNull com.android.server.SystemService.TargetUser);
+    method protected final void publishBinderService(@NonNull String, @NonNull android.os.IBinder);
+    method protected final void publishBinderService(@NonNull String, @NonNull android.os.IBinder, boolean);
+    field public static final int PHASE_ACTIVITY_MANAGER_READY = 550; // 0x226
+    field public static final int PHASE_BOOT_COMPLETED = 1000; // 0x3e8
+    field public static final int PHASE_DEVICE_SPECIFIC_SERVICES_READY = 520; // 0x208
+    field public static final int PHASE_LOCK_SETTINGS_READY = 480; // 0x1e0
+    field public static final int PHASE_SYSTEM_SERVICES_READY = 500; // 0x1f4
+    field public static final int PHASE_THIRD_PARTY_APPS_CAN_START = 600; // 0x258
+    field public static final int PHASE_WAIT_FOR_DEFAULT_DISPLAY = 100; // 0x64
+  }
+
+  public static final class SystemService.TargetUser {
+    method @NonNull public android.os.UserHandle getUserHandle();
+  }
+
+}
+
+package com.android.server.role {
+
+  public interface RoleServicePlatformHelper {
+    method @NonNull public String computePackageStateHash(int);
+    method @NonNull public java.util.Map<java.lang.String,java.util.Set<java.lang.String>> getLegacyRoleState(int);
+  }
+
+}
+
+package com.android.server.wifi {
+
+  public class SupplicantManager {
+    method public static void start();
+    method public static void stop();
+  }
+
+}
+
diff --git a/services/api/non-updatable-lint-baseline.txt b/services/api/non-updatable-lint-baseline.txt
new file mode 100644
index 0000000..b46d21e
--- /dev/null
+++ b/services/api/non-updatable-lint-baseline.txt
@@ -0,0 +1,9 @@
+// Baseline format: 1.0
+NotCloseable: com.android.server.wifi.SupplicantManager:
+    Classes that release resources (stop()) should implement AutoClosable and CloseGuard: class com.android.server.wifi.SupplicantManager
+
+
+ProtectedMember: com.android.server.SystemService#publishBinderService(String, android.os.IBinder):
+    Protected methods not allowed; must be public: method com.android.server.SystemService.publishBinderService(String,android.os.IBinder)}
+ProtectedMember: com.android.server.SystemService#publishBinderService(String, android.os.IBinder, boolean):
+    Protected methods not allowed; must be public: method com.android.server.SystemService.publishBinderService(String,android.os.IBinder,boolean)}
diff --git a/services/api/non-updatable-removed.txt b/services/api/non-updatable-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/services/api/non-updatable-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/appprediction/Android.bp b/services/appprediction/Android.bp
index bc43db1..53c461b 100644
--- a/services/appprediction/Android.bp
+++ b/services/appprediction/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.appprediction-sources",
     srcs: ["java/**/*.java"],
diff --git a/services/appwidget/Android.bp b/services/appwidget/Android.bp
index e46e5c8..8119073 100644
--- a/services/appwidget/Android.bp
+++ b/services/appwidget/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.appwidget-sources",
     srcs: ["java/**/*.java"],
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 809304b..e251700 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -19,6 +19,7 @@
 import static android.content.Context.KEYGUARD_SERVICE;
 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.content.res.Resources.ID_NULL;
 
 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
 
@@ -137,7 +138,6 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
@@ -181,9 +181,6 @@
             }
 
             switch (action) {
-                case Intent.ACTION_CONFIGURATION_CHANGED:
-                    onConfigurationChanged();
-                    break;
                 case Intent.ACTION_MANAGED_PROFILE_AVAILABLE:
                 case Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE:
                     synchronized (mLock) {
@@ -243,8 +240,6 @@
     private Handler mSaveStateHandler;
     private Handler mCallbackHandler;
 
-    private Locale mLocale;
-
     private final SparseIntArray mNextAppWidgetIds = new SparseIntArray();
 
     private boolean mSafeMode;
@@ -290,13 +285,6 @@
     }
 
     private void registerBroadcastReceiver() {
-        // Register for configuration changes so we can update the names
-        // of the widgets when the locale changes.
-        IntentFilter configFilter = new IntentFilter();
-        configFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
-        mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
-                configFilter, null, null);
-
         // Register for broadcasts about package install, etc., so we can
         // update the provider list.
         IntentFilter packageFilter = new IntentFilter();
@@ -338,62 +326,6 @@
         mSafeMode = safeMode;
     }
 
-    private void onConfigurationChanged() {
-        if (DEBUG) {
-            Slog.i(TAG, "onConfigurationChanged()");
-        }
-
-        Locale revised = Locale.getDefault();
-        if (revised == null || mLocale == null || !revised.equals(mLocale)) {
-            mLocale = revised;
-
-            synchronized (mLock) {
-                SparseIntArray changedGroups = null;
-
-                // Note: updateProvidersForPackageLocked() may remove providers, so we must copy the
-                // list of installed providers and skip providers that we don't need to update.
-                // Also note that remove the provider does not clear the Provider component data.
-                ArrayList<Provider> installedProviders = new ArrayList<>(mProviders);
-                HashSet<ProviderId> removedProviders = new HashSet<>();
-
-                int N = installedProviders.size();
-                for (int i = N - 1; i >= 0; i--) {
-                    Provider provider = installedProviders.get(i);
-
-                    final int userId = provider.getUserId();
-                    if (!mUserManager.isUserUnlockingOrUnlocked(userId) ||
-                            isProfileWithLockedParent(userId)) {
-                        continue;
-                    }
-                    ensureGroupStateLoadedLocked(userId);
-
-                    if (!removedProviders.contains(provider.id)) {
-                        final boolean changed = updateProvidersForPackageLocked(
-                                provider.id.componentName.getPackageName(),
-                                provider.getUserId(), removedProviders);
-
-                        if (changed) {
-                            if (changedGroups == null) {
-                                changedGroups = new SparseIntArray();
-                            }
-                            final int groupId = mSecurityPolicy.getGroupParent(
-                                    provider.getUserId());
-                            changedGroups.put(groupId, groupId);
-                        }
-                    }
-                }
-
-                if (changedGroups != null) {
-                    final int groupCount = changedGroups.size();
-                    for (int i = 0; i < groupCount; i++) {
-                        final int groupId = changedGroups.get(i);
-                        saveGroupStateAsync(groupId);
-                    }
-                }
-            }
-        }
-    }
-
     private void onPackageBroadcastReceived(Intent intent, int userId) {
         final String action = intent.getAction();
         boolean added = false;
@@ -2647,9 +2579,9 @@
             info.updatePeriodMillis = sa.getInt(
                     com.android.internal.R.styleable.AppWidgetProviderInfo_updatePeriodMillis, 0);
             info.initialLayout = sa.getResourceId(
-                    com.android.internal.R.styleable.AppWidgetProviderInfo_initialLayout, 0);
+                    com.android.internal.R.styleable.AppWidgetProviderInfo_initialLayout, ID_NULL);
             info.initialKeyguardLayout = sa.getResourceId(com.android.internal.R.styleable.
-                    AppWidgetProviderInfo_initialKeyguardLayout, 0);
+                    AppWidgetProviderInfo_initialKeyguardLayout, ID_NULL);
 
             String className = sa
                     .getString(com.android.internal.R.styleable.AppWidgetProviderInfo_configure);
@@ -2660,11 +2592,12 @@
             info.label = activityInfo.loadLabel(pm).toString();
             info.icon = activityInfo.getIconResource();
             info.previewImage = sa.getResourceId(
-                    com.android.internal.R.styleable.AppWidgetProviderInfo_previewImage, 0);
+                    com.android.internal.R.styleable.AppWidgetProviderInfo_previewImage, ID_NULL);
             info.previewLayout = sa.getResourceId(
-                    com.android.internal.R.styleable.AppWidgetProviderInfo_previewLayout, 0);
+                    com.android.internal.R.styleable.AppWidgetProviderInfo_previewLayout, ID_NULL);
             info.autoAdvanceViewId = sa.getResourceId(
-                    com.android.internal.R.styleable.AppWidgetProviderInfo_autoAdvanceViewId, -1);
+                    com.android.internal.R.styleable.AppWidgetProviderInfo_autoAdvanceViewId,
+                    View.NO_ID);
             info.resizeMode = sa.getInt(
                     com.android.internal.R.styleable.AppWidgetProviderInfo_resizeMode,
                     AppWidgetProviderInfo.RESIZE_NONE);
@@ -2673,9 +2606,8 @@
                     AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN);
             info.widgetFeatures = sa.getInt(
                     com.android.internal.R.styleable.AppWidgetProviderInfo_widgetFeatures, 0);
-            info.descriptionResource = sa.getResourceId(
-                    com.android.internal.R.styleable.AppWidgetProviderInfo_description,
-                    Resources.ID_NULL);
+            info.descriptionRes = sa.getResourceId(
+                    com.android.internal.R.styleable.AppWidgetProviderInfo_description, ID_NULL);
             sa.recycle();
             return info;
         } catch (IOException | PackageManager.NameNotFoundException | XmlPullParserException e) {
diff --git a/services/autofill/Android.bp b/services/autofill/Android.bp
index c448066..eb23f2f 100644
--- a/services/autofill/Android.bp
+++ b/services/autofill/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.autofill-sources",
     srcs: ["java/**/*.java"],
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index 8902087..27ea3d6 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -203,7 +203,7 @@
                     .getInteger(com.android.internal.R.integer.autofill_max_visible_datasets);
         }
 
-        final RemoteViews.OnClickHandler interceptionHandler = (view, pendingIntent, r) -> {
+        final RemoteViews.InteractionHandler interceptionHandler = (view, pendingIntent, r) -> {
             if (pendingIntent != null) {
                 mCallback.startIntentSender(pendingIntent.getIntentSender());
             }
@@ -258,10 +258,11 @@
                         + mVisibleDatasetsMaxCount);
             }
 
-            RemoteViews.OnClickHandler clickBlocker = null;
+            RemoteViews.InteractionHandler interactionBlocker = null;
             if (headerPresentation != null) {
-                clickBlocker = newClickBlocker();
-                mHeader = headerPresentation.applyWithTheme(mContext, null, clickBlocker, mThemeId);
+                interactionBlocker = newInteractionBlocker();
+                mHeader = headerPresentation.applyWithTheme(
+                        mContext, null, interactionBlocker, mThemeId);
                 final LinearLayout headerContainer =
                         decor.findViewById(R.id.autofill_dataset_header);
                 applyCancelAction(mHeader, response.getCancelIds());
@@ -276,11 +277,11 @@
                 final LinearLayout footerContainer =
                         decor.findViewById(R.id.autofill_dataset_footer);
                 if (footerContainer != null) {
-                    if (clickBlocker == null) { // already set for header
-                        clickBlocker = newClickBlocker();
+                    if (interactionBlocker == null) { // already set for header
+                        interactionBlocker = newInteractionBlocker();
                     }
                     mFooter = footerPresentation.applyWithTheme(
-                            mContext, null, clickBlocker, mThemeId);
+                            mContext, null, interactionBlocker, mThemeId);
                     applyCancelAction(mFooter, response.getCancelIds());
                     // Footer not supported on some platform e.g. TV
                     if (sVerbose) Slog.v(TAG, "adding footer");
@@ -397,9 +398,9 @@
     }
 
     /**
-     * Creates a remoteview interceptor used to block clicks.
+     * Creates a remoteview interceptor used to block clicks or other interactions.
      */
-    private RemoteViews.OnClickHandler newClickBlocker() {
+    private RemoteViews.InteractionHandler newInteractionBlocker() {
         return (view, pendingIntent, response) -> {
             if (sVerbose) Slog.v(TAG, "Ignoring click on " + view);
             return true;
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index 9d46c26..826a98a 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -388,18 +388,20 @@
             }
         }
 
-        final RemoteViews.OnClickHandler handler = (view, pendingIntent, response) -> {
-            Intent intent = response.getLaunchOptions(view).first;
-            final boolean isValid = isValidLink(pendingIntent, intent);
-            if (!isValid) {
-                final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_SAVE_LINK_TAPPED, mType);
-                log.setType(MetricsEvent.TYPE_UNKNOWN);
-                mMetricsLogger.write(log);
-                return false;
-            }
+        final RemoteViews.InteractionHandler handler =
+                (view, pendingIntent, response) -> {
+                    Intent intent = response.getLaunchOptions(view).first;
+                    final boolean isValid = isValidLink(pendingIntent, intent);
+                    if (!isValid) {
+                        final LogMaker log =
+                                newLogMaker(MetricsEvent.AUTOFILL_SAVE_LINK_TAPPED, mType);
+                        log.setType(MetricsEvent.TYPE_UNKNOWN);
+                        mMetricsLogger.write(log);
+                        return false;
+                    }
 
-            startIntentSenderWithRestore(pendingIntent, intent);
-            return true;
+                    startIntentSenderWithRestore(pendingIntent, intent);
+                    return true;
         };
 
         try {
diff --git a/services/backup/Android.bp b/services/backup/Android.bp
index 68376c5..ead8aff 100644
--- a/services/backup/Android.bp
+++ b/services/backup/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.backup-sources",
     srcs: ["java/**/*.java"],
diff --git a/services/backup/backuplib/Android.bp b/services/backup/backuplib/Android.bp
index 00f51c9..5a28891 100644
--- a/services/backup/backuplib/Android.bp
+++ b/services/backup/backuplib/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "backuplib-sources",
     srcs: ["java/**/*.java"],
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 6c30999..38275f7 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -1245,10 +1245,9 @@
 
     @Override
     public IRestoreSession beginRestoreSessionForUser(
-            int userId, String packageName, String transportID,
-            @OperationType int operationType) throws RemoteException {
+            int userId, String packageName, String transportID) throws RemoteException {
         return isUserReadyForBackup(userId)
-                ? beginRestoreSession(userId, packageName, transportID, operationType) : null;
+                ? beginRestoreSession(userId, packageName, transportID) : null;
     }
 
     /**
@@ -1257,15 +1256,13 @@
      */
     @Nullable
     public IRestoreSession beginRestoreSession(
-            @UserIdInt int userId, String packageName, String transportName,
-            @OperationType int operationType) {
+            @UserIdInt int userId, String packageName, String transportName) {
         UserBackupManagerService userBackupManagerService =
                 getServiceForUserIfCallerHasPermission(userId, "beginRestoreSession()");
 
         return userBackupManagerService == null
                 ? null
-                : userBackupManagerService.beginRestoreSession(packageName, transportName,
-                        operationType);
+                : userBackupManagerService.beginRestoreSession(packageName, transportName);
     }
 
     @Override
@@ -1350,15 +1347,15 @@
         if (!isUserReadyForBackup(userId)) {
             return BackupManager.ERROR_BACKUP_NOT_ALLOWED;
         }
-        return requestBackup(userId, packages, observer, monitor, flags, OperationType.BACKUP);
+        return requestBackup(userId, packages, observer, monitor, flags);
     }
 
     @Override
     public int requestBackup(String[] packages, IBackupObserver observer,
-            IBackupManagerMonitor monitor, int flags, @OperationType int operationType)
+            IBackupManagerMonitor monitor, int flags)
             throws RemoteException {
         return requestBackup(binderGetCallingUserId(), packages,
-                observer, monitor, flags, operationType);
+                observer, monitor, flags);
     }
 
     /**
@@ -1370,15 +1367,13 @@
             String[] packages,
             IBackupObserver observer,
             IBackupManagerMonitor monitor,
-            int flags,
-            @OperationType int operationType) {
+            int flags) {
         UserBackupManagerService userBackupManagerService =
                 getServiceForUserIfCallerHasPermission(userId, "requestBackup()");
 
         return userBackupManagerService == null
                 ? BackupManager.ERROR_BACKUP_NOT_ALLOWED
-                : userBackupManagerService.requestBackup(packages, observer, monitor, flags,
-                        operationType);
+                : userBackupManagerService.requestBackup(packages, observer, monitor, flags);
     }
 
     @Override
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 136cd22f..9ee0159 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -96,6 +96,7 @@
 import android.util.ArraySet;
 import android.util.AtomicFile;
 import android.util.EventLog;
+import android.util.FeatureFlagUtils;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -127,6 +128,7 @@
 import com.android.server.backup.restore.ActiveRestoreSession;
 import com.android.server.backup.restore.PerformUnifiedRestoreTask;
 import com.android.server.backup.transport.TransportClient;
+import com.android.server.backup.transport.TransportNotAvailableException;
 import com.android.server.backup.transport.TransportNotRegisteredException;
 import com.android.server.backup.utils.BackupEligibilityRules;
 import com.android.server.backup.utils.BackupManagerMonitorUtils;
@@ -1860,19 +1862,10 @@
 
     /**
      * Requests a backup for the inputted {@code packages} with a specified {@link
-     * IBackupManagerMonitor}.
-     */
-    public int requestBackup(String[] packages, IBackupObserver observer,
-            IBackupManagerMonitor monitor, int flags) {
-        return requestBackup(packages, observer, monitor, flags, OperationType.BACKUP);
-    }
-
-    /**
-     * Requests a backup for the inputted {@code packages} with a specified {@link
      * IBackupManagerMonitor} and {@link OperationType}.
      */
     public int requestBackup(String[] packages, IBackupObserver observer,
-            IBackupManagerMonitor monitor, int flags, @OperationType int operationType) {
+            IBackupManagerMonitor monitor, int flags) {
         mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "requestBackup");
 
         if (packages == null || packages.length < 1) {
@@ -1903,13 +1896,16 @@
 
         final TransportClient transportClient;
         final String transportDirName;
+        int operationType;
         try {
             transportDirName =
                     mTransportManager.getTransportDirName(
                             mTransportManager.getCurrentTransportName());
             transportClient =
                     mTransportManager.getCurrentTransportClientOrThrow("BMS.requestBackup()");
-        } catch (TransportNotRegisteredException e) {
+            operationType = getOperationTypeFromTransport(transportClient);
+        } catch (TransportNotRegisteredException | TransportNotAvailableException
+                | RemoteException e) {
             BackupObserverUtils.sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
             monitor = BackupManagerMonitorUtils.monitorEvent(monitor,
                     BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_IS_NULL,
@@ -4024,15 +4020,13 @@
     }
 
     /** Hand off a restore session. */
-    public IRestoreSession beginRestoreSession(String packageName, String transport,
-            @OperationType int operationType) {
+    public IRestoreSession beginRestoreSession(String packageName, String transport) {
         if (DEBUG) {
             Slog.v(
                     TAG,
                     addUserIdToLogMessage(
                             mUserId,
-                            "beginRestoreSession: pkg=" + packageName + " transport=" + transport
-                                + "operationType=" + operationType));
+                            "beginRestoreSession: pkg=" + packageName + " transport=" + transport));
         }
 
         boolean needPermission = true;
@@ -4073,6 +4067,17 @@
             }
         }
 
+        int operationType;
+        try {
+            operationType = getOperationTypeFromTransport(
+                    mTransportManager.getTransportClientOrThrow(transport, /* caller */
+                            "BMS.beginRestoreSession"));
+        } catch (TransportNotAvailableException | TransportNotRegisteredException
+                | RemoteException e) {
+            Slog.w(TAG, "Failed to get operation type from transport: " + e);
+            return null;
+        }
+
         synchronized (this) {
             if (mActiveRestoreSession != null) {
                 Slog.i(
@@ -4356,6 +4361,34 @@
         }
     }
 
+    @VisibleForTesting
+    @OperationType int getOperationTypeFromTransport(TransportClient transportClient)
+            throws TransportNotAvailableException, RemoteException {
+        if (!shouldUseNewBackupEligibilityRules()) {
+            // Return the default to stick to the legacy behaviour.
+            return OperationType.BACKUP;
+        }
+
+        long oldCallingId = Binder.clearCallingIdentity();
+        try {
+            IBackupTransport transport = transportClient.connectOrThrow(
+                    /* caller */ "BMS.getOperationTypeFromTransport");
+            if ((transport.getTransportFlags() & BackupAgent.FLAG_DEVICE_TO_DEVICE_TRANSFER) != 0) {
+                return OperationType.MIGRATION;
+            } else {
+                return OperationType.BACKUP;
+            }
+        } finally {
+            Binder.restoreCallingIdentity(oldCallingId);
+        }
+    }
+
+    @VisibleForTesting
+    boolean shouldUseNewBackupEligibilityRules() {
+        return FeatureFlagUtils.isEnabled(mContext,
+                FeatureFlagUtils.SETTINGS_USE_NEW_BACKUP_ELIGIBILITY_RULES);
+    }
+
     private static String addUserIdToLogMessage(int userId, String message) {
         return "[UserID:" + userId + "] " + message;
     }
diff --git a/services/companion/Android.bp b/services/companion/Android.bp
index 6aa54c4..4ae9365 100644
--- a/services/companion/Android.bp
+++ b/services/companion/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.companion-sources",
     srcs: ["java/**/*.java"],
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 76c8d30..21cae45 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -142,18 +142,13 @@
 import java.util.concurrent.ConcurrentMap;
 import java.util.function.Function;
 
-//TODO onStop schedule unbind in 5 seconds
-//TODO make sure APIs are only callable from currently focused app
-//TODO schedule stopScan on activity destroy(except if configuration change)
-//TODO on associate called again after configuration change -> replace old callback with new
-//TODO avoid leaking calling activity in IFindDeviceCallback (see PrintManager#print for example)
 /** @hide */
 @SuppressLint("LongLogTag")
 public class CompanionDeviceManagerService extends SystemService implements Binder.DeathRecipient {
 
     private static final ComponentName SERVICE_TO_BIND_TO = ComponentName.createRelative(
             CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME,
-            ".DeviceDiscoveryService");
+            ".CompanionDeviceDiscoveryService");
 
     private static final long DEVICE_DISAPPEARED_TIMEOUT_MS = 10 * 1000;
     private static final long DEVICE_DISAPPEARED_UNBIND_TIMEOUT_MS = 10 * 60 * 1000;
@@ -747,6 +742,15 @@
                 }
             }
         }
+
+        if (association.isNotifyOnDeviceNearby()) {
+            ServiceConnector<ICompanionDeviceService> serviceConnector =
+                    mDeviceListenerServiceConnectors.forUser(association.getUserId())
+                            .get(association.getPackageName());
+            if (serviceConnector != null) {
+                serviceConnector.unbind();
+            }
+        }
     }
 
     private void updateSpecialAccessPermissionForAssociatedPackage(Association association) {
@@ -1422,7 +1426,9 @@
         }
 
         @Override
-        public void onDeviceDisconnected(BluetoothDevice device) {
+        public void onDeviceDisconnected(BluetoothDevice device, @DisconnectReason int reason) {
+            Slog.d(LOG_TAG, device.getAddress() + " disconnected w/ reason: (" + reason + ") "
+                    + BluetoothAdapter.BluetoothConnectionCallback.disconnectReasonText(reason));
             CompanionDeviceManagerService.this.onDeviceDisconnected(device.getAddress());
         }
     }
diff --git a/services/contentcapture/Android.bp b/services/contentcapture/Android.bp
index 688c0b1..434f239 100644
--- a/services/contentcapture/Android.bp
+++ b/services/contentcapture/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.contentcapture-sources",
     srcs: ["java/**/*.java"],
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 0be485b..02930dc 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -88,7 +88,6 @@
 import com.android.internal.infra.GlobalWhitelistState;
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.util.DumpUtils;
-import com.android.internal.util.Preconditions;
 import com.android.server.LocalServices;
 import com.android.server.infra.AbstractMasterSystemService;
 import com.android.server.infra.FrameworkResourcesServiceNameResolver;
@@ -101,6 +100,7 @@
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
@@ -602,10 +602,11 @@
 
         @Override
         public void startSession(@NonNull IBinder activityToken,
-                @NonNull ComponentName componentName, int sessionId, int flags,
-                @NonNull IResultReceiver result) {
-            Preconditions.checkNotNull(activityToken);
-            Preconditions.checkNotNull(sessionId);
+                @NonNull IBinder shareableActivityToken, @NonNull ComponentName componentName,
+                int sessionId, int flags, @NonNull IResultReceiver result) {
+            Objects.requireNonNull(activityToken);
+            Objects.requireNonNull(shareableActivityToken);
+            Objects.requireNonNull(sessionId);
             final int userId = UserHandle.getCallingUserId();
 
             final ActivityPresentationInfo activityPresentationInfo = getAmInternal()
@@ -617,14 +618,14 @@
                     setClientState(result, STATE_DISABLED, /* binder= */ null);
                     return;
                 }
-                service.startSessionLocked(activityToken, activityPresentationInfo, sessionId,
-                        Binder.getCallingUid(), flags, result);
+                service.startSessionLocked(activityToken, shareableActivityToken,
+                        activityPresentationInfo, sessionId, Binder.getCallingUid(), flags, result);
             }
         }
 
         @Override
         public void finishSession(int sessionId) {
-            Preconditions.checkNotNull(sessionId);
+            Objects.requireNonNull(sessionId);
             final int userId = UserHandle.getCallingUserId();
 
             synchronized (mLock) {
@@ -650,7 +651,7 @@
 
         @Override
         public void removeData(@NonNull DataRemovalRequest request) {
-            Preconditions.checkNotNull(request);
+            Objects.requireNonNull(request);
             assertCalledByPackageOwner(request.getPackageName());
 
             final int userId = UserHandle.getCallingUserId();
@@ -663,8 +664,8 @@
         @Override
         public void shareData(@NonNull DataShareRequest request,
                 @NonNull IDataShareWriteAdapter clientAdapter) {
-            Preconditions.checkNotNull(request);
-            Preconditions.checkNotNull(clientAdapter);
+            Objects.requireNonNull(request);
+            Objects.requireNonNull(clientAdapter);
 
             assertCalledByPackageOwner(request.getPackageName());
 
@@ -795,6 +796,23 @@
             new ContentCaptureManagerServiceShellCommand(ContentCaptureManagerService.this).exec(
                     this, in, out, err, args, callback, resultReceiver);
         }
+
+        @Override
+        public void resetTemporaryService(@UserIdInt int userId) {
+            ContentCaptureManagerService.this.resetTemporaryService(userId);
+        }
+
+        @Override
+        public void setTemporaryService(
+                @UserIdInt int userId, @NonNull String serviceName, int duration) {
+            ContentCaptureManagerService.this.setTemporaryService(
+                    userId, serviceName, duration);
+        }
+
+        @Override
+        public void setDefaultServiceEnabled(@UserIdInt int userId, boolean enabled) {
+            ContentCaptureManagerService.this.setDefaultServiceEnabled(userId, enabled);
+        }
     }
 
     private final class LocalService extends ContentCaptureManagerInternal {
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index ea68e19..53cdc33 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -35,6 +35,7 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManagerInternal;
+import android.app.assist.ActivityId;
 import android.app.assist.AssistContent;
 import android.app.assist.AssistStructure;
 import android.content.ComponentName;
@@ -241,6 +242,7 @@
 
     @GuardedBy("mLock")
     public void startSessionLocked(@NonNull IBinder activityToken,
+            @NonNull IBinder shareableActivityToken,
             @NonNull ActivityPresentationInfo activityPresentationInfo, int sessionId, int uid,
             int flags, @NonNull IResultReceiver clientReceiver) {
         if (activityPresentationInfo == null) {
@@ -340,8 +342,8 @@
         mRemoteService.ensureBoundLocked();
 
         final ContentCaptureServerSession newSession = new ContentCaptureServerSession(mLock,
-                activityToken, this, componentName, clientReceiver, taskId, displayId, sessionId,
-                uid, flags);
+                activityToken, new ActivityId(taskId, shareableActivityToken), this, componentName,
+                clientReceiver, taskId, displayId, sessionId, uid, flags);
         if (mMaster.verbose) {
             Slog.v(TAG, "startSession(): new session for "
                     + ComponentName.flattenToShortString(componentName) + " and id " + sessionId);
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
index 06ab426..9f3045e 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
@@ -25,6 +25,7 @@
 import static android.view.contentcapture.ContentCaptureSession.STATE_SERVICE_UPDATING;
 
 import android.annotation.NonNull;
+import android.app.assist.ActivityId;
 import android.content.ComponentName;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -75,9 +76,9 @@
     public final ComponentName appComponentName;
 
     ContentCaptureServerSession(@NonNull Object lock, @NonNull IBinder activityToken,
-            @NonNull ContentCapturePerUserService service, @NonNull ComponentName appComponentName,
-            @NonNull IResultReceiver sessionStateReceiver, int taskId, int displayId, int sessionId,
-            int uid, int flags) {
+            @NonNull ActivityId activityId, @NonNull ContentCapturePerUserService service,
+            @NonNull ComponentName appComponentName, @NonNull IResultReceiver sessionStateReceiver,
+            int taskId, int displayId, int sessionId, int uid, int flags) {
         Preconditions.checkArgument(sessionId != NO_SESSION_ID);
         mLock = lock;
         mActivityToken = activityToken;
@@ -86,7 +87,7 @@
         mId = sessionId;
         mUid = uid;
         mContentCaptureContext = new ContentCaptureContext(/* clientContext= */ null,
-                appComponentName, taskId, displayId, flags);
+                activityId, appComponentName, displayId, flags);
         mSessionStateReceiver = sessionStateReceiver;
         try {
             sessionStateReceiver.asBinder().linkToDeath(() -> onClientDeath(), 0);
diff --git a/services/contentsuggestions/Android.bp b/services/contentsuggestions/Android.bp
index 1b4d7e2..9f28b72 100644
--- a/services/contentsuggestions/Android.bp
+++ b/services/contentsuggestions/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.contentsuggestions-sources",
     srcs: ["java/**/*.java"],
diff --git a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
index 00c91fe..57c643b 100644
--- a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
+++ b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
@@ -21,6 +21,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.app.contentsuggestions.ClassificationsRequest;
 import android.app.contentsuggestions.ContentSuggestionsManager;
 import android.app.contentsuggestions.IClassificationsCallback;
@@ -253,6 +254,23 @@
             receiver.send(isDisabled ? 0 : 1, null);
         }
 
+        @Override
+        public void resetTemporaryService(@UserIdInt int userId) {
+            ContentSuggestionsManagerService.this.resetTemporaryService(userId);
+        }
+
+        @Override
+        public void setTemporaryService(
+                @UserIdInt int userId, @NonNull String serviceName, int duration) {
+            ContentSuggestionsManagerService.this.setTemporaryService(
+                    userId, serviceName, duration);
+        }
+
+        @Override
+        public void setDefaultServiceEnabled(@UserIdInt int userId, boolean enabled) {
+            ContentSuggestionsManagerService.this.setDefaultServiceEnabled(userId, enabled);
+        }
+
         public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
                 @Nullable FileDescriptor err,
                 @NonNull String[] args, @Nullable ShellCallback callback,
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 0725bb2..b67bdc2 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.core-sources-am-wm",
     srcs: [
diff --git a/services/core/java/android/power/PowerStatsInternal.java b/services/core/java/android/power/PowerStatsInternal.java
index 40107a5..27da142 100644
--- a/services/core/java/android/power/PowerStatsInternal.java
+++ b/services/core/java/android/power/PowerStatsInternal.java
@@ -50,7 +50,8 @@
      *                          requested.
      *
      * @return A Future containing a list of {@link EnergyConsumerResult} objects containing energy
-     *         consumer results for all listed {@link EnergyConsumerId}.
+     *         consumer results for all listed {@link EnergyConsumerId}. null if
+     *         {@link EnergyConsumer} not supported
      */
     @NonNull
     public abstract CompletableFuture<EnergyConsumerResult[]> getEnergyConsumedAsync(
@@ -59,8 +60,10 @@
     /**
      * Returns the power entity info for all available {@link PowerEntity}
      *
-     * @return List of available {@link PowerEntity}
+     * @return List of available {@link PowerEntity} or null if {@link PowerEntity} not
+     * supported
      */
+    @Nullable
     public abstract PowerEntity[] getPowerEntityInfo();
 
     /**
@@ -71,7 +74,8 @@
      *                          requested.
      *
      * @return A Future containing a list of {@link StateResidencyResult} objects containing state
-     *         residency results for all listed {@link PowerEntity.id}.
+     *         residency results for all listed {@link PowerEntity.id}. null if {@link PowerEntity}
+     *         not supported
      */
     @NonNull
     public abstract CompletableFuture<StateResidencyResult[]> getStateResidencyAsync(
@@ -80,8 +84,9 @@
     /**
      * Returns the channel info for all available {@link Channel}
      *
-     * @return List of available {@link Channel}
+     * @return List of available {@link Channel} or null if {@link Channel} not supported
      */
+    @Nullable
     public abstract Channel[] getEnergyMeterInfo();
 
     /**
@@ -91,7 +96,8 @@
      * @param channelIds Array of {@link Channel.id} for accumulated energy is being requested.
      *
      * @return A Future containing a list of {@link EnergyMeasurement} objects containing
-     *         accumulated energy measurements for all listed {@link Channel.id}.
+     *         accumulated energy measurements for all listed {@link Channel.id}. null if
+     *         {@link Channel} not supported
      */
     @NonNull
     public abstract CompletableFuture<EnergyMeasurement[]> readEnergyMeterAsync(
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 154e183..542d527 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -44,6 +44,7 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE;
@@ -90,7 +91,7 @@
 import android.net.IConnectivityManager;
 import android.net.IDnsResolver;
 import android.net.INetd;
-import android.net.INetworkManagementEventObserver;
+import android.net.INetworkActivityListener;
 import android.net.INetworkMonitor;
 import android.net.INetworkMonitorCallbacks;
 import android.net.INetworkPolicyListener;
@@ -147,13 +148,13 @@
 import android.net.shared.PrivateDnsConfig;
 import android.net.util.MultinetworkPolicyTracker;
 import android.net.util.NetdService;
+import android.os.BatteryStatsManager;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
-import android.os.INetworkActivityListener;
 import android.os.INetworkManagementService;
 import android.os.Looper;
 import android.os.Message;
@@ -163,6 +164,7 @@
 import android.os.PersistableBundle;
 import android.os.PowerManager;
 import android.os.Process;
+import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
 import android.os.SystemClock;
@@ -172,6 +174,7 @@
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.LocalLog;
 import android.util.Log;
@@ -185,14 +188,17 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.BitUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.LocationPermissionChecker;
 import com.android.internal.util.MessageUtils;
 import com.android.modules.utils.BasicShellCommandHandler;
+import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
+import com.android.net.module.util.CollectionUtils;
 import com.android.net.module.util.LinkPropertiesUtils.CompareOrUpdateResult;
 import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
+import com.android.net.module.util.PermissionUtils;
 import com.android.server.am.BatteryStatsService;
 import com.android.server.connectivity.AutodestructReference;
 import com.android.server.connectivity.DataConnectionStats;
@@ -209,7 +215,6 @@
 import com.android.server.connectivity.PermissionMonitor;
 import com.android.server.connectivity.ProxyTracker;
 import com.android.server.connectivity.QosCallbackTracker;
-import com.android.server.net.BaseNetworkObserver;
 import com.android.server.net.NetworkPolicyManagerInternal;
 import com.android.server.utils.PriorityDump;
 
@@ -327,6 +332,7 @@
     private INetworkStatsService mStatsService;
     private NetworkPolicyManager mPolicyManager;
     private NetworkPolicyManagerInternal mPolicyManagerInternal;
+    private final NetdCallback mNetdCallback;
 
     /**
      * TestNetworkService (lazily) created upon first usage. Locked to prevent creation of multiple
@@ -559,6 +565,11 @@
     private static final int EVENT_SET_OEM_NETWORK_PREFERENCE = 48;
 
     /**
+     * Used to indicate the system default network becomes active.
+     */
+    private static final int EVENT_REPORT_NETWORK_ACTIVITY = 49;
+
+    /**
      * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
      * should be shown.
      */
@@ -1192,7 +1203,14 @@
         mUserAllContext.registerReceiver(mIntentReceiver, intentFilter,
                 null /* broadcastPermission */, mHandler);
 
-        mNetworkActivityTracker = new LegacyNetworkActivityTracker(mContext, mNMS);
+        mNetworkActivityTracker = new LegacyNetworkActivityTracker(mContext, mHandler, mNMS, mNetd);
+
+        mNetdCallback = new NetdCallback();
+        try {
+            mNetd.registerUnsolicitedEventListener(mNetdCallback);
+        } catch (RemoteException | ServiceSpecificException e) {
+            loge("Error registering event listener :" + e);
+        }
 
         mSettingsObserver = new SettingsObserver(mContext, mHandler);
         registerSettingsCallbacks();
@@ -1231,6 +1249,7 @@
     private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) {
         final NetworkCapabilities netCap = new NetworkCapabilities();
         netCap.addCapability(NET_CAPABILITY_INTERNET);
+        netCap.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
         netCap.removeCapability(NET_CAPABILITY_NOT_VPN);
         netCap.setSingleUid(uid);
         return netCap;
@@ -1245,6 +1264,7 @@
             int transportType, NetworkRequest.Type type) {
         final NetworkCapabilities netCap = new NetworkCapabilities();
         netCap.addCapability(NET_CAPABILITY_INTERNET);
+        netCap.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
         netCap.setRequestorUidAndPackageName(Process.myUid(), mContext.getPackageName());
         if (transportType > TYPE_NONE) {
             netCap.addTransportType(transportType);
@@ -1502,7 +1522,7 @@
 
     @Override
     public Network getActiveNetworkForUid(int uid, boolean ignoreBlocked) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         return getActiveNetworkForUidInternal(uid, ignoreBlocked);
     }
 
@@ -1525,7 +1545,7 @@
 
     @Override
     public NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         final NetworkState state = getUnfilteredActiveNetworkState(uid);
         filterNetworkStateForUid(state, uid, ignoreBlocked);
         return state.networkInfo;
@@ -1869,7 +1889,7 @@
     @Override
     public NetworkState[] getAllNetworkState() {
         // This contains IMSI details, so make sure the caller is privileged.
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
 
         final ArrayList<NetworkState> result = new ArrayList<>();
         for (Network network : getAllNetworks()) {
@@ -2293,7 +2313,7 @@
 
     // Public because it's used by mLockdownTracker.
     public void sendConnectedBroadcast(NetworkInfo info) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         sendGeneralBroadcast(info, CONNECTIVITY_ACTION);
     }
 
@@ -2404,7 +2424,7 @@
      */
     @Override
     public void registerNetworkActivityListener(@NonNull INetworkActivityListener l) {
-        // TODO: Replace network activity listener registry in ConnectivityManager from NMS to here
+        mNetworkActivityTracker.registerNetworkActivityListener(l);
     }
 
     /**
@@ -2412,7 +2432,7 @@
      */
     @Override
     public void unregisterNetworkActivityListener(@NonNull INetworkActivityListener l) {
-        // TODO: Replace network activity listener registry in ConnectivityManager from NMS to here
+        mNetworkActivityTracker.unregisterNetworkActivityListener(l);
     }
 
     /**
@@ -2420,8 +2440,7 @@
      */
     @Override
     public boolean isDefaultNetworkActive() {
-        // TODO: Replace isNetworkActive() in NMS.
-        return false;
+        return mNetworkActivityTracker.isDefaultNetworkActive();
     }
 
     /**
@@ -2558,13 +2577,13 @@
         if (!checkDumpPermission(mContext, TAG, pw)) return;
         if (asProto) return;
 
-        if (ArrayUtils.contains(args, DIAG_ARG)) {
+        if (CollectionUtils.contains(args, DIAG_ARG)) {
             dumpNetworkDiagnostics(pw);
             return;
-        } else if (ArrayUtils.contains(args, NETWORK_ARG)) {
+        } else if (CollectionUtils.contains(args, NETWORK_ARG)) {
             dumpNetworks(pw);
             return;
-        } else if (ArrayUtils.contains(args, REQUEST_ARG)) {
+        } else if (CollectionUtils.contains(args, REQUEST_ARG)) {
             dumpNetworkRequests(pw);
             return;
         }
@@ -2635,7 +2654,7 @@
 
         pw.println();
 
-        if (ArrayUtils.contains(args, SHORT_ARG) == false) {
+        if (!CollectionUtils.contains(args, SHORT_ARG)) {
             pw.println();
             pw.println("mNetworkRequestInfoLogs (most recent first):");
             pw.increaseIndent();
@@ -2686,6 +2705,12 @@
         pw.increaseIndent();
         mPermissionMonitor.dump(pw);
         pw.decreaseIndent();
+
+        pw.println();
+        pw.println("Legacy network activity:");
+        pw.increaseIndent();
+        mNetworkActivityTracker.dump(pw);
+        pw.decreaseIndent();
     }
 
     private void dumpNetworks(IndentingPrintWriter pw) {
@@ -3721,7 +3746,12 @@
         // Looking up the app passed param request in mRequests isn't possible since it may return
         // null for a request managed by a per-app default. Therefore use getNriForAppRequest() to
         // do the lookup since that will also find per-app default managed requests.
-        final NetworkRequestInfo nri = getNriForAppRequest(request);
+        // Additionally, this lookup needs to be relatively fast (hence the lookup optimization)
+        // to avoid potential race conditions when validating a package->uid mapping when sending
+        // the callback on the very low-chance that an application shuts down prior to the callback
+        // being sent.
+        final NetworkRequestInfo nri = mNetworkRequests.get(request) != null
+                ? mNetworkRequests.get(request) : getNriForAppRequest(request);
 
         if (nri != null) {
             if (Process.SYSTEM_UID != callingUid && Process.NETWORK_STACK_UID != callingUid
@@ -4447,6 +4477,9 @@
                         loge("handleMessage.EVENT_SET_OEM_NETWORK_PREFERENCE failed", e);
                     }
                     break;
+                case EVENT_REPORT_NETWORK_ACTIVITY:
+                    mNetworkActivityTracker.handleReportNetworkActivity();
+                    break;
             }
         }
     }
@@ -4663,7 +4696,7 @@
 
     @Override
     public void setGlobalProxy(final ProxyInfo proxyProperties) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         mProxyTracker.setGlobalProxy(proxyProperties);
     }
 
@@ -4788,7 +4821,7 @@
             }
         }
 
-        if (ArrayUtils.isEmpty(underlyingNetworks)) return null;
+        if (CollectionUtils.isEmpty(underlyingNetworks)) return null;
 
         List<String> interfaces = new ArrayList<>();
         for (Network network : underlyingNetworks) {
@@ -4832,7 +4865,7 @@
         if (!nai.supportsUnderlyingNetworks()) return false;
         final Network[] underlying = underlyingNetworksOrDefault(
                 nai.networkCapabilities.getOwnerUid(), nai.declaredUnderlyingNetworks);
-        return ArrayUtils.contains(underlying, network);
+        return CollectionUtils.contains(underlying, network);
     }
 
     /**
@@ -4865,7 +4898,7 @@
 
     @Override
     public void setRequireVpnForUids(boolean requireVpn, UidRange[] ranges) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_REQUIRE_VPN_FOR_UIDS,
                 encodeBool(requireVpn), 0 /* arg2 */, ranges));
     }
@@ -5296,8 +5329,7 @@
                 }
             }
         }
-        // TODO: use NetworkStackUtils.convertToIntArray after moving it
-        return ArrayUtils.convertToIntArray(new ArrayList<>(thresholds));
+        return CollectionUtils.toIntArray(new ArrayList<>(thresholds));
     }
 
     private void updateSignalStrengthThresholds(
@@ -6416,7 +6448,7 @@
             @NonNull NetworkCapabilities agentCaps, @NonNull NetworkCapabilities newNc) {
         underlyingNetworks = underlyingNetworksOrDefault(
                 agentCaps.getOwnerUid(), underlyingNetworks);
-        int[] transportTypes = agentCaps.getTransportTypes();
+        long transportTypes = BitUtils.packBits(agentCaps.getTransportTypes());
         int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
         int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
         // metered if any underlying is metered, or originally declared metered by the agent.
@@ -6435,7 +6467,7 @@
                 final NetworkCapabilities underlyingCaps = underlying.networkCapabilities;
                 hadUnderlyingNetworks = true;
                 for (int underlyingType : underlyingCaps.getTransportTypes()) {
-                    transportTypes = ArrayUtils.appendInt(transportTypes, underlyingType);
+                    transportTypes |= 1L << underlyingType;
                 }
 
                 // Merge capabilities of this underlying network. For bandwidth, assume the
@@ -6466,7 +6498,7 @@
             suspended = false;
         }
 
-        newNc.setTransportTypes(transportTypes);
+        newNc.setTransportTypes(BitUtils.unpackBits(transportTypes));
         newNc.setLinkDownstreamBandwidthKbps(downKbps);
         newNc.setLinkUpstreamBandwidthKbps(upKbps);
         newNc.setCapability(NET_CAPABILITY_NOT_METERED, !metered);
@@ -8531,14 +8563,14 @@
         for (NetworkAgentInfo virtual : mNetworkAgentInfos) {
             if (virtual.supportsUnderlyingNetworks()
                     && virtual.networkCapabilities.getOwnerUid() == callbackUid
-                    && ArrayUtils.contains(virtual.declaredUnderlyingNetworks, nai.network)) {
+                    && CollectionUtils.contains(virtual.declaredUnderlyingNetworks, nai.network)) {
                 return true;
             }
         }
 
         // Administrator UIDs also contains the Owner UID
         final int[] administratorUids = nai.networkCapabilities.getAdministratorUids();
-        return ArrayUtils.contains(administratorUids, callbackUid);
+        return CollectionUtils.contains(administratorUids, callbackUid);
     }
 
     @Override
@@ -8627,6 +8659,14 @@
         notifyDataStallSuspected(p, network.getNetId());
     }
 
+    private class NetdCallback extends BaseNetdUnsolicitedEventListener {
+        @Override
+        public void onInterfaceClassActivityChanged(boolean isActive, int timerLabel,
+                long timestampNs, int uid) {
+            mNetworkActivityTracker.setAndReportNetworkActive(isActive, timerLabel, timestampNs);
+        }
+    }
+
     private final LegacyNetworkActivityTracker mNetworkActivityTracker;
 
     /**
@@ -8634,30 +8674,78 @@
      * changes.
      */
     private static final class LegacyNetworkActivityTracker {
+        private static final int NO_UID = -1;
         private final Context mContext;
-        private final INetworkManagementService mNMS;
+        private final INetd mNetd;
+        private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners =
+                new RemoteCallbackList<>();
+        // Indicate the current system default network activity is active or not.
+        @GuardedBy("mActiveIdleTimers")
+        private boolean mNetworkActive;
+        @GuardedBy("mActiveIdleTimers")
+        private final ArrayMap<String, IdleTimerParams> mActiveIdleTimers = new ArrayMap();
+        private final Handler mHandler;
 
-        LegacyNetworkActivityTracker(@NonNull Context context,
-                @NonNull INetworkManagementService nms) {
-            mContext = context;
-            mNMS = nms;
-            try {
-                mNMS.registerObserver(mDataActivityObserver);
-            } catch (RemoteException e) {
-                loge("Error registering observer :" + e);
+        private class IdleTimerParams {
+            public final int timeout;
+            public final int transportType;
+
+            IdleTimerParams(int timeout, int transport) {
+                this.timeout = timeout;
+                this.transportType = transport;
             }
         }
 
-        // TODO: Migrate away the dependency with INetworkManagementEventObserver.
-        private final INetworkManagementEventObserver mDataActivityObserver =
-                new BaseNetworkObserver() {
-                    @Override
-                    public void interfaceClassDataActivityChanged(int transportType, boolean active,
-                            long tsNanos, int uid) {
-                        sendDataActivityBroadcast(transportTypeToLegacyType(transportType), active,
-                                tsNanos);
+        LegacyNetworkActivityTracker(@NonNull Context context, @NonNull Handler handler,
+                @NonNull INetworkManagementService nms, @NonNull INetd netd) {
+            mContext = context;
+            mNetd = netd;
+            mHandler = handler;
+        }
+
+        public void setAndReportNetworkActive(boolean active, int transportType, long tsNanos) {
+            sendDataActivityBroadcast(transportTypeToLegacyType(transportType), active, tsNanos);
+            synchronized (mActiveIdleTimers) {
+                mNetworkActive = active;
+                // If there are no idle timers, it means that system is not monitoring
+                // activity, so the system default network for those default network
+                // unspecified apps is always considered active.
+                //
+                // TODO: If the mActiveIdleTimers is empty, netd will actually not send
+                // any network activity change event. Whenever this event is received,
+                // the mActiveIdleTimers should be always not empty. The legacy behavior
+                // is no-op. Remove to refer to mNetworkActive only.
+                if (mNetworkActive || mActiveIdleTimers.isEmpty()) {
+                    mHandler.sendMessage(mHandler.obtainMessage(EVENT_REPORT_NETWORK_ACTIVITY));
+                }
+            }
+        }
+
+        // The network activity should only be updated from ConnectivityService handler thread
+        // when mActiveIdleTimers lock is held.
+        @GuardedBy("mActiveIdleTimers")
+        private void reportNetworkActive() {
+            final int length = mNetworkActivityListeners.beginBroadcast();
+            if (DDBG) log("reportNetworkActive, notify " + length + " listeners");
+            try {
+                for (int i = 0; i < length; i++) {
+                    try {
+                        mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive();
+                    } catch (RemoteException | RuntimeException e) {
+                        loge("Fail to send network activie to listener " + e);
                     }
-                };
+                }
+            } finally {
+                mNetworkActivityListeners.finishBroadcast();
+            }
+        }
+
+        @GuardedBy("mActiveIdleTimers")
+        public void handleReportNetworkActivity() {
+            synchronized (mActiveIdleTimers) {
+                reportNetworkActive();
+            }
+        }
 
         // This is deprecated and only to support legacy use cases.
         private int transportTypeToLegacyType(int type) {
@@ -8723,10 +8811,17 @@
                 return; // do not track any other networks
             }
 
+            updateRadioPowerState(true /* isActive */, type);
+
             if (timeout > 0 && iface != null) {
                 try {
-                    // TODO: Access INetd directly instead of NMS
-                    mNMS.addIdleTimer(iface, timeout, type);
+                    synchronized (mActiveIdleTimers) {
+                        // Networks start up.
+                        mNetworkActive = true;
+                        mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type));
+                        mNetd.idletimerAddInterface(iface, timeout, Integer.toString(type));
+                        reportNetworkActive();
+                    }
                 } catch (Exception e) {
                     // You shall not crash!
                     loge("Exception in setupDataActivityTracking " + e);
@@ -8741,16 +8836,28 @@
             final String iface = networkAgent.linkProperties.getInterfaceName();
             final NetworkCapabilities caps = networkAgent.networkCapabilities;
 
-            if (iface != null && (caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
-                    || caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))) {
-                try {
-                    // the call fails silently if no idle timer setup for this interface
-                    // TODO: Access INetd directly instead of NMS
-                    mNMS.removeIdleTimer(iface);
-                } catch (Exception e) {
-                    // You shall not crash!
-                    loge("Exception in removeDataActivityTracking " + e);
+            if (iface == null) return;
+
+            final int type;
+            if (caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
+                type = NetworkCapabilities.TRANSPORT_CELLULAR;
+            } else if (caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
+                type = NetworkCapabilities.TRANSPORT_WIFI;
+            } else {
+                return; // do not track any other networks
+            }
+
+            try {
+                updateRadioPowerState(false /* isActive */, type);
+                synchronized (mActiveIdleTimers) {
+                    final IdleTimerParams params = mActiveIdleTimers.remove(iface);
+                    // The call fails silently if no idle timer setup for this interface
+                    mNetd.idletimerRemoveInterface(iface, params.timeout,
+                            Integer.toString(params.transportType));
                 }
+            } catch (Exception e) {
+                // You shall not crash!
+                loge("Exception in removeDataActivityTracking " + e);
             }
         }
 
@@ -8766,6 +8873,53 @@
                 removeDataActivityTracking(oldNetwork);
             }
         }
+
+        private void updateRadioPowerState(boolean isActive, int transportType) {
+            final BatteryStatsManager bs = mContext.getSystemService(BatteryStatsManager.class);
+            switch (transportType) {
+                case NetworkCapabilities.TRANSPORT_CELLULAR:
+                    bs.reportMobileRadioPowerState(isActive, NO_UID);
+                    break;
+                case NetworkCapabilities.TRANSPORT_WIFI:
+                    bs.reportWifiRadioPowerState(isActive, NO_UID);
+                    break;
+                default:
+                    logw("Untracked transport type:" + transportType);
+            }
+        }
+
+        public boolean isDefaultNetworkActive() {
+            synchronized (mActiveIdleTimers) {
+                // If there are no idle timers, it means that system is not monitoring activity,
+                // so the default network is always considered active.
+                //
+                // TODO : Distinguish between the cases where mActiveIdleTimers is empty because
+                // tracking is disabled (negative idle timer value configured), or no active default
+                // network. In the latter case, this reports active but it should report inactive.
+                return mNetworkActive || mActiveIdleTimers.isEmpty();
+            }
+        }
+
+        public void registerNetworkActivityListener(@NonNull INetworkActivityListener l) {
+            mNetworkActivityListeners.register(l);
+        }
+
+        public void unregisterNetworkActivityListener(@NonNull INetworkActivityListener l) {
+            mNetworkActivityListeners.unregister(l);
+        }
+
+        public void dump(IndentingPrintWriter pw) {
+            synchronized (mActiveIdleTimers) {
+                pw.print("mNetworkActive="); pw.println(mNetworkActive);
+                pw.println("Idle timers:");
+                for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) {
+                    pw.print("  "); pw.print(ent.getKey()); pw.println(":");
+                    final IdleTimerParams params = ent.getValue();
+                    pw.print("    timeout="); pw.print(params.timeout);
+                    pw.print(" type="); pw.println(params.transportType);
+                }
+            }
+        }
     }
 
     /**
@@ -8883,7 +9037,8 @@
 
     private void updateDefaultNetworksForOemNetworkPreference(
             @NonNull final Set<NetworkRequestInfo> nris) {
-        handleRemoveNetworkRequests(mDefaultNetworkRequests);
+        // Pass in a defensive copy as this collection will be updated on remove.
+        handleRemoveNetworkRequests(new ArraySet<>(mDefaultNetworkRequests));
         addPerAppDefaultNetworkRequests(nris);
     }
 
diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java
index 88ce220..e29e894 100644
--- a/services/core/java/com/android/server/DynamicSystemService.java
+++ b/services/core/java/com/android/server/DynamicSystemService.java
@@ -28,6 +28,7 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.image.IDynamicSystemService;
+import android.os.storage.DiskInfo;
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
 import android.util.Slog;
@@ -40,6 +41,7 @@
  */
 public class DynamicSystemService extends IDynamicSystemService.Stub {
     private static final String TAG = "DynamicSystemService";
+    private static final long MINIMUM_SD_MB = (30L << 10);
     private static final int GSID_ROUGH_TIMEOUT_MS = 8192;
     private static final String PATH_DEFAULT = "/data/gsi/";
     private Context mContext;
@@ -95,6 +97,13 @@
                 if (!volume.isMountedWritable()) {
                     continue;
                 }
+                DiskInfo disk = volume.getDisk();
+                long mega = disk.size >> 20;
+                Slog.i(TAG, volume.getPath() + ": " + mega + " MB");
+                if (mega < MINIMUM_SD_MB) {
+                    Slog.i(TAG, volume.getPath() + ": insufficient storage");
+                    continue;
+                }
                 File sd_internal = volume.getInternalPathForUser(userId);
                 if (sd_internal != null) {
                     path = new File(sd_internal, dsuSlot).getPath();
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index b48bc90..81d4b9d 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -48,7 +48,6 @@
 import android.net.util.NetdService;
 import android.os.Binder;
 import android.os.IBinder;
-import android.os.INetworkManagementService;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
@@ -64,6 +63,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
+import com.android.net.module.util.NetdUtils;
 
 import libcore.io.IoUtils;
 
@@ -117,9 +117,6 @@
     /* Binder context for this service */
     private final Context mContext;
 
-    /* NetworkManager instance */
-    private final INetworkManagementService mNetworkManager;
-
     /**
      * The next non-repeating global ID for tracking resources between users, this service, and
      * kernel data structures. Accessing this variable is not thread safe, so it is only read or
@@ -1014,13 +1011,13 @@
      *
      * @param context Binder context for this service
      */
-    private IpSecService(Context context, INetworkManagementService networkManager) {
-        this(context, networkManager, IpSecServiceConfiguration.GETSRVINSTANCE);
+    private IpSecService(Context context) {
+        this(context, IpSecServiceConfiguration.GETSRVINSTANCE);
     }
 
-    static IpSecService create(Context context, INetworkManagementService networkManager)
+    static IpSecService create(Context context)
             throws InterruptedException {
-        final IpSecService service = new IpSecService(context, networkManager);
+        final IpSecService service = new IpSecService(context);
         service.connectNativeNetdService();
         return service;
     }
@@ -1034,11 +1031,9 @@
 
     /** @hide */
     @VisibleForTesting
-    public IpSecService(Context context, INetworkManagementService networkManager,
-            IpSecServiceConfiguration config) {
+    public IpSecService(Context context, IpSecServiceConfiguration config) {
         this(
                 context,
-                networkManager,
                 config,
                 (fd, uid) -> {
                     try {
@@ -1052,10 +1047,9 @@
 
     /** @hide */
     @VisibleForTesting
-    public IpSecService(Context context, INetworkManagementService networkManager,
-            IpSecServiceConfiguration config, UidFdTagger uidFdTagger) {
+    public IpSecService(Context context, IpSecServiceConfiguration config,
+            UidFdTagger uidFdTagger) {
         mContext = context;
-        mNetworkManager = Objects.requireNonNull(networkManager);
         mSrvConfig = config;
         mUidFdTagger = uidFdTagger;
     }
@@ -1335,7 +1329,7 @@
             netd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId);
 
             Binder.withCleanCallingIdentity(() -> {
-                mNetworkManager.setInterfaceUp(intfName);
+                NetdUtils.setInterfaceUp(netd, intfName);
             });
 
             for (int selAddrFamily : ADDRESS_FAMILIES) {
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index d30a640..4405408 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -69,7 +69,6 @@
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.INetworkActivityListener;
 import android.os.INetworkManagementService;
 import android.os.Process;
 import android.os.RemoteCallbackList;
@@ -80,7 +79,6 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.Trace;
-import android.telephony.DataConnectionRealTimeInfo;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Slog;
@@ -229,32 +227,9 @@
     @GuardedBy("mQuotaLock")
     private volatile boolean mDataSaverMode;
 
-    private final Object mIdleTimerLock = new Object();
-    /** Set of interfaces with active idle timers. */
-    private static class IdleTimerParams {
-        public final int timeout;
-        public final int type;
-        public int networkCount;
-
-        IdleTimerParams(int timeout, int type) {
-            this.timeout = timeout;
-            this.type = type;
-            this.networkCount = 1;
-        }
-    }
-    private HashMap<String, IdleTimerParams> mActiveIdleTimers = Maps.newHashMap();
-
     private volatile boolean mFirewallEnabled;
     private volatile boolean mStrictEnabled;
 
-    private boolean mMobileActivityFromRadio = false;
-    private int mLastPowerStateFromRadio = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
-    private int mLastPowerStateFromWifi = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
-
-    private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners =
-            new RemoteCallbackList<>();
-    private boolean mNetworkActive;
-
     /**
      * Constructs a new NetworkManagementService instance
      *
@@ -397,55 +372,8 @@
      */
     private void notifyInterfaceClassActivity(int type, boolean isActive, long tsNanos,
             int uid) {
-        final boolean isMobile = ConnectivityManager.isNetworkTypeMobile(type);
-        int powerState = isActive
-                ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
-                : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
-        if (isMobile) {
-            if (mLastPowerStateFromRadio != powerState) {
-                mLastPowerStateFromRadio = powerState;
-                try {
-                    // TODO: The interface changes that comes from netd are handled by BSS itself.
-                    // There are still events caused by setting or removing idle timer, so keep
-                    // reporting from here until setting idler timer moved to CS.
-                    getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos, uid);
-                } catch (RemoteException e) {
-                }
-            }
-        }
-
-        if (ConnectivityManager.isNetworkTypeWifi(type)) {
-            if (mLastPowerStateFromWifi != powerState) {
-                mLastPowerStateFromWifi = powerState;
-                try {
-                    // TODO: The interface changes that comes from netd are handled by BSS itself.
-                    // There are still events caused by setting or removing idle timer, so keep
-                    // reporting from here until setting idler timer moved to CS.
-                    getBatteryStats().noteWifiRadioPowerState(powerState, tsNanos, uid);
-                } catch (RemoteException e) {
-                }
-            }
-        }
-
-        final boolean active = isActive;
         invokeForAllObservers(o -> o.interfaceClassDataActivityChanged(
-                type, active, tsNanos, uid));
-
-        boolean report = false;
-        synchronized (mIdleTimerLock) {
-            if (mActiveIdleTimers.isEmpty()) {
-                // If there are no idle timers, we are not monitoring activity, so we
-                // are always considered active.
-                isActive = true;
-            }
-            if (mNetworkActive != isActive) {
-                mNetworkActive = isActive;
-                report = isActive;
-            }
-        }
-        if (report) {
-            reportNetworkActive();
-        }
+                type, isActive, tsNanos, uid));
     }
 
     @Override
@@ -1122,60 +1050,6 @@
     }
 
     @Override
-    public void addIdleTimer(String iface, int timeout, final int type) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-
-        if (DBG) Slog.d(TAG, "Adding idletimer");
-
-        synchronized (mIdleTimerLock) {
-            IdleTimerParams params = mActiveIdleTimers.get(iface);
-            if (params != null) {
-                // the interface already has idletimer, update network count
-                params.networkCount++;
-                return;
-            }
-
-            try {
-                mNetdService.idletimerAddInterface(iface, timeout, Integer.toString(type));
-            } catch (RemoteException | ServiceSpecificException e) {
-                throw new IllegalStateException(e);
-            }
-            mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type));
-
-            // Networks start up.
-            if (ConnectivityManager.isNetworkTypeMobile(type)) {
-                mNetworkActive = false;
-            }
-            mDaemonHandler.post(() -> notifyInterfaceClassActivity(type, true,
-                    SystemClock.elapsedRealtimeNanos(), -1));
-        }
-    }
-
-    @Override
-    public void removeIdleTimer(String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-
-        if (DBG) Slog.d(TAG, "Removing idletimer");
-
-        synchronized (mIdleTimerLock) {
-            final IdleTimerParams params = mActiveIdleTimers.get(iface);
-            if (params == null || --(params.networkCount) > 0) {
-                return;
-            }
-
-            try {
-                mNetdService.idletimerRemoveInterface(iface,
-                        params.timeout, Integer.toString(params.type));
-            } catch (RemoteException | ServiceSpecificException e) {
-                throw new IllegalStateException(e);
-            }
-            mActiveIdleTimers.remove(iface);
-            mDaemonHandler.post(() -> notifyInterfaceClassActivity(params.type, false,
-                    SystemClock.elapsedRealtimeNanos(), -1));
-        }
-    }
-
-    @Override
     public void setInterfaceQuota(String iface, long quotaBytes) {
         NetworkStack.checkNetworkStackPermission(mContext);
 
@@ -1813,44 +1687,9 @@
     }
 
     @Override
-    public void registerNetworkActivityListener(INetworkActivityListener listener) {
-        mNetworkActivityListeners.register(listener);
-    }
-
-    @Override
-    public void unregisterNetworkActivityListener(INetworkActivityListener listener) {
-        mNetworkActivityListeners.unregister(listener);
-    }
-
-    @Override
-    public boolean isNetworkActive() {
-        synchronized (mNetworkActivityListeners) {
-            return mNetworkActive || mActiveIdleTimers.isEmpty();
-        }
-    }
-
-    private void reportNetworkActive() {
-        final int length = mNetworkActivityListeners.beginBroadcast();
-        try {
-            for (int i = 0; i < length; i++) {
-                try {
-                    mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive();
-                } catch (RemoteException | RuntimeException e) {
-                }
-            }
-        } finally {
-            mNetworkActivityListeners.finishBroadcast();
-        }
-    }
-
-    @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
-        pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio);
-                pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio);
-        pw.print("mNetworkActive="); pw.println(mNetworkActive);
-
         synchronized (mQuotaLock) {
             pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString());
             pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString());
@@ -1882,17 +1721,6 @@
                     mUidFirewallRestrictedRules);
         }
 
-        synchronized (mIdleTimerLock) {
-            pw.println("Idle timers:");
-            for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) {
-                pw.print("  "); pw.print(ent.getKey()); pw.println(":");
-                IdleTimerParams params = ent.getValue();
-                pw.print("    timeout="); pw.print(params.timeout);
-                pw.print(" type="); pw.print(params.type);
-                pw.print(" networkCount="); pw.println(params.networkCount);
-            }
-        }
-
         pw.print("Firewall enabled: "); pw.println(mFirewallEnabled);
         pw.print("Netd service status: " );
         if (mNetdService == null) {
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 67f6ec9..f5c2aac 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -259,10 +259,7 @@
             mIsPackagesReady = true;
             mHealthCheckController.setCallbacks(packageName -> onHealthCheckPassed(packageName),
                     packages -> onSupportedPackages(packages),
-                    () -> {
-                            syncRequestsAsync();
-                            mSyncRequired = true;
-                    });
+                    this::onSyncRequestNotified);
             setPropertyChangedListenerLocked();
             updateConfigs();
             registerConnectivityModuleHealthListener();
@@ -537,6 +534,7 @@
         synchronized (mLock) {
             mIsHealthCheckEnabled = enabled;
             mHealthCheckController.setEnabled(enabled);
+            mSyncRequired = true;
             // Prune to update internal state whenever health check is enabled/disabled
             syncState("health check state " + (enabled ? "enabled" : "disabled"));
         }
@@ -788,6 +786,13 @@
         }
     }
 
+    private void onSyncRequestNotified() {
+        synchronized (mLock) {
+            mSyncRequired = true;
+            syncRequestsAsync();
+        }
+    }
+
     @GuardedBy("mLock")
     private Set<String> getPackagesPendingHealthChecksLocked() {
         Set<String> packages = new ArraySet<>();
diff --git a/services/core/java/com/android/server/SensorPrivacyService.java b/services/core/java/com/android/server/SensorPrivacyService.java
index edaf6a90..f2782f6 100644
--- a/services/core/java/com/android/server/SensorPrivacyService.java
+++ b/services/core/java/com/android/server/SensorPrivacyService.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import static android.Manifest.permission.MANAGE_SENSOR_PRIVACY;
 import static android.app.ActivityManager.RunningServiceInfo;
 import static android.app.ActivityManager.RunningTaskInfo;
 import static android.app.AppOpsManager.MODE_ALLOWED;
@@ -24,9 +25,9 @@
 import static android.content.Intent.EXTRA_PACKAGE_NAME;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.hardware.SensorPrivacyManager.EXTRA_SENSOR;
+import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
+import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
 import static android.os.UserHandle.USER_SYSTEM;
-import static android.service.SensorPrivacyIndividualEnabledSensorProto.CAMERA;
-import static android.service.SensorPrivacyIndividualEnabledSensorProto.MICROPHONE;
 import static android.service.SensorPrivacyIndividualEnabledSensorProto.UNKNOWN;
 
 import android.annotation.NonNull;
@@ -197,18 +198,20 @@
                                     Intent.EXTRA_USER)).getIdentifier(),
                             intent.getIntExtra(EXTRA_SENSOR, UNKNOWN), false);
                 }
-            }, new IntentFilter(ACTION_DISABLE_INDIVIDUAL_SENSOR_PRIVACY));
+            }, new IntentFilter(ACTION_DISABLE_INDIVIDUAL_SENSOR_PRIVACY),
+                    MANAGE_SENSOR_PRIVACY, null);
         }
 
         @Override
-        public void onOpStarted(int code, int uid, String packageName,
+        public void onOpStarted(int code, int uid, String packageName, String attributionTag,
                 @AppOpsManager.OpFlags int flags, @AppOpsManager.Mode int result) {
-            onOpNoted(code, uid, packageName, flags, result);
+            onOpNoted(code, uid, packageName, attributionTag, flags, result);
         }
 
         @Override
         public void onOpNoted(int code, int uid, String packageName,
-                @AppOpsManager.OpFlags int flags, @AppOpsManager.Mode int result) {
+                String attributionTag, @AppOpsManager.OpFlags int flags,
+                @AppOpsManager.Mode int result) {
             if (result != MODE_ALLOWED || (flags & AppOpsManager.OP_FLAGS_ALL_TRUSTED) == 0) {
                 return;
             }
@@ -403,12 +406,12 @@
          */
         @Override
         public void setSensorPrivacy(boolean enable) {
+            enforceManageSensorPrivacyPermission();
             // Keep the state consistent between all users to make it a single global state
             forAllUsers(userId -> setSensorPrivacy(userId, enable));
         }
 
         private void setSensorPrivacy(@UserIdInt int userId, boolean enable) {
-            enforceSensorPrivacyPermission();
             synchronized (mLock) {
                 mEnabled.put(userId, enable);
                 persistSensorPrivacyStateLocked();
@@ -418,7 +421,7 @@
 
         @Override
         public void setIndividualSensorPrivacy(@UserIdInt int userId, int sensor, boolean enable) {
-            enforceSensorPrivacyPermission();
+            enforceManageSensorPrivacyPermission();
             synchronized (mLock) {
                 SparseBooleanArray userIndividualEnabled = mIndividualEnabled.get(userId,
                         new SparseBooleanArray());
@@ -445,6 +448,7 @@
         @Override
         public void setIndividualSensorPrivacyForProfileGroup(@UserIdInt int userId, int sensor,
                 boolean enable) {
+            enforceManageSensorPrivacyPermission();
             int parentId = mUserManagerInternal.getProfileParentId(userId);
             forAllUsers(userId2 -> {
                 if (parentId == mUserManagerInternal.getProfileParentId(userId2)) {
@@ -457,14 +461,27 @@
          * Enforces the caller contains the necessary permission to change the state of sensor
          * privacy.
          */
-        private void enforceSensorPrivacyPermission() {
-            if (mContext.checkCallingOrSelfPermission(
-                    android.Manifest.permission.MANAGE_SENSOR_PRIVACY) == PERMISSION_GRANTED) {
+        private void enforceManageSensorPrivacyPermission() {
+            enforcePermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY,
+                    "Changing sensor privacy requires the following permission: "
+                            + MANAGE_SENSOR_PRIVACY);
+        }
+
+        /**
+         * Enforces the caller contains the necessary permission to observe changes to the sate of
+         * sensor privacy.
+         */
+        private void enforceObserveSensorPrivacyPermission() {
+            enforcePermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY,
+                    "Observing sensor privacy changes requires the following permission: "
+                            + android.Manifest.permission.OBSERVE_SENSOR_PRIVACY);
+        }
+
+        private void enforcePermission(String permission, String message) {
+            if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) {
                 return;
             }
-            throw new SecurityException(
-                    "Changing sensor privacy requires the following permission: "
-                            + android.Manifest.permission.MANAGE_SENSOR_PRIVACY);
+            throw new SecurityException(message);
         }
 
         /**
@@ -472,6 +489,7 @@
          */
         @Override
         public boolean isSensorPrivacyEnabled() {
+            enforceObserveSensorPrivacyPermission();
             return isSensorPrivacyEnabled(USER_SYSTEM);
         }
 
@@ -483,6 +501,7 @@
 
         @Override
         public boolean isIndividualSensorPrivacyEnabled(@UserIdInt int userId, int sensor) {
+            enforceObserveSensorPrivacyPermission();
             synchronized (mLock) {
                 SparseBooleanArray states = mIndividualEnabled.get(userId);
                 if (states == null) {
@@ -700,6 +719,7 @@
          */
         @Override
         public void addSensorPrivacyListener(ISensorPrivacyListener listener) {
+            enforceObserveSensorPrivacyPermission();
             if (listener == null) {
                 throw new NullPointerException("listener cannot be null");
             }
@@ -712,6 +732,7 @@
         @Override
         public void addIndividualSensorPrivacyListener(int userId, int sensor,
                 ISensorPrivacyListener listener) {
+            enforceObserveSensorPrivacyPermission();
             if (listener == null) {
                 throw new NullPointerException("listener cannot be null");
             }
@@ -723,6 +744,7 @@
          */
         @Override
         public void removeSensorPrivacyListener(ISensorPrivacyListener listener) {
+            enforceObserveSensorPrivacyPermission();
             if (listener == null) {
                 throw new NullPointerException("listener cannot be null");
             }
@@ -732,6 +754,7 @@
         @Override
         public void suppressIndividualSensorPrivacyReminders(int userId, String packageName,
                 IBinder token, boolean suppress) {
+            enforceManageSensorPrivacyPermission();
             Objects.requireNonNull(packageName);
             Objects.requireNonNull(token);
 
@@ -883,13 +906,13 @@
         }
 
         /**
-         * Convert a string into a {@link SensorPrivacyManager.IndividualSensor id}.
+         * Convert a string into a {@link SensorPrivacyManager.Sensors.Sensor id}.
          *
          * @param sensor The name to convert
          *
          * @return The id corresponding to the name
          */
-        private @SensorPrivacyManager.IndividualSensor int sensorStrToId(@Nullable String sensor) {
+        private @SensorPrivacyManager.Sensors.Sensor int sensorStrToId(@Nullable String sensor) {
             if (sensor == null) {
                 return UNKNOWN;
             }
@@ -947,7 +970,7 @@
                                 return -1;
                             }
 
-                            enforceSensorPrivacyPermission();
+                            enforceManageSensorPrivacyPermission();
 
                             synchronized (mLock) {
                                 SparseBooleanArray individualEnabled =
diff --git a/services/core/java/com/android/server/ServiceWatcher.java b/services/core/java/com/android/server/ServiceWatcher.java
index c2d8fa2..8a2894c 100644
--- a/services/core/java/com/android/server/ServiceWatcher.java
+++ b/services/core/java/com/android/server/ServiceWatcher.java
@@ -45,14 +45,18 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.util.ArrayMap;
 import android.util.Log;
 
+import com.android.internal.annotations.Immutable;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.pooled.PooledLambda;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.function.Predicate;
 
@@ -87,26 +91,30 @@
     /** Function to run on binder interface when first bound. */
     public interface OnBindRunner {
         /** Called to run client code with the binder. */
-        void run(IBinder binder, ComponentName service) throws RemoteException;
+        void run(IBinder binder, BoundService service) throws RemoteException;
     }
 
     /**
      * Information on the service ServiceWatcher has selected as the best option for binding.
      */
-    private static final class ServiceInfo implements Comparable<ServiceInfo> {
+    @Immutable
+    public static final class BoundService implements Comparable<BoundService> {
 
-        public static final ServiceInfo NONE = new ServiceInfo(Integer.MIN_VALUE, null,
-                UserHandle.USER_NULL, false);
+        public static final BoundService NONE = new BoundService(Integer.MIN_VALUE, null,
+                false, null, -1);
 
         public final int version;
-        @Nullable public final ComponentName component;
-        @UserIdInt public final int userId;
+        @Nullable
+        public final ComponentName component;
         public final boolean serviceIsMultiuser;
+        public final int uid;
+        @Nullable
+        public final Bundle metadata;
 
-        ServiceInfo(ResolveInfo resolveInfo, int currentUserId) {
+        BoundService(ResolveInfo resolveInfo) {
             Preconditions.checkArgument(resolveInfo.serviceInfo.getComponentName() != null);
 
-            Bundle metadata = resolveInfo.serviceInfo.metaData;
+            metadata = resolveInfo.serviceInfo.metaData;
             if (metadata != null) {
                 version = metadata.getInt(EXTRA_SERVICE_VERSION, Integer.MIN_VALUE);
                 serviceIsMultiuser = metadata.getBoolean(EXTRA_SERVICE_IS_MULTIUSER, false);
@@ -116,16 +124,17 @@
             }
 
             component = resolveInfo.serviceInfo.getComponentName();
-            userId = serviceIsMultiuser ? UserHandle.USER_SYSTEM : currentUserId;
+            uid = resolveInfo.serviceInfo.applicationInfo.uid;
         }
 
-        private ServiceInfo(int version, @Nullable ComponentName component, int userId,
-                boolean serviceIsMultiuser) {
+        private BoundService(int version, @Nullable ComponentName component,
+                boolean serviceIsMultiuser, @Nullable Bundle metadata, int uid) {
             Preconditions.checkArgument(component != null || version == Integer.MIN_VALUE);
             this.version = version;
             this.component = component;
-            this.userId = userId;
             this.serviceIsMultiuser = serviceIsMultiuser;
+            this.metadata = metadata;
+            this.uid = uid;
         }
 
         public @Nullable String getPackageName() {
@@ -137,21 +146,21 @@
             if (this == o) {
                 return true;
             }
-            if (!(o instanceof ServiceInfo)) {
+            if (!(o instanceof BoundService)) {
                 return false;
             }
-            ServiceInfo that = (ServiceInfo) o;
-            return version == that.version && userId == that.userId
+            BoundService that = (BoundService) o;
+            return version == that.version && uid == that.uid
                     && Objects.equals(component, that.component);
         }
 
         @Override
         public int hashCode() {
-            return Objects.hash(version, component, userId);
+            return Objects.hash(version, component, uid);
         }
 
         @Override
-        public int compareTo(ServiceInfo that) {
+        public int compareTo(BoundService that) {
             // ServiceInfos with higher version numbers always win (having a version number >
             // MIN_VALUE implies having a non-null component). if version numbers are equal, a
             // non-null component wins over a null component. if the version numbers are equal and
@@ -164,10 +173,11 @@
                 } else if (component != null && that.component == null) {
                     ret = 1;
                 } else {
-                    if (userId != UserHandle.USER_SYSTEM && that.userId == UserHandle.USER_SYSTEM) {
+                    if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM
+                            && UserHandle.getUserId(that.uid) == UserHandle.USER_SYSTEM) {
                         ret = -1;
-                    } else if (userId == UserHandle.USER_SYSTEM
-                            && that.userId != UserHandle.USER_SYSTEM) {
+                    } else if (UserHandle.getUserId(uid) == UserHandle.USER_SYSTEM
+                            && UserHandle.getUserId(that.uid) != UserHandle.USER_SYSTEM) {
                         ret = 1;
                     }
                 }
@@ -180,7 +190,8 @@
             if (component == null) {
                 return "none";
             } else {
-                return component.toShortString() + "@" + version + "[u" + userId + "]";
+                return component.toShortString() + "@" + version + "[u"
+                        + UserHandle.getUserId(uid) + "]";
             }
         }
     }
@@ -227,17 +238,23 @@
         }
     };
 
-    @Nullable private final OnBindRunner mOnBind;
-    @Nullable private final Runnable mOnUnbind;
+    // read/write from handler thread only
+    private final Map<ComponentName, BoundService> mPendingBinds = new ArrayMap<>();
 
-    // write from caller thread only, read anywhere
-    private volatile boolean mRegistered;
+    @Nullable
+    private final OnBindRunner mOnBind;
+
+    @Nullable
+    private final Runnable mOnUnbind;
+
+    // read/write from handler thread only
+    private boolean mRegistered;
 
     // read/write from handler thread only
     private int mCurrentUserId;
 
     // write from handler thread only, read anywhere
-    private volatile ServiceInfo mTargetService;
+    private volatile BoundService mTargetService;
     private volatile IBinder mBinder;
 
     public ServiceWatcher(Context context, String action,
@@ -274,7 +291,7 @@
 
         mCurrentUserId = UserHandle.USER_NULL;
 
-        mTargetService = ServiceInfo.NONE;
+        mTargetService = BoundService.NONE;
         mBinder = null;
     }
 
@@ -299,6 +316,11 @@
      * Starts the process of determining the best matching service and maintaining a binding to it.
      */
     public void register() {
+        mHandler.sendMessage(PooledLambda.obtainMessage(ServiceWatcher::registerInternal,
+                ServiceWatcher.this));
+    }
+
+    private void registerInternal() {
         Preconditions.checkState(!mRegistered);
 
         mPackageMonitor.register(mContext, UserHandle.ALL, true, mHandler);
@@ -309,6 +331,8 @@
         mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, intentFilter, null,
                 mHandler);
 
+        // TODO: This makes the behavior of the class unpredictable as the caller needs
+        // to know the internal impl detail that calling register would pick the current user.
         mCurrentUserId = ActivityManager.getCurrentUser();
 
         mRegistered = true;
@@ -320,6 +344,11 @@
      * Stops the process of determining the best matching service and releases any binding.
      */
     public void unregister() {
+        mHandler.sendMessage(PooledLambda.obtainMessage(ServiceWatcher::unregisterInternal,
+                ServiceWatcher.this));
+    }
+
+    private void unregisterInternal() {
         Preconditions.checkState(mRegistered);
 
         mRegistered = false;
@@ -333,7 +362,7 @@
     private void onBestServiceChanged(boolean forceRebind) {
         Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
 
-        ServiceInfo bestServiceInfo = ServiceInfo.NONE;
+        BoundService bestServiceInfo = BoundService.NONE;
 
         if (mRegistered) {
             List<ResolveInfo> resolveInfos = mContext.getPackageManager().queryIntentServicesAsUser(
@@ -344,7 +373,7 @@
                 if (!mServiceCheckPredicate.test(resolveInfo)) {
                     continue;
                 }
-                ServiceInfo serviceInfo = new ServiceInfo(resolveInfo, mCurrentUserId);
+                BoundService serviceInfo = new BoundService(resolveInfo);
                 if (serviceInfo.compareTo(bestServiceInfo) > 0) {
                     bestServiceInfo = serviceInfo;
                 }
@@ -356,21 +385,22 @@
         }
     }
 
-    private void rebind(ServiceInfo newServiceInfo) {
+    private void rebind(BoundService newServiceInfo) {
         Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
 
-        if (!mTargetService.equals(ServiceInfo.NONE)) {
+        if (!mTargetService.equals(BoundService.NONE)) {
             if (D) {
                 Log.d(TAG, "[" + mIntent.getAction() + "] unbinding from " + mTargetService);
             }
 
             mContext.unbindService(this);
             onServiceDisconnected(mTargetService.component);
-            mTargetService = ServiceInfo.NONE;
+            mPendingBinds.remove(mTargetService.component);
+            mTargetService = BoundService.NONE;
         }
 
         mTargetService = newServiceInfo;
-        if (mTargetService.equals(ServiceInfo.NONE)) {
+        if (mTargetService.equals(BoundService.NONE)) {
             return;
         }
 
@@ -381,10 +411,12 @@
         Intent bindIntent = new Intent(mIntent).setComponent(mTargetService.component);
         if (!mContext.bindServiceAsUser(bindIntent, this,
                 BIND_AUTO_CREATE | BIND_NOT_FOREGROUND | BIND_NOT_VISIBLE,
-                mHandler, UserHandle.of(mTargetService.userId))) {
-            mTargetService = ServiceInfo.NONE;
+                mHandler, UserHandle.of(UserHandle.getUserId(mTargetService.uid)))) {
+            mTargetService = BoundService.NONE;
             Log.e(TAG, getLogPrefix() + " unexpected bind failure - retrying later");
             mHandler.postDelayed(() -> onBestServiceChanged(false), RETRY_DELAY_MS);
+        } else {
+            mPendingBinds.put(mTargetService.component, mTargetService);
         }
     }
 
@@ -397,10 +429,15 @@
             Log.d(TAG, getLogPrefix() + " connected to " + component.toShortString());
         }
 
+        final BoundService boundService = mPendingBinds.remove(component);
+        if (boundService == null) {
+            return;
+        }
+
         mBinder = binder;
         if (mOnBind != null) {
             try {
-                mOnBind.run(binder, component);
+                mOnBind.run(binder, boundService);
             } catch (RuntimeException | RemoteException e) {
                 // binders may propagate some specific non-RemoteExceptions from the other side
                 // through the binder as well - we cannot allow those to crash the system server
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 2f98199..233a50d 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -51,6 +51,7 @@
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
+import android.app.AnrController;
 import android.app.AppOpsManager;
 import android.app.IActivityManager;
 import android.app.KeyguardManager;
@@ -938,14 +939,29 @@
 
         if (transcodeEnabled) {
             LocalServices.getService(ActivityManagerInternal.class)
-                    .registerAnrController((packageName, uid) -> {
-                        try {
-                            return mStorageSessionController.getAnrDelayMillis(packageName, uid);
-                        } catch (ExternalStorageServiceException e) {
-                            Log.e(TAG, "Failed to get ANR delay for " + packageName, e);
-                            return 0;
-                        }
-                    });
+                .registerAnrController(new ExternalStorageServiceAnrController());
+        }
+    }
+
+    // TODO(b/170486601): Check transcoding status based on events pushed from the MediaProvider
+    private class ExternalStorageServiceAnrController implements AnrController {
+        @Override
+        public long getAnrDelayMillis(String packageName, int uid) {
+            int delay = SystemProperties.getInt("sys.fuse.transcode_anr_delay", 0);
+            Log.d(TAG, "getAnrDelayMillis: " + packageName + ". Delaying for " + delay + "ms");
+            return delay;
+        }
+
+        @Override
+        public void onAnrDelayStarted(String packageName, int uid) {
+            Log.d(TAG, "onAnrDelayStarted: " + packageName);
+        }
+
+        @Override
+        public boolean onAnrDelayCompleted(String packageName, int uid) {
+            boolean show = SystemProperties.getBoolean("sys.fuse.transcode_anr_dialog_show", true);
+            Log.d(TAG, "onAnrDelayCompleted: " + packageName + ". Show: " + show);
+            return show;
         }
     }
 
@@ -3322,6 +3338,39 @@
         }
     }
 
+    @Override
+    public void notifyAppIoBlocked(String volumeUuid, int uid, int tid, int reason) {
+        enforceExternalStorageService();
+
+        mStorageSessionController.notifyAppIoBlocked(volumeUuid, uid, tid, reason);
+    }
+
+    @Override
+    public void notifyAppIoResumed(String volumeUuid, int uid, int tid, int reason) {
+        enforceExternalStorageService();
+
+        mStorageSessionController.notifyAppIoResumed(volumeUuid, uid, tid, reason);
+    }
+
+    private boolean isAppIoBlocked(int uid) {
+        return mStorageSessionController.isAppIoBlocked(uid);
+    }
+
+    /**
+     * Enforces that the caller is the {@link ExternalStorageService}
+     *
+     * @throws SecurityException if the caller doesn't have the
+     * {@link android.Manifest.permission.WRITE_MEDIA_STORAGE} permission or is not the
+     * {@link ExternalStorageService}
+     */
+    private void enforceExternalStorageService() {
+        enforcePermission(android.Manifest.permission.WRITE_MEDIA_STORAGE);
+        int callingAppId = UserHandle.getAppId(Binder.getCallingUid());
+        if (callingAppId != mMediaStoreAuthorityAppId) {
+            throw new SecurityException("Only the ExternalStorageService is permitted");
+        }
+    }
+
     /** Not thread safe */
     class AppFuseMountScope extends AppFuseBridge.MountScope {
         private boolean mMounted = false;
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index b09b6ca..5a5f1a3 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -313,9 +313,9 @@
 
     private List<PhysicalChannelConfig> mPhysicalChannelConfigs;
 
-    private boolean mIsDataEnabled = false;
+    private boolean[] mIsDataEnabled;
 
-    private int mDataEnabledReason;
+    private int[] mDataEnabledReason;
 
     private Map<Integer, Long> mAllowedNetworkTypesList;
 
@@ -524,6 +524,8 @@
         mOutgoingCallEmergencyNumber = copyOf(mOutgoingCallEmergencyNumber, mNumPhones);
         mOutgoingSmsEmergencyNumber = copyOf(mOutgoingSmsEmergencyNumber, mNumPhones);
         mTelephonyDisplayInfos = copyOf(mTelephonyDisplayInfos, mNumPhones);
+        mIsDataEnabled= copyOf(mIsDataEnabled, mNumPhones);
+        mDataEnabledReason = copyOf(mDataEnabledReason, mNumPhones);
 
         // ds -> ss switch.
         if (mNumPhones < oldNumPhones) {
@@ -565,6 +567,8 @@
             mPreciseDataConnectionStates.add(new ArrayMap<>());
             mBarringInfo.add(i, new BarringInfo());
             mTelephonyDisplayInfos[i] = null;
+            mIsDataEnabled[i] = false;
+            mDataEnabledReason[i] = TelephonyManager.DATA_ENABLED_REASON_USER;
             mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig.Builder().build());
         }
     }
@@ -626,6 +630,8 @@
         mTelephonyDisplayInfos = new TelephonyDisplayInfo[numPhones];
         mPhysicalChannelConfigs = new ArrayList<>();
         mAllowedNetworkTypesList = new HashMap<>();
+        mIsDataEnabled = new boolean[numPhones];
+        mDataEnabledReason = new int[numPhones];
         for (int i = 0; i < numPhones; i++) {
             mCallState[i] =  TelephonyManager.CALL_STATE_IDLE;
             mDataActivity[i] = TelephonyManager.DATA_ACTIVITY_NONE;
@@ -655,6 +661,8 @@
             mPreciseDataConnectionStates.add(new ArrayMap<>());
             mBarringInfo.add(i, new BarringInfo());
             mTelephonyDisplayInfos[i] = null;
+            mIsDataEnabled[i] = false;
+            mDataEnabledReason[i] = TelephonyManager.DATA_ENABLED_REASON_USER;
             mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig.Builder().build());
         }
 
@@ -1150,7 +1158,8 @@
                 if (events.contains(
                         PhoneStateListener.EVENT_DATA_ENABLED_CHANGED)) {
                     try {
-                        r.callback.onDataEnabledChanged(mIsDataEnabled, mDataEnabledReason);
+                        r.callback.onDataEnabledChanged(
+                                mIsDataEnabled[phoneId], mDataEnabledReason[phoneId]);
                     } catch (RemoteException ex) {
                         remove(r.binder);
                     }
@@ -2370,30 +2379,36 @@
     /**
      * Notify that the data enabled has changed.
      *
+     * @param phoneId the phone id.
+     * @param subId the subId.
      * @param enabled True if data is enabled, otherwise disabled.
      * @param reason  Reason for data enabled/disabled. See {@code DATA_*} in
      *                {@link TelephonyManager}.
      */
-    public void notifyDataEnabled(boolean enabled,
+    public void notifyDataEnabled(int phoneId, int subId, boolean enabled,
                                   @TelephonyManager.DataEnabledReason int reason) {
         if (!checkNotifyPermission("notifyDataEnabled()")) {
             return;
         }
 
         if (VDBG) {
-            log("notifyDataEnabled: enabled=" + enabled + " reason=" + reason);
+            log("notifyDataEnabled: PhoneId=" + phoneId + " subId=" + subId +
+                    " enabled=" + enabled + " reason=" + reason);
         }
 
-        mIsDataEnabled = enabled;
-        mDataEnabledReason = reason;
         synchronized (mRecords) {
-            for (Record r : mRecords) {
-                if (r.matchPhoneStateListenerEvent(
-                        PhoneStateListener.EVENT_DATA_ENABLED_CHANGED)) {
-                    try {
-                        r.callback.onDataEnabledChanged(enabled, reason);
-                    } catch (RemoteException ex) {
-                        mRemoveList.add(r.binder);
+            if (validatePhoneId(phoneId)) {
+                mIsDataEnabled[phoneId] = enabled;
+                mDataEnabledReason[phoneId] = reason;
+                for (Record r : mRecords) {
+                    if (r.matchPhoneStateListenerEvent(
+                            PhoneStateListener.EVENT_DATA_ENABLED_CHANGED)
+                            && idMatch(r.subId, subId, phoneId)) {
+                        try {
+                            r.callback.onDataEnabledChanged(enabled, reason);
+                        } catch (RemoteException ex) {
+                            mRemoveList.add(r.binder);
+                        }
                     }
                 }
             }
@@ -2481,6 +2496,8 @@
                 pw.println("mOutgoingSmsEmergencyNumber=" + mOutgoingSmsEmergencyNumber[i]);
                 pw.println("mBarringInfo=" + mBarringInfo.get(i));
                 pw.println("mTelephonyDisplayInfo=" + mTelephonyDisplayInfos[i]);
+                pw.println("mIsDataEnabled=" + mIsDataEnabled);
+                pw.println("mDataEnabledReason=" + mDataEnabledReason);
                 pw.decreaseIndent();
             }
             pw.println("mCarrierNetworkChangeState=" + mCarrierNetworkChangeState);
@@ -2491,8 +2508,6 @@
             pw.println("mDefaultPhoneId=" + mDefaultPhoneId);
             pw.println("mDefaultSubId=" + mDefaultSubId);
             pw.println("mPhysicalChannelConfigs=" + mPhysicalChannelConfigs);
-            pw.println("mIsDataEnabled=" + mIsDataEnabled);
-            pw.println("mDataEnabledReason=" + mDataEnabledReason);
 
             pw.decreaseIndent();
 
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index ed4e1d9..8d5d3d9 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -16,6 +16,8 @@
 
 package com.android.server;
 
+import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
+
 import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
 import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionTrackerCallback;
 
@@ -33,6 +35,7 @@
 import android.net.vcn.IVcnStatusCallback;
 import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
 import android.net.vcn.VcnConfig;
+import android.net.vcn.VcnManager.VcnErrorCode;
 import android.net.vcn.VcnUnderlyingNetworkPolicy;
 import android.net.wifi.WifiInfo;
 import android.os.Binder;
@@ -304,8 +307,8 @@
                 @NonNull ParcelUuid subscriptionGroup,
                 @NonNull VcnConfig config,
                 @NonNull TelephonySubscriptionSnapshot snapshot,
-                @NonNull VcnSafeModeCallback safeModeCallback) {
-            return new Vcn(vcnContext, subscriptionGroup, config, snapshot, safeModeCallback);
+                @NonNull VcnCallback vcnCallback) {
+            return new Vcn(vcnContext, subscriptionGroup, config, snapshot, vcnCallback);
         }
 
         /** Gets the subId indicated by the given {@link WifiInfo}. */
@@ -457,12 +460,10 @@
         // TODO(b/176939047): Support multiple VCNs active at the same time, or limit to one active
         //                    VCN.
 
-        final VcnSafeModeCallbackImpl safeModeCallback =
-                new VcnSafeModeCallbackImpl(subscriptionGroup);
+        final VcnCallbackImpl vcnCallback = new VcnCallbackImpl(subscriptionGroup);
 
         final Vcn newInstance =
-                mDeps.newVcn(
-                        mVcnContext, subscriptionGroup, config, mLastSnapshot, safeModeCallback);
+                mDeps.newVcn(mVcnContext, subscriptionGroup, config, mLastSnapshot, vcnCallback);
         mVcns.put(subscriptionGroup, newInstance);
 
         // Now that a new VCN has started, notify all registered listeners to refresh their
@@ -784,20 +785,47 @@
     }
 
     // TODO(b/180452282): Make name more generic and implement directly with VcnManagementService
-    /** Callback for signalling when a Vcn has entered safe mode. */
-    public interface VcnSafeModeCallback {
+    /** Callback for Vcn signals sent up to VcnManagementService. */
+    public interface VcnCallback {
         /** Called by a Vcn to signal that it has entered safe mode. */
         void onEnteredSafeMode();
+
+        /** Called by a Vcn to signal that an error occurred. */
+        void onGatewayConnectionError(
+                @NonNull int[] networkCapabilities,
+                @VcnErrorCode int errorCode,
+                @Nullable String exceptionClass,
+                @Nullable String exceptionMessage);
     }
 
-    /** VcnSafeModeCallback is used by Vcns to notify VcnManagementService on entering safe mode. */
-    private class VcnSafeModeCallbackImpl implements VcnSafeModeCallback {
+    /** VcnCallbackImpl for Vcn signals sent up to VcnManagementService. */
+    private class VcnCallbackImpl implements VcnCallback {
         @NonNull private final ParcelUuid mSubGroup;
 
-        private VcnSafeModeCallbackImpl(@NonNull final ParcelUuid subGroup) {
+        private VcnCallbackImpl(@NonNull final ParcelUuid subGroup) {
             mSubGroup = Objects.requireNonNull(subGroup, "Missing subGroup");
         }
 
+        private boolean isCallbackPermissioned(@NonNull VcnStatusCallbackInfo cbInfo) {
+            if (!mSubGroup.equals(cbInfo.mSubGroup)) {
+                return false;
+            }
+
+            if (!mLastSnapshot.packageHasPermissionsForSubscriptionGroup(
+                    mSubGroup, cbInfo.mPkgName)) {
+                return false;
+            }
+
+            if (!mLocationPermissionChecker.checkLocationPermission(
+                    cbInfo.mPkgName,
+                    "VcnStatusCallback" /* featureId */,
+                    cbInfo.mUid,
+                    null /* message */)) {
+                return false;
+            }
+            return true;
+        }
+
         @Override
         public void onEnteredSafeMode() {
             synchronized (mLock) {
@@ -810,23 +838,39 @@
 
                 // Notify all registered StatusCallbacks for this subGroup
                 for (VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
-                    if (!mSubGroup.equals(cbInfo.mSubGroup)) {
-                        continue;
+                    if (isCallbackPermissioned(cbInfo)) {
+                        Binder.withCleanCallingIdentity(
+                                () ->
+                                        cbInfo.mCallback.onVcnStatusChanged(
+                                                VCN_STATUS_CODE_SAFE_MODE));
                     }
-                    if (!mLastSnapshot.packageHasPermissionsForSubscriptionGroup(
-                            mSubGroup, cbInfo.mPkgName)) {
-                        continue;
-                    }
+                }
+            }
+        }
 
-                    if (!mLocationPermissionChecker.checkLocationPermission(
-                            cbInfo.mPkgName,
-                            "VcnStatusCallback" /* featureId */,
-                            cbInfo.mUid,
-                            null /* message */)) {
-                        continue;
-                    }
+        @Override
+        public void onGatewayConnectionError(
+                @NonNull int[] networkCapabilities,
+                @VcnErrorCode int errorCode,
+                @Nullable String exceptionClass,
+                @Nullable String exceptionMessage) {
+            synchronized (mLock) {
+                // Ignore if this subscription group doesn't exist anymore
+                if (!mVcns.containsKey(mSubGroup)) {
+                    return;
+                }
 
-                    Binder.withCleanCallingIdentity(() -> cbInfo.mCallback.onEnteredSafeMode());
+                // Notify all registered StatusCallbacks for this subGroup
+                for (VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
+                    if (isCallbackPermissioned(cbInfo)) {
+                        Binder.withCleanCallingIdentity(
+                                () ->
+                                        cbInfo.mCallback.onGatewayConnectionError(
+                                                networkCapabilities,
+                                                errorCode,
+                                                exceptionClass,
+                                                exceptionMessage));
+                    }
                 }
             }
         }
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index a4ff230..d998ebb 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -20,10 +20,35 @@
 import static android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND;
 import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
 import static android.app.ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
+import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT;
 import static android.app.ActivityManager.PROCESS_STATE_RECEIVER;
 import static android.app.ActivityManager.PROCESS_STATE_TOP;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST;
+import static android.os.PowerWhitelistManager.REASON_ACTIVITY_STARTER;
+import static android.os.PowerWhitelistManager.REASON_ALLOWLISTED_PACKAGE;
+import static android.os.PowerWhitelistManager.REASON_BACKGROUND_ACTIVITY_PERMISSION;
+import static android.os.PowerWhitelistManager.REASON_BACKGROUND_FGS_PERMISSION;
+import static android.os.PowerWhitelistManager.REASON_COMPANION_DEVICE_MANAGER;
+import static android.os.PowerWhitelistManager.REASON_DENIED;
+import static android.os.PowerWhitelistManager.REASON_DEVICE_DEMO_MODE;
+import static android.os.PowerWhitelistManager.REASON_DEVICE_OWNER;
+import static android.os.PowerWhitelistManager.REASON_EXEMPTED_PACKAGE;
+import static android.os.PowerWhitelistManager.REASON_FGS_BINDING;
+import static android.os.PowerWhitelistManager.REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION;
+import static android.os.PowerWhitelistManager.REASON_INSTR_BACKGROUND_FGS_PERMISSION;
+import static android.os.PowerWhitelistManager.REASON_PROC_STATE_PERSISTENT;
+import static android.os.PowerWhitelistManager.REASON_PROC_STATE_PERSISTENT_UI;
+import static android.os.PowerWhitelistManager.REASON_PROC_STATE_TOP;
+import static android.os.PowerWhitelistManager.REASON_PROFILE_OWNER;
+import static android.os.PowerWhitelistManager.REASON_START_ACTIVITY_FLAG;
+import static android.os.PowerWhitelistManager.REASON_SYSTEM_ALERT_WINDOW_PERMISSION;
+import static android.os.PowerWhitelistManager.REASON_SYSTEM_ALLOW_LISTED;
+import static android.os.PowerWhitelistManager.REASON_SYSTEM_UID;
+import static android.os.PowerWhitelistManager.REASON_UID_VISIBLE;
+import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+import static android.os.PowerWhitelistManager.getReasonCodeFromProcState;
+import static android.os.PowerWhitelistManager.reasonCodeToString;
 import static android.os.Process.NFC_UID;
 import static android.os.Process.ROOT_UID;
 import static android.os.Process.SHELL_UID;
@@ -43,7 +68,6 @@
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 
-import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
@@ -52,6 +76,7 @@
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
 import android.app.BroadcastOptions;
+import android.app.ForegroundServiceStartNotAllowedException;
 import android.app.IApplicationThread;
 import android.app.IServiceConnection;
 import android.app.Notification;
@@ -85,6 +110,8 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.PowerWhitelistManager;
+import android.os.PowerWhitelistManager.ReasonCode;
 import android.os.Process;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
@@ -129,8 +156,6 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Comparator;
@@ -151,58 +176,6 @@
 
     private static final boolean SHOW_DUNGEON_NOTIFICATION = false;
 
-    public static final int FGS_FEATURE_DENIED = 0;
-    public static final int FGS_FEATURE_ALLOWED_BY_UID_STATE = 1;
-    public static final int FGS_FEATURE_ALLOWED_BY_PROC_STATE = 2;
-    public static final int FGS_FEATURE_ALLOWED_BY_UID_VISIBLE = 3;
-    public static final int FGS_FEATURE_ALLOWED_BY_FLAG = 4;
-    public static final int FGS_FEATURE_ALLOWED_BY_SYSTEM_UID = 5;
-    public static final int FGS_FEATURE_ALLOWED_BY_INSTR_BACKGROUND_ACTIVITY_PERMISSION = 6;
-    public static final int FGS_FEATURE_ALLOWED_BY_INSTR_BACKGROUND_FGS_PERMISSION = 7;
-    public static final int FGS_FEATURE_ALLOWED_BY_ACTIVITY_TOKEN = 8;
-    public static final int FGS_FEATURE_ALLOWED_BY_FGS_TOKEN = 9;
-    public static final int FGS_FEATURE_ALLOWED_BY_BACKGROUND_ACTIVITY_PERMISSION = 10;
-    public static final int FGS_FEATURE_ALLOWED_BY_BACKGROUND_FGS_PERMISSION = 12;
-    public static final int FGS_FEATURE_ALLOWED_BY_ALLOWLIST = 13;
-    public static final int FGS_FEATURE_ALLOWED_BY_DEVICE_OWNER = 14;
-    public static final int FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST = 15;
-    public static final int FGS_FEATURE_ALLOWED_BY_SYSTEM_ALERT_WINDOW_PERMISSION = 16;
-    public static final int FGS_FEATURE_ALLOWED_BY_FGS_BINDING = 17;
-    public static final int FGS_FEATURE_ALLOWED_BY_DEVICE_DEMO_MODE = 18;
-    public static final int FGS_FEATURE_ALLOWED_BY_PROCESS_RECORD = 19;
-    public static final int FGS_FEATURE_ALLOWED_BY_EXEMPTED_PACKAGES = 20;
-    public static final int FGS_FEATURE_ALLOWED_BY_ACTIVITY_STARTER = 21;
-    public static final int FGS_FEATURE_ALLOWED_BY_COMPANION_APP = 22;
-    public static final int FGS_FEATURE_ALLOWED_BY_PROFILE_OWNER = 23;
-
-    @IntDef(flag = true, prefix = { "FGS_FEATURE_" }, value = {
-            FGS_FEATURE_DENIED,
-            FGS_FEATURE_ALLOWED_BY_UID_STATE,
-            FGS_FEATURE_ALLOWED_BY_PROC_STATE,
-            FGS_FEATURE_ALLOWED_BY_UID_VISIBLE,
-            FGS_FEATURE_ALLOWED_BY_FLAG,
-            FGS_FEATURE_ALLOWED_BY_SYSTEM_UID,
-            FGS_FEATURE_ALLOWED_BY_INSTR_BACKGROUND_ACTIVITY_PERMISSION,
-            FGS_FEATURE_ALLOWED_BY_INSTR_BACKGROUND_FGS_PERMISSION,
-            FGS_FEATURE_ALLOWED_BY_ACTIVITY_TOKEN,
-            FGS_FEATURE_ALLOWED_BY_FGS_TOKEN,
-            FGS_FEATURE_ALLOWED_BY_BACKGROUND_ACTIVITY_PERMISSION,
-            FGS_FEATURE_ALLOWED_BY_BACKGROUND_FGS_PERMISSION,
-            FGS_FEATURE_ALLOWED_BY_ALLOWLIST,
-            FGS_FEATURE_ALLOWED_BY_DEVICE_OWNER,
-            FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST,
-            FGS_FEATURE_ALLOWED_BY_SYSTEM_ALERT_WINDOW_PERMISSION,
-            FGS_FEATURE_ALLOWED_BY_FGS_BINDING,
-            FGS_FEATURE_ALLOWED_BY_DEVICE_DEMO_MODE,
-            FGS_FEATURE_ALLOWED_BY_PROCESS_RECORD,
-            FGS_FEATURE_ALLOWED_BY_EXEMPTED_PACKAGES,
-            FGS_FEATURE_ALLOWED_BY_ACTIVITY_STARTER,
-            FGS_FEATURE_ALLOWED_BY_COMPANION_APP,
-            FGS_FEATURE_ALLOWED_BY_PROFILE_OWNER
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface FgsFeatureRetCode {}
-
     // How long we wait for a service to finish executing.
     static final int SERVICE_TIMEOUT = 20*1000;
 
@@ -274,7 +247,7 @@
 
     AppWidgetManagerInternal mAppWidgetManagerInternal;
 
-    // white listed packageName.
+    // allowlisted packageName.
     ArraySet<String> mAllowListWhileInUsePermissionInFgs = new ArraySet<>();
 
     // TODO: remove this after feature development is done
@@ -674,7 +647,7 @@
 
         if (fgRequired) {
             logFgsBackgroundStart(r);
-            if (r.mAllowStartForeground == FGS_FEATURE_DENIED && isBgFgsRestrictionEnabled(r)) {
+            if (r.mAllowStartForeground == REASON_DENIED && isBgFgsRestrictionEnabled(r)) {
                 String msg = "startForegroundService() not allowed due to "
                         + "mAllowStartForeground false: service "
                         + r.shortInstanceName;
@@ -693,7 +666,7 @@
                             + "could not resolve client package " + callingPackage);
                 }
                 if (CompatChanges.isChangeEnabled(FGS_START_EXCEPTION_CHANGE_ID, aInfo.uid)) {
-                    throw new IllegalStateException(msg);
+                    throw new ForegroundServiceStartNotAllowedException(msg);
                 }
                 return null;
             }
@@ -1767,8 +1740,7 @@
 
                 if (!ignoreForeground) {
                     logFgsBackgroundStart(r);
-                    if (r.mAllowStartForeground == FGS_FEATURE_DENIED
-                            && isBgFgsRestrictionEnabled(r)) {
+                    if (r.mAllowStartForeground == REASON_DENIED && isBgFgsRestrictionEnabled(r)) {
                         final String msg = "Service.startForeground() not allowed due to "
                                 + "mAllowStartForeground false: service "
                                 + r.shortInstanceName;
@@ -1778,7 +1750,7 @@
                         ignoreForeground = true;
                         if (CompatChanges.isChangeEnabled(FGS_START_EXCEPTION_CHANGE_ID,
                                 r.appInfo.uid)) {
-                            throw new IllegalStateException(msg);
+                            throw new ForegroundServiceStartNotAllowedException(msg);
                         }
                     }
                 }
@@ -2111,7 +2083,8 @@
         private final AppOpsManager.OnOpNotedListener mOpNotedCallback =
                 new AppOpsManager.OnOpNotedListener() {
                     @Override
-                    public void onOpNoted(int op, int uid, String pkgName, int flags, int result) {
+                    public void onOpNoted(int op, int uid, String pkgName,
+                            String attributionTag, int flags, int result) {
                         incrementOpCountIfNeeded(op, uid, result);
                     }
         };
@@ -2119,7 +2092,8 @@
         private final AppOpsManager.OnOpStartedListener mOpStartedCallback =
                 new AppOpsManager.OnOpStartedListener() {
                     @Override
-                    public void onOpStarted(int op, int uid, String pkgName, int flags,
+                    public void onOpStarted(int op, int uid, String pkgName,
+                            String attributionTag, int flags,
                             int result) {
                         incrementOpCountIfNeeded(op, uid, result);
                     }
@@ -2247,7 +2221,7 @@
         psr.mAllowlistManager = false;
         for (int i = psr.numberOfRunningServices() - 1; i >= 0; i--) {
             ServiceRecord sr = psr.getRunningServiceAt(i);
-            if (sr.whitelistManager) {
+            if (sr.allowlistManager) {
                 psr.mAllowlistManager = true;
                 break;
             }
@@ -2258,7 +2232,7 @@
         final ProcessServiceRecord psr = service.app.mServices;
         psr.stopService(service);
         psr.updateBoundClientUids();
-        if (service.whitelistManager) {
+        if (service.allowlistManager) {
             updateAllowlistManagerLocked(psr);
         }
     }
@@ -2480,7 +2454,7 @@
                 clientPsr.setHasAboveClient(true);
             }
             if ((c.flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
-                s.whitelistManager = true;
+                s.allowlistManager = true;
             }
             if ((flags & Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS) != 0) {
                 s.setAllowedBgActivityStartsByBinding(true);
@@ -2517,7 +2491,7 @@
                 if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
                     servicePsr.setTreatLikeActivity(true);
                 }
-                if (s.whitelistManager) {
+                if (s.allowlistManager) {
                     servicePsr.mAllowlistManager = true;
                 }
                 // This could have made the service more important.
@@ -2946,7 +2920,6 @@
                     final ServiceRestarter res = new ServiceRestarter();
                     r = new ServiceRecord(mAm, className, name, definingPackageName,
                             definingUid, filter, sInfo, callingFromFg, res);
-                    r.mRecentCallingPackage = callingPackage;
                     res.setService(r);
                     smap.mServicesByInstanceName.put(name, r);
                     smap.mServicesByIntent.put(filter, r);
@@ -2975,6 +2948,8 @@
             }
         }
         if (r != null) {
+            r.mRecentCallingPackage = callingPackage;
+            r.mRecentCallingUid = callingUid;
             if (!mAm.validateAssociationAllowedLocked(callingPackage, callingUid, r.packageName,
                     r.appInfo.uid)) {
                 String msg = "association not allowed between packages "
@@ -3437,12 +3412,13 @@
 
         if (r.fgRequired) {
             if (DEBUG_FOREGROUND_SERVICE) {
-                Slog.v(TAG, "Whitelisting " + UserHandle.formatUid(r.appInfo.uid)
+                Slog.v(TAG, "Allowlisting " + UserHandle.formatUid(r.appInfo.uid)
                         + " for fg-service launch");
             }
             mAm.tempAllowlistUidLocked(r.appInfo.uid,
-                    SERVICE_START_FOREGROUND_TIMEOUT, "fg-service-launch",
-                    BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED);
+                    SERVICE_START_FOREGROUND_TIMEOUT, PowerWhitelistManager.REASON_SERVICE_LAUNCH,
+                    "fg-service-launch", TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+                    r.mRecentCallingUid);
         }
 
         if (!mPendingServices.contains(r)) {
@@ -3548,7 +3524,7 @@
             }
         }
 
-        if (r.whitelistManager) {
+        if (r.allowlistManager) {
             psr.mAllowlistManager = true;
         }
 
@@ -3865,6 +3841,8 @@
                     r.name.getClassName());
             stopServiceAndUpdateAllowlistManagerLocked(r);
             if (r.app.getThread() != null) {
+                // Bump the process to the top of LRU list
+                mAm.updateLruProcessLocked(r.app, false, null);
                 updateServiceForegroundLocked(r.app.mServices, false);
                 try {
                     bumpServiceExecutingLocked(r, false, "destroy");
@@ -3938,11 +3916,11 @@
             if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
                 psr.updateHasAboveClientLocked();
             }
-            // If this connection requested whitelist management, see if we should
+            // If this connection requested allowlist management, see if we should
             // now clear that state.
             if ((c.flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
-                s.updateWhitelistManager();
-                if (!s.whitelistManager && s.app != null) {
+                s.updateAllowlistManager();
+                if (!s.allowlistManager && s.app != null) {
                     updateAllowlistManagerLocked(s.app.mServices);
                 }
             }
@@ -5397,13 +5375,13 @@
         }
 
         if (!r.mAllowWhileInUsePermissionInFgs
-                || (r.mAllowStartForeground == FGS_FEATURE_DENIED)) {
-            final @FgsFeatureRetCode int allowWhileInUse = shouldAllowFgsWhileInUsePermissionLocked(
+                || (r.mAllowStartForeground == REASON_DENIED)) {
+            final @ReasonCode int allowWhileInUse = shouldAllowFgsWhileInUsePermissionLocked(
                     callingPackage, callingPid, callingUid, r, allowBackgroundActivityStarts);
             if (!r.mAllowWhileInUsePermissionInFgs) {
-                r.mAllowWhileInUsePermissionInFgs = (allowWhileInUse != FGS_FEATURE_DENIED);
+                r.mAllowWhileInUsePermissionInFgs = (allowWhileInUse != REASON_DENIED);
             }
-            if (r.mAllowStartForeground == FGS_FEATURE_DENIED) {
+            if (r.mAllowStartForeground == REASON_DENIED) {
                 r.mAllowStartForeground = shouldAllowFgsStartForegroundLocked(allowWhileInUse,
                         callingPackage, callingPid, callingUid, intent, r,
                         allowBackgroundActivityStarts);
@@ -5417,37 +5395,37 @@
      * @param callingPackage caller app's package name.
      * @param callingUid caller app's uid.
      * @param r the service to start.
-     * @return {@link FgsFeatureRetCode}
+     * @return {@link ReasonCode}
      */
-    private @FgsFeatureRetCode int shouldAllowFgsWhileInUsePermissionLocked(String callingPackage,
+    private @ReasonCode int shouldAllowFgsWhileInUsePermissionLocked(String callingPackage,
             int callingPid, int callingUid, ServiceRecord r,
             boolean allowBackgroundActivityStarts) {
-        int ret = FGS_FEATURE_DENIED;
+        int ret = REASON_DENIED;
 
         final int uidState = mAm.getUidStateLocked(callingUid);
-        if (ret == FGS_FEATURE_DENIED) {
+        if (ret == REASON_DENIED) {
             // Is the calling UID at PROCESS_STATE_TOP or above?
             if (uidState <= PROCESS_STATE_TOP) {
-                ret = FGS_FEATURE_ALLOWED_BY_UID_STATE;
+                ret = getReasonCodeFromProcState(uidState);
             }
         }
 
-        if (ret == FGS_FEATURE_DENIED) {
+        if (ret == REASON_DENIED) {
             // Does the calling UID have any visible activity?
             final boolean isCallingUidVisible = mAm.mAtmInternal.isUidForeground(callingUid);
             if (isCallingUidVisible) {
-                ret = FGS_FEATURE_ALLOWED_BY_UID_VISIBLE;
+                ret = REASON_UID_VISIBLE;
             }
         }
 
-        if (ret == FGS_FEATURE_DENIED) {
+        if (ret == REASON_DENIED) {
             // Is the allow activity background start flag on?
             if (allowBackgroundActivityStarts) {
-                ret = FGS_FEATURE_ALLOWED_BY_FLAG;
+                ret = REASON_START_ACTIVITY_FLAG;
             }
         }
 
-        if (ret == FGS_FEATURE_DENIED) {
+        if (ret == REASON_DENIED) {
             boolean isCallerSystem = false;
             final int callingAppId = UserHandle.getAppId(callingUid);
             switch (callingAppId) {
@@ -5463,15 +5441,15 @@
             }
 
             if (isCallerSystem) {
-                ret = FGS_FEATURE_ALLOWED_BY_SYSTEM_UID;
+                ret = REASON_SYSTEM_UID;
             }
         }
 
-        if (ret == FGS_FEATURE_DENIED) {
+        if (ret == REASON_DENIED) {
             final Integer allowedType = mAm.mProcessList.searchEachLruProcessesLOSP(false, pr -> {
                 if (pr.uid == callingUid) {
                     if (pr.getWindowProcessController().areBackgroundFgsStartsAllowed()) {
-                        return FGS_FEATURE_ALLOWED_BY_ACTIVITY_STARTER;
+                        return REASON_ACTIVITY_STARTER;
                     }
                 }
                 return null;
@@ -5481,35 +5459,35 @@
             }
         }
 
-        if (ret == FGS_FEATURE_DENIED) {
+        if (ret == REASON_DENIED) {
             if (r.app != null) {
                 ActiveInstrumentation instr = r.app.getActiveInstrumentation();
                 if (instr != null && instr.mHasBackgroundActivityStartsPermission) {
-                    ret = FGS_FEATURE_ALLOWED_BY_INSTR_BACKGROUND_ACTIVITY_PERMISSION;
+                    ret = REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION;
                 }
             }
         }
 
-        if (ret == FGS_FEATURE_DENIED) {
+        if (ret == REASON_DENIED) {
             if (mAm.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
                     == PERMISSION_GRANTED) {
-                ret = FGS_FEATURE_ALLOWED_BY_BACKGROUND_ACTIVITY_PERMISSION;
+                ret = REASON_BACKGROUND_ACTIVITY_PERMISSION;
             }
         }
 
-        if (ret == FGS_FEATURE_DENIED) {
+        if (ret == REASON_DENIED) {
             final boolean isAllowedPackage =
                     mAllowListWhileInUsePermissionInFgs.contains(callingPackage);
             if (isAllowedPackage) {
-                ret = FGS_FEATURE_ALLOWED_BY_ALLOWLIST;
+                ret = REASON_ALLOWLISTED_PACKAGE;
             }
         }
 
-        if (ret == FGS_FEATURE_DENIED) {
+        if (ret == REASON_DENIED) {
             // Is the calling UID a device owner app?
             final boolean isDeviceOwner = mAm.mInternal.isDeviceOwner(callingUid);
             if (isDeviceOwner) {
-                ret = FGS_FEATURE_ALLOWED_BY_DEVICE_OWNER;
+                ret = REASON_DEVICE_OWNER;
             }
         }
         return ret;
@@ -5524,38 +5502,40 @@
      * @param callingUid caller app's uid.
      * @param intent intent to start/bind service.
      * @param r the service to start.
-     * @return {@link FgsFeatureRetCode}
+     * @return {@link ReasonCode}
      */
-    private @FgsFeatureRetCode int shouldAllowFgsStartForegroundLocked(
-            @FgsFeatureRetCode int allowWhileInUse, String callingPackage, int callingPid,
+    private @ReasonCode int shouldAllowFgsStartForegroundLocked(
+            @ReasonCode int allowWhileInUse, String callingPackage, int callingPid,
             int callingUid, Intent intent, ServiceRecord r, boolean allowBackgroundActivityStarts) {
         int ret = allowWhileInUse;
+        FgsStartTempAllowList.TempFgsAllowListEntry tempAllowListReason =
+                r.mInfoTempFgsAllowListReason = mAm.isAllowlistedForFgsStartLOSP(callingUid);
 
         final StringBuilder sb = new StringBuilder(64);
         final int uidState = mAm.getUidStateLocked(callingUid);
-        if (ret == FGS_FEATURE_DENIED) {
+        if (ret == REASON_DENIED) {
             // Is the calling UID at PROCESS_STATE_TOP or above?
             if (uidState <= PROCESS_STATE_TOP) {
                 sb.append("uidState=").append(uidState);
-                ret = FGS_FEATURE_ALLOWED_BY_UID_STATE;
+                ret = getReasonCodeFromProcState(uidState);
             }
         }
 
-        if (ret == FGS_FEATURE_DENIED) {
+        if (ret == REASON_DENIED) {
             final Integer allowedType = mAm.mProcessList.searchEachLruProcessesLOSP(false, app -> {
                 if (app.uid == callingUid) {
                     final ProcessStateRecord state = app.mState;
-                    if (state.getAllowedStartFgs() != FGS_FEATURE_DENIED) {
+                    if (state.getAllowedStartFgs() != REASON_DENIED) {
                         return state.getAllowedStartFgs();
                     } else if (state.isAllowedStartFgsState()) {
-                        return FGS_FEATURE_ALLOWED_BY_PROC_STATE;
+                        return getReasonCodeFromProcState(state.getAllowStartFgsState());
                     } else if (state.areBackgroundFgsStartsAllowedByToken()) {
-                        return FGS_FEATURE_ALLOWED_BY_FGS_BINDING;
+                        return REASON_FGS_BINDING;
                     } else {
                         final ActiveInstrumentation instr = app.getActiveInstrumentation();
                         if (instr != null
                                 && instr.mHasBackgroundForegroundServiceStartsPermission) {
-                            return FGS_FEATURE_ALLOWED_BY_INSTR_BACKGROUND_FGS_PERMISSION;
+                            return REASON_INSTR_BACKGROUND_FGS_PERMISSION;
                         }
                     }
                 }
@@ -5566,55 +5546,59 @@
             }
         }
 
-        if (ret == FGS_FEATURE_DENIED) {
+        if (ret == REASON_DENIED) {
             if (mAm.checkPermission(START_FOREGROUND_SERVICES_FROM_BACKGROUND, callingPid,
                     callingUid) == PERMISSION_GRANTED) {
-                ret = FGS_FEATURE_ALLOWED_BY_BACKGROUND_FGS_PERMISSION;
+                ret = REASON_BACKGROUND_FGS_PERMISSION;
             }
         }
 
-        if (ret == FGS_FEATURE_DENIED) {
+        if (ret == REASON_DENIED) {
             if (mAm.checkPermission(SYSTEM_ALERT_WINDOW, callingPid,
                     callingUid) == PERMISSION_GRANTED) {
-                ret = FGS_FEATURE_ALLOWED_BY_SYSTEM_ALERT_WINDOW_PERMISSION;
+                ret = REASON_SYSTEM_ALERT_WINDOW_PERMISSION;
             }
         }
 
-        if (ret == FGS_FEATURE_DENIED) {
-            if (mAm.isAllowlistedForFgsStartLOSP(callingUid)) {
-                // uid is on DeviceIdleController's user/system allowlist
-                // or AMS's FgsStartTempAllowList.
-                ret = FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST;
+        if (ret == REASON_DENIED) {
+            FgsStartTempAllowList.TempFgsAllowListEntry entry =
+                    mAm.isAllowlistedForFgsStartLOSP(callingUid);
+            if (entry != null) {
+                if (entry == ActivityManagerService.FAKE_TEMP_ALLOWLIST_ENTRY) {
+                    ret = REASON_SYSTEM_ALLOW_LISTED;
+                } else {
+                    ret = entry.mReasonCode;
+                }
             }
         }
 
-        if (ret == FGS_FEATURE_DENIED) {
+        if (ret == REASON_DENIED) {
             if (UserManager.isDeviceInDemoMode(mAm.mContext)) {
-                ret = FGS_FEATURE_ALLOWED_BY_DEVICE_DEMO_MODE;
+                ret = REASON_DEVICE_DEMO_MODE;
             }
         }
 
-        if (ret == FGS_FEATURE_DENIED) {
+        if (ret == REASON_DENIED) {
             // Is the calling UID a profile owner app?
             final boolean isProfileOwner = mAm.mInternal.isProfileOwner(callingUid);
             if (isProfileOwner) {
-                ret = FGS_FEATURE_ALLOWED_BY_PROFILE_OWNER;
+                ret = REASON_PROFILE_OWNER;
             }
         }
 
         // NOTE this should always be the last check.
-        if (ret == FGS_FEATURE_DENIED) {
+        if (ret == REASON_DENIED) {
             if (isPackageExemptedFromFgsRestriction(r.appInfo.packageName, r.appInfo.uid)
                     || isPackageExemptedFromFgsRestriction(callingPackage, callingUid)) {
-                ret = FGS_FEATURE_ALLOWED_BY_EXEMPTED_PACKAGES;
+                ret = REASON_EXEMPTED_PACKAGE;
             }
         }
 
-        if (ret == FGS_FEATURE_DENIED) {
+        if (ret == REASON_DENIED) {
             final boolean isCompanionApp = mAm.mInternal.isAssociatedCompanionApp(
                     UserHandle.getUserId(callingUid), callingUid);
             if (isCompanionApp) {
-                ret = FGS_FEATURE_ALLOWED_BY_COMPANION_APP;
+                ret = REASON_COMPANION_DEVICE_MANAGER;
             }
         }
 
@@ -5623,7 +5607,15 @@
                         + "; callingUid: " + callingUid
                         + "; uidState: " + ProcessList.makeProcStateString(uidState)
                         + "; intent: " + intent
-                        + "; code:" + fgsCodeToString(ret)
+                        + "; code:" + reasonCodeToString(ret)
+                        + "; tempAllowListReason:<" +
+                        (tempAllowListReason == null ? null :
+                                (tempAllowListReason.mReason
+                                + ",reasonCode:"
+                                + reasonCodeToString(tempAllowListReason.mReasonCode)
+                                + ",duration:" + tempAllowListReason.mDuration
+                                + ",callingUid:" + tempAllowListReason.mCallingUid))
+                        + ">"
                         + "; extra:" + sb.toString()
                         + "; targetSdkVersion:" + r.appInfo.targetSdkVersion
                         + "]";
@@ -5657,62 +5649,11 @@
         return CompatChanges.isChangeEnabled(FGS_BG_START_USE_EXEMPTION_LIST_CHANGE_ID, uid);
     }
 
-    static String fgsCodeToString(@FgsFeatureRetCode int code) {
-        switch (code) {
-            case FGS_FEATURE_DENIED:
-                return "DENIED";
-            case FGS_FEATURE_ALLOWED_BY_UID_STATE:
-                return "ALLOWED_BY_UID_STATE";
-            case FGS_FEATURE_ALLOWED_BY_PROC_STATE:
-                return "ALLOWED_BY_PROC_STATE";
-            case FGS_FEATURE_ALLOWED_BY_UID_VISIBLE:
-                return "ALLOWED_BY_UID_VISIBLE";
-            case FGS_FEATURE_ALLOWED_BY_FLAG:
-                return "ALLOWED_BY_FLAG";
-            case FGS_FEATURE_ALLOWED_BY_SYSTEM_UID:
-                return "ALLOWED_BY_SYSTEM_UID";
-            case FGS_FEATURE_ALLOWED_BY_INSTR_BACKGROUND_ACTIVITY_PERMISSION:
-                return "ALLOWED_BY_INSTR_BACKGROUND_ACTIVITY_PERMISSION";
-            case FGS_FEATURE_ALLOWED_BY_INSTR_BACKGROUND_FGS_PERMISSION:
-                return "ALLOWED_BY_INSTR_BACKGROUND_FGS_PERMISSION";
-            case FGS_FEATURE_ALLOWED_BY_ACTIVITY_TOKEN:
-                return "ALLOWED_BY_ACTIVITY_TOKEN";
-            case FGS_FEATURE_ALLOWED_BY_FGS_TOKEN:
-                return "ALLOWED_BY_FGS_TOKEN";
-            case FGS_FEATURE_ALLOWED_BY_BACKGROUND_ACTIVITY_PERMISSION:
-                return "ALLOWED_BY_BACKGROUND_ACTIVITY_PERMISSION";
-            case FGS_FEATURE_ALLOWED_BY_BACKGROUND_FGS_PERMISSION:
-                return "ALLOWED_BY_BACKGROUND_FGS_PERMISSION";
-            case FGS_FEATURE_ALLOWED_BY_ALLOWLIST:
-                return "ALLOWED_BY_ALLOWLIST";
-            case FGS_FEATURE_ALLOWED_BY_DEVICE_OWNER:
-                return "ALLOWED_BY_DEVICE_OWNER";
-            case FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST:
-                return "ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST";
-            case FGS_FEATURE_ALLOWED_BY_SYSTEM_ALERT_WINDOW_PERMISSION:
-                return "ALLOWED_BY_SYSTEM_ALERT_WINDOW_PERMISSION";
-            case FGS_FEATURE_ALLOWED_BY_FGS_BINDING:
-                return "ALLOWED_BY_FGS_BINDING";
-            case FGS_FEATURE_ALLOWED_BY_DEVICE_DEMO_MODE:
-                return "ALLOWED_BY_DEVICE_DEMO_MODE";
-            case FGS_FEATURE_ALLOWED_BY_PROCESS_RECORD:
-                return "ALLOWED_BY_PROCESS_RECORD";
-            case FGS_FEATURE_ALLOWED_BY_EXEMPTED_PACKAGES:
-                return "FGS_FEATURE_ALLOWED_BY_EXEMPTED_PACKAGES";
-            case FGS_FEATURE_ALLOWED_BY_ACTIVITY_STARTER:
-                return "ALLOWED_BY_ACTIVITY_STARTER";
-            case FGS_FEATURE_ALLOWED_BY_COMPANION_APP:
-                return "ALLOWED_BY_COMPANION_APP";
-            case FGS_FEATURE_ALLOWED_BY_PROFILE_OWNER:
-                return "ALLOWED_BY_PROFILE_OWNER";
-            default:
-                return "";
-        }
-    }
-
-    private static boolean isFgsBgStart(@FgsFeatureRetCode int code) {
-        return code != FGS_FEATURE_ALLOWED_BY_UID_STATE
-                && code != FGS_FEATURE_ALLOWED_BY_UID_VISIBLE;
+    private static boolean isFgsBgStart(@ReasonCode int code) {
+        return code != REASON_PROC_STATE_PERSISTENT
+                && code != REASON_PROC_STATE_PERSISTENT_UI
+                && code != REASON_PROC_STATE_TOP
+                && code != REASON_UID_VISIBLE;
     }
 
     // TODO: remove this notification after feature development is done
@@ -5751,10 +5692,10 @@
         }
         if (!r.mLoggedInfoAllowStartForeground) {
             final String msg = "Background started FGS: "
-                    + ((r.mAllowStartForeground != FGS_FEATURE_DENIED) ? "Allowed " : "Disallowed ")
+                    + ((r.mAllowStartForeground != REASON_DENIED) ? "Allowed " : "Disallowed ")
                     + r.mInfoAllowStartForeground;
             Slog.wtfQuiet(TAG, msg);
-            if (r.mAllowStartForeground != FGS_FEATURE_DENIED) {
+            if (r.mAllowStartForeground != REASON_DENIED) {
                 Slog.i(TAG, msg);
             } else {
                 Slog.w(TAG, msg);
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index 171b20c..9d1c838 100644
--- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -68,7 +68,7 @@
     static final boolean DEBUG_UID_OBSERVERS = DEBUG_ALL || false;
     static final boolean DEBUG_USAGE_STATS = DEBUG_ALL || false;
     static final boolean DEBUG_PERMISSIONS_REVIEW = DEBUG_ALL || false;
-    static final boolean DEBUG_WHITELISTS = DEBUG_ALL || false;
+    static final boolean DEBUG_ALLOWLISTS = DEBUG_ALL || false;
 
     static final String POSTFIX_BACKUP = (APPEND_CATEGORY_NAME) ? "_Backup" : "";
     static final String POSTFIX_BROADCAST = (APPEND_CATEGORY_NAME) ? "_Broadcast" : "";
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0b1c115..7cd49497 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -33,7 +33,6 @@
 import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
 import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
 import static android.app.AppOpsManager.OP_NONE;
-import static android.app.BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
 import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_DEFAULT;
 import static android.content.pm.PackageManager.GET_SHARED_LIBRARY_FILES;
 import static android.content.pm.PackageManager.MATCH_ALL;
@@ -50,8 +49,12 @@
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
 import static android.os.IServiceManager.DUMP_FLAG_PROTO;
+import static android.os.PowerWhitelistManager.REASON_SYSTEM_ALLOW_LISTED;
+import static android.os.PowerWhitelistManager.REASON_UNKNOWN;
+import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
 import static android.os.Process.BLUETOOTH_UID;
 import static android.os.Process.FIRST_APPLICATION_UID;
+import static android.os.Process.INVALID_UID;
 import static android.os.Process.NETWORK_STACK_UID;
 import static android.os.Process.NFC_UID;
 import static android.os.Process.PHONE_UID;
@@ -101,7 +104,7 @@
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_POWER;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESSES;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SERVICE;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_WHITELISTS;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALLOWLISTS;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_BACKUP;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_BROADCAST;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CLEANUP;
@@ -130,6 +133,7 @@
 import static com.android.server.wm.ActivityTaskManagerService.DUMP_RECENTS_CMD;
 import static com.android.server.wm.ActivityTaskManagerService.DUMP_RECENTS_SHORT_CMD;
 import static com.android.server.wm.ActivityTaskManagerService.DUMP_STARTER_CMD;
+import static com.android.server.wm.ActivityTaskManagerService.DUMP_TOP_RESUMED_ACTIVITY;
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
 import static com.android.server.wm.ActivityTaskManagerService.relaunchReasonToString;
 
@@ -141,6 +145,8 @@
 import android.app.Activity;
 import android.app.ActivityClient;
 import android.app.ActivityManager;
+import android.app.ActivityManager.PendingIntentInfo;
+import android.app.ActivityManager.ProcessCapability;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityManagerInternal;
 import android.app.ActivityTaskManager.RootTaskInfo;
@@ -172,6 +178,7 @@
 import android.app.PendingIntent;
 import android.app.ProcessMemoryState;
 import android.app.ProfilerInfo;
+import android.app.PropertyInvalidatedCache;
 import android.app.WaitResult;
 import android.app.backup.BackupManager.OperationType;
 import android.app.backup.IBackupManager;
@@ -180,7 +187,6 @@
 import android.app.usage.UsageStatsManager;
 import android.app.usage.UsageStatsManagerInternal;
 import android.appwidget.AppWidgetManager;
-import android.compat.Compatibility;
 import android.content.AutofillOptions;
 import android.content.BroadcastReceiver;
 import android.content.ComponentCallbacks2;
@@ -250,6 +256,7 @@
 import android.os.PowerManager;
 import android.os.PowerManager.ServiceType;
 import android.os.PowerManagerInternal;
+import android.os.PowerWhitelistManager.ReasonCode;
 import android.os.PowerWhitelistManager.TempAllowListType;
 import android.os.Process;
 import android.os.RemoteCallback;
@@ -304,8 +311,8 @@
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.app.ProcessMap;
 import com.android.internal.app.SystemUserHomeActivity;
+import com.android.internal.app.procstats.ProcessState;
 import com.android.internal.app.procstats.ProcessStats;
-import com.android.internal.compat.CompatibilityChangeConfig;
 import com.android.internal.content.PackageHelper;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.notification.SystemNotificationChannels;
@@ -353,6 +360,7 @@
 import com.android.server.firewall.IntentFirewall;
 import com.android.server.graphics.fonts.FontManagerInternal;
 import com.android.server.job.JobSchedulerInternal;
+import com.android.server.os.NativeTombstoneManager;
 import com.android.server.pm.Installer;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
 import com.android.server.uri.GrantUri;
@@ -621,7 +629,7 @@
      */
     private volatile String mDeviceOwnerName;
 
-    private volatile int mDeviceOwnerUid = Process.INVALID_UID;
+    private volatile int mDeviceOwnerUid = INVALID_UID;
 
     /**
      * Map userId to its companion app uids.
@@ -1147,13 +1155,13 @@
     DeviceIdleInternal mLocalDeviceIdleController;
 
     /**
-     * Power-save whitelisted app-ids (not including except-idle-whitelisted ones).
+     * Power-save allowlisted app-ids (not including except-idle-allowlisted ones).
      */
     @CompositeRWLock({"this", "mProcLock"})
     int[] mDeviceIdleAllowlist = new int[0];
 
     /**
-     * Power-save whitelisted app-ids (including except-idle-whitelisted ones).
+     * Power-save allowlisted app-ids (including except-idle-allowlisted ones).
      */
     @CompositeRWLock({"this", "mProcLock"})
     int[] mDeviceIdleExceptIdleAllowlist = new int[0];
@@ -1169,20 +1177,27 @@
         final long duration;
         final String tag;
         final int type;
+        final @ReasonCode int reasonCode;
 
-        PendingTempAllowlist(int targetUid, long duration, String tag, int type) {
+        PendingTempAllowlist(int targetUid, long duration, @ReasonCode int reasonCode, String tag,
+                int type) {
             this.targetUid = targetUid;
             this.duration = duration;
             this.tag = tag;
             this.type = type;
+            this.reasonCode = reasonCode;
         }
 
         void dumpDebug(ProtoOutputStream proto, long fieldId) {
             final long token = proto.start(fieldId);
-            proto.write(ActivityManagerServiceDumpProcessesProto.PendingTempWhitelist.TARGET_UID, targetUid);
-            proto.write(ActivityManagerServiceDumpProcessesProto.PendingTempWhitelist.DURATION_MS, duration);
+            proto.write(ActivityManagerServiceDumpProcessesProto.PendingTempWhitelist.TARGET_UID,
+                    targetUid);
+            proto.write(ActivityManagerServiceDumpProcessesProto.PendingTempWhitelist.DURATION_MS,
+                    duration);
             proto.write(ActivityManagerServiceDumpProcessesProto.PendingTempWhitelist.TAG, tag);
             proto.write(ActivityManagerServiceDumpProcessesProto.PendingTempWhitelist.TYPE, type);
+            proto.write(ActivityManagerServiceDumpProcessesProto.PendingTempWhitelist.REASON_CODE,
+                    reasonCode);
             proto.end(token);
         }
     }
@@ -1196,6 +1211,9 @@
     @CompositeRWLock({"this", "mProcLock"})
     final FgsStartTempAllowList mFgsStartTempAllowList = new FgsStartTempAllowList();
 
+    static final FgsStartTempAllowList.TempFgsAllowListEntry FAKE_TEMP_ALLOWLIST_ENTRY = new
+            FgsStartTempAllowList.TempFgsAllowListEntry(Long.MAX_VALUE, Long.MAX_VALUE,
+            REASON_SYSTEM_ALLOW_LISTED, "", INVALID_UID);
     /**
      * Information about and control over application operations
      */
@@ -1817,6 +1835,15 @@
         ncl.start();
     }
 
+    /**
+     * Sets a policy for handling app ops.
+     *
+     * @param appOpsPolicy The policy.
+     */
+    public void setAppOpsPolicy(@Nullable CheckOpsDelegate appOpsPolicy) {
+        mAppOpsService.setAppOpsPolicy(appOpsPolicy);
+    }
+
     public IAppOpsService getAppOpsService() {
         return mAppOpsService;
     }
@@ -3776,10 +3803,11 @@
                                 mi.getTotalUss(), mi.getTotalRss(), false,
                                 ProcessStats.ADD_PSS_EXTERNAL_SLOW, duration);
                         proc.getPkgList().forEachPackageProcessStats(holder -> {
+                            final ProcessState state = holder.state;
                             FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_MEMORY_STAT_REPORTED,
                                     proc.info.uid,
-                                    holder.state.getName(),
-                                    holder.state.getPackage(),
+                                    state != null ? state.getName() : proc.processName,
+                                    state != null ? state.getPackage() : proc.info.packageName,
                                     mi.getTotalPss(),
                                     mi.getTotalUss(),
                                     mi.getTotalRss(),
@@ -4815,12 +4843,12 @@
     }
 
     @Override
-    public int sendIntentSender(IIntentSender target, IBinder whitelistToken, int code,
+    public int sendIntentSender(IIntentSender target, IBinder allowlistToken, int code,
             Intent intent, String resolvedType,
             IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
         if (target instanceof PendingIntentRecord) {
             return ((PendingIntentRecord)target).sendWithResult(code, intent, resolvedType,
-                    whitelistToken, finishedReceiver, requiredPermission, options);
+                    allowlistToken, finishedReceiver, requiredPermission, options);
         } else {
             if (intent == null) {
                 // Weird case: someone has given us their own custom IIntentSender, and now
@@ -4832,7 +4860,7 @@
                 intent = new Intent(Intent.ACTION_MAIN);
             }
             try {
-                target.send(code, intent, resolvedType, whitelistToken, null,
+                target.send(code, intent, resolvedType, allowlistToken, null,
                         requiredPermission, options);
             } catch (RemoteException e) {
             }
@@ -4857,19 +4885,6 @@
     }
 
     @Override
-    public String getPackageForIntentSender(IIntentSender pendingResult) {
-        if (!(pendingResult instanceof PendingIntentRecord)) {
-            return null;
-        }
-        try {
-            PendingIntentRecord res = (PendingIntentRecord)pendingResult;
-            return res.key.packageName;
-        } catch (ClassCastException e) {
-        }
-        return null;
-    }
-
-    @Override
     public void registerIntentSenderCancelListener(IIntentSender sender, IResultReceiver receiver) {
         mPendingIntentController.registerIntentSenderCancelListener(sender, receiver);
     }
@@ -4881,15 +4896,17 @@
     }
 
     @Override
-    public int getUidForIntentSender(IIntentSender sender) {
+    public PendingIntentInfo getInfoForIntentSender(IIntentSender sender) {
         if (sender instanceof PendingIntentRecord) {
-            try {
-                PendingIntentRecord res = (PendingIntentRecord)sender;
-                return res.uid;
-            } catch (ClassCastException e) {
-            }
+            PendingIntentRecord res = (PendingIntentRecord) sender;
+            return new PendingIntentInfo(
+                    res.key.packageName,
+                    res.uid,
+                    (res.key.flags & PendingIntent.FLAG_IMMUTABLE) != 0,
+                    res.key.type);
+        } else {
+            throw new IllegalArgumentException();
         }
-        return -1;
     }
 
     @Override
@@ -4915,15 +4932,6 @@
     }
 
     @Override
-    public boolean isIntentSenderImmutable(IIntentSender pendingResult) {
-        if (pendingResult instanceof PendingIntentRecord) {
-            final PendingIntentRecord res = (PendingIntentRecord) pendingResult;
-            return (res.key.flags & PendingIntent.FLAG_IMMUTABLE) != 0;
-        }
-        return false;
-    }
-
-    @Override
     public boolean isIntentSenderAnActivity(IIntentSender pendingResult) {
         if (!(pendingResult instanceof PendingIntentRecord)) {
             return false;
@@ -4940,33 +4948,6 @@
     }
 
     @Override
-    public boolean isIntentSenderAForegroundService(IIntentSender pendingResult) {
-        if (pendingResult instanceof PendingIntentRecord) {
-            final PendingIntentRecord res = (PendingIntentRecord) pendingResult;
-            return res.key.type == ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE;
-        }
-        return false;
-    }
-
-    @Override
-    public boolean isIntentSenderAService(IIntentSender pendingResult) {
-        if (pendingResult instanceof PendingIntentRecord) {
-            final PendingIntentRecord res = (PendingIntentRecord) pendingResult;
-            return res.key.type == ActivityManager.INTENT_SENDER_SERVICE;
-        }
-        return false;
-    }
-
-    @Override
-    public boolean isIntentSenderABroadcast(IIntentSender pendingResult) {
-        if (pendingResult instanceof PendingIntentRecord) {
-            final PendingIntentRecord res = (PendingIntentRecord) pendingResult;
-            return res.key.type == ActivityManager.INTENT_SENDER_BROADCAST;
-        }
-        return false;
-    }
-
-    @Override
     public Intent getIntentForIntentSender(IIntentSender pendingResult) {
         enforceCallingPermission(Manifest.permission.GET_INTENT_SENDER_INTENT,
                 "getIntentForIntentSender()");
@@ -5447,7 +5428,7 @@
         }
         switch (appop) {
             case AppOpsManager.MODE_ALLOWED:
-                // If force-background-check is enabled, restrict all apps that aren't whitelisted.
+                // If force-background-check is enabled, restrict all apps that aren't allowlisted.
                 if (mForceBackgroundCheck &&
                         !UserHandle.isCore(uid) &&
                         !isOnDeviceIdleAllowlistLOSP(uid, /*allowExceptIdleToo=*/ true)) {
@@ -5483,7 +5464,7 @@
         if (uidOnBackgroundAllowlistLOSP(uid)) {
             if (DEBUG_BACKGROUND_CHECK) {
                 Slog.i(TAG, "App " + uid + "/" + packageName
-                        + " on background whitelist; not restricted in background");
+                        + " on background allowlist; not restricted in background");
             }
             return ActivityManager.APP_START_MODE_NORMAL;
         }
@@ -5492,7 +5473,7 @@
         if (isOnDeviceIdleAllowlistLOSP(uid, /*allowExceptIdleToo=*/ false)) {
             if (DEBUG_BACKGROUND_CHECK) {
                 Slog.i(TAG, "App " + uid + "/" + packageName
-                        + " on idle whitelist; not restricted in background");
+                        + " on idle allowlist; not restricted in background");
             }
             return ActivityManager.APP_START_MODE_NORMAL;
         }
@@ -5580,10 +5561,19 @@
                 || mPendingTempAllowlist.indexOfKey(uid) >= 0;
     }
 
+    /**
+     * Is the uid allowlisted to start FGS?
+     * @param uid
+     * @return a TempAllowListEntry if the uid is allowed.
+     *         null if the uid is not allowed.
+     */
+    @Nullable
     @GuardedBy(anyOf = {"this", "mProcLock"})
-    boolean isAllowlistedForFgsStartLOSP(int uid) {
-        return Arrays.binarySearch(mDeviceIdleExceptIdleAllowlist, UserHandle.getAppId(uid)) >= 0
-                || mFgsStartTempAllowList.isAllowed(uid);
+    FgsStartTempAllowList.TempFgsAllowListEntry isAllowlistedForFgsStartLOSP(int uid) {
+        if (Arrays.binarySearch(mDeviceIdleExceptIdleAllowlist, UserHandle.getAppId(uid)) >= 0) {
+            return FAKE_TEMP_ALLOWLIST_ENTRY;
+        }
+        return mFgsStartTempAllowList.getAllowedDurationAndReason(uid);
     }
 
     /**
@@ -6055,13 +6045,13 @@
     }
 
     @Override
-    public void backgroundWhitelistUid(final int uid) {
+    public void backgroundAllowlistUid(final int uid) {
         if (Binder.getCallingUid() != Process.SYSTEM_UID) {
-            throw new SecurityException("Only the OS may call backgroundWhitelistUid()");
+            throw new SecurityException("Only the OS may call backgroundAllowlistUid()");
         }
 
         if (DEBUG_BACKGROUND_CHECK) {
-            Slog.i(TAG, "Adding uid " + uid + " to bg uid whitelist");
+            Slog.i(TAG, "Adding uid " + uid + " to bg uid allowlist");
         }
         synchronized (this) {
             synchronized (mProcLock) {
@@ -6081,10 +6071,18 @@
                 abiOverride, zygotePolicyFlags);
     }
 
-    // TODO: Move to ProcessList?
     @GuardedBy("this")
     final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
             boolean disableHiddenApiChecks, String abiOverride, int zygotePolicyFlags) {
+        return addAppLocked(info, customProcess, isolated, disableHiddenApiChecks,
+                false /* disableTestApiChecks */, abiOverride, zygotePolicyFlags);
+    }
+
+    // TODO: Move to ProcessList?
+    @GuardedBy("this")
+    final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
+            boolean disableHiddenApiChecks, boolean disableTestApiChecks,
+            String abiOverride, int zygotePolicyFlags) {
         ProcessRecord app;
         if (!isolated) {
             app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName,
@@ -6119,7 +6117,8 @@
             mPersistentStartingProcesses.add(app);
             mProcessList.startProcessLocked(app, new HostingRecord("added application",
                     customProcess != null ? customProcess : app.processName),
-                    zygotePolicyFlags, disableHiddenApiChecks, abiOverride);
+                    zygotePolicyFlags, disableHiddenApiChecks, disableTestApiChecks,
+                    abiOverride);
         }
 
         return app;
@@ -6622,6 +6621,18 @@
     }
 
     @Override
+    public @ProcessCapability int getUidProcessCapabilities(int uid, String callingPackage) {
+        if (!hasUsageStatsPermission(callingPackage)) {
+            enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS,
+                    "getUidProcessState");
+        }
+
+        synchronized (mProcLock) {
+            return mProcessList.getUidProcessCapabilityLOSP(uid);
+        }
+    }
+
+    @Override
     public void registerUidObserver(IUidObserver observer, int which, int cutpoint,
             String callingPackage) {
         if (!hasUsageStatsPermission(callingPackage)) {
@@ -7237,6 +7248,9 @@
             final long memoryGrowthThreshold =
                     Math.max(totalMemoryInKb / 100, MINIMUM_MEMORY_GROWTH_THRESHOLD);
             mProcessList.forEachLruProcessesLOSP(false, proc -> {
+                if (proc.getThread() == null) {
+                    return;
+                }
                 final ProcessProfileRecord pr = proc.mProfile;
                 final ProcessStateRecord state = proc.mState;
                 final int setProcState = state.getSetProcState();
@@ -8273,18 +8287,23 @@
         mUserController.handleIncomingUser(callingPid, callingUid, userId, true, ALLOW_NON_FULL,
                 "getHistoricalProcessExitReasons", null);
 
+        NativeTombstoneManager tombstoneService = LocalServices.getService(
+                NativeTombstoneManager.class);
+
         final ArrayList<ApplicationExitInfo> results = new ArrayList<ApplicationExitInfo>();
         if (!TextUtils.isEmpty(packageName)) {
             final int uid = enforceDumpPermissionForPackage(packageName, userId, callingUid,
                       "getHistoricalProcessExitReasons");
-            if (uid != Process.INVALID_UID) {
+            if (uid != INVALID_UID) {
                 mProcessList.mAppExitInfoTracker.getExitInfo(
                         packageName, uid, pid, maxNum, results);
+                tombstoneService.collectTombstones(results, uid, pid, maxNum);
             }
         } else {
             // If no package name is given, use the caller's uid as the filter uid.
             mProcessList.mAppExitInfoTracker.getExitInfo(
                     packageName, callingUid, pid, maxNum, results);
+            tombstoneService.collectTombstones(results, callingUid, pid, maxNum);
         }
 
         return new ParceledListSlice<ApplicationExitInfo>(results);
@@ -8309,7 +8328,7 @@
     int enforceDumpPermissionForPackage(String packageName, int userId, int callingUid,
             String function) {
         final long identity = Binder.clearCallingIdentity();
-        int uid = Process.INVALID_UID;
+        int uid = INVALID_UID;
         try {
             uid = mPackageManagerInt.getPackageUid(packageName,
                     MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, userId);
@@ -8668,7 +8687,8 @@
             if (DUMP_ACTIVITIES_CMD.equals(cmd) || DUMP_ACTIVITIES_SHORT_CMD.equals(cmd)
                     || DUMP_LASTANR_CMD.equals(cmd) || DUMP_LASTANR_TRACES_CMD.equals(cmd)
                     || DUMP_STARTER_CMD.equals(cmd) || DUMP_CONTAINERS_CMD.equals(cmd)
-                    || DUMP_RECENTS_CMD.equals(cmd) || DUMP_RECENTS_SHORT_CMD.equals(cmd)) {
+                    || DUMP_RECENTS_CMD.equals(cmd) || DUMP_RECENTS_SHORT_CMD.equals(cmd)
+                    || DUMP_TOP_RESUMED_ACTIVITY.equals(cmd)) {
                 mAtmInternal.dump(
                         cmd, fd, pw, args, opti, true /* dumpAll */, dumpClient, dumpPackage);
             } else if ("binder-proxies".equals(cmd)) {
@@ -9200,6 +9220,8 @@
                     pw.println(ptw.tag);
                     pw.print(" ");
                     pw.print(ptw.type);
+                    pw.print(" ");
+                    pw.print(ptw.reasonCode);
                 }
             }
         }
@@ -9855,6 +9877,10 @@
             if (thread != null) {
                 pw.println("\n\n** Cache info for pid " + pid + " [" + r.processName + "] **");
                 pw.flush();
+                if (pid == MY_PID) {
+                    PropertyInvalidatedCache.dumpCacheInfo(fd, args);
+                    continue;
+                }
                 try {
                     TransferPipe tp = new TransferPipe();
                     try {
@@ -10057,6 +10083,7 @@
             ProcessList.PERSISTENT_SERVICE_ADJ, ProcessList.FOREGROUND_APP_ADJ,
             ProcessList.VISIBLE_APP_ADJ,
             ProcessList.PERCEPTIBLE_APP_ADJ, ProcessList.PERCEPTIBLE_LOW_APP_ADJ,
+            ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ,
             ProcessList.BACKUP_APP_ADJ, ProcessList.HEAVY_WEIGHT_APP_ADJ,
             ProcessList.SERVICE_ADJ, ProcessList.HOME_APP_ADJ,
             ProcessList.PREVIOUS_APP_ADJ, ProcessList.SERVICE_B_ADJ, ProcessList.CACHED_APP_MIN_ADJ
@@ -10064,7 +10091,7 @@
     static final String[] DUMP_MEM_OOM_LABEL = new String[] {
             "Native",
             "System", "Persistent", "Persistent Service", "Foreground",
-            "Visible", "Perceptible", "Perceptible Low",
+            "Visible", "Perceptible", "Perceptible Low", "Perceptible Medium",
             "Heavy Weight", "Backup",
             "A Services", "Home",
             "Previous", "B Services", "Cached"
@@ -10072,7 +10099,7 @@
     static final String[] DUMP_MEM_OOM_COMPACT_LABEL = new String[] {
             "native",
             "sys", "pers", "persvc", "fore",
-            "vis", "percept", "perceptl",
+            "vis", "percept", "perceptl", "perceptm",
             "heavy", "backup",
             "servicea", "home",
             "prev", "serviceb", "cached"
@@ -10380,6 +10407,8 @@
                     }
                     endTime = SystemClock.currentThreadTimeMillis();
                     hasSwapPss = mi.hasSwappedOutPss;
+                    memtrackGraphics = mi.getOtherPrivate(Debug.MemoryInfo.OTHER_GRAPHICS);
+                    memtrackGl = mi.getOtherPrivate(Debug.MemoryInfo.OTHER_GL);
                 } else {
                     reportType = ProcessStats.ADD_PSS_EXTERNAL;
                     startTime = SystemClock.currentThreadTimeMillis();
@@ -10531,6 +10560,8 @@
                         if (!Debug.getMemoryInfo(st.pid, info)) {
                             return;
                         }
+                        memtrackGraphics = info.getOtherPrivate(Debug.MemoryInfo.OTHER_GRAPHICS);
+                        memtrackGl = info.getOtherPrivate(Debug.MemoryInfo.OTHER_GL);
                     } else {
                         long pss = Debug.getPss(st.pid, tmpLong, memtrackTmp);
                         if (pss == 0) {
@@ -12548,7 +12579,7 @@
         BroadcastOptions brOptions = null;
         if (bOptions != null) {
             brOptions = new BroadcastOptions(bOptions);
-            if (brOptions.getTemporaryAppWhitelistDuration() > 0) {
+            if (brOptions.getTemporaryAppAllowlistDuration() > 0) {
                 // See if the caller is allowed to do this.  Note we are checking against
                 // the actual real caller (not whoever provided the operation as say a
                 // PendingIntent), because that who is actually supplied the arguments.
@@ -13549,8 +13580,6 @@
             if (disableHiddenApiChecks || disableTestApiChecks) {
                 enforceCallingPermission(android.Manifest.permission.DISABLE_HIDDEN_API_CHECKS,
                         "disable hidden API checks");
-
-                enableTestApiAccess(ai.packageName);
             }
 
             final long origId = Binder.clearCallingIdentity();
@@ -13568,8 +13597,8 @@
                         mUsageStatsService.reportEvent(ii.targetPackage, userId,
                                 UsageEvents.Event.SYSTEM_INTERACTION);
                     }
-                    app = addAppLocked(ai, defProcess, false, disableHiddenApiChecks, abiOverride,
-                            ZYGOTE_POLICY_FLAG_EMPTY);
+                    app = addAppLocked(ai, defProcess, false, disableHiddenApiChecks,
+                            disableTestApiChecks, abiOverride, ZYGOTE_POLICY_FLAG_EMPTY);
                 }
 
                 app.setActiveInstrumentation(activeInstr);
@@ -13724,25 +13753,6 @@
                     app.userId,
                     "finished inst");
         }
-
-        disableTestApiAccess(app.info.packageName);
-    }
-
-    private void enableTestApiAccess(String packageName) {
-        if (mPlatformCompat != null) {
-            Compatibility.ChangeConfig config = new Compatibility.ChangeConfig(
-                    Collections.singleton(166236554L /* VMRuntime.ALLOW_TEST_API_ACCESS */),
-                    Collections.emptySet());
-            CompatibilityChangeConfig override = new CompatibilityChangeConfig(config);
-            mPlatformCompat.setOverridesForTest(override, packageName);
-        }
-    }
-
-    private void disableTestApiAccess(String packageName) {
-        if (mPlatformCompat != null) {
-            mPlatformCompat.clearOverrideForTest(166236554L /* VMRuntime.ALLOW_TEST_API_ACCESS */,
-                    packageName);
-        }
     }
 
     public void finishInstrumentation(IApplicationThread target,
@@ -13951,7 +13961,7 @@
     }
 
     void noteUidProcessState(final int uid, final int state,
-                final @ActivityManager.ProcessCapability int capability) {
+                final @ProcessCapability int capability) {
         mBatteryStatsService.noteUidProcessState(uid, state);
         mAppOpsService.updateUidProcState(uid, state, capability);
         if (mTrackingAssociations) {
@@ -14002,6 +14012,9 @@
             final long uptimeSince = curUptime - mLastPowerCheckUptime;
             mLastPowerCheckUptime = curUptime;
             mProcessList.forEachLruProcessesLOSP(false, app -> {
+                if (app.getThread() == null) {
+                    return;
+                }
                 if (app.mState.getSetProcState() >= ActivityManager.PROCESS_STATE_HOME) {
                     int cpuLimit;
                     long checkDur = curUptime - app.mState.getWhenUnimportant();
@@ -14103,11 +14116,12 @@
                 mBatteryStatsService.reportExcessiveCpu(app.info.uid, app.processName,
                         uptimeSince, cputimeUsed);
                 app.getPkgList().forEachPackageProcessStats(holder -> {
+                    final ProcessState state = holder.state;
                     FrameworkStatsLog.write(
                             FrameworkStatsLog.EXCESSIVE_CPU_USAGE_REPORTED,
                             app.info.uid,
                             processName,
-                            holder.state.getPackage(),
+                            state != null ? state.getPackage() : app.info.packageName,
                             holder.appVersion);
                 });
                 return true;
@@ -14447,8 +14461,8 @@
      */
     @GuardedBy("this")
     void tempAllowlistForPendingIntentLocked(int callerPid, int callerUid, int targetUid,
-            long duration, int type, String tag) {
-        if (DEBUG_WHITELISTS) {
+            long duration, int type, @ReasonCode int reasonCode, String reason) {
+        if (DEBUG_ALLOWLISTS) {
             Slog.d(TAG, "tempAllowlistForPendingIntentLocked(" + callerPid + ", " + callerUid + ", "
                     + targetUid + ", " + duration + ", " + type + ")");
         }
@@ -14467,7 +14481,7 @@
                         != PackageManager.PERMISSION_GRANTED
                         && checkPermission(START_FOREGROUND_SERVICES_FROM_BACKGROUND, callerPid,
                         callerUid) != PackageManager.PERMISSION_GRANTED) {
-                    if (DEBUG_WHITELISTS) {
+                    if (DEBUG_ALLOWLISTS) {
                         Slog.d(TAG, "tempAllowlistForPendingIntentLocked() for target " + targetUid
                                 + ": pid " + callerPid + " is not allowed");
                     }
@@ -14476,22 +14490,23 @@
             }
         }
 
-        tempAllowlistUidLocked(targetUid, duration, tag, type);
+        tempAllowlistUidLocked(targetUid, duration, reasonCode, reason, type, callerUid);
     }
 
     /**
      * Allowlists {@code targetUid} to temporarily bypass Power Save mode.
      */
     @GuardedBy("this")
-    void tempAllowlistUidLocked(int targetUid, long duration, String tag, int type) {
+    void tempAllowlistUidLocked(int targetUid, long duration, @ReasonCode int reasonCode,
+            String reason, int type, int callingUid) {
         synchronized (mProcLock) {
             mPendingTempAllowlist.put(targetUid,
-                    new PendingTempAllowlist(targetUid, duration, tag, type));
+                    new PendingTempAllowlist(targetUid, duration, reasonCode, reason, type));
             setUidTempAllowlistStateLSP(targetUid, true);
             mUiHandler.obtainMessage(PUSH_TEMP_ALLOWLIST_UI_MSG).sendToTarget();
 
-            if (type == TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED) {
-                mFgsStartTempAllowList.add(targetUid, duration);
+            if (type == TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED) {
+                mFgsStartTempAllowList.add(targetUid, duration, reasonCode, reason, callingUid);
             }
         }
     }
@@ -14517,7 +14532,7 @@
             for (int i = 0; i < N; i++) {
                 PendingTempAllowlist ptw = list[i];
                 mLocalDeviceIdleController.addPowerSaveTempWhitelistAppDirect(ptw.targetUid,
-                        ptw.duration, ptw.type, true, ptw.tag);
+                        ptw.duration, ptw.type, true, ptw.reasonCode, ptw.tag);
             }
         }
 
@@ -15105,10 +15120,10 @@
         }
 
         @Override
-        public void setPendingIntentWhitelistDuration(IIntentSender target, IBinder whitelistToken,
-                long duration, int type) {
-            mPendingIntentController.setPendingIntentWhitelistDuration(target, whitelistToken,
-                    duration, type);
+        public void setPendingIntentAllowlistDuration(IIntentSender target, IBinder allowlistToken,
+                long duration, int type, @ReasonCode int reasonCode, @Nullable String reason) {
+            mPendingIntentController.setPendingIntentAllowlistDuration(target, allowlistToken,
+                    duration, type, reasonCode, reason);
         }
 
         @Override
@@ -15118,32 +15133,32 @@
 
         @Override
         public void setPendingIntentAllowBgActivityStarts(IIntentSender target,
-                IBinder whitelistToken, int flags) {
+                IBinder allowlistToken, int flags) {
             if (!(target instanceof PendingIntentRecord)) {
                 Slog.w(TAG, "setPendingIntentAllowBgActivityStarts():"
                         + " not a PendingIntentRecord: " + target);
                 return;
             }
             synchronized (ActivityManagerService.this) {
-                ((PendingIntentRecord) target).setAllowBgActivityStarts(whitelistToken, flags);
+                ((PendingIntentRecord) target).setAllowBgActivityStarts(allowlistToken, flags);
             }
         }
 
         @Override
         public void clearPendingIntentAllowBgActivityStarts(IIntentSender target,
-                IBinder whitelistToken) {
+                IBinder allowlistToken) {
             if (!(target instanceof PendingIntentRecord)) {
                 Slog.w(TAG, "clearPendingIntentAllowBgActivityStarts():"
                         + " not a PendingIntentRecord: " + target);
                 return;
             }
             synchronized (ActivityManagerService.this) {
-                ((PendingIntentRecord) target).clearAllowBgActivityStarts(whitelistToken);
+                ((PendingIntentRecord) target).clearAllowBgActivityStarts(allowlistToken);
             }
         }
 
         @Override
-        public void setDeviceIdleWhitelist(int[] allAppids, int[] exceptIdleAppids) {
+        public void setDeviceIdleAllowlist(int[] allAppids, int[] exceptIdleAppids) {
             synchronized (ActivityManagerService.this) {
                 synchronized (mProcLock) {
                     mDeviceIdleAllowlist = allAppids;
@@ -15153,17 +15168,19 @@
         }
 
         @Override
-        public void updateDeviceIdleTempWhitelist(int[] appids, int changingUid, boolean adding,
-                long durationMs, @TempAllowListType int type) {
+        public void updateDeviceIdleTempAllowlist(int[] appids, int changingUid, boolean adding,
+                long durationMs, @TempAllowListType int type, @ReasonCode int reasonCode,
+                @Nullable String reason, int callingUid) {
             synchronized (ActivityManagerService.this) {
                 synchronized (mProcLock) {
                     mDeviceIdleTempAllowlist = appids;
                     if (adding) {
-                        if (type == TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED) {
-                            mFgsStartTempAllowList.add(changingUid, durationMs);
+                        if (type == TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED) {
+                            mFgsStartTempAllowList.add(changingUid, durationMs, reasonCode, reason,
+                                    callingUid);
                         }
+                        setAppIdTempAllowlistStateLSP(changingUid, adding);
                     }
-                    setAppIdTempAllowlistStateLSP(changingUid, adding);
                 }
             }
         }
@@ -15524,11 +15541,11 @@
         }
 
         @Override
-        public void tempWhitelistForPendingIntent(int callerPid, int callerUid, int targetUid,
-                long duration, int type, String tag) {
+        public void tempAllowlistForPendingIntent(int callerPid, int callerUid, int targetUid,
+                long duration, int type, @ReasonCode int reasonCode, String reason) {
             synchronized (ActivityManagerService.this) {
                 ActivityManagerService.this.tempAllowlistForPendingIntentLocked(
-                        callerPid, callerUid, targetUid, duration, type, tag);
+                        callerPid, callerUid, targetUid, duration, type, reasonCode, reason);
             }
         }
 
diff --git a/services/core/java/com/android/server/am/AppErrorDialog.java b/services/core/java/com/android/server/am/AppErrorDialog.java
index 48222cb..a9e5571 100644
--- a/services/core/java/com/android/server/am/AppErrorDialog.java
+++ b/services/core/java/com/android/server/am/AppErrorDialog.java
@@ -18,10 +18,7 @@
 
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 
-import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.res.Resources;
 import android.os.Build;
 import android.os.Bundle;
@@ -138,19 +135,6 @@
         findViewById(com.android.internal.R.id.customPanel).setVisibility(View.VISIBLE);
     }
 
-    @Override
-    public void onStart() {
-        super.onStart();
-        getContext().registerReceiver(mReceiver,
-                new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
-    }
-
-    @Override
-    protected void onStop() {
-        super.onStop();
-        getContext().unregisterReceiver(mReceiver);
-    }
-
     private final Handler mHandler = new Handler() {
         public void handleMessage(Message msg) {
             setResult(msg.what);
@@ -204,15 +188,6 @@
         }
     }
 
-    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
-                cancel();
-            }
-        }
-    };
-
     static class Data {
         AppErrorResult result;
         int taskId;
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index e5a5cff..3602f44 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -29,6 +29,7 @@
 
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
+import android.app.AnrController;
 import android.app.ApplicationErrorReport;
 import android.app.ApplicationExitInfo;
 import android.content.ActivityNotFoundException;
@@ -1058,7 +1059,26 @@
                     Settings.Secure.ANR_SHOW_BACKGROUND, 0,
                     mService.mUserController.getCurrentUserId()) != 0;
             if (mService.mAtmInternal.canShowErrorDialogs() || showBackground) {
-                errState.getDialogController().showAnrDialogs(data);
+                AnrController anrController = errState.getDialogController().getAnrController();
+                if (anrController == null) {
+                    errState.getDialogController().showAnrDialogs(data);
+                } else {
+                    String packageName = proc.info.packageName;
+                    int uid = proc.info.uid;
+                    boolean showDialog = anrController.onAnrDelayCompleted(packageName, uid);
+
+                    if (showDialog) {
+                        Slog.d(TAG, "ANR delay completed. Showing ANR dialog for package: "
+                                + packageName);
+                        errState.getDialogController().showAnrDialogs(data);
+                    } else {
+                        Slog.d(TAG, "ANR delay completed. Cancelling ANR dialog for package: "
+                                + packageName);
+                        errState.setNotResponding(false);
+                        errState.setNotRespondingReport(null);
+                        errState.getDialogController().clearAnrDialogs();
+                    }
+                }
             } else {
                 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
                         AppNotRespondingDialog.CANT_SHOW);
diff --git a/services/core/java/com/android/server/am/AppExitInfoTracker.java b/services/core/java/com/android/server/am/AppExitInfoTracker.java
index 17be210..b85d729 100644
--- a/services/core/java/com/android/server/am/AppExitInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppExitInfoTracker.java
@@ -63,8 +63,10 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.IoThread;
+import com.android.server.LocalServices;
 import com.android.server.ServiceThread;
 import com.android.server.SystemServiceManager;
+import com.android.server.os.NativeTombstoneManager;
 
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
@@ -78,6 +80,7 @@
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
+import java.util.Optional;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.BiConsumer;
@@ -762,6 +765,10 @@
      * Helper function for shell command
      */
     void clearHistoryProcessExitInfo(String packageName, int userId) {
+        NativeTombstoneManager tombstoneService = LocalServices.getService(
+                NativeTombstoneManager.class);
+        Optional<Integer> appId = Optional.empty();
+
         if (TextUtils.isEmpty(packageName)) {
             synchronized (mLock) {
                 removeByUserIdLocked(userId);
@@ -769,10 +776,13 @@
         } else {
             final int uid = mService.mPackageManagerInt.getPackageUid(packageName,
                     PackageManager.MATCH_ALL, userId);
+            appId = Optional.of(UserHandle.getAppId(uid));
             synchronized (mLock) {
                 removePackageLocked(packageName, uid, true, userId);
             }
         }
+
+        tombstoneService.purge(Optional.of(userId), appId);
         schedulePersistProcessExitInfo(true);
     }
 
diff --git a/services/core/java/com/android/server/am/AppNotRespondingDialog.java b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
index 77d2898..b233a2c 100644
--- a/services/core/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
@@ -181,6 +181,11 @@
         }
     };
 
+    @Override
+    protected void closeDialog() {
+        mHandler.obtainMessage(FORCE_CLOSE).sendToTarget();
+    }
+
     static class Data {
         final ProcessRecord proc;
         final ApplicationInfo aInfo;
diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java
index c8630fa..f8494d8 100644
--- a/services/core/java/com/android/server/am/AppProfiler.java
+++ b/services/core/java/com/android/server/am/AppProfiler.java
@@ -1327,6 +1327,8 @@
         // Get a list of Stats that have vsize > 0
         final List<ProcessCpuTracker.Stats> stats = getCpuStats(st -> st.vsize > 0);
         final int statsCount = stats.size();
+        long totalMemtrackGraphics = 0;
+        long totalMemtrackGl = 0;
         for (int i = 0; i < statsCount; i++) {
             ProcessCpuTracker.Stats st = stats.get(i);
             long pss = Debug.getPss(st.pid, swaptrackTmp, memtrackTmp);
@@ -1337,6 +1339,8 @@
                     mi.pss = pss;
                     mi.swapPss = swaptrackTmp[1];
                     mi.memtrack = memtrackTmp[0];
+                    totalMemtrackGraphics += memtrackTmp[1];
+                    totalMemtrackGl += memtrackTmp[2];
                     memInfos.add(mi);
                 }
             }
@@ -1345,20 +1349,18 @@
         long totalPss = 0;
         long totalSwapPss = 0;
         long totalMemtrack = 0;
-        long totalMemtrackGraphics = 0;
-        long totalMemtrackGl = 0;
         for (int i = 0, size = memInfos.size(); i < size; i++) {
             ProcessMemInfo mi = memInfos.get(i);
             if (mi.pss == 0) {
                 mi.pss = Debug.getPss(mi.pid, swaptrackTmp, memtrackTmp);
                 mi.swapPss = swaptrackTmp[1];
                 mi.memtrack = memtrackTmp[0];
+                totalMemtrackGraphics += memtrackTmp[1];
+                totalMemtrackGl += memtrackTmp[2];
             }
             totalPss += mi.pss;
             totalSwapPss += mi.swapPss;
             totalMemtrack += mi.memtrack;
-            totalMemtrackGraphics += memtrackTmp[1];
-            totalMemtrackGl += memtrackTmp[2];
         }
         Collections.sort(memInfos, new Comparator<ProcessMemInfo>() {
             @Override public int compare(ProcessMemInfo lhs, ProcessMemInfo rhs) {
diff --git a/services/core/java/com/android/server/am/AppWaitingForDebuggerDialog.java b/services/core/java/com/android/server/am/AppWaitingForDebuggerDialog.java
index 3ce2471..262e795 100644
--- a/services/core/java/com/android/server/am/AppWaitingForDebuggerDialog.java
+++ b/services/core/java/com/android/server/am/AppWaitingForDebuggerDialog.java
@@ -61,6 +61,11 @@
     public void onStop() {
     }
 
+    @Override
+    protected void closeDialog() {
+        /* Do nothing */
+    }
+
     private final Handler mHandler = new Handler() {
         public void handleMessage(Message msg) {
             switch (msg.what) {
diff --git a/services/core/java/com/android/server/am/BaseErrorDialog.java b/services/core/java/com/android/server/am/BaseErrorDialog.java
index aabb587..7b5f2cd 100644
--- a/services/core/java/com/android/server/am/BaseErrorDialog.java
+++ b/services/core/java/com/android/server/am/BaseErrorDialog.java
@@ -16,16 +16,19 @@
 
 package com.android.server.am;
 
-import com.android.internal.R;
-
 import android.app.AlertDialog;
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.os.Handler;
 import android.os.Message;
 import android.view.KeyEvent;
 import android.view.WindowManager;
 import android.widget.Button;
 
+import com.android.internal.R;
+
 public class BaseErrorDialog extends AlertDialog {
     private static final int ENABLE_BUTTONS = 0;
     private static final int DISABLE_BUTTONS = 1;
@@ -44,10 +47,19 @@
         getWindow().setAttributes(attrs);
     }
 
+    @Override
     public void onStart() {
         super.onStart();
         mHandler.sendEmptyMessage(DISABLE_BUTTONS);
         mHandler.sendMessageDelayed(mHandler.obtainMessage(ENABLE_BUTTONS), 1000);
+        getContext().registerReceiver(mReceiver,
+                new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+        getContext().unregisterReceiver(mReceiver);
     }
 
     public boolean dispatchKeyEvent(KeyEvent event) {
@@ -84,4 +96,24 @@
             }
         }
     };
+
+    /**
+     * Called when received ACTION_CLOSE_SYSTEM_DIALOGS.
+     */
+    protected void closeDialog() {
+        if (mCancelable) {
+            cancel();
+        } else {
+            dismiss();
+        }
+    }
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
+                closeDialog();
+            }
+        }
+    };
 }
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 6500f6d..167c2b1 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -216,6 +216,8 @@
             return;
         }
 
+        if (results == null) return;
+
         for (int i = 0; i < results.length; i++) {
             final StateResidencyResult result = results[i];
             RpmStats.PowerStateSubsystem subsystem =
@@ -257,7 +259,7 @@
             return EMPTY;
         }
 
-        if (results.length == 0) return EMPTY;
+        if (results == null || results.length == 0) return EMPTY;
 
         int charsLeft = MAX_LOW_POWER_STATS_SIZE;
         StringBuilder builder = new StringBuilder("SubsystemPowerState");
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 8b6fabd..2906193 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -22,6 +22,7 @@
 
 import static com.android.server.am.ActivityManagerDebugConfig.*;
 
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
@@ -43,6 +44,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.PowerWhitelistManager;
 import android.os.PowerWhitelistManager.TempAllowListType;
 import android.os.Process;
 import android.os.RemoteException;
@@ -825,7 +827,8 @@
                         r.resultExtras, r.ordered, r.initialSticky, r.userId);
                 // parallel broadcasts are fire-and-forget, not bookended by a call to
                 // finishReceiverLocked(), so we manage their activity-start token here
-                if (r.allowBackgroundActivityStarts && !r.ordered) {
+                if (filter.receiverList.app != null
+                        && r.allowBackgroundActivityStarts && !r.ordered) {
                     postActivityStartTokenRemoval(filter.receiverList.app, r);
                 }
             }
@@ -902,8 +905,9 @@
         return false;
     }
 
-    final void scheduleTempWhitelistLocked(int uid, long duration, BroadcastRecord r,
-            @TempAllowListType int type) {
+    final void scheduleTempAllowlistLocked(int uid, long duration, BroadcastRecord r,
+            @TempAllowListType int type, @PowerWhitelistManager.ReasonCode int reasonCode,
+            @Nullable String reason) {
         if (duration > Integer.MAX_VALUE) {
             duration = Integer.MAX_VALUE;
         }
@@ -925,10 +929,11 @@
             b.append(r.intent.getData());
         }
         if (DEBUG_BROADCAST) {
-            Slog.v(TAG, "Broadcast temp whitelist uid=" + uid + " duration=" + duration
+            Slog.v(TAG, "Broadcast temp allowlist uid=" + uid + " duration=" + duration
                     + " type=" + type + " : " + b.toString());
         }
-        mService.tempAllowlistUidLocked(uid, duration, b.toString(), type);
+        mService.tempAllowlistUidLocked(uid, duration, reasonCode, b.toString(), type,
+                r.callingUid);
     }
 
     /**
@@ -1331,10 +1336,12 @@
                     // r is guaranteed ordered at this point, so we know finishReceiverLocked()
                     // will get a callback and handle the activity start token lifecycle.
                 }
-                if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
-                    scheduleTempWhitelistLocked(filter.owningUid,
-                            brOptions.getTemporaryAppWhitelistDuration(), r,
-                            brOptions.getTemporaryAppWhitelistType());
+                if (brOptions != null && brOptions.getTemporaryAppAllowlistDuration() > 0) {
+                    scheduleTempAllowlistLocked(filter.owningUid,
+                            brOptions.getTemporaryAppAllowlistDuration(), r,
+                            brOptions.getTemporaryAppAllowlistType(),
+                            brOptions.getTemporaryAppAllowlistReasonCode(),
+                            brOptions.getTemporaryAppAllowlistReason());
                 }
             }
             return;
@@ -1618,11 +1625,13 @@
         }
 
         final boolean isActivityCapable =
-                (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0);
+                (brOptions != null && brOptions.getTemporaryAppAllowlistDuration() > 0);
         if (isActivityCapable) {
-            scheduleTempWhitelistLocked(receiverUid,
-                    brOptions.getTemporaryAppWhitelistDuration(), r,
-                    brOptions.getTemporaryAppWhitelistType());
+            scheduleTempAllowlistLocked(receiverUid,
+                    brOptions.getTemporaryAppAllowlistDuration(), r,
+                    brOptions.getTemporaryAppAllowlistType(),
+                    brOptions.getTemporaryAppAllowlistReasonCode(),
+                    brOptions.getTemporaryAppAllowlistReason());
         }
 
         // Broadcast is being executed, its package can't be stopped.
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 7bdf43c..c5f082a 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -66,6 +66,10 @@
     @VisibleForTesting static final String KEY_COMPACT_THROTTLE_4 = "compact_throttle_4";
     @VisibleForTesting static final String KEY_COMPACT_THROTTLE_5 = "compact_throttle_5";
     @VisibleForTesting static final String KEY_COMPACT_THROTTLE_6 = "compact_throttle_6";
+    @VisibleForTesting static final String KEY_COMPACT_THROTTLE_MIN_OOM_ADJ =
+            "compact_throttle_min_oom_adj";
+    @VisibleForTesting static final String KEY_COMPACT_THROTTLE_MAX_OOM_ADJ =
+            "compact_throttle_max_oom_adj";
     @VisibleForTesting static final String KEY_COMPACT_STATSD_SAMPLE_RATE =
             "compact_statsd_sample_rate";
     @VisibleForTesting static final String KEY_FREEZER_STATSD_SAMPLE_RATE =
@@ -101,6 +105,10 @@
     @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_4 = 10_000;
     @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_5 = 10 * 60 * 1000;
     @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_6 = 10 * 60 * 1000;
+    @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ =
+            ProcessList.CACHED_APP_MIN_ADJ;
+    @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ =
+            ProcessList.CACHED_APP_MAX_ADJ;
     // The sampling rate to push app compaction events into statsd for upload.
     @VisibleForTesting static final float DEFAULT_STATSD_SAMPLE_RATE = 0.1f;
     @VisibleForTesting static final long DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB = 12_000L;
@@ -186,6 +194,10 @@
                                 updateFullDeltaRssThrottle();
                             } else if (KEY_COMPACT_PROC_STATE_THROTTLE.equals(name)) {
                                 updateProcStateThrottle();
+                            } else if (KEY_COMPACT_THROTTLE_MIN_OOM_ADJ.equals(name)) {
+                                updateMinOomAdjThrottle();
+                            } else if (KEY_COMPACT_THROTTLE_MAX_OOM_ADJ.equals(name)) {
+                                updateMaxOomAdjThrottle();
                             }
                         }
                     }
@@ -217,6 +229,12 @@
     @GuardedBy("mPhenotypeFlagLock")
     @VisibleForTesting volatile long mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6;
     @GuardedBy("mPhenotypeFlagLock")
+    @VisibleForTesting volatile long mCompactThrottleMinOomAdj =
+            DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ;
+    @GuardedBy("mPhenotypeFlagLock")
+    @VisibleForTesting volatile long mCompactThrottleMaxOomAdj =
+            DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ;
+    @GuardedBy("mPhenotypeFlagLock")
     private volatile boolean mUseCompaction = DEFAULT_USE_COMPACTION;
     private volatile boolean mUseFreezer = DEFAULT_USE_FREEZER;
     @GuardedBy("this")
@@ -282,6 +300,7 @@
      * starts the background thread if necessary.
      */
     public void init() {
+        // TODO: initialize flags to default and only update them if values are set in DeviceConfig
         DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                 ActivityThread.currentApplication().getMainExecutor(), mOnFlagsChangedListener);
         synchronized (mPhenotypeFlagLock) {
@@ -294,6 +313,8 @@
             updateFullDeltaRssThrottle();
             updateProcStateThrottle();
             updateUseFreezer();
+            updateMinOomAdjThrottle();
+            updateMaxOomAdjThrottle();
         }
     }
 
@@ -328,6 +349,8 @@
             pw.println("  " + KEY_COMPACT_THROTTLE_4 + "=" + mCompactThrottleFullFull);
             pw.println("  " + KEY_COMPACT_THROTTLE_5 + "=" + mCompactThrottleBFGS);
             pw.println("  " + KEY_COMPACT_THROTTLE_6 + "=" + mCompactThrottlePersistent);
+            pw.println("  " + KEY_COMPACT_THROTTLE_MIN_OOM_ADJ + "=" + mCompactThrottleMinOomAdj);
+            pw.println("  " + KEY_COMPACT_THROTTLE_MAX_OOM_ADJ + "=" + mCompactThrottleMaxOomAdj);
             pw.println("  " + KEY_COMPACT_STATSD_SAMPLE_RATE + "=" + mCompactStatsdSampleRate);
             pw.println("  " + KEY_COMPACT_FULL_RSS_THROTTLE_KB + "="
                     + mFullAnonRssThrottleKb);
@@ -367,12 +390,23 @@
 
     @GuardedBy("mProcLock")
     void compactAppFull(ProcessRecord app) {
-        app.mOptRecord.setReqCompactAction(COMPACT_PROCESS_FULL);
-        mPendingCompactionProcesses.add(app);
-        mCompactionHandler.sendMessage(
+        // Apply OOM adj score throttle for Full App Compaction.
+        if ((app.mState.getSetAdj() < mCompactThrottleMinOomAdj
+                || app.mState.getSetAdj() > mCompactThrottleMaxOomAdj)
+                && app.mState.getCurAdj() >= mCompactThrottleMinOomAdj
+                && app.mState.getCurAdj() <= mCompactThrottleMaxOomAdj) {
+            app.mOptRecord.setReqCompactAction(COMPACT_PROCESS_FULL);
+            mPendingCompactionProcesses.add(app);
+            mCompactionHandler.sendMessage(
                 mCompactionHandler.obtainMessage(
-                COMPACT_PROCESS_MSG, app.mState.getSetAdj(), app.mState.getSetProcState()));
-
+                    COMPACT_PROCESS_MSG, app.mState.getSetAdj(), app.mState.getSetProcState()));
+        } else {
+            if (DEBUG_COMPACTION) {
+                Slog.d(TAG_AM, "Skipping full compaction for " + app.processName
+                        + " oom adj score changed from " + app.mState.getSetAdj()
+                        + " to " + app.mState.getCurAdj());
+            }
+        }
     }
 
     @GuardedBy("mProcLock")
@@ -502,18 +536,6 @@
     }
 
     /**
-     * Enable or disable the freezer. When enable == false all frozen processes are unfrozen,
-     * but aren't removed from the freezer. While in this state, processes can be added or removed
-     * by using Process.setProcessFrozen(), but they wouldn't be actually frozen until the freezer
-     * is enabled. If enable == true all processes in the freezer are frozen.
-     *
-     * @param enable Specify whether to enable (true) or disable (false) the freezer.
-     *
-     * @hide
-     */
-    private static native void enableFreezerInternal(boolean enable);
-
-    /**
      * Informs binder that a process is about to be frozen. If freezer is enabled on a process via
      * this method, this method will synchronously dispatch all pending transactions to the
      * specified pid. This method will not add significant latencies when unfreezing.
@@ -556,10 +578,6 @@
 
             if (state == '1' || state == '0') {
                 supported = true;
-                // This is a workaround after reverting the cgroup v2 uid/pid hierarchy due to
-                // http://b/179006802.
-                // TODO: remove once the uid/pid hierarchy is restored
-                enableFreezerInternal(true);
             } else {
                 Slog.e(TAG_AM, "unexpected value in cgroup.freeze");
             }
@@ -629,6 +647,7 @@
     @GuardedBy("mPhenotypeFlagLock")
     private void updateCompactionThrottles() {
         boolean useThrottleDefaults = false;
+        // TODO: improve efficiency by calling DeviceConfig only once for all flags.
         String throttleSomeSomeFlag =
                 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                     KEY_COMPACT_THROTTLE_1);
@@ -647,12 +666,20 @@
         String throttlePersistentFlag =
                 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                     KEY_COMPACT_THROTTLE_6);
+        String throttleMinOomAdjFlag =
+                DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                    KEY_COMPACT_THROTTLE_MIN_OOM_ADJ);
+        String throttleMaxOomAdjFlag =
+                DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                    KEY_COMPACT_THROTTLE_MAX_OOM_ADJ);
 
         if (TextUtils.isEmpty(throttleSomeSomeFlag) || TextUtils.isEmpty(throttleSomeFullFlag)
                 || TextUtils.isEmpty(throttleFullSomeFlag)
                 || TextUtils.isEmpty(throttleFullFullFlag)
                 || TextUtils.isEmpty(throttleBFGSFlag)
-                || TextUtils.isEmpty(throttlePersistentFlag)) {
+                || TextUtils.isEmpty(throttlePersistentFlag)
+                || TextUtils.isEmpty(throttleMinOomAdjFlag)
+                || TextUtils.isEmpty(throttleMaxOomAdjFlag)) {
             // Set defaults for all if any are not set.
             useThrottleDefaults = true;
         } else {
@@ -663,6 +690,8 @@
                 mCompactThrottleFullFull = Integer.parseInt(throttleFullFullFlag);
                 mCompactThrottleBFGS = Integer.parseInt(throttleBFGSFlag);
                 mCompactThrottlePersistent = Integer.parseInt(throttlePersistentFlag);
+                mCompactThrottleMinOomAdj = Long.parseLong(throttleMinOomAdjFlag);
+                mCompactThrottleMaxOomAdj = Long.parseLong(throttleMaxOomAdjFlag);
             } catch (NumberFormatException e) {
                 useThrottleDefaults = true;
             }
@@ -675,6 +704,8 @@
             mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4;
             mCompactThrottleBFGS = DEFAULT_COMPACT_THROTTLE_5;
             mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6;
+            mCompactThrottleMinOomAdj = DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ;
+            mCompactThrottleMaxOomAdj = DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ;
         }
     }
 
@@ -729,6 +760,28 @@
         }
     }
 
+    @GuardedBy("mPhenotypeFlagLock")
+    private void updateMinOomAdjThrottle() {
+        mCompactThrottleMinOomAdj = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+            KEY_COMPACT_THROTTLE_MIN_OOM_ADJ, DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ);
+
+        // Should only compact cached processes.
+        if (mCompactThrottleMinOomAdj < ProcessList.CACHED_APP_MIN_ADJ) {
+            mCompactThrottleMinOomAdj = DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ;
+        }
+    }
+
+    @GuardedBy("mPhenotypeFlagLock")
+    private void updateMaxOomAdjThrottle() {
+        mCompactThrottleMaxOomAdj = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+            KEY_COMPACT_THROTTLE_MAX_OOM_ADJ, DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ);
+
+        // Should only compact cached processes.
+        if (mCompactThrottleMaxOomAdj > ProcessList.CACHED_APP_MAX_ADJ) {
+            mCompactThrottleMaxOomAdj = DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ;
+        }
+    }
+
     private boolean parseProcStateThrottle(String procStateThrottleString) {
         String[] procStates = TextUtils.split(procStateThrottleString, ",");
         mProcStateThrottle.clear();
diff --git a/services/core/java/com/android/server/am/ErrorDialogController.java b/services/core/java/com/android/server/am/ErrorDialogController.java
index ef135d5..f23d309 100644
--- a/services/core/java/com/android/server/am/ErrorDialogController.java
+++ b/services/core/java/com/android/server/am/ErrorDialogController.java
@@ -16,6 +16,8 @@
 
 package com.android.server.am;
 
+import android.annotation.Nullable;
+import android.app.AnrController;
 import android.app.Dialog;
 import android.content.Context;
 
@@ -57,6 +59,13 @@
     @GuardedBy("mProcLock")
     private AppWaitingForDebuggerDialog mWaitDialog;
 
+    /**
+     * ANR dialog controller
+     */
+    @GuardedBy("mProcLock")
+    @Nullable
+    private AnrController mAnrController;
+
     @GuardedBy("mProcLock")
     boolean hasCrashDialogs() {
         return mCrashDialogs != null;
@@ -118,6 +127,7 @@
         }
         forAllDialogs(mAnrDialogs, Dialog::dismiss);
         mAnrDialogs = null;
+        mAnrController = null;
     }
 
     @GuardedBy("mProcLock")
@@ -220,6 +230,17 @@
         });
     }
 
+    @GuardedBy("mProcLock")
+    @Nullable
+    AnrController getAnrController() {
+        return mAnrController;
+    }
+
+    @GuardedBy("mProcLock")
+    void setAnrController(AnrController controller) {
+        mAnrController = controller;
+    }
+
     /**
      * Helper function to collect contexts from crashed app located displays.
      *
diff --git a/services/core/java/com/android/server/am/FgsStartTempAllowList.java b/services/core/java/com/android/server/am/FgsStartTempAllowList.java
index 4d8749c..1f897b5 100644
--- a/services/core/java/com/android/server/am/FgsStartTempAllowList.java
+++ b/services/core/java/com/android/server/am/FgsStartTempAllowList.java
@@ -18,24 +18,53 @@
 
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 
+import android.annotation.Nullable;
+import android.os.PowerWhitelistManager.ReasonCode;
 import android.os.SystemClock;
 import android.util.Slog;
-import android.util.SparseLongArray;
+import android.util.SparseArray;
 
 /**
  * List of uids that are temporarily allowed to start FGS from background.
  */
 final class FgsStartTempAllowList {
     private static final int MAX_SIZE = 100;
+
+    public static final class TempFgsAllowListEntry {
+        final long mExpirationTime;
+        final long mDuration;
+        final @ReasonCode int mReasonCode;
+        final String mReason;
+        final int mCallingUid;
+
+        TempFgsAllowListEntry(long expirationTime, long duration, @ReasonCode int reasonCode,
+                String reason, int callingUid) {
+            mExpirationTime = expirationTime;
+            mDuration = duration;
+            mReasonCode = reasonCode;
+            mReason = reason;
+            mCallingUid = callingUid;
+        }
+    }
+
     /**
-     * The key is the uid, the value is expiration elapse time in ms of this temp-allowed uid.
+     * The key is the uid, the value is a TempAllowListEntry.
      */
-    private final SparseLongArray mTempAllowListFgs = new SparseLongArray();
+    private final SparseArray<TempFgsAllowListEntry> mTempAllowListFgs = new SparseArray<>();
 
     FgsStartTempAllowList() {
     }
 
-    void add(int uid, long duration) {
+    /**
+     * Add a uid and its duration with reason into the FGS temp-allowlist.
+     * @param uid
+     * @param duration temp-allowlisted duration in milliseconds.
+     * @param reason A human-readable reason for logging purposes.
+     * @param callingUid the callingUid that setup this temp allowlist, only valid when param adding
+     *                   is true.
+     */
+    void add(int uid, long duration, @ReasonCode int reasonCode, @Nullable String reason,
+            int callingUid) {
         if (duration <= 0) {
             Slog.e(TAG_AM, "FgsStartTempAllowList bad duration:" + duration + " uid: "
                     + uid);
@@ -48,26 +77,36 @@
         }
         final long now = SystemClock.elapsedRealtime();
         for (int index = mTempAllowListFgs.size() - 1; index >= 0; index--) {
-            if (mTempAllowListFgs.valueAt(index) < now) {
+            if (mTempAllowListFgs.valueAt(index).mExpirationTime < now) {
                 mTempAllowListFgs.removeAt(index);
             }
         }
-        final long existingExpirationTime = mTempAllowListFgs.get(uid, -1);
+        final TempFgsAllowListEntry existing = mTempAllowListFgs.get(uid);
         final long expirationTime = now + duration;
-        if (existingExpirationTime == -1 || existingExpirationTime < expirationTime) {
-            mTempAllowListFgs.put(uid, expirationTime);
+        if (existing == null || existing.mExpirationTime < expirationTime) {
+            mTempAllowListFgs.put(uid,
+                    new TempFgsAllowListEntry(expirationTime, duration, reasonCode,
+                            reason == null ? "" : reason, callingUid));
         }
     }
 
-    boolean isAllowed(int uid) {
+    /**
+     * Is this uid temp-allowlisted to start FGS.
+     * @param uid
+     * @return If uid is in the temp-allowlist, return the {@link TempFgsAllowListEntry}; If not in
+     *         temp-allowlist, return null.
+     */
+    @Nullable
+    TempFgsAllowListEntry getAllowedDurationAndReason(int uid) {
         final int index = mTempAllowListFgs.indexOfKey(uid);
         if (index < 0) {
-            return false;
-        } else if (mTempAllowListFgs.valueAt(index) < SystemClock.elapsedRealtime()) {
+            return null;
+        } else if (mTempAllowListFgs.valueAt(index).mExpirationTime
+                < SystemClock.elapsedRealtime()) {
             mTempAllowListFgs.removeAt(index);
-            return false;
+            return null;
         } else {
-            return true;
+            return mTempAllowListFgs.valueAt(index);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index d79fb8a..06e879b 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -21,6 +21,7 @@
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_NETWORK;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
 import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
@@ -41,6 +42,7 @@
 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION;
 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE;
+import static android.os.PowerWhitelistManager.REASON_DENIED;
 import static android.os.Process.SCHED_OTHER;
 import static android.os.Process.THREAD_GROUP_BACKGROUND;
 import static android.os.Process.THREAD_GROUP_DEFAULT;
@@ -51,7 +53,6 @@
 import static android.os.Process.setThreadPriority;
 import static android.os.Process.setThreadScheduler;
 
-import static com.android.server.am.ActiveServices.FGS_FEATURE_DENIED;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKUP;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LRU;
@@ -72,6 +73,7 @@
 import static com.android.server.am.ProcessList.TAG_PROCESS_OBSERVERS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
 
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityThread;
 import android.app.ApplicationExitInfo;
@@ -229,6 +231,22 @@
     private final ArrayDeque<ProcessRecord> mTmpQueue;
     private final ArraySet<ProcessRecord> mPendingProcessSet = new ArraySet<>();
 
+    /**
+     * Flag to mark if there is an ongoing oomAdjUpdate: potentially the oomAdjUpdate
+     * could be called recursively because of the indirect calls during the update;
+     * however the oomAdjUpdate itself doesn't support recursion - in this case we'd
+     * have to queue up the new targets found during the update, and perform another
+     * round of oomAdjUpdate at the end of last update.
+     */
+    @GuardedBy("mService")
+    private boolean mOomAdjUpdateOngoing = false;
+
+    /**
+     * Flag to mark if there is a pending full oomAdjUpdate.
+     */
+    @GuardedBy("mService")
+    private boolean mPendingFullOomAdjUpdate = false;
+
     private final PlatformCompatCache mPlatformCompatCache;
 
     private static class PlatformCompatCache {
@@ -439,6 +457,23 @@
         if (oomAdjAll && mConstants.OOMADJ_UPDATE_QUICK) {
             return updateOomAdjLSP(app, oomAdjReason);
         }
+        if (checkAndEnqueueOomAdjTargetLocked(app)) {
+            // Simply return true as there is an oomAdjUpdate ongoing
+            return true;
+        }
+        try {
+            mOomAdjUpdateOngoing = true;
+            return performUpdateOomAdjLSP(app, oomAdjAll, oomAdjReason);
+        } finally {
+            // Kick off the handling of any pending targets enqueued during the above update
+            mOomAdjUpdateOngoing = false;
+            updateOomAdjPendingTargetsLocked(oomAdjReason);
+        }
+    }
+
+    @GuardedBy({"mService", "mProcLock"})
+    private boolean performUpdateOomAdjLSP(ProcessRecord app, boolean oomAdjAll,
+            String oomAdjReason) {
         final ProcessRecord topApp = mService.getTopApp();
         final ProcessStateRecord state = app.mState;
         final boolean wasCached = state.isCached();
@@ -453,20 +488,21 @@
                 ? state.getCurRawAdj() : ProcessList.UNKNOWN_ADJ;
         // Check if this process is in the pending list too, remove from pending list if so.
         mPendingProcessSet.remove(app);
-        boolean success = updateOomAdjLSP(app, cachedAdj, topApp, false,
+        boolean success = performUpdateOomAdjLSP(app, cachedAdj, topApp, false,
                 SystemClock.uptimeMillis());
         if (oomAdjAll
                 && (wasCached != state.isCached()
                     || state.getCurRawAdj() == ProcessList.UNKNOWN_ADJ)) {
             // Changed to/from cached state, so apps after it in the LRU
             // list may also be changed.
-            updateOomAdjLSP(oomAdjReason);
+            performUpdateOomAdjLSP(oomAdjReason);
         }
+
         return success;
     }
 
     @GuardedBy({"mService", "mProcLock"})
-    private boolean updateOomAdjLSP(ProcessRecord app, int cachedAdj,
+    private boolean performUpdateOomAdjLSP(ProcessRecord app, int cachedAdj,
             ProcessRecord TOP_APP, boolean doingAll, long now) {
         if (app.getThread() == null) {
             return false;
@@ -486,8 +522,6 @@
 
         computeOomAdjLSP(app, cachedAdj, TOP_APP, doingAll, now, false, true);
 
-        boolean success = applyOomAdjLSP(app, doingAll, now, SystemClock.elapsedRealtime());
-
         if (uidRec != null) {
             // After uidRec.reset() above, for UidRecord with multiple processes (ProcessRecord),
             // we need to apply all ProcessRecord into UidRecord.
@@ -504,7 +538,7 @@
             }
         }
 
-        return success;
+        return applyOomAdjLSP(app, doingAll, now, SystemClock.elapsedRealtime());
     }
 
     /**
@@ -519,6 +553,22 @@
 
     @GuardedBy({"mService", "mProcLock"})
     private void updateOomAdjLSP(String oomAdjReason) {
+        if (checkAndEnqueueOomAdjTargetLocked(null)) {
+            // Simply return as there is an oomAdjUpdate ongoing
+            return;
+        }
+        try {
+            mOomAdjUpdateOngoing = true;
+            performUpdateOomAdjLSP(oomAdjReason);
+        } finally {
+            // Kick off the handling of any pending targets enqueued during the above update
+            mOomAdjUpdateOngoing = false;
+            updateOomAdjPendingTargetsLocked(oomAdjReason);
+        }
+    }
+
+    @GuardedBy({"mService", "mProcLock"})
+    private void performUpdateOomAdjLSP(String oomAdjReason) {
         final ProcessRecord topApp = mService.getTopApp();
         // Clear any pending ones because we are doing a full update now.
         mPendingProcessSet.clear();
@@ -548,6 +598,23 @@
             return true;
         }
 
+        if (checkAndEnqueueOomAdjTargetLocked(app)) {
+            // Simply return true as there is an oomAdjUpdate ongoing
+            return true;
+        }
+
+        try {
+            mOomAdjUpdateOngoing = true;
+            return performUpdateOomAdjLSP(app, oomAdjReason);
+        } finally {
+            // Kick off the handling of any pending targets enqueued during the above update
+            mOomAdjUpdateOngoing = false;
+            updateOomAdjPendingTargetsLocked(oomAdjReason);
+        }
+    }
+
+    @GuardedBy({"mService", "mProcLock"})
+    private boolean performUpdateOomAdjLSP(ProcessRecord app, String oomAdjReason) {
         final ProcessRecord topApp = mService.getTopApp();
 
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
@@ -567,7 +634,7 @@
         state.resetCachedInfo();
         // Check if this process is in the pending list too, remove from pending list if so.
         mPendingProcessSet.remove(app);
-        boolean success = updateOomAdjLSP(app, cachedAdj, topApp, false,
+        boolean success = performUpdateOomAdjLSP(app, cachedAdj, topApp, false,
                 SystemClock.uptimeMillis());
         if (!success || (wasCached == state.isCached() && oldAdj != ProcessList.INVALID_ADJ
                 && wasBackground == ActivityManager.isProcStateBackground(
@@ -696,14 +763,59 @@
     }
 
     /**
+     * Check if there is an ongoing oomAdjUpdate, enqueue the given process record
+     * to {@link #mPendingProcessSet} if there is one.
+     *
+     * @param app The target app to get an oomAdjUpdate, or a full oomAdjUpdate if it's null.
+     * @return {@code true} if there is an ongoing oomAdjUpdate.
+     */
+    @GuardedBy("mService")
+    private boolean checkAndEnqueueOomAdjTargetLocked(@Nullable ProcessRecord app) {
+        if (!mOomAdjUpdateOngoing) {
+            return false;
+        }
+        if (app != null) {
+            mPendingProcessSet.add(app);
+        } else {
+            mPendingFullOomAdjUpdate = true;
+        }
+        return true;
+    }
+
+    /**
      * Kick off an oom adj update pass for the pending targets which are enqueued via
      * {@link #enqueueOomAdjTargetLocked}.
      */
     @GuardedBy("mService")
     void updateOomAdjPendingTargetsLocked(String oomAdjReason) {
+        // First check if there is pending full update
+        if (mPendingFullOomAdjUpdate) {
+            mPendingFullOomAdjUpdate = false;
+            mPendingProcessSet.clear();
+            updateOomAdjLocked(oomAdjReason);
+            return;
+        }
         if (mPendingProcessSet.isEmpty()) {
             return;
         }
+
+        if (mOomAdjUpdateOngoing) {
+            // There's another oomAdjUpdate ongoing, return from here now;
+            // that ongoing update would call us again at the end of it.
+            return;
+        }
+        try {
+            mOomAdjUpdateOngoing = true;
+            performUpdateOomAdjPendingTargetsLocked(oomAdjReason);
+        } finally {
+            // Kick off the handling of any pending targets enqueued during the above update
+            mOomAdjUpdateOngoing = false;
+            updateOomAdjPendingTargetsLocked(oomAdjReason);
+        }
+    }
+
+    @GuardedBy("mService")
+    private void performUpdateOomAdjPendingTargetsLocked(String oomAdjReason) {
         final ProcessRecord topApp = mService.getTopApp();
 
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
@@ -1846,15 +1958,15 @@
                         computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now,
                                 cycleReEval, true);
                     } else {
-                        cstate.setCurRawAdj(cstate.getSetAdj());
-                        cstate.setCurRawProcState(cstate.getSetProcState());
+                        cstate.setCurRawAdj(cstate.getCurAdj());
+                        cstate.setCurRawProcState(cstate.getCurProcState());
                     }
 
                     int clientAdj = cstate.getCurRawAdj();
                     int clientProcState = cstate.getCurRawProcState();
 
                     // pass client's mAllowStartFgs to the app if client is not persistent process.
-                    if (cstate.getAllowedStartFgs() != FGS_FEATURE_DENIED
+                    if (cstate.getAllowedStartFgs() != REASON_DENIED
                             && cstate.getMaxAdj() >= ProcessList.FOREGROUND_APP_ADJ) {
                         state.setAllowStartFgs(cstate.getAllowedStartFgs());
                     }
@@ -1868,6 +1980,21 @@
                             capability |= cstate.getCurCapability();
                         }
 
+                        // If an app has network capability by default
+                        // (by having procstate <= BFGS), then the apps it binds to will get
+                        // elevated to a high enough procstate anyway to get network unless they
+                        // request otherwise, so don't propagate the network capability by default
+                        // in this case unless they explicitly request it.
+                        if ((cstate.getCurCapability() & PROCESS_CAPABILITY_NETWORK) != 0) {
+                            if (clientProcState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
+                                if ((cr.flags & Context.BIND_ALLOW_NETWORK_ACCESS) != 0) {
+                                    capability |= PROCESS_CAPABILITY_NETWORK;
+                                }
+                            } else {
+                                capability |= PROCESS_CAPABILITY_NETWORK;
+                            }
+                        }
+
                         if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
                             // If the other app is cached for any reason, for purposes here
                             // we are going to consider it empty.  The specific cached state
@@ -1935,6 +2062,10 @@
                                         && clientAdj <= ProcessList.PERCEPTIBLE_APP_ADJ
                                         && adj >= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
                                     newAdj = ProcessList.PERCEPTIBLE_LOW_APP_ADJ;
+                                } else if ((cr.flags & Context.BIND_ALMOST_PERCEPTIBLE) != 0
+                                        && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
+                                        && adj >= ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ) {
+                                    newAdj = ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ;
                                 } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
                                         && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
                                         && adj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
@@ -2004,13 +2135,13 @@
                                 if (enabled) {
                                     if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
                                         // TOP process passes all capabilities to the service.
-                                        capability |= PROCESS_CAPABILITY_ALL;
+                                        capability |= cstate.getCurCapability();
                                     } else {
                                         // TOP process passes no capability to the service.
                                     }
                                 } else {
                                     // TOP process passes all capabilities to the service.
-                                    capability |= PROCESS_CAPABILITY_ALL;
+                                    capability |= cstate.getCurCapability();
                                 }
                             }
                         } else if ((cr.flags & Context.BIND_IMPORTANT_BACKGROUND) == 0) {
@@ -2130,8 +2261,8 @@
                 if (computeClients) {
                     computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now, cycleReEval, true);
                 } else {
-                    cstate.setCurRawAdj(cstate.getSetAdj());
-                    cstate.setCurRawProcState(cstate.getSetProcState());
+                    cstate.setCurRawAdj(cstate.getCurAdj());
+                    cstate.setCurRawProcState(cstate.getCurProcState());
                 }
 
                 if (shouldSkipDueToCycle(state, cstate, procState, adj, cycleReEval)) {
@@ -2335,20 +2466,20 @@
             case PROCESS_STATE_TOP:
                 return PROCESS_CAPABILITY_ALL;
             case PROCESS_STATE_BOUND_TOP:
-                return PROCESS_CAPABILITY_NONE;
+                return PROCESS_CAPABILITY_NETWORK;
             case PROCESS_STATE_FOREGROUND_SERVICE:
                 if (psr.hasForegroundServices()) {
                     // Capability from FGS are conditional depending on foreground service type in
                     // manifest file and the mAllowWhileInUsePermissionInFgs flag.
-                    return PROCESS_CAPABILITY_NONE;
+                    return PROCESS_CAPABILITY_NETWORK;
                 } else {
                     // process has no FGS, the PROCESS_STATE_FOREGROUND_SERVICE is from client.
                     // the implicit capability could be removed in the future, client should use
                     // BIND_INCLUDE_CAPABILITY flag.
-                    return PROCESS_CAPABILITY_ALL_IMPLICIT;
+                    return PROCESS_CAPABILITY_ALL_IMPLICIT | PROCESS_CAPABILITY_NETWORK;
                 }
             case PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
-                return PROCESS_CAPABILITY_NONE;
+                return PROCESS_CAPABILITY_NETWORK;
             default:
                 return PROCESS_CAPABILITY_NONE;
         }
@@ -2428,9 +2559,7 @@
                         && (state.getCurAdj() == ProcessList.PREVIOUS_APP_ADJ
                             || state.getCurAdj() == ProcessList.HOME_APP_ADJ)) {
                     mCachedAppOptimizer.compactAppSome(app);
-                } else if ((state.getSetAdj() < ProcessList.CACHED_APP_MIN_ADJ
-                                || state.getSetAdj() > ProcessList.CACHED_APP_MAX_ADJ)
-                        && state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ
+                } else if (state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ
                         && state.getCurAdj() <= ProcessList.CACHED_APP_MAX_ADJ) {
                     mCachedAppOptimizer.compactAppFull(app);
                 }
diff --git a/services/core/java/com/android/server/am/PendingIntentController.java b/services/core/java/com/android/server/am/PendingIntentController.java
index 42172bf..534bd84 100644
--- a/services/core/java/com/android/server/am/PendingIntentController.java
+++ b/services/core/java/com/android/server/am/PendingIntentController.java
@@ -36,6 +36,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.PowerWhitelistManager;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -300,15 +301,16 @@
         }
     }
 
-    void setPendingIntentWhitelistDuration(IIntentSender target, IBinder whitelistToken,
-            long duration, int type) {
+    void setPendingIntentAllowlistDuration(IIntentSender target, IBinder allowlistToken,
+            long duration, int type, @PowerWhitelistManager.ReasonCode int reasonCode,
+            @Nullable String reason) {
         if (!(target instanceof PendingIntentRecord)) {
             Slog.w(TAG, "markAsSentFromNotification(): not a PendingIntentRecord: " + target);
             return;
         }
         synchronized (mLock) {
-            ((PendingIntentRecord) target).setWhitelistDurationLocked(whitelistToken, duration,
-                    type);
+            ((PendingIntentRecord) target).setAllowlistDurationLocked(allowlistToken, duration,
+                    type, reasonCode, reason);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 0eb48f6..51666ac 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -31,13 +31,14 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.PowerWhitelistManager;
+import android.os.PowerWhitelistManager.ReasonCode;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.TransactionTooLargeException;
 import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.ArraySet;
-import android.util.Pair;
 import android.util.Slog;
 import android.util.TimeUtils;
 
@@ -67,7 +68,7 @@
      * milliseconds, Integer is allowlist type defined at
      * {@link android.os.PowerWhitelistManager.TempAllowListType}
      */
-    private ArrayMap<IBinder, Pair<Long, Integer>> mWhitelistDuration;
+    private ArrayMap<IBinder, TempAllowListDuration> mAllowlistDuration;
     private RemoteCallbackList<IResultReceiver> mCancelCallbacks;
     private ArraySet<IBinder> mAllowBgActivityStartsForActivitySender = new ArraySet<>();
     private ArraySet<IBinder> mAllowBgActivityStartsForBroadcastSender = new ArraySet<>();
@@ -214,6 +215,21 @@
         }
     }
 
+    static final class TempAllowListDuration {
+        long duration;
+        int type;
+        @ReasonCode int reasonCode;
+        @Nullable String reason;
+
+        TempAllowListDuration(long _duration, int _type, @ReasonCode int _reasonCode,
+                String _reason) {
+            duration = _duration;
+            type = _type;
+            reasonCode = _reasonCode;
+            reason = _reason;
+        }
+    }
+
     PendingIntentRecord(PendingIntentController _controller, Key _k, int _u) {
         controller = _controller;
         key = _k;
@@ -221,18 +237,19 @@
         ref = new WeakReference<>(this);
     }
 
-    void setWhitelistDurationLocked(IBinder whitelistToken, long duration, int type) {
+    void setAllowlistDurationLocked(IBinder allowlistToken, long duration, int type,
+            @ReasonCode int reasonCode, @Nullable String reason) {
         if (duration > 0) {
-            if (mWhitelistDuration == null) {
-                mWhitelistDuration = new ArrayMap<>();
+            if (mAllowlistDuration == null) {
+                mAllowlistDuration = new ArrayMap<>();
             }
-            mWhitelistDuration.put(whitelistToken, new Pair(duration, type));
-        } else if (mWhitelistDuration != null) {
-            mWhitelistDuration.remove(whitelistToken);
-            if (mWhitelistDuration.size() <= 0) {
-                mWhitelistDuration = null;
+            mAllowlistDuration.put(allowlistToken,
+                    new TempAllowListDuration(duration, type, reasonCode, reason));
+        } else if (mAllowlistDuration != null) {
+            mAllowlistDuration.remove(allowlistToken);
+            if (mAllowlistDuration.size() <= 0) {
+                mAllowlistDuration = null;
             }
-
         }
         this.stringName = null;
     }
@@ -280,25 +297,25 @@
         return listeners;
     }
 
-    public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
+    public void send(int code, Intent intent, String resolvedType, IBinder allowlistToken,
             IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
-        sendInner(code, intent, resolvedType, whitelistToken, finishedReceiver,
+        sendInner(code, intent, resolvedType, allowlistToken, finishedReceiver,
                 requiredPermission, null, null, 0, 0, 0, options);
     }
 
-    public int sendWithResult(int code, Intent intent, String resolvedType, IBinder whitelistToken,
+    public int sendWithResult(int code, Intent intent, String resolvedType, IBinder allowlistToken,
             IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
-        return sendInner(code, intent, resolvedType, whitelistToken, finishedReceiver,
+        return sendInner(code, intent, resolvedType, allowlistToken, finishedReceiver,
                 requiredPermission, null, null, 0, 0, 0, options);
     }
 
-    public int sendInner(int code, Intent intent, String resolvedType, IBinder whitelistToken,
+    public int sendInner(int code, Intent intent, String resolvedType, IBinder allowlistToken,
             IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo,
             String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options) {
         if (intent != null) intent.setDefusable(true);
         if (options != null) options.setDefusable(true);
 
-        Pair<Long, Integer> duration = null;
+        TempAllowListDuration duration = null;
         Intent finalIntent = null;
         Intent[] allIntents = null;
         String[] allResolvedTypes = null;
@@ -347,8 +364,8 @@
                 mergedOptions.setCallerOptions(opts);
             }
 
-            if (mWhitelistDuration != null) {
-                duration = mWhitelistDuration.get(whitelistToken);
+            if (mAllowlistDuration != null) {
+                duration = mAllowlistDuration.get(allowlistToken);
             }
 
             if (key.type == ActivityManager.INTENT_SENDER_ACTIVITY
@@ -377,7 +394,9 @@
         try {
             if (duration != null) {
                 StringBuilder tag = new StringBuilder(64);
-                tag.append("pendingintent:");
+                tag.append("setPendingIntentAllowlistDuration,reason:");
+                tag.append(duration.reason == null ? "" : duration.reason);
+                tag.append(",pendingintent:");
                 UserHandle.formatUid(tag, callingUid);
                 tag.append(":");
                 if (finalIntent.getAction() != null) {
@@ -387,8 +406,8 @@
                 } else if (finalIntent.getData() != null) {
                     tag.append(finalIntent.getData().toSafeString());
                 }
-                controller.mAmInternal.tempWhitelistForPendingIntent(callingPid, callingUid,
-                        uid, duration.first, duration.second, tag.toString());
+                controller.mAmInternal.tempAllowlistForPendingIntent(callingPid, callingUid,
+                        uid, duration.duration, duration.type, duration.reasonCode, tag.toString());
             }
 
             boolean sendFinish = finishedReceiver != null;
@@ -417,7 +436,8 @@
                                     allIntents, allResolvedTypes, resultTo, mergedOptions, userId,
                                     false /* validateIncomingUser */,
                                     this /* originatingPendingIntent */,
-                                    mAllowBgActivityStartsForActivitySender.contains(whitelistToken));
+                                    mAllowBgActivityStartsForActivitySender.contains(
+                                            allowlistToken));
                         } else {
                             res = controller.mAtmInternal.startActivityInPackage(uid, callingPid,
                                     callingUid, key.packageName, key.featureId, finalIntent,
@@ -426,7 +446,7 @@
                                     false /* validateIncomingUser */,
                                     this /* originatingPendingIntent */,
                                     mAllowBgActivityStartsForActivitySender.contains(
-                                            whitelistToken));
+                                            allowlistToken));
                         }
                     } catch (RuntimeException e) {
                         Slog.w(TAG, "Unable to send startActivity intent", e);
@@ -439,8 +459,8 @@
                 case ActivityManager.INTENT_SENDER_BROADCAST:
                     try {
                         final boolean allowedByToken =
-                                mAllowBgActivityStartsForBroadcastSender.contains(whitelistToken);
-                        final IBinder bgStartsToken = (allowedByToken) ? whitelistToken : null;
+                                mAllowBgActivityStartsForBroadcastSender.contains(allowlistToken);
+                        final IBinder bgStartsToken = (allowedByToken) ? allowlistToken : null;
 
                         // If a completion callback has been requested, require
                         // that the broadcast be delivered synchronously
@@ -460,8 +480,8 @@
                 case ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE:
                     try {
                         final boolean allowedByToken =
-                                mAllowBgActivityStartsForServiceSender.contains(whitelistToken);
-                        final IBinder bgStartsToken = (allowedByToken) ? whitelistToken : null;
+                                mAllowBgActivityStartsForServiceSender.contains(allowlistToken);
+                        final IBinder bgStartsToken = (allowedByToken) ? allowlistToken : null;
 
                         controller.mAmInternal.startServiceInPackage(uid, finalIntent, resolvedType,
                                 key.type == ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE,
@@ -533,18 +553,23 @@
             pw.print(prefix); pw.print("sent="); pw.print(sent);
                     pw.print(" canceled="); pw.println(canceled);
         }
-        if (mWhitelistDuration != null) {
+        if (mAllowlistDuration != null) {
             pw.print(prefix);
-            pw.print("whitelistDuration=");
-            for (int i = 0; i < mWhitelistDuration.size(); i++) {
+            pw.print("allowlistDuration=");
+            for (int i = 0; i < mAllowlistDuration.size(); i++) {
                 if (i != 0) {
                     pw.print(", ");
                 }
-                pw.print(Integer.toHexString(System.identityHashCode(mWhitelistDuration.keyAt(i))));
+                TempAllowListDuration entry = mAllowlistDuration.valueAt(i);
+                pw.print(Integer.toHexString(System.identityHashCode(mAllowlistDuration.keyAt(i))));
                 pw.print(":");
-                TimeUtils.formatDuration(mWhitelistDuration.valueAt(i).first, pw);
+                TimeUtils.formatDuration(entry.duration, pw);
                 pw.print("/");
-                pw.print(mWhitelistDuration.valueAt(i).second);
+                pw.print(entry.type);
+                pw.print("/");
+                pw.print(PowerWhitelistManager.reasonCodeToString(entry.reasonCode));
+                pw.print("/");
+                pw.print(entry.reason);
             }
             pw.println();
         }
@@ -572,18 +597,23 @@
         }
         sb.append(' ');
         sb.append(key.typeName());
-        if (mWhitelistDuration != null) {
-            sb.append( " (whitelist: ");
-            for (int i = 0; i < mWhitelistDuration.size(); i++) {
+        if (mAllowlistDuration != null) {
+            sb.append(" (allowlist: ");
+            for (int i = 0; i < mAllowlistDuration.size(); i++) {
                 if (i != 0) {
                     sb.append(",");
                 }
+                TempAllowListDuration entry = mAllowlistDuration.valueAt(i);
                 sb.append(Integer.toHexString(System.identityHashCode(
-                        mWhitelistDuration.keyAt(i))));
+                        mAllowlistDuration.keyAt(i))));
                 sb.append(":");
-                TimeUtils.formatDuration(mWhitelistDuration.valueAt(i).first, sb);
+                TimeUtils.formatDuration(entry.duration, sb);
                 sb.append("/");
-                sb.append(mWhitelistDuration.valueAt(i).second);
+                sb.append(entry.type);
+                sb.append("/");
+                sb.append(PowerWhitelistManager.reasonCodeToString(entry.reasonCode));
+                sb.append("/");
+                sb.append(entry.reason);
             }
             sb.append(")");
         }
diff --git a/services/core/java/com/android/server/am/PreBootBroadcaster.java b/services/core/java/com/android/server/am/PreBootBroadcaster.java
index 60b2467..984fe40 100644
--- a/services/core/java/com/android/server/am/PreBootBroadcaster.java
+++ b/services/core/java/com/android/server/am/PreBootBroadcaster.java
@@ -17,6 +17,8 @@
 package com.android.server.am;
 
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
+import static android.os.PowerWhitelistManager.REASON_PRE_BOOT_COMPLETED;
+import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
 
 import android.app.ActivityManagerInternal;
 import android.app.AppOpsManager;
@@ -117,9 +119,9 @@
             duration = amInternal.getBootTimeTempAllowListDuration();
         }
         final BroadcastOptions bOptions = BroadcastOptions.makeBasic();
-        bOptions.setTemporaryAppWhitelistDuration(
-                BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
-                duration);
+        bOptions.setTemporaryAppAllowlist(duration,
+                TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+                REASON_PRE_BOOT_COMPLETED, "");
         synchronized (mService) {
             mService.broadcastIntentLocked(null, null, null, mIntent, null, this, 0, null, null,
                     null, AppOpsManager.OP_NONE, bOptions.toBundle(), true,
diff --git a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
index 1653123..3258f8a 100644
--- a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
@@ -22,6 +22,7 @@
 import static com.android.server.am.ProcessRecord.TAG;
 
 import android.app.ActivityManager;
+import android.app.AnrController;
 import android.app.ApplicationErrorReport;
 import android.app.ApplicationExitInfo;
 import android.content.ComponentName;
@@ -418,10 +419,16 @@
 
         // Retrieve max ANR delay from AnrControllers without the mService lock since the
         // controllers might in turn call into apps
-        long anrDialogDelayMs = mService.mActivityTaskManager.getMaxAnrDelayMillis(aInfo);
-        if (aInfo != null && aInfo.packageName != null && anrDialogDelayMs > 0) {
-            Slog.i(TAG, "Delaying ANR dialog for " + aInfo.packageName + " for " + anrDialogDelayMs
-                    + "ms");
+        AnrController anrController = mService.mActivityTaskManager.getAnrController(aInfo);
+        long anrDialogDelayMs = 0;
+        if (anrController != null) {
+            String packageName = aInfo.packageName;
+            int uid = aInfo.uid;
+            anrDialogDelayMs = anrController.getAnrDelayMillis(packageName, uid);
+            // Might execute an async binder call to a system app to show an interim
+            // ANR progress UI
+            anrController.onAnrDelayStarted(packageName, uid);
+            Slog.i(TAG, "ANR delay of " + anrDialogDelayMs + "ms started for " + packageName);
         }
 
         synchronized (mService) {
@@ -440,6 +447,7 @@
                 // Set the app's notResponding state, and look up the errorReportReceiver
                 makeAppNotRespondingLSP(activityShortComponentName,
                         annotation != null ? "ANR " + annotation : "ANR", info.toString());
+                mDialogController.setAnrController(anrController);
             }
 
             // Notify package manager service to possibly update package state
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 172f707..38330fe 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
 import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
 import static android.app.ActivityThread.PROC_START_SEQ_IDENT;
@@ -57,6 +58,7 @@
 
 import android.annotation.NonNull;
 import android.app.ActivityManager;
+import android.app.ActivityManager.ProcessCapability;
 import android.app.ActivityThread;
 import android.app.AppGlobals;
 import android.app.AppProtoEnums;
@@ -228,6 +230,11 @@
     // not so perceptible that it affects the user immediately if killed.
     static final int PERCEPTIBLE_LOW_APP_ADJ = 250;
 
+    // This is a process hosting services that are not perceptible to the user but the
+    // client (system) binding to it requested to treat it as if it is perceptible and avoid killing
+    // it if possible.
+    static final int PERCEPTIBLE_MEDIUM_APP_ADJ = 225;
+
     // This is a process only hosting components that are perceptible to the
     // user, and we really want to avoid killing them, but they are not
     // immediately visible. An example is background music playback.
@@ -1027,6 +1034,9 @@
         } else if (setAdj >= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
             return buildOomTag("prcl  ", "prcl", null, setAdj,
                     ProcessList.PERCEPTIBLE_LOW_APP_ADJ, compact);
+        } else if (setAdj >= ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ) {
+            return buildOomTag("prcm  ", "prcm", null, setAdj,
+                    ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ, compact);
         } else if (setAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
             return buildOomTag("prcp  ", "prcp", null, setAdj,
                     ProcessList.PERCEPTIBLE_APP_ADJ, compact);
@@ -1054,76 +1064,7 @@
     }
 
     public static String makeProcStateString(int curProcState) {
-        String procState;
-        switch (curProcState) {
-            case ActivityManager.PROCESS_STATE_PERSISTENT:
-                procState = "PER ";
-                break;
-            case ActivityManager.PROCESS_STATE_PERSISTENT_UI:
-                procState = "PERU";
-                break;
-            case ActivityManager.PROCESS_STATE_TOP:
-                procState = "TOP ";
-                break;
-            case ActivityManager.PROCESS_STATE_BOUND_TOP:
-                procState = "BTOP";
-                break;
-            case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE:
-                procState = "FGS ";
-                break;
-            case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
-                procState = "BFGS";
-                break;
-            case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND:
-                procState = "IMPF";
-                break;
-            case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND:
-                procState = "IMPB";
-                break;
-            case ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND:
-                procState = "TRNB";
-                break;
-            case ActivityManager.PROCESS_STATE_BACKUP:
-                procState = "BKUP";
-                break;
-            case ActivityManager.PROCESS_STATE_SERVICE:
-                procState = "SVC ";
-                break;
-            case ActivityManager.PROCESS_STATE_RECEIVER:
-                procState = "RCVR";
-                break;
-            case ActivityManager.PROCESS_STATE_TOP_SLEEPING:
-                procState = "TPSL";
-                break;
-            case ActivityManager.PROCESS_STATE_HEAVY_WEIGHT:
-                procState = "HVY ";
-                break;
-            case ActivityManager.PROCESS_STATE_HOME:
-                procState = "HOME";
-                break;
-            case ActivityManager.PROCESS_STATE_LAST_ACTIVITY:
-                procState = "LAST";
-                break;
-            case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
-                procState = "CAC ";
-                break;
-            case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
-                procState = "CACC";
-                break;
-            case ActivityManager.PROCESS_STATE_CACHED_RECENT:
-                procState = "CRE ";
-                break;
-            case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
-                procState = "CEM ";
-                break;
-            case ActivityManager.PROCESS_STATE_NONEXISTENT:
-                procState = "NONE";
-                break;
-            default:
-                procState = "??";
-                break;
-        }
-        return procState;
+        return ActivityManager.procStateToString(curProcState);
     }
 
     public static int makeProcStateProtoEnum(int curProcState) {
@@ -1828,7 +1769,8 @@
      */
     @GuardedBy("mService")
     boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
-            int zygotePolicyFlags, boolean disableHiddenApiChecks, String abiOverride) {
+            int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,
+            String abiOverride) {
         if (app.isPendingStart()) {
             return true;
         }
@@ -1974,6 +1916,10 @@
                     throw new IllegalStateException("Invalid API policy: " + policy);
                 }
                 runtimeFlags |= policyBits;
+
+                if (disableTestApiChecks) {
+                    runtimeFlags |= Zygote.DISABLE_TEST_API_ENFORCEMENT_POLICY;
+                }
             }
 
             String useAppImageCache = SystemProperties.get(
@@ -2437,7 +2383,8 @@
     boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
             int zygotePolicyFlags, String abiOverride) {
         return startProcessLocked(app, hostingRecord, zygotePolicyFlags,
-                false /* disableHiddenApiChecks */, abiOverride);
+                false /* disableHiddenApiChecks */, false /* disableTestApiChecks */,
+                abiOverride);
     }
 
     @GuardedBy("mService")
@@ -4458,6 +4405,7 @@
             printOomLevel(pw, "FOREGROUND_APP_ADJ", FOREGROUND_APP_ADJ);
             printOomLevel(pw, "VISIBLE_APP_ADJ", VISIBLE_APP_ADJ);
             printOomLevel(pw, "PERCEPTIBLE_APP_ADJ", PERCEPTIBLE_APP_ADJ);
+            printOomLevel(pw, "PERCEPTIBLE_MEDIUM_APP_ADJ", PERCEPTIBLE_MEDIUM_APP_ADJ);
             printOomLevel(pw, "PERCEPTIBLE_LOW_APP_ADJ", PERCEPTIBLE_LOW_APP_ADJ);
             printOomLevel(pw, "BACKUP_APP_ADJ", BACKUP_APP_ADJ);
             printOomLevel(pw, "HEAVY_WEIGHT_APP_ADJ", HEAVY_WEIGHT_APP_ADJ);
@@ -4721,13 +4669,26 @@
         }
     }
 
-    /** Returns the uid's process state or PROCESS_STATE_NONEXISTENT if not running */
+    /**
+     * Returns the uid's process state or {@link ActivityManager#PROCESS_STATE_NONEXISTENT}
+     * if not running
+     */
     @GuardedBy(anyOf = {"mService", "mProcLock"})
     int getUidProcStateLOSP(int uid) {
         UidRecord uidRec = mActiveUids.get(uid);
         return uidRec == null ? PROCESS_STATE_NONEXISTENT : uidRec.getCurProcState();
     }
 
+    /**
+     * Returns the uid's process capability or {@link ActivityManager#PROCESS_CAPABILITY_NONE}
+     * if not running
+     */
+    @GuardedBy(anyOf = {"mService", "mProcLock"})
+    @ProcessCapability int getUidProcessCapabilityLOSP(int uid) {
+        UidRecord uidRec = mActiveUids.get(uid);
+        return uidRec == null ? PROCESS_CAPABILITY_NONE : uidRec.getCurCapability();
+    }
+
     /** Returns the UidRecord for the given uid, if it exists. */
     @GuardedBy(anyOf = {"mService", "mProcLock"})
     UidRecord getUidRecordLOSP(int uid) {
@@ -4768,11 +4729,13 @@
     int getBlockStateForUid(UidRecord uidRec) {
         // Denotes whether uid's process state is currently allowed network access.
         final boolean isAllowed =
-                isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.getCurProcState())
+                isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.getCurProcState(),
+                        uidRec.getCurCapability())
                 || isProcStateAllowedWhileOnRestrictBackground(uidRec.getCurProcState());
         // Denotes whether uid's process state was previously allowed network access.
         final boolean wasAllowed =
-                isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.getSetProcState())
+                isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.getSetProcState(),
+                        uidRec.getSetCapability())
                 || isProcStateAllowedWhileOnRestrictBackground(uidRec.getSetProcState());
 
         // When the uid is coming to foreground, AMS should inform the app thread that it should
@@ -4810,8 +4773,9 @@
             if (!UserHandle.isApp(uidRec.getUid()) || !uidRec.hasInternetPermission) {
                 continue;
             }
-            // If process state is not changed, then there's nothing to do.
-            if (uidRec.getSetProcState() == uidRec.getCurProcState()) {
+            // If process state and capabilities are not changed, then there's nothing to do.
+            if (uidRec.getSetProcState() == uidRec.getCurProcState()
+                    && uidRec.getSetCapability() == uidRec.getCurCapability()) {
                 continue;
             }
             final int blockState = getBlockStateForUid(uidRec);
diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java
index 499fbcb..6d783fc 100644
--- a/services/core/java/com/android/server/am/ProcessStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessStateRecord.java
@@ -23,22 +23,23 @@
 import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.os.PowerWhitelistManager.REASON_BACKGROUND_ACTIVITY_PERMISSION;
+import static android.os.PowerWhitelistManager.REASON_BACKGROUND_FGS_PERMISSION;
+import static android.os.PowerWhitelistManager.REASON_COMPANION_DEVICE_MANAGER;
+import static android.os.PowerWhitelistManager.REASON_DENIED;
+import static android.os.PowerWhitelistManager.REASON_DEVICE_OWNER;
+import static android.os.PowerWhitelistManager.REASON_PROFILE_OWNER;
+import static android.os.PowerWhitelistManager.REASON_SYSTEM_ALERT_WINDOW_PERMISSION;
+import static android.os.PowerWhitelistManager.REASON_SYSTEM_ALLOW_LISTED;
+import static android.os.PowerWhitelistManager.REASON_SYSTEM_UID;
+import static android.os.PowerWhitelistManager.ReasonCode;
+import static android.os.PowerWhitelistManager.getReasonCodeFromProcState;
+import static android.os.PowerWhitelistManager.reasonCodeToString;
 import static android.os.Process.NFC_UID;
 import static android.os.Process.ROOT_UID;
 import static android.os.Process.SHELL_UID;
 import static android.os.Process.SYSTEM_UID;
 
-import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_BACKGROUND_ACTIVITY_PERMISSION;
-import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_BACKGROUND_FGS_PERMISSION;
-import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_COMPANION_APP;
-import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST;
-import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_DEVICE_OWNER;
-import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_PROC_STATE;
-import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_PROFILE_OWNER;
-import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_SYSTEM_ALERT_WINDOW_PERMISSION;
-import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_SYSTEM_UID;
-import static com.android.server.am.ActiveServices.FGS_FEATURE_DENIED;
-import static com.android.server.am.ActiveServices.fgsCodeToString;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
 import static com.android.server.am.ProcessRecord.TAG;
 
@@ -329,7 +330,7 @@
      * Does the process has permission to start FGS from background.
      */
     @GuardedBy("mService")
-    private @ActiveServices.FgsFeatureRetCode int mAllowStartFgsByPermission;
+    private @ReasonCode int mAllowStartFgsByPermission = REASON_DENIED;
 
     /**
      * Can this process start FGS from background?
@@ -337,7 +338,7 @@
      * another process through service binding.
      */
     @GuardedBy("mService")
-    private @ActiveServices.FgsFeatureRetCode int mAllowStartFgs;
+    private @ReasonCode int mAllowStartFgs = REASON_DENIED;
 
     /**
      * Debugging: primary thing impacting oom_adj.
@@ -1152,44 +1153,47 @@
     }
 
     @GuardedBy("mService")
+    int getAllowStartFgsState() {
+        return mAllowStartFgsState;
+    }
+
+    @GuardedBy("mService")
     boolean isAllowedStartFgsState() {
         return mAllowStartFgsState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
     }
 
     @GuardedBy("mService")
     void setAllowStartFgsByPermission() {
-        int ret = FGS_FEATURE_DENIED;
-        if (ret == FGS_FEATURE_DENIED) {
-            boolean isSystem = false;
-            final int uid = UserHandle.getAppId(mApp.info.uid);
-            switch (uid) {
-                case ROOT_UID:
-                case SYSTEM_UID:
-                case NFC_UID:
-                case SHELL_UID:
-                    isSystem = true;
-                    break;
-                default:
-                    isSystem = false;
-                    break;
-            }
-
-            if (isSystem) {
-                ret = FGS_FEATURE_ALLOWED_BY_SYSTEM_UID;
-            }
+        int ret = REASON_DENIED;
+        boolean isSystem = false;
+        final int uid = UserHandle.getAppId(mApp.info.uid);
+        switch (uid) {
+            case ROOT_UID:
+            case SYSTEM_UID:
+            case NFC_UID:
+            case SHELL_UID:
+                isSystem = true;
+                break;
+            default:
+                isSystem = false;
+                break;
         }
 
-        if (ret == FGS_FEATURE_DENIED) {
+        if (isSystem) {
+            ret = REASON_SYSTEM_UID;
+        }
+
+        if (ret == REASON_DENIED) {
             if (ActivityManager.checkComponentPermission(START_ACTIVITIES_FROM_BACKGROUND,
                     mApp.info.uid, -1, true) == PERMISSION_GRANTED) {
-                ret = FGS_FEATURE_ALLOWED_BY_BACKGROUND_ACTIVITY_PERMISSION;
+                ret = REASON_BACKGROUND_ACTIVITY_PERMISSION;
             } else if (ActivityManager.checkComponentPermission(
                     START_FOREGROUND_SERVICES_FROM_BACKGROUND,
                     mApp.info.uid, -1, true) == PERMISSION_GRANTED) {
-                ret = FGS_FEATURE_ALLOWED_BY_BACKGROUND_FGS_PERMISSION;
+                ret = REASON_BACKGROUND_FGS_PERMISSION;
             } else if (ActivityManager.checkComponentPermission(SYSTEM_ALERT_WINDOW,
                     mApp.info.uid, -1, true) == PERMISSION_GRANTED) {
-                ret = FGS_FEATURE_ALLOWED_BY_SYSTEM_ALERT_WINDOW_PERMISSION;
+                ret = REASON_SYSTEM_ALERT_WINDOW_PERMISSION;
             }
         }
         mAllowStartFgs = mAllowStartFgsByPermission = ret;
@@ -1197,59 +1201,65 @@
 
     @GuardedBy("mService")
     void setAllowStartFgs() {
-        if (mAllowStartFgs != FGS_FEATURE_DENIED) {
+        if (mAllowStartFgs != REASON_DENIED) {
             return;
         }
-        if (mAllowStartFgs == FGS_FEATURE_DENIED) {
+        if (mAllowStartFgs == REASON_DENIED) {
             if (isAllowedStartFgsState()) {
-                mAllowStartFgs = FGS_FEATURE_ALLOWED_BY_PROC_STATE;
+                mAllowStartFgs = getReasonCodeFromProcState(mAllowStartFgsState);
             }
         }
 
-        if (mAllowStartFgs == FGS_FEATURE_DENIED) {
+        if (mAllowStartFgs == REASON_DENIED) {
             // Is the calling UID a device owner app?
             if (mService.mInternal != null) {
                 if (mService.mInternal.isDeviceOwner(mApp.info.uid)) {
-                    mAllowStartFgs = FGS_FEATURE_ALLOWED_BY_DEVICE_OWNER;
+                    mAllowStartFgs = REASON_DEVICE_OWNER;
                 }
             }
         }
 
-        if (mAllowStartFgs == FGS_FEATURE_DENIED) {
+        if (mAllowStartFgs == REASON_DENIED) {
             if (mService.mInternal != null) {
                 final boolean isCompanionApp = mService.mInternal.isAssociatedCompanionApp(
                         UserHandle.getUserId(mApp.info.uid), mApp.info.uid);
                 if (isCompanionApp) {
-                    mAllowStartFgs = FGS_FEATURE_ALLOWED_BY_COMPANION_APP;
+                    mAllowStartFgs = REASON_COMPANION_DEVICE_MANAGER;
                 }
             }
         }
 
-        if (mAllowStartFgs == FGS_FEATURE_DENIED) {
+        if (mAllowStartFgs == REASON_DENIED) {
             // Is the calling UID a profile owner app?
             if (mService.mInternal != null) {
                 if (mService.mInternal.isProfileOwner(mApp.info.uid)) {
-                    mAllowStartFgs = FGS_FEATURE_ALLOWED_BY_PROFILE_OWNER;
+                    mAllowStartFgs = REASON_PROFILE_OWNER;
                 }
             }
         }
 
-        if (mAllowStartFgs == FGS_FEATURE_DENIED) {
+        if (mAllowStartFgs == REASON_DENIED) {
             // uid is on DeviceIdleController's user/system allowlist
             // or AMS's FgsStartTempAllowList.
-            if (mService.isAllowlistedForFgsStartLOSP(mApp.info.uid)) {
-                mAllowStartFgs = FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST;
+            FgsStartTempAllowList.TempFgsAllowListEntry entry =
+                    mService.isAllowlistedForFgsStartLOSP(mApp.info.uid);
+            if (entry != null) {
+                if (entry == ActivityManagerService.FAKE_TEMP_ALLOWLIST_ENTRY) {
+                    mAllowStartFgs = REASON_SYSTEM_ALLOW_LISTED;
+                } else {
+                    mAllowStartFgs = entry.mReasonCode;
+                }
             }
         }
     }
 
     @GuardedBy("mService")
-    void setAllowStartFgs(@ActiveServices.FgsFeatureRetCode int allowStartFgs) {
+    void setAllowStartFgs(@ReasonCode int allowStartFgs) {
         mAllowStartFgs = allowStartFgs;
     }
 
     @GuardedBy("mService")
-    @ActiveServices.FgsFeatureRetCode int getAllowedStartFgs() {
+    @ReasonCode int getAllowedStartFgs() {
         return mAllowStartFgs;
     }
 
@@ -1291,9 +1301,9 @@
         pw.println();
         pw.print(prefix); pw.print("allowStartFgsState=");
         pw.println(mAllowStartFgsState);
-        if (mAllowStartFgs != FGS_FEATURE_DENIED) {
+        if (mAllowStartFgs != REASON_DENIED) {
             pw.print(prefix); pw.print("allowStartFgs=");
-            pw.println(fgsCodeToString(mAllowStartFgs));
+            pw.println(reasonCodeToString(mAllowStartFgs));
         }
         if (mHasShownUi || mApp.mProfile.hasPendingUiClean()) {
             pw.print(prefix); pw.print("hasShownUi="); pw.print(mHasShownUi);
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 485087d..3ab95d1 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -18,6 +18,7 @@
 
 import static android.app.PendingIntent.FLAG_IMMUTABLE;
 import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
+import static android.os.PowerWhitelistManager.REASON_DENIED;
 
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -36,6 +37,7 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.IBinder;
+import android.os.PowerWhitelistManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -101,7 +103,7 @@
     ProcessRecord isolatedProc; // keep track of isolated process, if requested
     ServiceState tracker; // tracking service execution, may be null
     ServiceState restartTracker; // tracking service restart
-    boolean whitelistManager; // any bindings to this service have BIND_ALLOW_WHITELIST_MANAGEMENT?
+    boolean allowlistManager; // any bindings to this service have BIND_ALLOW_WHITELIST_MANAGEMENT?
     boolean delayed;        // are we waiting to start this service in the background?
     boolean fgRequired;     // is the service required to go foreground after starting?
     boolean fgWaiting;      // is a timeout for going foreground already scheduled?
@@ -156,11 +158,14 @@
 
     // the most recent package that start/bind this service.
     String mRecentCallingPackage;
+    // the most recent uid that start/bind this service.
+    int mRecentCallingUid;
 
     // allow the service becomes foreground service? Service started from background may not be
     // allowed to become a foreground service.
-    @ActiveServices.FgsFeatureRetCode int mAllowStartForeground;
+    @PowerWhitelistManager.ReasonCode int mAllowStartForeground = REASON_DENIED;
     String mInfoAllowStartForeground;
+    FgsStartTempAllowList.TempFgsAllowListEntry mInfoTempFgsAllowListReason;
     boolean mLoggedInfoAllowStartForeground;
 
     String stringName;      // caching of toString
@@ -309,7 +314,7 @@
         if (isolatedProc != null) {
             isolatedProc.dumpDebug(proto, ServiceRecordProto.ISOLATED_PROC);
         }
-        proto.write(ServiceRecordProto.WHITELIST_MANAGER, whitelistManager);
+        proto.write(ServiceRecordProto.WHITELIST_MANAGER, allowlistManager);
         proto.write(ServiceRecordProto.DELAYED, delayed);
         if (isForeground || foregroundId != 0) {
             long fgToken = proto.start(ServiceRecordProto.FOREGROUND);
@@ -410,8 +415,8 @@
         if (isolatedProc != null) {
             pw.print(prefix); pw.print("isolatedProc="); pw.println(isolatedProc);
         }
-        if (whitelistManager) {
-            pw.print(prefix); pw.print("whitelistManager="); pw.println(whitelistManager);
+        if (allowlistManager) {
+            pw.print(prefix); pw.print("allowlistManager="); pw.println(allowlistManager);
         }
         if (mIsAllowedBgActivityStartsByBinding) {
             pw.print(prefix); pw.print("mIsAllowedBgActivityStartsByBinding=");
@@ -429,6 +434,8 @@
                 pw.println(mAllowWhileInUsePermissionInFgs);
         pw.print(prefix); pw.print("recentCallingPackage=");
                 pw.println(mRecentCallingPackage);
+        pw.print(prefix); pw.print("recentCallingUid=");
+        pw.println(mRecentCallingUid);
         pw.print(prefix); pw.print("allowStartForeground=");
         pw.println(mAllowStartForeground);
         pw.print(prefix); pw.print("infoAllowStartForeground=");
@@ -894,13 +901,13 @@
         return false;
     }
 
-    public void updateWhitelistManager() {
-        whitelistManager = false;
+    public void updateAllowlistManager() {
+        allowlistManager = false;
         for (int conni=connections.size()-1; conni>=0; conni--) {
             ArrayList<ConnectionRecord> cr = connections.valueAt(conni);
             for (int i=0; i<cr.size(); i++) {
                 if ((cr.get(i).flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
-                    whitelistManager = true;
+                    allowlistManager = true;
                     return;
                 }
             }
diff --git a/services/core/java/com/android/server/am/StrictModeViolationDialog.java b/services/core/java/com/android/server/am/StrictModeViolationDialog.java
index 4cc1fc1..9dddd65 100644
--- a/services/core/java/com/android/server/am/StrictModeViolationDialog.java
+++ b/services/core/java/com/android/server/am/StrictModeViolationDialog.java
@@ -82,6 +82,11 @@
                 DISMISS_TIMEOUT);
     }
 
+    @Override
+    protected void closeDialog() {
+        mHandler.obtainMessage(ACTION_OK).sendToTarget();
+    }
+
     private final Handler mHandler = new Handler() {
         public void handleMessage(Message msg) {
             synchronized (mService.mProcLock) {
diff --git a/services/core/java/com/android/server/am/TEST_MAPPING b/services/core/java/com/android/server/am/TEST_MAPPING
index 4061df4..03eddc9 100644
--- a/services/core/java/com/android/server/am/TEST_MAPPING
+++ b/services/core/java/com/android/server/am/TEST_MAPPING
@@ -44,6 +44,23 @@
           "exclude-annotation": "androidx.test.filters.FlakyTest"
         }
       ]
+    },
+    {
+      "file_patterns": ["Battery[^/]*\\.java", "MeasuredEnergy[^/]*\\.java"],
+      "name": "FrameworksCoreTests",
+      "options": [
+        { "include-filter": "com.android.internal.os.BatteryStatsTests" },
+        { "exclude-annotation": "com.android.internal.os.SkipPresubmit" }
+      ]
+    },
+    {
+      "file_patterns": ["Battery[^/]*\\.java", "MeasuredEnergy[^/]*\\.java"],
+      "name": "FrameworksServicesTests",
+      "options": [
+        { "include-filter": "com.android.server.am.BatteryStatsServiceTest" },
+        { "include-filter": "com.android.server.am.MeasuredEnergySnapshotTest" },
+        { "include-filter": "com.android.server.am.BatteryExternalStatsWorkerTest" }
+      ]
     }
   ],
   "postsubmit": [
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 6dd78e7..caf2510 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -27,6 +27,9 @@
 import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
 import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
 import static android.app.ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE;
+import static android.os.PowerWhitelistManager.REASON_BOOT_COMPLETED;
+import static android.os.PowerWhitelistManager.REASON_LOCKED_BOOT_COMPLETED;
+import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
 import static android.os.Process.SHELL_UID;
 import static android.os.Process.SYSTEM_UID;
 
@@ -74,6 +77,7 @@
 import android.os.IUserManager;
 import android.os.Looper;
 import android.os.Message;
+import android.os.PowerWhitelistManager;
 import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
@@ -522,7 +526,8 @@
                 mInjector.broadcastIntent(intent, null, resultTo, 0, null, null,
                         new String[]{android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
                         AppOpsManager.OP_NONE,
-                        getTemporaryAppWhitelistBroadcastOptions().toBundle(), true,
+                        getTemporaryAppAllowlistBroadcastOptions(REASON_LOCKED_BOOT_COMPLETED)
+                                .toBundle(), true,
                         false, MY_PID, SYSTEM_UID,
                         Binder.getCallingUid(), Binder.getCallingPid(), userId);
             }
@@ -770,9 +775,8 @@
                     }, 0, null, null,
                     new String[]{android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
                     AppOpsManager.OP_NONE,
-                    getTemporaryAppWhitelistBroadcastOptions().toBundle(), true,
-                    false, MY_PID, SYSTEM_UID,
-                    callingUid, callingPid, userId);
+                    getTemporaryAppAllowlistBroadcastOptions(REASON_BOOT_COMPLETED).toBundle(),
+                    true, false, MY_PID, SYSTEM_UID, callingUid, callingPid, userId);
         });
     }
 
@@ -2811,7 +2815,8 @@
         }
     }
 
-    private BroadcastOptions getTemporaryAppWhitelistBroadcastOptions() {
+    private BroadcastOptions getTemporaryAppAllowlistBroadcastOptions(
+            @PowerWhitelistManager.ReasonCode int reasonCode) {
         long duration = 10_000;
         final ActivityManagerInternal amInternal =
                 LocalServices.getService(ActivityManagerInternal.class);
@@ -2819,9 +2824,8 @@
             duration = amInternal.getBootTimeTempAllowListDuration();
         }
         final BroadcastOptions bOptions = BroadcastOptions.makeBasic();
-        bOptions.setTemporaryAppWhitelistDuration(
-                BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
-                duration);
+        bOptions.setTemporaryAppAllowlist(duration,
+                TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, reasonCode, "");
         return bOptions;
     }
 
diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
index e97f0b4..32ae878 100644
--- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java
+++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
@@ -23,9 +23,12 @@
 import static android.content.pm.PackageManager.MATCH_ANY_USER;
 import static android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION;
 
+import static com.android.server.apphibernation.AppHibernationConstants.KEY_APP_HIBERNATION_ENABLED;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.ActivityThread;
 import android.app.IActivityManager;
 import android.apphibernation.IAppHibernationService;
 import android.content.BroadcastReceiver;
@@ -45,6 +48,8 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.DeviceConfig;
+import android.provider.DeviceConfig.Properties;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Slog;
@@ -52,10 +57,13 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.DumpUtils;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.SystemService;
 
 import java.io.File;
 import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -93,6 +101,9 @@
     private final HibernationStateDiskStore<GlobalLevelState> mGlobalLevelHibernationDiskStore;
     private final Injector mInjector;
 
+    @VisibleForTesting
+    boolean mIsServiceEnabled;
+
     /**
      * Initializes the system service.
      * <p>
@@ -139,6 +150,13 @@
                 initializeGlobalHibernationStates(states);
             }
         }
+        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+            mIsServiceEnabled = isAppHibernationEnabled();
+            DeviceConfig.addOnPropertiesChangedListener(
+                    NAMESPACE_APP_HIBERNATION,
+                    ActivityThread.currentApplication().getMainExecutor(),
+                    this::onDeviceConfigChanged);
+        }
     }
 
     /**
@@ -149,6 +167,10 @@
      * @return true if package is hibernating for the user
      */
     boolean isHibernatingForUser(String packageName, int userId) {
+        if (!checkHibernationEnabled("isHibernatingForUser")) {
+            return false;
+        }
+
         userId = handleIncomingUser(userId, "isHibernating");
         if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
             Slog.e(TAG, "Attempt to get hibernation state of stopped or nonexistent user "
@@ -174,6 +196,9 @@
      * @param packageName package to check
      */
     boolean isHibernatingGlobally(String packageName) {
+        if (!checkHibernationEnabled("isHibernatingGlobally")) {
+            return false;
+        }
         synchronized (mLock) {
             GlobalLevelState state = mGlobalHibernationStates.get(packageName);
             if (state == null) {
@@ -192,6 +217,9 @@
      * @param isHibernating new hibernation state
      */
     void setHibernatingForUser(String packageName, int userId, boolean isHibernating) {
+        if (!checkHibernationEnabled("setHibernatingForUser")) {
+            return;
+        }
         userId = handleIncomingUser(userId, "setHibernating");
         if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
             Slog.w(TAG, "Attempt to set hibernation state for a stopped or nonexistent user "
@@ -229,6 +257,9 @@
      * @param isHibernating new hibernation state
      */
     void setHibernatingGlobally(String packageName, boolean isHibernating) {
+        if (!checkHibernationEnabled("setHibernatingGlobally")) {
+            return;
+        }
         synchronized (mLock) {
             GlobalLevelState state = mGlobalHibernationStates.get(packageName);
             if (state == null) {
@@ -421,6 +452,9 @@
 
     private void onPackageAdded(@NonNull String packageName, int userId) {
         synchronized (mLock) {
+            if (!mUserStates.contains(userId)) {
+                return;
+            }
             UserLevelState userState = new UserLevelState();
             userState.packageName = packageName;
             mUserStates.get(userId).put(packageName, userState);
@@ -434,6 +468,9 @@
 
     private void onPackageRemoved(@NonNull String packageName, int userId) {
         synchronized (mLock) {
+            if (!mUserStates.contains(userId)) {
+                return;
+            }
             mUserStates.get(userId).remove(packageName);
         }
     }
@@ -444,6 +481,15 @@
         }
     }
 
+    private void onDeviceConfigChanged(Properties properties) {
+        for (String key : properties.getKeyset()) {
+            if (TextUtils.equals(KEY_APP_HIBERNATION_ENABLED, key)) {
+                mIsServiceEnabled = isAppHibernationEnabled();
+                break;
+            }
+        }
+    }
+
     /**
      * Private helper method to get the real user id and enforce permission checks.
      *
@@ -461,6 +507,44 @@
         }
     }
 
+    private boolean checkHibernationEnabled(String methodName) {
+        if (!mIsServiceEnabled) {
+            Slog.w(TAG, String.format("Attempted to call %s on unsupported device.", methodName));
+        }
+        return mIsServiceEnabled;
+    }
+
+    private void dump(PrintWriter pw) {
+        // Check usage stats permission since hibernation indirectly informs usage.
+        if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
+
+        IndentingPrintWriter idpw = new IndentingPrintWriter(pw, "  ");
+
+        synchronized (mLock) {
+            final int userCount = mUserStates.size();
+            for (int i = 0; i < userCount; i++) {
+                final int userId = mUserStates.keyAt(i);
+                idpw.print("User Level Hibernation States, ");
+                idpw.printPair("user", userId);
+                idpw.println();
+                Map<String, UserLevelState> stateMap = mUserStates.get(i);
+                idpw.increaseIndent();
+                for (UserLevelState state : stateMap.values()) {
+                    idpw.print(state);
+                    idpw.println();
+                }
+                idpw.decreaseIndent();
+            }
+            idpw.println();
+            idpw.print("Global Level Hibernation States");
+            idpw.println();
+            for (GlobalLevelState state : mGlobalHibernationStates.values()) {
+                idpw.print(state);
+                idpw.println();
+            }
+        }
+    }
+
     private final AppHibernationServiceStub mServiceStub = new AppHibernationServiceStub(this);
 
     static final class AppHibernationServiceStub extends IAppHibernationService.Stub {
@@ -497,6 +581,12 @@
             new AppHibernationShellCommand(mService).exec(this, in, out, err, args, callback,
                     resultReceiver);
         }
+
+        @Override
+        protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout,
+                @Nullable String[] args) {
+            mService.dump(fout);
+        }
     }
 
     // Broadcast receiver for package add/removal events
@@ -536,7 +626,7 @@
     public static boolean isAppHibernationEnabled() {
         return DeviceConfig.getBoolean(
                 NAMESPACE_APP_HIBERNATION,
-                AppHibernationConstants.KEY_APP_HIBERNATION_ENABLED,
+                KEY_APP_HIBERNATION_ENABLED,
                 false /* defaultValue */);
     }
 
diff --git a/services/core/java/com/android/server/apphibernation/GlobalLevelState.java b/services/core/java/com/android/server/apphibernation/GlobalLevelState.java
index 4f75675..baa84b7 100644
--- a/services/core/java/com/android/server/apphibernation/GlobalLevelState.java
+++ b/services/core/java/com/android/server/apphibernation/GlobalLevelState.java
@@ -22,4 +22,12 @@
 final class GlobalLevelState {
     public String packageName;
     public boolean hibernated;
+
+    @Override
+    public String toString() {
+        return "GlobalLevelState{"
+                + "packageName='" + packageName + '\''
+                + ", hibernated=" + hibernated
+                + '}';
+    }
 }
diff --git a/services/core/java/com/android/server/apphibernation/UserLevelState.java b/services/core/java/com/android/server/apphibernation/UserLevelState.java
index c66dad8..272d3d1 100644
--- a/services/core/java/com/android/server/apphibernation/UserLevelState.java
+++ b/services/core/java/com/android/server/apphibernation/UserLevelState.java
@@ -22,4 +22,12 @@
 final class UserLevelState {
     public String packageName;
     public boolean hibernated;
+
+    @Override
+    public String toString() {
+        return "UserLevelState{"
+                + "packageName='" + packageName + '\''
+                + ", hibernated=" + hibernated
+                + '}';
+    }
 }
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index c92abd4..44dcc20 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -339,7 +339,10 @@
     SparseIntArray mProfileOwners;
 
     @GuardedBy("this")
-    private CheckOpsDelegate mCheckOpsDelegate;
+    private CheckOpsDelegate mAppOpsPolicy;
+
+    @GuardedBy("this")
+    private CheckOpsDelegateDispatcher mCheckOpsDelegateDispatcher;
 
     /**
       * Reverse lookup for {@link AppOpsManager#opToSwitch(int)}. Initialized once and never
@@ -1770,6 +1773,17 @@
         mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
     }
 
+    /**
+     * Sets a policy for handling app ops.
+     *
+     * @param appOpsPolicy The policy.
+     */
+    public void setAppOpsPolicy(@Nullable CheckOpsDelegate appOpsPolicy) {
+        synchronized (AppOpsService.this) {
+            mAppOpsPolicy = appOpsPolicy;
+        }
+    }
+
     public void packageRemoved(int uid, String packageName) {
         synchronized (this) {
             UidState uidState = mUidStates.get(uid);
@@ -2868,13 +2882,19 @@
 
     public CheckOpsDelegate getAppOpsServiceDelegate() {
         synchronized (this) {
-            return mCheckOpsDelegate;
+            return (mCheckOpsDelegateDispatcher != null)
+                    ? mCheckOpsDelegateDispatcher.getCheckOpsDelegate()
+                    : null;
         }
     }
 
     public void setAppOpsServiceDelegate(CheckOpsDelegate delegate) {
         synchronized (this) {
-            mCheckOpsDelegate = delegate;
+            if (delegate != null) {
+                mCheckOpsDelegateDispatcher = new CheckOpsDelegateDispatcher(delegate);
+            } else {
+                mCheckOpsDelegateDispatcher = null;
+            }
         }
     }
 
@@ -2889,19 +2909,28 @@
     }
 
     private int checkOperationInternal(int code, int uid, String packageName, boolean raw) {
-        final CheckOpsDelegate delegate;
-        synchronized (this) {
-            delegate = mCheckOpsDelegate;
+        final CheckOpsDelegate policy;
+        final CheckOpsDelegateDispatcher delegateDispatcher;
+        synchronized (AppOpsService.this) {
+            policy = mAppOpsPolicy;
+            delegateDispatcher = mCheckOpsDelegateDispatcher;
         }
-        if (delegate == null) {
-            return checkOperationImpl(code, uid, packageName, raw);
+        if (policy != null) {
+            if (delegateDispatcher != null) {
+                return policy.checkOperation(code, uid, packageName, raw,
+                        delegateDispatcher::checkOperationImpl);
+            } else {
+                return policy.checkOperation(code, uid, packageName, raw,
+                        AppOpsService.this::checkOperationImpl);
+            }
+        } else if (delegateDispatcher != null) {
+            delegateDispatcher.getCheckOpsDelegate().checkOperation(code, uid,
+                    packageName, raw, AppOpsService.this::checkOperationImpl);
         }
-        return delegate.checkOperation(code, uid, packageName, raw,
-                    AppOpsService.this::checkOperationImpl);
+        return checkOperationImpl(code, uid, packageName, raw);
     }
 
-    private int checkOperationImpl(int code, int uid, String packageName,
-                boolean raw) {
+    private int checkOperationImpl(int code, int uid, String packageName, boolean raw) {
         verifyIncomingOp(code);
         verifyIncomingPackage(packageName, UserHandle.getUserId(uid));
 
@@ -2956,15 +2985,25 @@
 
     @Override
     public int checkAudioOperation(int code, int usage, int uid, String packageName) {
-        final CheckOpsDelegate delegate;
-        synchronized (this) {
-            delegate = mCheckOpsDelegate;
+        final CheckOpsDelegate policy;
+        final CheckOpsDelegateDispatcher delegateDispatcher;
+        synchronized (AppOpsService.this) {
+            policy = mAppOpsPolicy;
+            delegateDispatcher = mCheckOpsDelegateDispatcher;
         }
-        if (delegate == null) {
-            return checkAudioOperationImpl(code, usage, uid, packageName);
+        if (policy != null) {
+            if (delegateDispatcher != null) {
+                return policy.checkAudioOperation(code, usage, uid, packageName,
+                        delegateDispatcher::checkAudioOperationImpl);
+            } else {
+                return policy.checkAudioOperation(code, usage, uid, packageName,
+                        AppOpsService.this::checkAudioOperationImpl);
+            }
+        } else if (delegateDispatcher != null) {
+            delegateDispatcher.getCheckOpsDelegate().checkAudioOperation(code, usage,
+                    uid, packageName, AppOpsService.this::checkAudioOperationImpl);
         }
-        return delegate.checkAudioOperation(code, usage, uid, packageName,
-                AppOpsService.this::checkAudioOperationImpl);
+        return checkAudioOperationImpl(code, usage, uid, packageName);
     }
 
     private int checkAudioOperationImpl(int code, int usage, int uid, String packageName) {
@@ -3078,17 +3117,29 @@
     @Override
     public int noteOperation(int code, int uid, String packageName, String attributionTag,
             boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage) {
-        final CheckOpsDelegate delegate;
-        synchronized (this) {
-            delegate = mCheckOpsDelegate;
+        final CheckOpsDelegate policy;
+        final CheckOpsDelegateDispatcher delegateDispatcher;
+        synchronized (AppOpsService.this) {
+            policy = mAppOpsPolicy;
+            delegateDispatcher = mCheckOpsDelegateDispatcher;
         }
-        if (delegate == null) {
-            return noteOperationImpl(code, uid, packageName, attributionTag,
-                    shouldCollectAsyncNotedOp, message, shouldCollectMessage);
+        if (policy != null) {
+            if (delegateDispatcher != null) {
+                return policy.noteOperation(code, uid, packageName, attributionTag,
+                        shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+                        delegateDispatcher::noteOperationImpl);
+            } else {
+                return policy.noteOperation(code, uid, packageName, attributionTag,
+                        shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+                        AppOpsService.this::noteOperationImpl);
+            }
+        } else if (delegateDispatcher != null) {
+            delegateDispatcher.getCheckOpsDelegate().noteOperation(code, uid, packageName,
+                    attributionTag, shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+                    AppOpsService.this::noteOperationImpl);
         }
-        return delegate.noteOperation(code, uid, packageName, attributionTag,
-                shouldCollectAsyncNotedOp, message, shouldCollectMessage,
-                AppOpsService.this::noteOperationImpl);
+        return noteOperationImpl(code, uid, packageName, attributionTag,
+                shouldCollectAsyncNotedOp, message, shouldCollectMessage);
     }
 
     private int noteOperationImpl(int code, int uid, @Nullable String packageName,
@@ -3124,7 +3175,7 @@
             final Ops ops = getOpsLocked(uid, packageName, attributionTag, bypass,
                     true /* edit */);
             if (ops == null) {
-                scheduleOpNotedIfNeededLocked(code, uid, packageName, flags,
+                scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags,
                         AppOpsManager.MODE_IGNORED);
                 if (DEBUG) Slog.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
                         + " package " + packageName);
@@ -3142,7 +3193,7 @@
             final UidState uidState = ops.uidState;
             if (isOpRestrictedLocked(uid, code, packageName, bypass)) {
                 attributedOp.rejected(uidState.state, flags);
-                scheduleOpNotedIfNeededLocked(code, uid, packageName, flags,
+                scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags,
                         AppOpsManager.MODE_IGNORED);
                 return AppOpsManager.MODE_IGNORED;
             }
@@ -3155,7 +3206,8 @@
                             + switchCode + " (" + code + ") uid " + uid + " package "
                             + packageName);
                     attributedOp.rejected(uidState.state, flags);
-                    scheduleOpNotedIfNeededLocked(code, uid, packageName, flags, uidMode);
+                    scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags,
+                            uidMode);
                     return uidMode;
                 }
             } else {
@@ -3167,7 +3219,8 @@
                             + switchCode + " (" + code + ") uid " + uid + " package "
                             + packageName);
                     attributedOp.rejected(uidState.state, flags);
-                    scheduleOpNotedIfNeededLocked(code, uid, packageName, flags, mode);
+                    scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags,
+                            mode);
                     return mode;
                 }
             }
@@ -3177,7 +3230,7 @@
                                 + packageName + (attributionTag == null ? ""
                                 : "." + attributionTag));
             }
-            scheduleOpNotedIfNeededLocked(code, uid, packageName, flags,
+            scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags,
                     AppOpsManager.MODE_ALLOWED);
             attributedOp.accessed(proxyUid, proxyPackageName, proxyAttributionTag, uidState.state,
                     flags);
@@ -3580,7 +3633,7 @@
             final Ops ops = getOpsLocked(uid, packageName, attributionTag, bypass, true /* edit */);
             if (ops == null) {
                 if (!dryRun) {
-                    scheduleOpStartedIfNeededLocked(code, uid, packageName,
+                    scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag,
                             flags, AppOpsManager.MODE_IGNORED);
                 }
                 if (DEBUG) Slog.d(TAG, "startOperation: no op for code " + code + " uid " + uid
@@ -3590,7 +3643,7 @@
             final Op op = getOpLocked(ops, code, uid, true);
             if (isOpRestrictedLocked(uid, code, packageName, bypass)) {
                 if (!dryRun) {
-                    scheduleOpStartedIfNeededLocked(code, uid, packageName,
+                    scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag,
                             flags, AppOpsManager.MODE_IGNORED);
                 }
                 return AppOpsManager.MODE_IGNORED;
@@ -3611,7 +3664,8 @@
                     }
                     if (!dryRun) {
                         attributedOp.rejected(uidState.state, flags);
-                        scheduleOpStartedIfNeededLocked(code, uid, packageName, flags, uidMode);
+                        scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag,
+                                flags, uidMode);
                     }
                     return uidMode;
                 }
@@ -3626,7 +3680,8 @@
                             + packageName);
                     if (!dryRun) {
                         attributedOp.rejected(uidState.state, flags);
-                        scheduleOpStartedIfNeededLocked(code, uid, packageName, flags, mode);
+                        scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag,
+                                flags, mode);
                     }
                     return mode;
                 }
@@ -3634,7 +3689,7 @@
             if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid
                     + " package " + packageName);
             if (!dryRun) {
-                scheduleOpStartedIfNeededLocked(code, uid, packageName, flags,
+                scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag, flags,
                         AppOpsManager.MODE_ALLOWED);
                 try {
                     attributedOp.started(clientId, proxyUid, proxyPackageName, proxyAttributionTag,
@@ -3774,7 +3829,7 @@
     }
 
     private void scheduleOpStartedIfNeededLocked(int code, int uid, String pkgName,
-            @OpFlags int flags, @Mode int result) {
+            String attributionTag, @OpFlags int flags, @Mode int result) {
         ArraySet<StartedCallback> dispatchedCallbacks = null;
         final int callbackListCount = mStartedWatchers.size();
         for (int i = 0; i < callbackListCount; i++) {
@@ -3799,18 +3854,21 @@
 
         mHandler.sendMessage(PooledLambda.obtainMessage(
                 AppOpsService::notifyOpStarted,
-                this, dispatchedCallbacks, code, uid, pkgName, flags, result));
+                this, dispatchedCallbacks, code, uid, pkgName, attributionTag, flags,
+                result));
     }
 
     private void notifyOpStarted(ArraySet<StartedCallback> callbacks,
-            int code, int uid, String packageName, @OpFlags int flags, @Mode int result) {
+            int code, int uid, String packageName, String attributionTag, @OpFlags int flags,
+            @Mode int result) {
         final long identity = Binder.clearCallingIdentity();
         try {
             final int callbackCount = callbacks.size();
             for (int i = 0; i < callbackCount; i++) {
                 final StartedCallback callback = callbacks.valueAt(i);
                 try {
-                    callback.mCallback.opStarted(code, uid, packageName, flags, result);
+                    callback.mCallback.opStarted(code, uid, packageName, attributionTag, flags,
+                            result);
                 } catch (RemoteException e) {
                     /* do nothing */
                 }
@@ -3821,7 +3879,7 @@
     }
 
     private void scheduleOpNotedIfNeededLocked(int code, int uid, String packageName,
-            @OpFlags int flags, @Mode int result) {
+            String attributionTag, @OpFlags int flags, @Mode int result) {
         ArraySet<NotedCallback> dispatchedCallbacks = null;
         final int callbackListCount = mNotedWatchers.size();
         for (int i = 0; i < callbackListCount; i++) {
@@ -3842,11 +3900,13 @@
         }
         mHandler.sendMessage(PooledLambda.obtainMessage(
                 AppOpsService::notifyOpChecked,
-                this, dispatchedCallbacks, code, uid, packageName, flags, result));
+                this, dispatchedCallbacks, code, uid, packageName, attributionTag, flags,
+                result));
     }
 
     private void notifyOpChecked(ArraySet<NotedCallback> callbacks,
-            int code, int uid, String packageName, @OpFlags int flags, @Mode int result) {
+            int code, int uid, String packageName, String attributionTag, @OpFlags int flags,
+            @Mode int result) {
         // There are features watching for checks in our process. The callbacks in
         // these features may require permissions our remote caller does not have.
         final long identity = Binder.clearCallingIdentity();
@@ -3855,7 +3915,8 @@
             for (int i = 0; i < callbackCount; i++) {
                 final NotedCallback callback = callbacks.valueAt(i);
                 try {
-                    callback.mCallback.opNoted(code, uid, packageName, flags, result);
+                    callback.mCallback.opNoted(code, uid, packageName, attributionTag, flags,
+                            result);
                 } catch (RemoteException e) {
                     /* do nothing */
                 }
@@ -6579,7 +6640,6 @@
         }
     }
 
-
     /**
      * Async task for writing note op stack trace, op code, package name and version to file
      * More specifically, writes all the collected ops from {@link #mNoteOpCallerStacktraces}
@@ -6716,4 +6776,34 @@
             }
         }
     }
+
+    private final class CheckOpsDelegateDispatcher {
+        private final @NonNull CheckOpsDelegate mCheckOpsDelegate;
+
+        CheckOpsDelegateDispatcher(@NonNull CheckOpsDelegate checkOpsDelegate) {
+            mCheckOpsDelegate = checkOpsDelegate;
+        }
+
+        public @NonNull CheckOpsDelegate getCheckOpsDelegate() {
+            return mCheckOpsDelegate;
+        }
+
+        public int checkOperationImpl(int code, int uid, String packageName, boolean raw) {
+            return mCheckOpsDelegate.checkOperation(code, uid, packageName, raw,
+                    AppOpsService.this::checkOperationImpl);
+        }
+
+        public int checkAudioOperationImpl(int code, int usage, int uid, String packageName) {
+            return mCheckOpsDelegate.checkAudioOperation(code, usage, uid, packageName,
+                    AppOpsService.this::checkAudioOperationImpl);
+        }
+
+        public int noteOperationImpl(int code, int uid, @Nullable String packageName,
+                @Nullable String featureId, boolean shouldCollectAsyncNotedOp,
+                @Nullable String message, boolean shouldCollectMessage) {
+            return mCheckOpsDelegate.noteOperation(code, uid, packageName, featureId,
+                    shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+                    AppOpsService.this::noteOperationImpl);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 6f625a7..f5b9417 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -178,6 +178,7 @@
 import java.util.Set;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.BooleanSupplier;
 import java.util.stream.Collectors;
 
@@ -330,7 +331,8 @@
 
     private SettingsObserver mSettingsObserver;
 
-    private int mMode = AudioSystem.MODE_NORMAL;
+    private AtomicInteger mMode = new AtomicInteger(AudioSystem.MODE_NORMAL);
+
     // protects mRingerMode
     private final Object mSettingsLock = new Object();
 
@@ -724,7 +726,7 @@
     // caches the value returned by AudioSystem.isMicrophoneMuted()
     private boolean mMicMuteFromSystemCached;
 
-    private boolean mFastScrollSoundEffectsEnabled;
+    private boolean mNavigationRepeatSoundEffectsEnabled;
     private boolean mHomeSoundEffectEnabled;
 
     @GuardedBy("mSettingsLock")
@@ -2323,15 +2325,15 @@
                 VOL_ADJUST_NORMAL);
     }
 
-    public void setFastScrollSoundEffectsEnabled(boolean enabled) {
-        mFastScrollSoundEffectsEnabled = enabled;
+    public void setNavigationRepeatSoundEffectsEnabled(boolean enabled) {
+        mNavigationRepeatSoundEffectsEnabled = enabled;
     }
 
     /**
      * @return true if the fast scroll sound effects are enabled
      */
-    public boolean areFastScrollSoundEffectsEnabled() {
-        return mFastScrollSoundEffectsEnabled;
+    public boolean areNavigationRepeatSoundEffectsEnabled() {
+        return mNavigationRepeatSoundEffectsEnabled;
     }
 
     public void setHomeSoundEffectEnabled(boolean enabled) {
@@ -2996,7 +2998,7 @@
     }
 
     /*package*/ int getHearingAidStreamType() {
-        return getHearingAidStreamType(getMode());
+        return getHearingAidStreamType(mMode.get());
     }
 
     private int getHearingAidStreamType(int mode) {
@@ -3136,7 +3138,8 @@
 
     private void dumpAudioMode(PrintWriter pw) {
         pw.println("\nAudio mode: ");
-        pw.println("- Current mode = " + AudioSystem.modeToString(getMode()));
+        pw.println("- Requested mode = " + AudioSystem.modeToString(getMode()));
+        pw.println("- Actual mode = " + AudioSystem.modeToString(mMode.get()));
         pw.println("- Mode owner: ");
         SetModeDeathHandler hdlr = getAudioModeOwnerHandler();
         if (hdlr != null) {
@@ -4477,10 +4480,10 @@
             pid = currentModeHandler.getPid();
         }
         if (DEBUG_MODE) {
-            Log.v(TAG, "onUpdateAudioMode() mode: " + mode + ", mMode: " + mMode
-                    + " requestedMode: " + requestedMode);
+            Log.v(TAG, "onUpdateAudioMode() new mode: " + mode + ", current mode: "
+                    + mMode.get() + " requested mode: " + requestedMode);
         }
-        if (mode != mMode) {
+        if (mode != mMode.get()) {
             final long identity = Binder.clearCallingIdentity();
             int status = mAudioSystem.setPhoneState(mode, uid);
             Binder.restoreCallingIdentity(identity);
@@ -4488,8 +4491,7 @@
                 if (DEBUG_MODE) {
                     Log.v(TAG, "onUpdateAudioMode: mode successfully set to " + mode);
                 }
-                int previousMode = mMode;
-                mMode = mode;
+                int previousMode = mMode.getAndSet(mode);
                 // Note: newModeOwnerPid is always 0 when actualMode is MODE_NORMAL
                 mModeLogger.log(new PhoneStateEvent(requesterPackage, requesterPid,
                         requestedMode, pid, mode));
@@ -5413,8 +5415,10 @@
         IsInCall = telecomManager.isInCall();
         Binder.restoreCallingIdentity(ident);
 
-        return (IsInCall || getMode() == AudioManager.MODE_IN_COMMUNICATION ||
-                getMode() == AudioManager.MODE_IN_CALL);
+        int mode = mMode.get();
+        return (IsInCall
+                || mode == AudioManager.MODE_IN_COMMUNICATION
+                || mode == AudioManager.MODE_IN_CALL);
     }
 
     /**
@@ -8566,6 +8570,7 @@
         public void postDisplaySafeVolumeWarning(int flags) {
             if (mController == null)
                 return;
+            flags = flags | AudioManager.FLAG_SHOW_UI;
             try {
                 mController.displaySafeVolumeWarning(flags);
             } catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/audio/SoundEffectsHelper.java b/services/core/java/com/android/server/audio/SoundEffectsHelper.java
index c14bb3e..7031e02 100644
--- a/services/core/java/com/android/server/audio/SoundEffectsHelper.java
+++ b/services/core/java/com/android/server/audio/SoundEffectsHelper.java
@@ -52,6 +52,7 @@
  * used by AudioService. As its methods are called on the message handler thread
  * of AudioService, the actual work is offloaded to a dedicated thread.
  * This helps keeping AudioService responsive.
+ *
  * @hide
  */
 class SoundEffectsHelper {
@@ -89,15 +90,18 @@
         final String mFileName;
         int mSampleId;
         boolean mLoaded;  // for effects in SoundPool
+
         Resource(String fileName) {
             mFileName = fileName;
             mSampleId = EFFECT_NOT_IN_SOUND_POOL;
         }
+
         void unload() {
             mSampleId = EFFECT_NOT_IN_SOUND_POOL;
             mLoaded = false;
         }
     }
+
     // All the fields below are accessed by the worker thread exclusively
     private final List<Resource> mResources = new ArrayList<Resource>();
     private final int[] mEffects = new int[AudioManager.NUM_SOUND_EFFECTS]; // indexes in mResources
@@ -116,9 +120,9 @@
     }
 
     /**
-     *  Unloads samples from the sound pool.
-     *  This method can be called to free some memory when
-     *  sound effects are disabled.
+     * Unloads samples from the sound pool.
+     * This method can be called to free some memory when
+     * sound effects are disabled.
      */
     /*package*/ void unloadSoundEffects() {
         sendMsg(MSG_UNLOAD_EFFECTS, 0, 0, null, 0);
@@ -385,12 +389,12 @@
                     }
                 }
 
-                boolean fastScrollSoundEffectsParsed = allFastScrollSoundsParsed(parserCounter);
+                boolean navigationRepeatFxParsed = allNavigationRepeatSoundsParsed(parserCounter);
                 boolean homeSoundParsed = parserCounter.getOrDefault(AudioManager.FX_HOME, 0) > 0;
-                if (fastScrollSoundEffectsParsed || homeSoundParsed) {
+                if (navigationRepeatFxParsed || homeSoundParsed) {
                     AudioManager audioManager = mContext.getSystemService(AudioManager.class);
-                    if (audioManager != null && fastScrollSoundEffectsParsed) {
-                        audioManager.setFastScrollSoundEffectsEnabled(true);
+                    if (audioManager != null && navigationRepeatFxParsed) {
+                        audioManager.setNavigationRepeatSoundEffectsEnabled(true);
                     }
                     if (audioManager != null && homeSoundParsed) {
                         audioManager.setHomeSoundEffectEnabled(true);
@@ -410,13 +414,13 @@
         }
     }
 
-    private boolean allFastScrollSoundsParsed(Map<Integer, Integer> parserCounter) {
+    private boolean allNavigationRepeatSoundsParsed(Map<Integer, Integer> parserCounter) {
         int numFastScrollSoundEffectsParsed =
-                parserCounter.getOrDefault(AudioManager.FX_FAST_SCROLL_1, 0)
-                        + parserCounter.getOrDefault(AudioManager.FX_FAST_SCROLL_2, 0)
-                        + parserCounter.getOrDefault(AudioManager.FX_FAST_SCROLL_3, 0)
-                        + parserCounter.getOrDefault(AudioManager.FX_FAST_SCROLL_4, 0);
-        return numFastScrollSoundEffectsParsed == AudioManager.NUM_FAST_SCROLL_SOUND_EFFECTS;
+                parserCounter.getOrDefault(AudioManager.FX_FOCUS_NAVIGATION_REPEAT_1, 0)
+                        + parserCounter.getOrDefault(AudioManager.FX_FOCUS_NAVIGATION_REPEAT_2, 0)
+                        + parserCounter.getOrDefault(AudioManager.FX_FOCUS_NAVIGATION_REPEAT_3, 0)
+                        + parserCounter.getOrDefault(AudioManager.FX_FOCUS_NAVIGATION_REPEAT_4, 0);
+        return numFastScrollSoundEffectsParsed == AudioManager.NUM_NAVIGATION_REPEAT_SOUND_EFFECTS;
     }
 
     private int findOrAddResourceByFileName(String fileName) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java
index 16f82af..8197edc 100644
--- a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java
@@ -96,4 +96,9 @@
     public int getProtoEnum() {
         return BiometricsProto.CM_REMOVE;
     }
+
+    @Override
+    public boolean interruptsPrecedingClients() {
+        return true;
+    }
 }
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/ReEnrollNotificationUtils.java b/services/core/java/com/android/server/biometrics/sensors/face/ReEnrollNotificationUtils.java
new file mode 100644
index 0000000..f35a520
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/face/ReEnrollNotificationUtils.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors.face;
+
+import android.annotation.NonNull;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.UserHandle;
+
+import com.android.internal.R;
+
+public class ReEnrollNotificationUtils {
+
+    private static final String NOTIFICATION_TAG = "FaceService";
+    private static final int NOTIFICATION_ID = 1;
+
+    public static void showReEnrollmentNotification(@NonNull Context context) {
+        final NotificationManager notificationManager =
+                context.getSystemService(NotificationManager.class);
+
+        final String name =
+                context.getString(R.string.face_recalibrate_notification_name);
+        final String title =
+                context.getString(R.string.face_recalibrate_notification_title);
+        final String content =
+                context.getString(R.string.face_recalibrate_notification_content);
+
+        final Intent intent = new Intent("android.settings.FACE_SETTINGS");
+        intent.setPackage("com.android.settings");
+
+        final PendingIntent pendingIntent = PendingIntent.getActivityAsUser(context,
+                0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE /* flags */,
+                null /* options */, UserHandle.CURRENT);
+
+        final String channelName = "FaceEnrollNotificationChannel";
+
+        final NotificationChannel channel = new NotificationChannel(channelName, name,
+                NotificationManager.IMPORTANCE_HIGH);
+        final Notification notification = new Notification.Builder(context, channelName)
+                .setSmallIcon(R.drawable.ic_lock)
+                .setContentTitle(title)
+                .setContentText(content)
+                .setSubText(name)
+                .setOnlyAlertOnce(true)
+                .setLocalOnly(true)
+                .setAutoCancel(true)
+                .setCategory(Notification.CATEGORY_SYSTEM)
+                .setContentIntent(pendingIntent)
+                .setVisibility(Notification.VISIBILITY_SECRET)
+                .build();
+
+        notificationManager.createNotificationChannel(channel);
+        notificationManager.notifyAsUser(NOTIFICATION_TAG,
+                NOTIFICATION_ID, notification,
+                UserHandle.CURRENT);
+    }
+
+    public static void cancelNotification(@NonNull Context context) {
+        final NotificationManager notificationManager =
+                context.getSystemService(NotificationManager.class);
+        notificationManager.cancelAsUser(NOTIFICATION_TAG, NOTIFICATION_ID, UserHandle.CURRENT);
+    }
+
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index 8f55402..089cf1e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -41,6 +41,7 @@
 import com.android.server.biometrics.sensors.LockoutCache;
 import com.android.server.biometrics.sensors.LockoutConsumer;
 import com.android.server.biometrics.sensors.LockoutTracker;
+import com.android.server.biometrics.sensors.face.ReEnrollNotificationUtils;
 import com.android.server.biometrics.sensors.face.UsageStats;
 
 import java.util.ArrayList;
@@ -163,6 +164,9 @@
                     vibrateError();
                 }
                 break;
+            case BiometricConstants.BIOMETRIC_ERROR_RE_ENROLL:
+                ReEnrollNotificationUtils.showReEnrollmentNotification(getContext());
+                break;
             default:
                 break;
         }
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
index 898d81b..0eb51fd 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
@@ -41,6 +41,7 @@
 import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
 import com.android.server.biometrics.sensors.EnrollClient;
 import com.android.server.biometrics.sensors.face.FaceUtils;
+import com.android.server.biometrics.sensors.face.ReEnrollNotificationUtils;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -85,6 +86,13 @@
     }
 
     @Override
+    public void start(@NonNull Callback callback) {
+        super.start(callback);
+
+        ReEnrollNotificationUtils.cancelNotification(getContext());
+    }
+
+    @Override
     public void destroy() {
         try {
             AidlNativeHandleUtils.close(mPreviewSurface);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestHal.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestHal.java
index ff65c93..afa5bd2 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestHal.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestHal.java
@@ -22,6 +22,7 @@
 import android.hardware.biometrics.face.ISession;
 import android.hardware.biometrics.face.ISessionCallback;
 import android.hardware.biometrics.face.SensorProps;
+import android.hardware.biometrics.face.SessionState;
 import android.hardware.common.NativeHandle;
 import android.hardware.keymaster.HardwareAuthToken;
 import android.os.RemoteException;
@@ -131,6 +132,15 @@
                 Slog.w(TAG, "resetLockout, cookie: " + cookie);
                 cb.onLockoutCleared();
             }
+
+            @Override
+            public void close(int cookie) throws RemoteException {
+                cb.onStateChanged(cookie, SessionState.CLOSED);
+            }
         };
     }
+
+    @Override
+    public void reset() {
+    }
 }
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
index ee8823e..1b9bd7f 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
-import android.app.NotificationManager;
 import android.app.SynchronousUserSwitchObserver;
 import android.app.UserSwitchObserver;
 import android.content.Context;
@@ -71,6 +70,7 @@
 import com.android.server.biometrics.sensors.RemovalConsumer;
 import com.android.server.biometrics.sensors.face.FaceUtils;
 import com.android.server.biometrics.sensors.face.LockoutHalImpl;
+import com.android.server.biometrics.sensors.face.ReEnrollNotificationUtils;
 import com.android.server.biometrics.sensors.face.ServiceProvider;
 import com.android.server.biometrics.sensors.face.UsageStats;
 
@@ -96,8 +96,6 @@
 
     private static final String TAG = "Face10";
     private static final int ENROLL_TIMEOUT_SEC = 75;
-    static final String NOTIFICATION_TAG = "FaceService";
-    static final int NOTIFICATION_ID = 1;
 
     private boolean mTestHalEnabled;
 
@@ -109,7 +107,6 @@
     @NonNull private final LockoutResetDispatcher mLockoutResetDispatcher;
     @NonNull private final LockoutHalImpl mLockoutTracker;
     @NonNull private final UsageStats mUsageStats;
-    @NonNull private final NotificationManager mNotificationManager;
     @NonNull private final Map<Integer, Long> mAuthenticatorIds;
     @Nullable private IBiometricsFace mDaemon;
     @NonNull private final HalResultController mHalResultController;
@@ -343,7 +340,6 @@
         mUsageStats = new UsageStats(context);
         mAuthenticatorIds = new HashMap<>();
         mLazyDaemon = Face10.this::getDaemon;
-        mNotificationManager = mContext.getSystemService(NotificationManager.class);
         mLockoutTracker = new LockoutHalImpl();
         mLockoutResetDispatcher = lockoutResetDispatcher;
         mHalResultController = new HalResultController(sensorId, context, mHandler, mScheduler,
@@ -607,8 +603,7 @@
         mHandler.post(() -> {
             scheduleUpdateActiveUserWithoutHandler(userId);
 
-            mNotificationManager.cancelAsUser(NOTIFICATION_TAG, NOTIFICATION_ID,
-                    UserHandle.CURRENT);
+            ReEnrollNotificationUtils.cancelNotification(mContext);
 
             final FaceEnrollClient client = new FaceEnrollClient(mContext, mLazyDaemon, token,
                     new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
index a4b3ac5..3ca51d3 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
@@ -17,12 +17,7 @@
 package com.android.server.biometrics.sensors.face.hidl;
 
 import android.annotation.NonNull;
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
 import android.content.Context;
-import android.content.Intent;
 import android.content.res.Resources;
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricConstants;
@@ -32,7 +27,6 @@
 import android.hardware.face.FaceManager;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.os.UserHandle;
 import android.util.Slog;
 
 import com.android.internal.R;
@@ -40,6 +34,7 @@
 import com.android.server.biometrics.sensors.AuthenticationClient;
 import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
 import com.android.server.biometrics.sensors.LockoutTracker;
+import com.android.server.biometrics.sensors.face.ReEnrollNotificationUtils;
 import com.android.server.biometrics.sensors.face.UsageStats;
 
 import java.util.ArrayList;
@@ -52,7 +47,7 @@
 
     private static final String TAG = "FaceAuthenticationClient";
 
-    private final NotificationManager mNotificationManager;
+
     private final UsageStats mUsageStats;
 
     private final int[] mBiometricPromptIgnoreList;
@@ -72,7 +67,6 @@
                 owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
                 BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */,
                 lockoutTracker, isKeyguard);
-        mNotificationManager = context.getSystemService(NotificationManager.class);
         mUsageStats = usageStats;
 
         final Resources resources = getContext().getResources();
@@ -188,41 +182,7 @@
         mLastAcquire = acquireInfo;
 
         if (acquireInfo == FaceManager.FACE_ACQUIRED_RECALIBRATE) {
-            final String name =
-                    getContext().getString(R.string.face_recalibrate_notification_name);
-            final String title =
-                    getContext().getString(R.string.face_recalibrate_notification_title);
-            final String content =
-                    getContext().getString(R.string.face_recalibrate_notification_content);
-
-            final Intent intent = new Intent("android.settings.FACE_SETTINGS");
-            intent.setPackage("com.android.settings");
-
-            final PendingIntent pendingIntent = PendingIntent.getActivityAsUser(getContext(),
-                    0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE /* flags */,
-                    null /* options */, UserHandle.CURRENT);
-
-            final String channelName = "FaceEnrollNotificationChannel";
-
-            NotificationChannel channel = new NotificationChannel(channelName, name,
-                    NotificationManager.IMPORTANCE_HIGH);
-            Notification notification = new Notification.Builder(getContext(), channelName)
-                    .setSmallIcon(R.drawable.ic_lock)
-                    .setContentTitle(title)
-                    .setContentText(content)
-                    .setSubText(name)
-                    .setOnlyAlertOnce(true)
-                    .setLocalOnly(true)
-                    .setAutoCancel(true)
-                    .setCategory(Notification.CATEGORY_SYSTEM)
-                    .setContentIntent(pendingIntent)
-                    .setVisibility(Notification.VISIBILITY_SECRET)
-                    .build();
-
-            mNotificationManager.createNotificationChannel(channel);
-            mNotificationManager.notifyAsUser(Face10.NOTIFICATION_TAG,
-                    Face10.NOTIFICATION_ID, notification,
-                    UserHandle.CURRENT);
+            ReEnrollNotificationUtils.showReEnrollmentNotification(getContext());
         }
 
         final boolean shouldSend = shouldSend(acquireInfo, vendorCode);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestHal.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestHal.java
index 8ed24b6..9db2fcf 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestHal.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestHal.java
@@ -22,6 +22,7 @@
 import android.hardware.biometrics.fingerprint.ISession;
 import android.hardware.biometrics.fingerprint.ISessionCallback;
 import android.hardware.biometrics.fingerprint.SensorProps;
+import android.hardware.biometrics.fingerprint.SessionState;
 import android.hardware.keymaster.HardwareAuthToken;
 import android.os.RemoteException;
 import android.util.Slog;
@@ -119,6 +120,11 @@
             }
 
             @Override
+            public void close(int cookie) throws RemoteException {
+                cb.onStateChanged(cookie, SessionState.CLOSED);
+            }
+
+            @Override
             public void onPointerDown(int pointerId, int x, int y, float minor, float major) {
                 Slog.w(TAG, "onPointerDown");
             }
@@ -134,4 +140,9 @@
             }
         };
     }
+
+    @Override
+    public void reset() {
+    }
 }
+
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index 5076007..42fcd44 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -61,7 +61,6 @@
 
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
-import com.android.server.SystemService.TargetUser;
 import com.android.server.UiThread;
 import com.android.server.contentcapture.ContentCaptureManagerInternal;
 import com.android.server.uri.UriGrantsManagerInternal;
@@ -207,7 +206,7 @@
                                          new ClipData.Item(contents));
                         synchronized(mClipboards) {
                             setPrimaryClipInternal(getClipboard(0), clip,
-                                    android.os.Process.SYSTEM_UID);
+                                    android.os.Process.SYSTEM_UID, null);
                         }
                     }
                 });
@@ -247,6 +246,8 @@
         ClipData primaryClip;
         /** UID that set {@link #primaryClip}. */
         int primaryClipUid = android.os.Process.NOBODY_UID;
+        /** Package of the app that set {@link #primaryClip}. */
+        String mPrimaryClipPackage;
 
         final HashSet<String> activePermissionOwners
                 = new HashSet<String>();
@@ -365,7 +366,7 @@
                     return;
                 }
                 checkDataOwnerLocked(clip, intendingUid);
-                setPrimaryClipInternal(clip, intendingUid);
+                setPrimaryClipInternal(clip, intendingUid, callingPackage);
             }
         }
 
@@ -378,7 +379,7 @@
                         intendingUid, intendingUserId)) {
                     return;
                 }
-                setPrimaryClipInternal(null, intendingUid);
+                setPrimaryClipInternal(null, intendingUid, callingPackage);
             }
         }
 
@@ -509,6 +510,11 @@
     }
 
     void setPrimaryClipInternal(@Nullable ClipData clip, int uid) {
+        setPrimaryClipInternal(clip, uid, null);
+    }
+
+    private void setPrimaryClipInternal(
+            @Nullable ClipData clip, int uid, @Nullable String sourcePackage) {
         // Push clipboard to host, if any
         if (mHostClipboardMonitor != null) {
             if (clip == null) {
@@ -524,7 +530,7 @@
 
         // Update this user
         final int userId = UserHandle.getUserId(uid);
-        setPrimaryClipInternal(getClipboard(userId), clip, uid);
+        setPrimaryClipInternal(getClipboard(userId), clip, uid, sourcePackage);
 
         // Update related users
         List<UserInfo> related = getRelatedProfiles(userId);
@@ -558,7 +564,8 @@
                         final boolean canCopyIntoProfile = !hasRestriction(
                                 UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE, id);
                         if (canCopyIntoProfile) {
-                            setPrimaryClipInternal(getClipboard(id), clip, uid);
+                            setPrimaryClipInternal(
+                                    getClipboard(id), clip, uid, sourcePackage);
                         }
                     }
                 }
@@ -568,6 +575,11 @@
 
     void setPrimaryClipInternal(PerUserClipboard clipboard, @Nullable ClipData clip,
             int uid) {
+        setPrimaryClipInternal(clipboard, clip, uid, null);
+    }
+
+    private void setPrimaryClipInternal(PerUserClipboard clipboard, @Nullable ClipData clip,
+            int uid, @Nullable String sourcePackage) {
         revokeUris(clipboard);
         clipboard.activePermissionOwners.clear();
         if (clip == null && clipboard.primaryClip == null) {
@@ -576,8 +588,10 @@
         clipboard.primaryClip = clip;
         if (clip != null) {
             clipboard.primaryClipUid = uid;
+            clipboard.mPrimaryClipPackage = sourcePackage;
         } else {
             clipboard.primaryClipUid = android.os.Process.NOBODY_UID;
+            clipboard.mPrimaryClipPackage = null;
         }
         if (clip != null) {
             final ClipDescription description = clip.getDescription();
@@ -861,29 +875,34 @@
                 && mAutofillInternal.isAugmentedAutofillServiceForUser(uid, userId)) {
             return;
         }
-        // Load the labels for the calling app and the app that set the clipboard content.
-        final long ident = Binder.clearCallingIdentity();
+
+        // Retrieve the app label of the source of the clip data
+        CharSequence sourceAppLabel = null;
+        if (clipboard.mPrimaryClipPackage != null) {
+            try {
+                sourceAppLabel = mPm.getApplicationLabel(mPm.getApplicationInfoAsUser(
+                        clipboard.mPrimaryClipPackage, 0, userId));
+            } catch (PackageManager.NameNotFoundException e) {
+                // leave label as null
+            }
+        }
+
         try {
-            final IPackageManager pm = AppGlobals.getPackageManager();
+            CharSequence callingAppLabel = mPm.getApplicationLabel(
+                    mPm.getApplicationInfoAsUser(callingPackage, 0, userId));
             String message;
-            final CharSequence callingLabel = mPm.getApplicationLabel(
-                    pm.getApplicationInfo(callingPackage, 0, userId));
-            final String[] packagesForUid = pm.getPackagesForUid(clipboard.primaryClipUid);
-            if (packagesForUid != null && packagesForUid.length > 0) {
-                final CharSequence clipLabel = mPm.getApplicationLabel(
-                        pm.getApplicationInfo(packagesForUid[0], 0,
-                                UserHandle.getUserId(clipboard.primaryClipUid)));
-                message = callingLabel + " pasted from " + clipLabel;
+            if (sourceAppLabel != null) {
+                message = callingAppLabel + " pasted from " + sourceAppLabel;
             } else {
-                message = callingLabel + " pasted from clipboard";
+                message = callingAppLabel + " pasted from clipboard";
             }
             Slog.i(TAG, message);
-            Toast.makeText(getContext(), UiThread.get().getLooper(), message, Toast.LENGTH_SHORT)
-                    .show();
-        } catch (RemoteException e) {
-            /* ignore */
-        } finally {
-            Binder.restoreCallingIdentity(ident);
+            Binder.withCleanCallingIdentity(() ->
+                    Toast.makeText(getContext(), UiThread.get().getLooper(), message,
+                            Toast.LENGTH_SHORT)
+                            .show());
+        } catch (PackageManager.NameNotFoundException e) {
+            // do nothing
         }
     }
 }
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index 422991e..66a6520 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -50,6 +50,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -595,17 +596,23 @@
      * Rechecks all the existing overrides for a package.
      */
     void recheckOverrides(String packageName) {
+        // Local cache of compat changes. Holding a lock on mChanges for the whole duration of the
+        // method will cause a deadlock.
+        List<CompatChange> changes;
         synchronized (mChanges) {
-            boolean shouldInvalidateCache = false;
+            changes = new ArrayList<>(mChanges.size());
             for (int idx = 0; idx < mChanges.size(); ++idx) {
-                CompatChange c = mChanges.valueAt(idx);
-                OverrideAllowedState allowedState =
-                        mOverrideValidator.getOverrideAllowedState(c.getId(), packageName);
-                shouldInvalidateCache |= c.recheckOverride(packageName, allowedState, mContext);
+                changes.add(mChanges.valueAt(idx));
             }
-            if (shouldInvalidateCache) {
-                invalidateCache();
-            }
+        }
+        boolean shouldInvalidateCache = false;
+        for (CompatChange c: changes) {
+            OverrideAllowedState allowedState =
+                    mOverrideValidator.getOverrideAllowedState(c.getId(), packageName);
+            shouldInvalidateCache |= c.recheckOverride(packageName, allowedState, mContext);
+        }
+        if (shouldInvalidateCache) {
+            invalidateCache();
         }
     }
 
diff --git a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
index 21ef356..4ecc759 100644
--- a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
+++ b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
@@ -26,6 +26,7 @@
 import static android.net.NetworkPolicy.LIMIT_DISABLED;
 import static android.net.NetworkPolicy.WARNING_DISABLED;
 import static android.net.NetworkTemplate.NETWORK_TYPE_ALL;
+import static android.net.NetworkTemplate.OEM_MANAGED_ALL;
 import static android.provider.Settings.Global.NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES;
 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
@@ -226,7 +227,7 @@
             mNetworkTemplate = new NetworkTemplate(
                     NetworkTemplate.MATCH_MOBILE, subscriberId, new String[] { subscriberId },
                     null, NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
-                    NetworkStats.DEFAULT_NETWORK_NO, NETWORK_TYPE_ALL);
+                    NetworkStats.DEFAULT_NETWORK_NO, NETWORK_TYPE_ALL, OEM_MANAGED_ALL);
             mUsageCallback = new UsageCallback() {
                 @Override
                 public void onThresholdReached(int networkType, String subscriberId) {
@@ -274,7 +275,8 @@
                     null /* networkId, unused for matching mobile networks */,
                     !nc.hasCapability(NET_CAPABILITY_NOT_ROAMING),
                     !nc.hasCapability(NET_CAPABILITY_NOT_METERED),
-                    false /* defaultNetwork, templates should have DEFAULT_NETWORK_ALL */);
+                    false /* defaultNetwork, templates should have DEFAULT_NETWORK_ALL */,
+                    OEM_MANAGED_ALL);
         }
 
         private long getRemainingDailyBudget(long limitBytes,
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index 46c49e7..641287f 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -16,6 +16,8 @@
 
 package com.android.server.connectivity;
 
+import static com.android.net.module.util.CollectionUtils.contains;
+
 import android.annotation.NonNull;
 import android.net.ConnectivityManager;
 import android.net.IDnsResolver;
@@ -33,7 +35,6 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
 import com.android.net.module.util.NetworkStackConstants;
 import com.android.server.net.BaseNetworkObserver;
 
@@ -117,8 +118,8 @@
     @VisibleForTesting
     protected static boolean requiresClat(NetworkAgentInfo nai) {
         // TODO: migrate to NetworkCapabilities.TRANSPORT_*.
-        final boolean supported = ArrayUtils.contains(NETWORK_TYPES, nai.networkInfo.getType());
-        final boolean connected = ArrayUtils.contains(NETWORK_STATES, nai.networkInfo.getState());
+        final boolean supported = contains(NETWORK_TYPES, nai.networkInfo.getType());
+        final boolean connected = contains(NETWORK_STATES, nai.networkInfo.getState());
 
         // Only run clat on networks that have a global IPv6 address and don't have a native IPv4
         // address.
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index c05e253..4cf5274 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -899,7 +899,7 @@
                     ? networkAgentConfig.subscriberId : null;
             return new NetworkState(new NetworkInfo(networkInfo),
                     new LinkProperties(linkProperties),
-                    new NetworkCapabilities(networkCapabilities), network, subscriberId, null);
+                    new NetworkCapabilities(networkCapabilities), network, subscriberId);
         }
     }
 
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index 8bf1886..9411e33 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -28,6 +28,8 @@
 import static android.os.Process.INVALID_UID;
 import static android.os.Process.SYSTEM_UID;
 
+import static com.android.net.module.util.CollectionUtils.toIntArray;
+
 import android.annotation.NonNull;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -40,23 +42,21 @@
 import android.os.Build;
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
+import android.os.SystemConfigManager;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.system.OsConstants;
-import android.util.ArraySet;
 import android.util.Log;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.net.module.util.CollectionUtils;
 import com.android.server.LocalServices;
-import com.android.server.SystemConfig;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -80,6 +80,7 @@
 
     private final PackageManager mPackageManager;
     private final UserManager mUserManager;
+    private final SystemConfigManager mSystemConfigManager;
     private final INetd mNetd;
     private final Dependencies mDeps;
 
@@ -123,6 +124,7 @@
             @NonNull final Dependencies deps) {
         mPackageManager = context.getPackageManager();
         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        mSystemConfigManager = context.getSystemService(SystemConfigManager.class);
         mNetd = netd;
         mDeps = deps;
     }
@@ -174,20 +176,18 @@
 
         mUsers.addAll(mUserManager.getUserHandles(true /* excludeDying */));
 
-        final SparseArray<ArraySet<String>> systemPermission =
-                SystemConfig.getInstance().getSystemPermissions();
-        for (int i = 0; i < systemPermission.size(); i++) {
-            ArraySet<String> perms = systemPermission.valueAt(i);
-            int uid = systemPermission.keyAt(i);
-            int netdPermission = 0;
-            // Get the uids of native services that have UPDATE_DEVICE_STATS or INTERNET permission.
-            if (perms != null) {
-                netdPermission |= perms.contains(UPDATE_DEVICE_STATS)
-                        ? INetd.PERMISSION_UPDATE_DEVICE_STATS : 0;
-                netdPermission |= perms.contains(INTERNET)
-                        ? INetd.PERMISSION_INTERNET : 0;
+        final SparseArray<String> netdPermToSystemPerm = new SparseArray<>();
+        netdPermToSystemPerm.put(INetd.PERMISSION_INTERNET, INTERNET);
+        netdPermToSystemPerm.put(INetd.PERMISSION_UPDATE_DEVICE_STATS, UPDATE_DEVICE_STATS);
+        for (int i = 0; i < netdPermToSystemPerm.size(); i++) {
+            final int netdPermission = netdPermToSystemPerm.keyAt(i);
+            final String systemPermission = netdPermToSystemPerm.valueAt(i);
+            final int[] hasPermissionUids =
+                    mSystemConfigManager.getSystemPermissionUids(systemPermission);
+            for (int j = 0; j < hasPermissionUids.length; j++) {
+                final int uid = hasPermissionUids[j];
+                netdPermsUids.put(uid, netdPermsUids.get(uid) | netdPermission);
             }
-            netdPermsUids.put(uid, netdPermsUids.get(uid) | netdPermission);
         }
         log("Users: " + mUsers.size() + ", Apps: " + mApps.size());
         update(mUsers, mApps, true);
@@ -204,7 +204,7 @@
         if (app.requestedPermissions == null || app.requestedPermissionsFlags == null) {
             return false;
         }
-        final int index = ArrayUtils.indexOf(app.requestedPermissions, permission);
+        final int index = CollectionUtils.indexOf(app.requestedPermissions, permission);
         if (index < 0 || index >= app.requestedPermissionsFlags.length) return false;
         return (app.requestedPermissionsFlags[index] & REQUESTED_PERMISSION_GRANTED) != 0;
     }
@@ -246,15 +246,6 @@
         return mApps.containsKey(uid);
     }
 
-    private int[] toIntArray(Collection<Integer> list) {
-        int[] array = new int[list.size()];
-        int i = 0;
-        for (Integer item : list) {
-            array[i++] = item;
-        }
-        return array;
-    }
-
     private void update(Set<UserHandle> users, Map<Integer, Boolean> apps, boolean add) {
         List<Integer> network = new ArrayList<>();
         List<Integer> system = new ArrayList<>();
@@ -662,23 +653,23 @@
             if (allPermissionAppIds.size() != 0) {
                 mNetd.trafficSetNetPermForUids(
                         INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS,
-                        ArrayUtils.convertToIntArray(allPermissionAppIds));
+                        toIntArray(allPermissionAppIds));
             }
             if (internetPermissionAppIds.size() != 0) {
                 mNetd.trafficSetNetPermForUids(INetd.PERMISSION_INTERNET,
-                        ArrayUtils.convertToIntArray(internetPermissionAppIds));
+                        toIntArray(internetPermissionAppIds));
             }
             if (updateStatsPermissionAppIds.size() != 0) {
                 mNetd.trafficSetNetPermForUids(INetd.PERMISSION_UPDATE_DEVICE_STATS,
-                        ArrayUtils.convertToIntArray(updateStatsPermissionAppIds));
+                        toIntArray(updateStatsPermissionAppIds));
             }
             if (noPermissionAppIds.size() != 0) {
                 mNetd.trafficSetNetPermForUids(INetd.PERMISSION_NONE,
-                        ArrayUtils.convertToIntArray(noPermissionAppIds));
+                        toIntArray(noPermissionAppIds));
             }
             if (uninstalledAppIds.size() != 0) {
                 mNetd.trafficSetNetPermForUids(INetd.PERMISSION_UNINSTALLED,
-                        ArrayUtils.convertToIntArray(uninstalledAppIds));
+                        toIntArray(uninstalledAppIds));
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Pass appId list of special permission failed." + e);
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index a769e88..67f495a 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -22,6 +22,7 @@
 import static android.net.RouteInfo.RTN_THROW;
 import static android.net.RouteInfo.RTN_UNREACHABLE;
 import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN;
+import static android.os.PowerWhitelistManager.REASON_VPN;
 
 import static com.android.internal.util.Preconditions.checkArgument;
 import static com.android.internal.util.Preconditions.checkNotNull;
@@ -113,6 +114,7 @@
 import com.android.internal.net.LegacyVpnInfo;
 import com.android.internal.net.VpnConfig;
 import com.android.internal.net.VpnProfile;
+import com.android.net.module.util.NetdUtils;
 import com.android.net.module.util.NetworkStackConstants;
 import com.android.server.DeviceIdleInternal;
 import com.android.server.LocalServices;
@@ -824,7 +826,8 @@
             // a short time, so we can bootstrap the VPN service.
             DeviceIdleInternal idleController = mDeps.getDeviceIdleInternal();
             idleController.addPowerSaveTempWhitelistApp(Process.myUid(), alwaysOnPackage,
-                    VPN_LAUNCH_IDLE_ALLOWLIST_DURATION_MS, mUserId, false, "vpn");
+                    VPN_LAUNCH_IDLE_ALLOWLIST_DURATION_MS, mUserId, false, REASON_VPN,
+                    "vpn");
 
             // Start the VPN service declared in the app's manifest.
             Intent serviceIntent = new Intent(VpnConfig.SERVICE_INTERFACE);
@@ -1509,7 +1512,7 @@
             if (start != -1) ranges.add(new UidRange(start, stop));
         } else if (disallowedApplications != null) {
             // Add all ranges for user skipping UIDs for disallowedApplications.
-            final UidRange userRange = UidRange.createForUser(userId);
+            final UidRange userRange = UidRange.createForUser(UserHandle.of(userId));
             int start = userRange.start;
             for (int uid : getAppsUids(disallowedApplications, userId)) {
                 if (uid == start) {
@@ -1522,7 +1525,7 @@
             if (start <= userRange.stop) ranges.add(new UidRange(start, userRange.stop));
         } else {
             // Add all UIDs for the user.
-            ranges.add(UidRange.createForUser(userId));
+            ranges.add(UidRange.createForUser(UserHandle.of(userId)));
         }
     }
 
@@ -1531,7 +1534,7 @@
     private static List<UidRange> uidRangesForUser(int userId, Set<UidRange> existingRanges) {
         // UidRange#createForUser returns the entire range of UIDs available to a macro-user.
         // This is something like 0-99999 ; {@see UserHandle#PER_USER_RANGE}
-        final UidRange userRange = UidRange.createForUser(userId);
+        final UidRange userRange = UidRange.createForUser(UserHandle.of(userId));
         final List<UidRange> ranges = new ArrayList<>();
         for (UidRange range : existingRanges) {
             if (userRange.containsRange(range)) {
@@ -2528,7 +2531,7 @@
                                     address /* unused */,
                                     address /* unused */,
                                     network);
-                    mNms.setInterfaceUp(mTunnelIface.getInterfaceName());
+                    NetdUtils.setInterfaceUp(mNetd, mTunnelIface.getInterfaceName());
 
                     mSession = mIkev2SessionCreator.createIkeSession(
                             mContext,
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index fe89903..ae0e001 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -16,6 +16,8 @@
 
 package com.android.server.content;
 
+import static android.os.PowerWhitelistManager.REASON_SYNC_MANAGER;
+
 import static com.android.server.content.SyncLogger.logSafe;
 
 import android.accounts.Account;
@@ -264,6 +266,10 @@
 
     private final SyncLogger mLogger;
 
+    // NOTE: this is a temporary allow-list for testing purposes; it will be removed before release.
+    private final String[] mEjSyncAllowedPackages = new String[]{
+            "com.google.android.google", "com.android.frameworks.servicestests"};
+
     private boolean isJobIdInUseLockedH(int jobId, List<JobInfo> pendingJobs) {
         for (JobInfo job: pendingJobs) {
             if (job.getId() == jobId) {
@@ -983,6 +989,14 @@
             }
         }
 
+        final boolean scheduleAsEj =
+                extras.getBoolean(ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB, false);
+        // NOTE: this is a temporary check for internal testing - to be removed before release.
+        if (scheduleAsEj && !ArrayUtils.contains(mEjSyncAllowedPackages, callingPackage)) {
+            throw new IllegalArgumentException(
+                    callingPackage + " is not allowed to schedule a sync as an EJ yet.");
+        }
+
         for (AccountAndUser account : accounts) {
             // If userId is specified, do not sync accounts of other users
             if (userId >= UserHandle.USER_SYSTEM && account.userId >= UserHandle.USER_SYSTEM
@@ -1490,6 +1504,12 @@
                         + logSafe(syncOperation.target));
                 backoff = new Pair<Long, Long>(SyncStorageEngine.NOT_IN_BACKOFF_MODE,
                         SyncStorageEngine.NOT_IN_BACKOFF_MODE);
+            } else {
+                // if an EJ is being backed-off but doesn't have SYNC_EXTRAS_IGNORE_BACKOFF set,
+                // reschedule it as a regular job
+                if (syncOperation.isScheduledAsExpeditedJob()) {
+                    syncOperation.scheduleEjAsRegularJob = true;
+                }
             }
             long now = SystemClock.elapsedRealtime();
             long backoffDelay = backoff.first == SyncStorageEngine.NOT_IN_BACKOFF_MODE ? 0
@@ -1640,6 +1660,10 @@
             b.setRequiresCharging(true);
         }
 
+        if (syncOperation.isScheduledAsExpeditedJob() && !syncOperation.scheduleEjAsRegularJob) {
+            b.setExpedited(true);
+        }
+
         if (syncOperation.syncExemptionFlag
                 == ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP) {
             DeviceIdleInternal dic =
@@ -1649,7 +1673,7 @@
                         syncOperation.owningPackage,
                         mConstants.getKeyExemptionTempWhitelistDurationInSeconds() * 1000,
                         UserHandle.getUserId(syncOperation.owningUid),
-                        /* sync=*/ false, "sync by top app");
+                        /* sync=*/ false, REASON_SYNC_MANAGER, "sync by top app");
             }
         }
 
@@ -3951,6 +3975,9 @@
         if (key.equals(ContentResolver.SYNC_EXTRAS_EXPEDITED)) {
             return true;
         }
+        if (key.equals(ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB)) {
+            return true;
+        }
         if (key.equals(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS)) {
             return true;
         }
diff --git a/services/core/java/com/android/server/content/SyncOperation.java b/services/core/java/com/android/server/content/SyncOperation.java
index 4787635..c8654d1 100644
--- a/services/core/java/com/android/server/content/SyncOperation.java
+++ b/services/core/java/com/android/server/content/SyncOperation.java
@@ -103,6 +103,13 @@
     /** Stores the number of times this sync operation failed and had to be retried. */
     int retries;
 
+    /**
+     * Indicates if a sync that was originally scheduled as an EJ is being re-scheduled as a
+     * regular job. Specifically, this will be {@code true} if a sync is being backed-off but
+     * {@link ContentResolver#SYNC_EXTRAS_IGNORE_BACKOFF} is not set.
+     */
+    boolean scheduleEjAsRegularJob;
+
     /** jobId of the JobScheduler job corresponding to this sync */
     public int jobId;
 
@@ -408,6 +415,12 @@
         if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false)) {
             sb.append(" EXPEDITED");
         }
+        if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB, false)) {
+            sb.append(" EXPEDITED-JOB");
+            if (scheduleEjAsRegularJob) {
+                sb.append("(scheduled-as-regular)");
+            }
+        }
         switch (syncExemptionFlag) {
             case ContentResolver.SYNC_EXEMPTION_NONE:
                 break;
@@ -537,6 +550,11 @@
         return mImmutableExtras.getBoolean(ContentResolver.SYNC_EXTRAS_REQUIRE_CHARGING, false);
     }
 
+    boolean isScheduledAsExpeditedJob() {
+        return mImmutableExtras.getBoolean(
+                ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB, false);
+    }
+
     boolean isAppStandbyExempted() {
         return syncExemptionFlag != ContentResolver.SYNC_EXEMPTION_NONE;
     }
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index b3a6f26..835b468 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -25,6 +25,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.hardware.devicestate.DeviceStateInfo;
 import android.hardware.devicestate.DeviceStateManager;
 import android.hardware.devicestate.IDeviceStateManager;
 import android.hardware.devicestate.IDeviceStateManagerCallback;
@@ -47,6 +48,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Optional;
 
 /**
@@ -76,6 +78,9 @@
 public final class DeviceStateManagerService extends SystemService {
     private static final String TAG = "DeviceStateManagerService";
     private static final boolean DEBUG = false;
+    // The device state to use as a placeholder before callback from the DeviceStateProvider occurs.
+    private static final DeviceState UNSPECIFIED_DEVICE_STATE =
+            new DeviceState(MINIMUM_DEVICE_STATE, "UNSPECIFIED");
 
     private final Object mLock = new Object();
     @NonNull
@@ -87,11 +92,11 @@
     @GuardedBy("mLock")
     private SparseArray<DeviceState> mDeviceStates = new SparseArray<>();
 
-    // The current committed device state. The default of UNSET will be replaced by
-    // the current state after the initial callback from the DeviceStateProvider.
+    // The current committed device state. The default of UNSPECIFIED_DEVICE_STATE will be replaced
+    // by the current state after the initial callback from the DeviceStateProvider.
     @GuardedBy("mLock")
     @NonNull
-    private DeviceState mCommittedState = new DeviceState(MINIMUM_DEVICE_STATE, "UNSET");
+    private DeviceState mCommittedState = UNSPECIFIED_DEVICE_STATE;
     // The device state that is currently awaiting callback from the policy to be committed.
     @GuardedBy("mLock")
     @NonNull
@@ -103,7 +108,7 @@
     // The device state that is set by the device state provider.
     @GuardedBy("mLock")
     @NonNull
-    private Optional<DeviceState> mBaseState = Optional.empty();
+    private DeviceState mBaseState = UNSPECIFIED_DEVICE_STATE;
 
     // List of processes registered to receive notifications about changes to device state and
     // request status indexed by process id.
@@ -166,7 +171,7 @@
      * @see #getOverrideState()
      */
     @NonNull
-    Optional<DeviceState> getBaseState() {
+    DeviceState getBaseState() {
         synchronized (mLock) {
             return mBaseState;
         }
@@ -203,33 +208,47 @@
     /** Returns the list of currently supported device state identifiers. */
     private int[] getSupportedStateIdentifiers() {
         synchronized (mLock) {
-            int[] supportedStates = new int[mDeviceStates.size()];
-            for (int i = 0; i < supportedStates.length; i++) {
-                supportedStates[i] = mDeviceStates.valueAt(i).getIdentifier();
-            }
-            return supportedStates;
+            return getSupportedStateIdentifiersLocked();
         }
     }
 
+    /** Returns the list of currently supported device state identifiers. */
+    private int[] getSupportedStateIdentifiersLocked() {
+        int[] supportedStates = new int[mDeviceStates.size()];
+        for (int i = 0; i < supportedStates.length; i++) {
+            supportedStates[i] = mDeviceStates.valueAt(i).getIdentifier();
+        }
+        return supportedStates;
+    }
+
+    @NonNull
+    private DeviceStateInfo getDeviceStateInfoLocked() {
+        final int[] supportedStates = getSupportedStateIdentifiersLocked();
+        final int baseState = mBaseState.getIdentifier();
+        final int currentState = mCommittedState.getIdentifier();
+
+        return new DeviceStateInfo(supportedStates, baseState, currentState);
+    }
+
     @VisibleForTesting
     IDeviceStateManager getBinderService() {
         return mBinderService;
     }
 
     private void updateSupportedStates(DeviceState[] supportedDeviceStates) {
+        boolean updatedPendingState;
         synchronized (mLock) {
+            final int[] oldStateIdentifiers = getSupportedStateIdentifiersLocked();
+
             mDeviceStates.clear();
             for (int i = 0; i < supportedDeviceStates.length; i++) {
                 DeviceState state = supportedDeviceStates[i];
                 mDeviceStates.put(state.getIdentifier(), state);
             }
 
-            if (mBaseState.isPresent()
-                    && !isSupportedStateLocked(mBaseState.get().getIdentifier())) {
-                // The current base state is no longer valid. We'll clear it here, though
-                // we won't actually update the current state until a callback comes from the
-                // provider with the most recent state.
-                mBaseState = Optional.empty();
+            final int[] newStateIdentifiers = getSupportedStateIdentifiersLocked();
+            if (Arrays.equals(oldStateIdentifiers, newStateIdentifiers)) {
+                return;
             }
 
             final int requestSize = mRequestRecords.size();
@@ -240,7 +259,14 @@
                 }
             }
 
-            updatePendingStateLocked();
+            updatedPendingState = updatePendingStateLocked();
+        }
+
+        if (!updatedPendingState) {
+            // If the change in the supported states didn't result in a change of the pending state
+            // commitPendingState() will never be called and the callbacks will never be notified
+            // of the change.
+            notifyDeviceStateInfoChanged();
         }
 
         notifyRequestsOfStatusChangeIfNeeded();
@@ -265,23 +291,25 @@
     }
 
     /**
-     * Requests to set the base state. The request may not be honored under certain conditions, for
-     * example if the provided state is not supported.
+     * Sets the base state.
+     *
+     * @throws IllegalArgumentException if the {@code identifier} is not a supported state.
      *
      * @see #isSupportedStateLocked(int)
      */
     private void setBaseState(int identifier) {
+        boolean updatedPendingState;
         synchronized (mLock) {
-            if (mBaseState.isPresent() && mBaseState.get().getIdentifier() == identifier) {
-                // Base state hasn't changed. Nothing to do.
-                return;
-            }
-
-            final Optional<DeviceState> baseState = getStateLocked(identifier);
-            if (!baseState.isPresent()) {
+            final Optional<DeviceState> baseStateOptional = getStateLocked(identifier);
+            if (!baseStateOptional.isPresent()) {
                 throw new IllegalArgumentException("Base state is not supported");
             }
 
+            final DeviceState baseState = baseStateOptional.get();
+            if (mBaseState.equals(baseState)) {
+                // Base state hasn't changed. Nothing to do.
+                return;
+            }
             mBaseState = baseState;
 
             final int requestSize = mRequestRecords.size();
@@ -292,7 +320,14 @@
                 }
             }
 
-            updatePendingStateLocked();
+            updatedPendingState = updatePendingStateLocked();
+        }
+
+        if (!updatedPendingState) {
+            // If the change in base state didn't result in a change of the pending state
+            // commitPendingState() will never be called and the callbacks will never be notified
+            // of the change.
+            notifyDeviceStateInfoChanged();
         }
 
         notifyRequestsOfStatusChangeIfNeeded();
@@ -303,32 +338,39 @@
      * Tries to update the current pending state with the current requested state. Must call
      * {@link #notifyPolicyIfNeeded()} to actually notify the policy that the state is being
      * changed.
+     *
+     * @return {@code true} if the pending state has changed as a result of this call, {@code false}
+     * otherwise.
      */
-    private void updatePendingStateLocked() {
+    private boolean updatePendingStateLocked() {
         if (mPendingState.isPresent()) {
             // Have pending state, can not configure a new state until the state is committed.
-            return;
+            return false;
         }
 
         final DeviceState stateToConfigure;
         if (!mRequestRecords.isEmpty()) {
             stateToConfigure = mRequestRecords.get(mRequestRecords.size() - 1).mRequestedState;
+        } else if (isSupportedStateLocked(mBaseState.getIdentifier())) {
+            // Base state could have recently become unsupported after a change in supported states.
+            stateToConfigure = mBaseState;
         } else {
-            stateToConfigure = mBaseState.orElse(null);
+            stateToConfigure = null;
         }
 
         if (stateToConfigure == null) {
             // No currently requested state.
-            return;
+            return false;
         }
 
-        if (stateToConfigure == mCommittedState) {
+        if (stateToConfigure.equals(mCommittedState)) {
             // The state requesting to be committed already matches the current committed state.
-            return;
+            return false;
         }
 
         mPendingState = Optional.of(stateToConfigure);
         mIsPolicyWaitingForState = true;
+        return true;
     }
 
     /**
@@ -374,13 +416,11 @@
      */
     private void commitPendingState() {
         // Update the current state.
-        int newState;
         synchronized (mLock) {
             if (DEBUG) {
                 Slog.d(TAG, "Committing state: " + mPendingState);
             }
             mCommittedState = mPendingState.get();
-            newState = mCommittedState.getIdentifier();
 
             if (!mRequestRecords.isEmpty()) {
                 final OverrideRequestRecord topRequest =
@@ -393,7 +433,7 @@
         }
 
         // Notify callbacks of a change.
-        notifyDeviceStateChanged(newState);
+        notifyDeviceStateInfoChanged();
 
         // Notify the top request that it's active.
         notifyRequestsOfStatusChangeIfNeeded();
@@ -402,14 +442,15 @@
         notifyPolicyIfNeeded();
     }
 
-    private void notifyDeviceStateChanged(int deviceState) {
+    private void notifyDeviceStateInfoChanged() {
         if (Thread.holdsLock(mLock)) {
             throw new IllegalStateException(
                     "Attempting to notify callbacks with service lock held.");
         }
 
-        // Grab the lock and copy the process records.
+        // Grab the lock and copy the process records and the current info.
         ArrayList<ProcessRecord> registeredProcesses;
+        DeviceStateInfo info;
         synchronized (mLock) {
             if (mProcessRecords.size() == 0) {
                 return;
@@ -419,11 +460,13 @@
             for (int i = 0; i < mProcessRecords.size(); i++) {
                 registeredProcesses.add(mProcessRecords.valueAt(i));
             }
+
+            info = getDeviceStateInfoLocked();
         }
 
         // After releasing the lock, send the notifications out.
         for (int i = 0; i < registeredProcesses.size(); i++) {
-            registeredProcesses.get(i).notifyDeviceStateAsync(deviceState);
+            registeredProcesses.get(i).notifyDeviceStateInfoAsync(info);
         }
     }
 
@@ -454,28 +497,20 @@
     }
 
     private void registerProcess(int pid, IDeviceStateManagerCallback callback) {
-        int currentState;
-        ProcessRecord record;
-        // Grab the lock to register the callback and get the current state.
         synchronized (mLock) {
             if (mProcessRecords.contains(pid)) {
                 throw new SecurityException("The calling process has already registered an"
                         + " IDeviceStateManagerCallback.");
             }
 
-            record = new ProcessRecord(callback, pid);
+            ProcessRecord record = new ProcessRecord(callback, pid);
             try {
                 callback.asBinder().linkToDeath(record, 0);
             } catch (RemoteException ex) {
                 throw new RuntimeException(ex);
             }
-
             mProcessRecords.put(pid, record);
-            currentState = mCommittedState.getIdentifier();
         }
-
-        // Notify the callback of the state at registration.
-        record.notifyDeviceStateAsync(currentState);
     }
 
     private void handleProcessDied(ProcessRecord processRecord) {
@@ -626,9 +661,9 @@
             handleProcessDied(this);
         }
 
-        public void notifyDeviceStateAsync(int devicestate) {
+        public void notifyDeviceStateInfoAsync(@NonNull DeviceStateInfo info) {
             try {
-                mCallback.onDeviceStateChanged(devicestate);
+                mCallback.onDeviceStateInfoChanged(info);
             } catch (RemoteException ex) {
                 Slog.w(TAG, "Failed to notify process " + mPid + " that device state changed.",
                         ex);
@@ -752,6 +787,13 @@
     /** Implementation of {@link IDeviceStateManager} published as a binder service. */
     private final class BinderService extends IDeviceStateManager.Stub {
         @Override // Binder call
+        public DeviceStateInfo getDeviceStateInfo() {
+            synchronized (mLock) {
+                return getDeviceStateInfoLocked();
+            }
+        }
+
+        @Override // Binder call
         public void registerCallback(IDeviceStateManagerCallback callback) {
             if (callback == null) {
                 throw new IllegalArgumentException("Device state callback must not be null.");
@@ -767,16 +809,6 @@
         }
 
         @Override // Binder call
-        public int[] getSupportedDeviceStates() {
-            final long token = Binder.clearCallingIdentity();
-            try {
-                return getSupportedStateIdentifiers();
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override // Binder call
         public void requestState(IBinder token, int state, int flags) {
             getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
                     "Permission required to request device state.");
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java
index 6cc55a6..f346600 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java
@@ -64,13 +64,13 @@
 
     private void printState(PrintWriter pw) {
         DeviceState committedState = mService.getCommittedState();
-        Optional<DeviceState> baseState = mService.getBaseState();
+        DeviceState baseState = mService.getBaseState();
         Optional<DeviceState> overrideState = mService.getOverrideState();
 
         pw.println("Committed state: " + committedState);
         if (overrideState.isPresent()) {
             pw.println("----------------------");
-            pw.println("Base state: " + baseState.orElse(null));
+            pw.println("Base state: " + baseState);
             pw.println("Override state: " + overrideState.get());
         }
     }
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 225da7a..a2b9b96 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -354,6 +354,10 @@
         }
     }
 
+    public void stop() {
+        setLightSensorEnabled(false);
+    }
+
     public boolean hasUserDataPoints() {
         return mBrightnessMapper.hasUserDataPoints();
     }
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index a62f67a..30cbf27 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -61,7 +61,10 @@
     private static final Plog PLOG = Plog.createSystemPlog(TAG);
 
     @Nullable
-    public static BrightnessMappingStrategy create(Resources resources) {
+    public static BrightnessMappingStrategy create(Resources resources,
+            DisplayDeviceConfig displayDeviceConfig) {
+
+        // Display independent values
         float[] luxLevels = getLuxLevels(resources.getIntArray(
                 com.android.internal.R.array.config_autoBrightnessLevels));
         int[] brightnessLevelsBacklight = resources.getIntArray(
@@ -71,32 +74,22 @@
         float autoBrightnessAdjustmentMaxGamma = resources.getFraction(
                 com.android.internal.R.fraction.config_autoBrightnessAdjustmentMaxGamma,
                 1, 1);
-
-        float[] nitsRange = getFloatArray(resources.obtainTypedArray(
-                com.android.internal.R.array.config_screenBrightnessNits));
-        int[] backlightRange = resources.getIntArray(
-                com.android.internal.R.array.config_screenBrightnessBacklight);
-
         long shortTermModelTimeout = resources.getInteger(
                 com.android.internal.R.integer.config_autoBrightnessShortTermModelTimeout);
 
-        if (isValidMapping(nitsRange, backlightRange)
+        // Display dependent values - used for physical mapping strategy nits -> brightness
+        final float[] nitsRange = displayDeviceConfig.getNits();
+        final float[] brightnessRange = displayDeviceConfig.getBrightness();
+
+        if (isValidMapping(nitsRange, brightnessRange)
                 && isValidMapping(luxLevels, brightnessLevelsNits)) {
-            int minimumBacklight = resources.getInteger(
-                    com.android.internal.R.integer.config_screenBrightnessSettingMinimum);
-            int maximumBacklight = resources.getInteger(
-                    com.android.internal.R.integer.config_screenBrightnessSettingMaximum);
-            if (backlightRange[0] > minimumBacklight
-                    || backlightRange[backlightRange.length - 1] < maximumBacklight) {
-                Slog.w(TAG, "Screen brightness mapping does not cover whole range of available " +
-                        "backlight values, autobrightness functionality may be impaired.");
-            }
+
             BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(
                     luxLevels, brightnessLevelsNits);
             builder.setShortTermModelTimeoutMillis(shortTermModelTimeout);
             builder.setShortTermModelLowerLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO);
             builder.setShortTermModelUpperLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO);
-            return new PhysicalMappingStrategy(builder.build(), nitsRange, backlightRange,
+            return new PhysicalMappingStrategy(builder.build(), nitsRange, brightnessRange,
                     autoBrightnessAdjustmentMaxGamma);
         } else if (isValidMapping(luxLevels, brightnessLevelsBacklight)) {
             return new SimpleMappingStrategy(luxLevels, brightnessLevelsBacklight,
@@ -264,11 +257,11 @@
     public abstract boolean setAutoBrightnessAdjustment(float adjustment);
 
     /**
-     * Converts the provided backlight value to nits if possible.
+     * Converts the provided brightness value to nits if possible.
      *
-     * Returns -1.0f if there's no available mapping for the backlight to nits.
+     * Returns -1.0f if there's no available mapping for the brightness to nits.
      */
-    public abstract float convertToNits(int backlight);
+    public abstract float convertToNits(float brightness);
 
     /**
      * Adds a user interaction data point to the brightness mapping.
@@ -603,7 +596,7 @@
         }
 
         @Override
-        public float convertToNits(int backlight) {
+        public float convertToNits(float brightness) {
             return -1.0f;
         }
 
@@ -701,37 +694,39 @@
         // in nits.
         private Spline mBrightnessSpline;
 
-        // A spline mapping from nits to the corresponding backlight value, normalized to the range
+        // A spline mapping from nits to the corresponding brightness value, normalized to the range
         // [0, 1.0].
-        private Spline mNitsToBacklightSpline;
+        private Spline mNitsToBrightnessSpline;
+
+        // A spline mapping from the system brightness value, normalized to the range [0, 1.0], to
+        // a brightness in nits.
+        private Spline mBrightnessToNitsSpline;
 
         // The default brightness configuration.
         private final BrightnessConfiguration mDefaultConfig;
 
-        // A spline mapping from the device's backlight value, normalized to the range [0, 1.0], to
-        // a brightness in nits.
-        private Spline mBacklightToNitsSpline;
-
-        private float[] mNits;
-        private int[] mBacklight;
+        private final float[] mNits;
+        private final float[] mBrightness;
 
         private boolean mBrightnessRangeAdjustmentApplied;
 
-        private float mMaxGamma;
+        private final float mMaxGamma;
         private float mAutoBrightnessAdjustment;
         private float mUserLux;
         private float mUserBrightness;
 
         public PhysicalMappingStrategy(BrightnessConfiguration config, float[] nits,
-                                       int[] backlight, float maxGamma) {
-            Preconditions.checkArgument(nits.length != 0 && backlight.length != 0,
-                    "Nits and backlight arrays must not be empty!");
-            Preconditions.checkArgument(nits.length == backlight.length,
-                    "Nits and backlight arrays must be the same length!");
+                float[] brightness, float maxGamma) {
+
+            Preconditions.checkArgument(nits.length != 0 && brightness.length != 0,
+                    "Nits and brightness arrays must not be empty!");
+
+            Preconditions.checkArgument(nits.length == brightness.length,
+                    "Nits and brightness arrays must be the same length!");
             Objects.requireNonNull(config);
             Preconditions.checkArrayElementsInRange(nits, 0, Float.MAX_VALUE, "nits");
-            Preconditions.checkArrayElementsInRange(backlight,
-                    PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON, "backlight");
+            Preconditions.checkArrayElementsInRange(brightness,
+                    PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, "brightness");
 
             mMaxGamma = maxGamma;
             mAutoBrightnessAdjustment = 0;
@@ -739,7 +734,7 @@
             mUserBrightness = -1;
 
             mNits = nits;
-            mBacklight = backlight;
+            mBrightness = brightness;
             computeNitsBrightnessSplines(mNits);
 
             mDefaultConfig = config;
@@ -784,15 +779,15 @@
         public float getBrightness(float lux, String packageName,
                 @ApplicationInfo.Category int category) {
             float nits = mBrightnessSpline.interpolate(lux);
-            float backlight = mNitsToBacklightSpline.interpolate(nits);
+            float brightness = mNitsToBrightnessSpline.interpolate(nits);
             // Correct the brightness according to the current application and its category, but
-            // only if no user data point is set (as this will oevrride the user setting).
+            // only if no user data point is set (as this will override the user setting).
             if (mUserLux == -1) {
-                backlight = correctBrightness(backlight, packageName, category);
+                brightness = correctBrightness(brightness, packageName, category);
             } else if (mLoggingEnabled) {
                 Slog.d(TAG, "user point set, correction not applied");
             }
-            return backlight;
+            return brightness;
         }
 
         @Override
@@ -817,8 +812,8 @@
         }
 
         @Override
-        public float convertToNits(int backlight) {
-            return mBacklightToNitsSpline.interpolate(normalizeAbsoluteBrightness(backlight));
+        public float convertToNits(float brightness) {
+            return mBrightnessToNitsSpline.interpolate(brightness);
         }
 
         @Override
@@ -884,7 +879,8 @@
             pw.println("PhysicalMappingStrategy");
             pw.println("  mConfig=" + mConfig);
             pw.println("  mBrightnessSpline=" + mBrightnessSpline);
-            pw.println("  mNitsToBacklightSpline=" + mNitsToBacklightSpline);
+            pw.println("  mNitsToBrightnessSpline=" + mNitsToBrightnessSpline);
+            pw.println("  mBrightnessToNitsSpline=" + mBrightnessToNitsSpline);
             pw.println("  mMaxGamma=" + mMaxGamma);
             pw.println("  mAutoBrightnessAdjustment=" + mAutoBrightnessAdjustment);
             pw.println("  mUserLux=" + mUserLux);
@@ -894,31 +890,25 @@
         }
 
         private void computeNitsBrightnessSplines(float[] nits) {
-            final int len = nits.length;
-            float[] normalizedBacklight = new float[len];
-            for (int i = 0; i < len; i++) {
-                normalizedBacklight[i] = normalizeAbsoluteBrightness(mBacklight[i]);
-            }
-
-            mNitsToBacklightSpline = Spline.createSpline(nits, normalizedBacklight);
-            mBacklightToNitsSpline = Spline.createSpline(normalizedBacklight, nits);
+            mNitsToBrightnessSpline = Spline.createSpline(nits, mBrightness);
+            mBrightnessToNitsSpline = Spline.createSpline(mBrightness, nits);
         }
 
         private void computeSpline() {
             Pair<float[], float[]> defaultCurve = mConfig.getCurve();
             float[] defaultLux = defaultCurve.first;
             float[] defaultNits = defaultCurve.second;
-            float[] defaultBacklight = new float[defaultNits.length];
-            for (int i = 0; i < defaultBacklight.length; i++) {
-                defaultBacklight[i] = mNitsToBacklightSpline.interpolate(defaultNits[i]);
+            float[] defaultBrightness = new float[defaultNits.length];
+            for (int i = 0; i < defaultBrightness.length; i++) {
+                defaultBrightness[i] = mNitsToBrightnessSpline.interpolate(defaultNits[i]);
             }
-            Pair<float[], float[]> curve = getAdjustedCurve(defaultLux, defaultBacklight, mUserLux,
+            Pair<float[], float[]> curve = getAdjustedCurve(defaultLux, defaultBrightness, mUserLux,
                     mUserBrightness, mAutoBrightnessAdjustment, mMaxGamma);
             float[] lux = curve.first;
-            float[] backlight = curve.second;
-            float[] nits = new float[backlight.length];
+            float[] brightness = curve.second;
+            float[] nits = new float[brightness.length];
             for (int i = 0; i < nits.length; i++) {
-                nits[i] = mBacklightToNitsSpline.interpolate(backlight[i]);
+                nits[i] = mBrightnessToNitsSpline.interpolate(brightness[i]);
             }
             mBrightnessSpline = Spline.createSpline(lux, nits);
         }
@@ -926,7 +916,7 @@
         private float getUnadjustedBrightness(float lux) {
             Pair<float[], float[]> curve = mConfig.getCurve();
             Spline spline = Spline.createSpline(curve.first, curve.second);
-            return mNitsToBacklightSpline.interpolate(spline.interpolate(lux));
+            return mNitsToBrightnessSpline.interpolate(spline.interpolate(lux));
         }
 
         private float correctBrightness(float brightness, String packageName, int category) {
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index a186e33..06010f5 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -243,7 +243,6 @@
     }
 
     /** Stop listening for events */
-    @VisibleForTesting
     void stop() {
         if (DEBUG) {
             Slog.d(TAG, "Stop");
diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index 5e1df27..f212698 100644
--- a/services/core/java/com/android/server/display/ColorFade.java
+++ b/services/core/java/com/android/server/display/ColorFade.java
@@ -165,7 +165,7 @@
                     "Failed to take screenshot because internal display is disconnected");
             return false;
         }
-        boolean isWideColor = SurfaceControl.getActiveColorMode(token)
+        boolean isWideColor = SurfaceControl.getDynamicDisplayInfo(token).activeColorMode
                 == Display.COLOR_MODE_DISPLAY_P3;
 
         // Set mPrepared here so if initialization fails, resources can be cleaned up.
@@ -817,6 +817,12 @@
                 }
 
                 DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(mDisplayId);
+                if (displayInfo == null) {
+                    // displayInfo can be null if the associated display has been removed. There
+                    // is a delay between the display being removed and ColorFade being dismissed.
+                    return;
+                }
+
                 switch (displayInfo.rotation) {
                     case Surface.ROTATION_0:
                         t.setPosition(mSurfaceControl, 0, 0);
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index cd17cfe..b3070b7 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -16,6 +16,7 @@
 
 package com.android.server.display;
 
+import android.content.Context;
 import android.graphics.Rect;
 import android.hardware.display.DisplayViewport;
 import android.os.IBinder;
@@ -38,12 +39,14 @@
     private final IBinder mDisplayToken;
     private final String mUniqueId;
 
+    protected DisplayDeviceConfig mDisplayDeviceConfig;
     // The display device does not manage these properties itself, they are set by
     // the display manager service.  The display device shouldn't really be looking at these.
     private int mCurrentLayerStack = -1;
     private int mCurrentOrientation = -1;
     private Rect mCurrentLayerStackRect;
     private Rect mCurrentDisplayRect;
+    private final Context mContext;
 
     // The display device owns its surface, but it should only set it
     // within a transaction from performTraversalLocked.
@@ -53,10 +56,13 @@
     // Do not use for any other purpose.
     DisplayDeviceInfo mDebugLastLoggedDeviceInfo;
 
-    public DisplayDevice(DisplayAdapter displayAdapter, IBinder displayToken, String uniqueId) {
+    public DisplayDevice(DisplayAdapter displayAdapter, IBinder displayToken, String uniqueId,
+            Context context) {
         mDisplayAdapter = displayAdapter;
         mDisplayToken = displayToken;
         mUniqueId = uniqueId;
+        mDisplayDeviceConfig = null;
+        mContext = context;
     }
 
     /**
@@ -74,7 +80,10 @@
      * @return The DisplayDeviceConfig; {@code null} if not overridden.
      */
     public DisplayDeviceConfig getDisplayDeviceConfig() {
-        return null;
+        if (mDisplayDeviceConfig == null) {
+            mDisplayDeviceConfig = loadDisplayDeviceConfig();
+        }
+        return mDisplayDeviceConfig;
     }
 
     /**
@@ -292,4 +301,8 @@
         pw.println("mCurrentDisplayRect=" + mCurrentDisplayRect);
         pw.println("mCurrentSurface=" + mCurrentSurface);
     }
+
+    private DisplayDeviceConfig loadDisplayDeviceConfig() {
+        return DisplayDeviceConfig.create(mContext, false);
+    }
 }
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 1b25427..0071b2f 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -18,9 +18,12 @@
 
 import android.annotation.NonNull;
 import android.content.Context;
+import android.content.res.Resources;
 import android.os.Environment;
 import android.os.PowerManager;
+import android.util.MathUtils;
 import android.util.Slog;
+import android.util.Spline;
 import android.view.DisplayAddress;
 
 import com.android.internal.R;
@@ -72,15 +75,31 @@
 
     private final Context mContext;
 
+    // Nits and backlight values that are loaded from either the display device config file, or
+    // config.xml. These are the raw values and just used for the dumpsys
+    private float[] mRawNits;
+    private float[] mRawBacklight;
+
+    // These arrays are calculated from the raw arrays, but clamped to contain values equal to and
+    // between mBacklightMinimum and mBacklightMaximum. These three arrays should all be the same
+    // length
+    // Nits array that is used to store the entire range of nits values that the device supports
     private float[] mNits;
+    // Backlight array holds the values that the HAL uses to display the corresponding nits values
+    private float[] mBacklight;
+    // Purely an array that covers the ranges of values 0.0 - 1.0, indicating the system brightness
+    // for the corresponding values above
     private float[] mBrightness;
-    private float mBrightnessMinimum = Float.NaN;
-    private float mBrightnessMaximum = Float.NaN;
+
+    private float mBacklightMinimum = Float.NaN;
+    private float mBacklightMaximum = Float.NaN;
     private float mBrightnessDefault = Float.NaN;
     private float mBrightnessRampFastDecrease = Float.NaN;
     private float mBrightnessRampFastIncrease = Float.NaN;
     private float mBrightnessRampSlowDecrease = Float.NaN;
     private float mBrightnessRampSlowIncrease = Float.NaN;
+    private Spline mBrightnessToBacklightSpline;
+    private Spline mBacklightToBrightnessSpline;
     private List<String> mQuirks;
     private boolean mIsHighBrightnessModeEnabled = false;
     private HighBrightnessModeData mHbmData;
@@ -120,7 +139,20 @@
         // If no config can be loaded from any ddc xml at all,
         // prepare a whole config using the global config.xml.
         // Guaranteed not null
-        if (isDefaultDisplay) {
+        return create(context, isDefaultDisplay);
+    }
+
+    /**
+     * Creates an instance using global values since no display device config xml exists.
+     * Uses values from config or PowerManager.
+     *
+     * @param context
+     * @param useConfigXml
+     * @return A configuration instance.
+     */
+    public static DisplayDeviceConfig create(Context context, boolean useConfigXml) {
+        DisplayDeviceConfig config;
+        if (useConfigXml) {
             config = getConfigFromGlobalXml(context);
         } else {
             config = getConfigFromPmValues(context);
@@ -154,7 +186,7 @@
     }
 
     /**
-     * Return the brightness mapping nits array if one is defined in the configuration file.
+     * Return the brightness mapping nits array.
      *
      * @return The brightness mapping nits array.
      */
@@ -163,22 +195,40 @@
     }
 
     /**
-     * Return the brightness mapping value array if one is defined in the configuration file.
+     * Return the brightness mapping backlight array.
      *
-     * @return The brightness mapping value array.
+     * @return The backlight mapping value array.
+     */
+    public float[] getBacklight() {
+        return mBacklight;
+    }
+
+    /**
+     * Calculates the backlight value, as recognised by the HAL, from the brightness value
+     * given that the rest of the system deals with.
+     *
+     * @param brightness value on the framework scale of 0-1
+     * @return backlight value on the HAL scale of 0-1
+     */
+    public float getBacklightFromBrightness(float brightness) {
+        return mBrightnessToBacklightSpline.interpolate(brightness);
+    }
+
+    /**
+     * Return an array of equal length to backlight and nits, that covers the entire system
+     * brightness range of 0.0-1.0.
+     *
+     * @return brightness array
      */
     public float[] getBrightness() {
         return mBrightness;
     }
 
-    public float getBrightnessMinimum() {
-        return mBrightnessMinimum;
-    }
-
-    public float getBrightnessMaximum() {
-        return mBrightnessMaximum;
-    }
-
+    /**
+     * Return the default brightness on a scale of 0.0f - 1.0f
+     *
+     * @return default brightness
+     */
     public float getBrightnessDefault() {
         return mBrightnessDefault;
     }
@@ -224,10 +274,15 @@
     @Override
     public String toString() {
         String str = "DisplayDeviceConfig{"
-                + "mBrightness=" + Arrays.toString(mBrightness)
+                + "mBacklight=" + Arrays.toString(mBacklight)
                 + ", mNits=" + Arrays.toString(mNits)
-                + ", mBrightnessMinimum=" + mBrightnessMinimum
-                + ", mBrightnessMaximum=" + mBrightnessMaximum
+                + ", mRawBacklight=" + Arrays.toString(mRawBacklight)
+                + ", mRawNits=" + Arrays.toString(mRawNits)
+                + ", mBrightness=" + Arrays.toString(mBrightness)
+                + ", mBrightnessToBacklightSpline=" + mBrightnessToBacklightSpline
+                + ", mBacklightToBrightnessSpline=" + mBacklightToBrightnessSpline
+                + ", mBacklightMinimum=" + mBacklightMinimum
+                + ", mBacklightMaximum=" + mBacklightMaximum
                 + ", mBrightnessDefault=" + mBrightnessDefault
                 + ", mQuirks=" + mQuirks
                 + ", isHbmEnabled=" + mIsHighBrightnessModeEnabled
@@ -240,10 +295,6 @@
         return str;
     }
 
-    private float getMaxBrightness() {
-        return mBrightness[mBrightness.length - 1];
-    }
-
     private static DisplayDeviceConfig getConfigFromSuffix(Context context, File baseDirectory,
             String suffixFormat, long idNumber) {
 
@@ -251,7 +302,6 @@
         final String filename = String.format(CONFIG_FILE_FORMAT, suffix);
         final File filePath = Environment.buildPath(
                 baseDirectory, ETC_DIR, DISPLAY_CONFIG_DIR, filename);
-
         if (filePath.exists()) {
             final DisplayDeviceConfig config = new DisplayDeviceConfig(context);
             config.initFromFile(filePath);
@@ -286,9 +336,9 @@
         try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) {
             final DisplayConfiguration config = XmlParser.read(in);
             if (config != null) {
-                loadBrightnessMap(config);
                 loadBrightnessDefaultFromDdcXml(config);
                 loadBrightnessConstraintsFromConfigXml();
+                loadBrightnessMap(config);
                 loadHighBrightnessModeData(config);
                 loadQuirks(config);
                 loadBrightnessRamps(config);
@@ -305,13 +355,20 @@
         // If no ddc exists, use config.xml
         loadBrightnessDefaultFromConfigXml();
         loadBrightnessConstraintsFromConfigXml();
+        loadBrightnessMapFromConfigXml();
         loadBrightnessRampsFromConfigXml();
     }
 
     private void initFromPmValues() {
-        mBrightnessMinimum = PowerManager.BRIGHTNESS_MIN;
-        mBrightnessMaximum = PowerManager.BRIGHTNESS_MAX;
+        // Set all to basic values
+        mBacklightMinimum = PowerManager.BRIGHTNESS_MIN;
+        mBacklightMaximum = PowerManager.BRIGHTNESS_MAX;
         mBrightnessDefault = BRIGHTNESS_DEFAULT;
+        mBrightnessRampFastDecrease = PowerManager.BRIGHTNESS_MAX;
+        mBrightnessRampFastIncrease = PowerManager.BRIGHTNESS_MAX;
+        mBrightnessRampSlowDecrease = PowerManager.BRIGHTNESS_MAX;
+        mBrightnessRampSlowIncrease = PowerManager.BRIGHTNESS_MAX;
+        setSimpleMappingStrategyValues();
     }
 
     private void loadBrightnessDefaultFromDdcXml(DisplayConfiguration config) {
@@ -351,24 +408,27 @@
         final float max = mContext.getResources().getFloat(com.android.internal.R.dimen
                 .config_screenBrightnessSettingMaximumFloat);
         if (min == INVALID_BRIGHTNESS_IN_CONFIG || max == INVALID_BRIGHTNESS_IN_CONFIG) {
-            mBrightnessMinimum = BrightnessSynchronizer.brightnessIntToFloat(
+            mBacklightMinimum = BrightnessSynchronizer.brightnessIntToFloat(
                     mContext.getResources().getInteger(com.android.internal.R.integer
                             .config_screenBrightnessSettingMinimum));
-            mBrightnessMaximum = BrightnessSynchronizer.brightnessIntToFloat(
+            mBacklightMaximum = BrightnessSynchronizer.brightnessIntToFloat(
                     mContext.getResources().getInteger(com.android.internal.R.integer
                             .config_screenBrightnessSettingMaximum));
         } else {
-            mBrightnessMinimum = min;
-            mBrightnessMaximum = max;
+            mBacklightMinimum = min;
+            mBacklightMaximum = max;
         }
     }
 
     private void loadBrightnessMap(DisplayConfiguration config) {
         final NitsMap map = config.getScreenBrightnessMap();
-        // Map may not exist in config file
+        // Map may not exist in display device config
         if (map == null) {
+            loadBrightnessMapFromConfigXml();
             return;
         }
+
+        // Use the (preferred) display device config mapping
         final List<Point> points = map.getPoint();
         final int size = points.size();
 
@@ -395,8 +455,123 @@
             }
             ++i;
         }
-        mNits = nits;
-        mBrightness = backlight;
+        mRawNits = nits;
+        mRawBacklight = backlight;
+        constrainNitsAndBacklightArrays();
+    }
+
+    private void loadBrightnessMapFromConfigXml() {
+        // Use the config.xml mapping
+        final Resources res = mContext.getResources();
+        final float[] sysNits = BrightnessMappingStrategy.getFloatArray(res.obtainTypedArray(
+                com.android.internal.R.array.config_screenBrightnessNits));
+        final int[] sysBrightness = res.getIntArray(
+                com.android.internal.R.array.config_screenBrightnessBacklight);
+        final float[] sysBrightnessFloat = new float[sysBrightness.length];
+
+        for (int i = 0; i < sysBrightness.length; i++) {
+            sysBrightnessFloat[i] = BrightnessSynchronizer.brightnessIntToFloat(
+                    sysBrightness[i]);
+        }
+
+        // These arrays are allowed to be empty, we set null values so that
+        // BrightnessMappingStrategy will create a SimpleMappingStrategy instead.
+        if (sysBrightnessFloat.length == 0 || sysNits.length == 0) {
+            setSimpleMappingStrategyValues();
+            return;
+        }
+
+        mRawNits = sysNits;
+        mRawBacklight = sysBrightnessFloat;
+        constrainNitsAndBacklightArrays();
+    }
+
+    private void setSimpleMappingStrategyValues() {
+        // No translation from backlight to brightness should occur if we are using a
+        // SimpleMappingStrategy (ie they should be the same) so the splines are
+        // set to be linear, between 0.0 and 1.0
+        mNits = null;
+        mBacklight = null;
+        float[] simpleMappingStrategyArray = new float[]{0.0f, 1.0f};
+        mBrightnessToBacklightSpline = Spline.createSpline(simpleMappingStrategyArray,
+                simpleMappingStrategyArray);
+        mBacklightToBrightnessSpline = Spline.createSpline(simpleMappingStrategyArray,
+                simpleMappingStrategyArray);
+    }
+
+    /**
+     * Change the nits and backlight arrays, so that they cover only the allowed backlight values
+     * Use the brightness minimum and maximum values to clamp these arrays.
+     */
+    private void constrainNitsAndBacklightArrays() {
+        if (mRawBacklight[0] > mBacklightMinimum
+                || mRawBacklight[mRawBacklight.length - 1] < mBacklightMaximum
+                || mBacklightMinimum > mBacklightMaximum) {
+            throw new IllegalStateException("Min or max values are invalid"
+                    + "; raw min=" + mRawBacklight[0]
+                    + "; raw max=" + mRawBacklight[mRawBacklight.length - 1]
+                    + "; backlight min=" + mBacklightMinimum
+                    + "; backlight max=" + mBacklightMaximum);
+        }
+
+        float[] newNits = new float[mRawBacklight.length];
+        float[] newBacklight = new float[mRawBacklight.length];
+        // Find the starting index of the clamped arrays. This may be less than the min so
+        // we'll need to clamp this value still when actually doing the remapping.
+        int newStart = 0;
+        for (int i = 0; i < mRawBacklight.length - 1; i++) {
+            if (mRawBacklight[i + 1] > mBacklightMinimum) {
+                newStart = i;
+                break;
+            }
+        }
+
+        boolean isLastValue = false;
+        int newIndex = 0;
+        for (int i = newStart; i < mRawBacklight.length && !isLastValue; i++) {
+            newIndex = i - newStart;
+            final float newBacklightVal;
+            final float newNitsVal;
+            isLastValue = mRawBacklight[i] > mBacklightMaximum
+                    || i >= mRawBacklight.length - 1;
+            // Clamp beginning and end to valid backlight values.
+            if (newIndex == 0) {
+                newBacklightVal = MathUtils.max(mRawBacklight[i], mBacklightMinimum);
+                newNitsVal = rawBacklightToNits(i, newBacklightVal);
+            } else if (isLastValue) {
+                newBacklightVal = MathUtils.min(mRawBacklight[i], mBacklightMaximum);
+                newNitsVal = rawBacklightToNits(i - 1, newBacklightVal);
+            } else {
+                newBacklightVal = mRawBacklight[i];
+                newNitsVal = mRawNits[i];
+            }
+            newBacklight[newIndex] = newBacklightVal;
+            newNits[newIndex] = newNitsVal;
+        }
+        mBacklight = Arrays.copyOf(newBacklight, newIndex + 1);
+        mNits = Arrays.copyOf(newNits, newIndex + 1);
+        createBacklightConversionSplines();
+    }
+
+    private float rawBacklightToNits(int i, float backlight) {
+        return MathUtils.map(mRawBacklight[i], mRawBacklight[i + 1],
+                mRawNits[i], mRawNits[i + 1], backlight);
+    }
+
+    // This method creates a brightness spline that is of equal length with proportional increments
+    // to the backlight spline. The values of this array range from 0.0f to 1.0f instead of the
+    // potential constrained range that the backlight array covers
+    // These splines are used to convert from the system brightness value to the HAL backlight
+    // value
+    private void createBacklightConversionSplines() {
+        mBrightness = new float[mBacklight.length];
+        for (int i = 0; i < mBrightness.length; i++) {
+            mBrightness[i] = MathUtils.map(mBacklight[0],
+                    mBacklight[mBacklight.length - 1],
+                    PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, mBacklight[i]);
+        }
+        mBrightnessToBacklightSpline = Spline.createSpline(mBrightness, mBacklight);
+        mBacklightToBrightnessSpline = Spline.createSpline(mBacklight, mBrightness);
     }
 
     private void loadQuirks(DisplayConfiguration config) {
@@ -412,12 +587,14 @@
             mIsHighBrightnessModeEnabled = hbm.getEnabled();
             mHbmData = new HighBrightnessModeData();
             mHbmData.minimumLux = hbm.getMinimumLux_all().floatValue();
-            mHbmData.transitionPoint = hbm.getTransitionPoint_all().floatValue();
-            if (mHbmData.transitionPoint >= getMaxBrightness()) {
+            float transitionPointBacklightScale = hbm.getTransitionPoint_all().floatValue();
+            if (transitionPointBacklightScale >= mBacklightMaximum) {
                 throw new IllegalArgumentException("HBM transition point invalid. "
                         + mHbmData.transitionPoint + " is not less than "
-                        + getMaxBrightness());
+                        + mBacklightMaximum);
             }
+            mHbmData.transitionPoint =
+                    mBacklightToBrightnessSpline.interpolate(transitionPointBacklightScale);
             final HbmTiming hbmTiming = hbm.getTiming_all();
             mHbmData.timeWindowMillis = hbmTiming.getTimeWindowSecs_all().longValue() * 1000;
             mHbmData.timeMaxMillis = hbmTiming.getTimeMaxSecs_all().longValue() * 1000;
diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
index 501533d..40cee66 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
@@ -466,7 +466,7 @@
         sb.append(", supportedModes ").append(Arrays.toString(supportedModes));
         sb.append(", colorMode ").append(colorMode);
         sb.append(", supportedColorModes ").append(Arrays.toString(supportedColorModes));
-        sb.append(", HdrCapabilities ").append(hdrCapabilities);
+        sb.append(", hdrCapabilities ").append(hdrCapabilities);
         sb.append(", allmSupported ").append(allmSupported);
         sb.append(", gameContentTypeSupported ").append(gameContentTypeSupported);
         sb.append(", density ").append(densityDpi);
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 6a22941..52149ee 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -249,30 +249,48 @@
 
     /** {@link DisplayBlanker} used by all {@link DisplayPowerController}s. */
     private final DisplayBlanker mDisplayBlanker = new DisplayBlanker() {
+        // Synchronized to avoid race conditions when updating multiple display states.
         @Override
-        public void requestDisplayState(int displayId, int state, float brightness) {
-            // TODO (b/168210494): Stop applying default display state to all displays.
-            if (displayId != Display.DEFAULT_DISPLAY) {
-                return;
-            }
-            final int[] displayIds;
+        public synchronized void requestDisplayState(int displayId, int state, float brightness) {
+            boolean allInactive = true;
+            boolean allOff = true;
+            final boolean stateChanged;
             synchronized (mSyncRoot) {
-                displayIds = mLogicalDisplayMapper.getDisplayIdsLocked();
+                final int index = mDisplayStates.indexOfKey(displayId);
+                if (index > -1) {
+                    final int currentState = mDisplayStates.valueAt(index);
+                    stateChanged = state != currentState;
+                    if (stateChanged) {
+                        final int size = mDisplayStates.size();
+                        for (int i = 0; i < size; i++) {
+                            final int displayState = i == index ? state : mDisplayStates.valueAt(i);
+                            if (displayState != Display.STATE_OFF) {
+                                allOff = false;
+                            }
+                            if (Display.isActiveState(displayState)) {
+                                allInactive = false;
+                            }
+                            if (!allOff && !allInactive) {
+                                break;
+                            }
+                        }
+                    }
+                } else {
+                    stateChanged = false;
+                }
             }
 
             // The order of operations is important for legacy reasons.
             if (state == Display.STATE_OFF) {
-                for (int id : displayIds) {
-                    requestDisplayStateInternal(id, state, brightness);
-                }
+                requestDisplayStateInternal(displayId, state, brightness);
             }
 
-            mDisplayPowerCallbacks.onDisplayStateChange(state);
+            if (stateChanged) {
+                mDisplayPowerCallbacks.onDisplayStateChange(allInactive, allOff);
+            }
 
             if (state != Display.STATE_OFF) {
-                for (int id : displayIds) {
-                    requestDisplayStateInternal(id, state, brightness);
-                }
+                requestDisplayStateInternal(displayId, state, brightness);
             }
         }
     };
@@ -514,7 +532,7 @@
 
             DeviceStateManager deviceStateManager =
                     mContext.getSystemService(DeviceStateManager.class);
-            deviceStateManager.addDeviceStateListener(new HandlerExecutor(mHandler),
+            deviceStateManager.registerCallback(new HandlerExecutor(mHandler),
                     new DeviceStateListener());
 
             scheduleTraversalLocked(false);
@@ -1160,7 +1178,7 @@
 
     private void handleLogicalDisplayRemovedLocked(@NonNull LogicalDisplay display) {
         final int displayId = display.getDisplayIdLocked();
-        mDisplayPowerControllers.delete(displayId);
+        mDisplayPowerControllers.removeReturnOld(displayId).stop();
         mDisplayStates.delete(displayId);
         mDisplayBrightnesses.delete(displayId);
         DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
@@ -2758,8 +2776,22 @@
         public boolean requestPowerState(int groupId, DisplayPowerRequest request,
                 boolean waitForNegativeProximity) {
             synchronized (mSyncRoot) {
-                return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
-                        .requestPowerState(request, waitForNegativeProximity);
+                final DisplayGroup displayGroup = mLogicalDisplayMapper.getDisplayGroupLocked(
+                        groupId);
+                if (displayGroup == null) {
+                    return true;
+                }
+
+                final int size = displayGroup.getSizeLocked();
+                boolean ready = true;
+                for (int i = 0; i < size; i++) {
+                    final DisplayPowerController displayPowerController =
+                            mDisplayPowerControllers.get(displayGroup.getIdLocked(i));
+                    ready &= displayPowerController.requestPowerState(request,
+                            waitForNegativeProximity);
+                }
+
+                return ready;
             }
         }
 
@@ -2772,13 +2804,6 @@
         }
 
         @Override
-        public int getDisplayGroupId(int displayId) {
-            synchronized (mSyncRoot) {
-                return mLogicalDisplayMapper.getDisplayGroupIdLocked(displayId);
-            }
-        }
-
-        @Override
         public void registerDisplayGroupListener(DisplayGroupListener listener) {
             mDisplayGroupListeners.add(listener);
         }
@@ -2949,9 +2974,9 @@
     /**
      * Listens to changes in device state and reports the state to LogicalDisplayMapper.
      */
-    class DeviceStateListener implements DeviceStateManager.DeviceStateListener {
+    class DeviceStateListener implements DeviceStateManager.DeviceStateCallback {
         @Override
-        public void onDeviceStateChanged(int deviceState) {
+        public void onStateChanged(int deviceState) {
             synchronized (mSyncRoot) {
                 mLogicalDisplayMapper.setDeviceStateLocked(deviceState);
             }
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 9320f50..0117326 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -121,6 +121,7 @@
     private static final int MSG_SET_TEMPORARY_BRIGHTNESS = 6;
     private static final int MSG_SET_TEMPORARY_AUTO_BRIGHTNESS_ADJUSTMENT = 7;
     private static final int MSG_IGNORE_PROXIMITY = 8;
+    private static final int MSG_STOP = 9;
 
     private static final int PROXIMITY_UNKNOWN = -1;
     private static final int PROXIMITY_NEGATIVE = 0;
@@ -189,12 +190,6 @@
     // The dim screen brightness.
     private final float mScreenBrightnessDimConfig;
 
-    // The minimum allowed brightness.
-    private final float mScreenBrightnessRangeMinimum;
-
-    // The maximum allowed brightness.
-    private final float mScreenBrightnessRangeMaximum;
-
     private final float mScreenBrightnessDefault;
 
     // The minimum allowed brightness while in VR.
@@ -351,6 +346,7 @@
     @Nullable
     private final DisplayWhiteBalanceController mDisplayWhiteBalanceController;
 
+    @Nullable
     private final ColorDisplayServiceInternal mCdsi;
     private final float[] mNitsRange;
 
@@ -409,6 +405,9 @@
     private ObjectAnimator mColorFadeOffAnimator;
     private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
 
+    // True if this DisplayPowerController has been stopped and should no longer be running.
+    private boolean mStopped;
+
     /**
      * Creates the display power controller.
      */
@@ -438,8 +437,6 @@
 
         final Resources resources = context.getResources();
 
-        final float screenBrightnessSettingMinimumFloat = clampAbsoluteBrightness(
-                pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM));
 
         // DOZE AND DIM SETTINGS
         mScreenBrightnessDozeConfig = clampAbsoluteBrightness(
@@ -448,10 +445,6 @@
                 pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DIM));
 
         // NORMAL SCREEN SETTINGS
-        mScreenBrightnessRangeMinimum =
-                Math.min(screenBrightnessSettingMinimumFloat, mScreenBrightnessDimConfig);
-        mScreenBrightnessRangeMaximum = clampAbsoluteBrightness(
-                pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM));
         mScreenBrightnessDefault = clampAbsoluteBrightness(
                 mLogicalDisplay.getDisplayInfoLocked().brightnessDefault);
 
@@ -476,18 +469,10 @@
 
         DisplayDeviceConfig displayDeviceConfig = logicalDisplay
                 .getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig();
-        // TODO: (b/178183143) Ensure that the ddc is not null
-        if (displayDeviceConfig != null) {
-            mBrightnessRampRateFastDecrease = displayDeviceConfig.getBrightnessRampFastDecrease();
-            mBrightnessRampRateFastIncrease = displayDeviceConfig.getBrightnessRampFastIncrease();
-            mBrightnessRampRateSlowDecrease = displayDeviceConfig.getBrightnessRampSlowDecrease();
-            mBrightnessRampRateSlowIncrease = displayDeviceConfig.getBrightnessRampSlowIncrease();
-        } else {
-            mBrightnessRampRateFastDecrease = 1.0f;
-            mBrightnessRampRateFastIncrease = 1.0f;
-            mBrightnessRampRateSlowDecrease = 1.0f;
-            mBrightnessRampRateSlowIncrease = 1.0f;
-        }
+        mBrightnessRampRateFastDecrease = displayDeviceConfig.getBrightnessRampFastDecrease();
+        mBrightnessRampRateFastIncrease = displayDeviceConfig.getBrightnessRampFastIncrease();
+        mBrightnessRampRateSlowDecrease = displayDeviceConfig.getBrightnessRampSlowDecrease();
+        mBrightnessRampRateSlowIncrease = displayDeviceConfig.getBrightnessRampSlowIncrease();
         mSkipScreenOnBrightnessRamp = resources.getBoolean(
                 com.android.internal.R.bool.config_skipScreenOnBrightnessRamp);
 
@@ -540,12 +525,14 @@
                     com.android.internal.R.string.config_displayLightSensorType);
             Sensor lightSensor = findDisplayLightSensor(lightSensorType);
 
-            mBrightnessMapper = BrightnessMappingStrategy.create(resources);
+            final DisplayDeviceConfig ddc =
+                    logicalDisplay.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig();
+            mBrightnessMapper = BrightnessMappingStrategy.create(resources, ddc);
             if (mBrightnessMapper != null) {
                 mAutomaticBrightnessController = new AutomaticBrightnessController(this,
                         handler.getLooper(), sensorManager, lightSensor, mBrightnessMapper,
-                        lightSensorWarmUpTimeConfig, mScreenBrightnessRangeMinimum,
-                        mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
+                        lightSensorWarmUpTimeConfig, PowerManager.BRIGHTNESS_MIN,
+                        PowerManager.BRIGHTNESS_MAX, dozeScaleFactor, lightSensorRate,
                         initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
                         autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds,
                         screenBrightnessThresholds, logicalDisplay, context);
@@ -583,14 +570,16 @@
 
         DisplayWhiteBalanceSettings displayWhiteBalanceSettings = null;
         DisplayWhiteBalanceController displayWhiteBalanceController = null;
-        try {
-            displayWhiteBalanceSettings = new DisplayWhiteBalanceSettings(mContext, mHandler);
-            displayWhiteBalanceController = DisplayWhiteBalanceFactory.create(mHandler,
-                    mSensorManager, resources);
-            displayWhiteBalanceSettings.setCallbacks(this);
-            displayWhiteBalanceController.setCallbacks(this);
-        } catch (Exception e) {
-            Slog.e(TAG, "failed to set up display white-balance: " + e);
+        if (mDisplayId == Display.DEFAULT_DISPLAY) {
+            try {
+                displayWhiteBalanceSettings = new DisplayWhiteBalanceSettings(mContext, mHandler);
+                displayWhiteBalanceController = DisplayWhiteBalanceFactory.create(mHandler,
+                        mSensorManager, resources);
+                displayWhiteBalanceSettings.setCallbacks(this);
+                displayWhiteBalanceController.setCallbacks(this);
+            } catch (Exception e) {
+                Slog.e(TAG, "failed to set up display white-balance: " + e);
+            }
         }
         mDisplayWhiteBalanceSettings = displayWhiteBalanceSettings;
         mDisplayWhiteBalanceController = displayWhiteBalanceController;
@@ -602,20 +591,24 @@
             mNitsRange = BrightnessMappingStrategy.getFloatArray(context.getResources()
                     .obtainTypedArray(com.android.internal.R.array.config_screenBrightnessNits));
         }
-        mCdsi = LocalServices.getService(ColorDisplayServiceInternal.class);
-        boolean active = mCdsi.setReduceBrightColorsListener(new ReduceBrightColorsListener() {
-            @Override
-            public void onReduceBrightColorsActivationChanged(boolean activated) {
-                applyReduceBrightColorsSplineAdjustment();
-            }
+        if (mDisplayId == Display.DEFAULT_DISPLAY) {
+            mCdsi = LocalServices.getService(ColorDisplayServiceInternal.class);
+            boolean active = mCdsi.setReduceBrightColorsListener(new ReduceBrightColorsListener() {
+                @Override
+                public void onReduceBrightColorsActivationChanged(boolean activated) {
+                    applyReduceBrightColorsSplineAdjustment();
+                }
 
-            @Override
-            public void onReduceBrightColorsStrengthChanged(int strength) {
+                @Override
+                public void onReduceBrightColorsStrengthChanged(int strength) {
+                    applyReduceBrightColorsSplineAdjustment();
+                }
+            });
+            if (active) {
                 applyReduceBrightColorsSplineAdjustment();
             }
-        });
-        if (active) {
-            applyReduceBrightColorsSplineAdjustment();
+        } else {
+            mCdsi = null;
         }
     }
 
@@ -713,6 +706,10 @@
         }
 
         synchronized (mLock) {
+            if (mStopped) {
+                return true;
+            }
+
             boolean changed = false;
 
             if (waitForNegativeProximity
@@ -731,11 +728,10 @@
 
             if (changed) {
                 mDisplayReadyLocked = false;
-            }
-
-            if (changed && !mPendingRequestChangedLocked) {
-                mPendingRequestChangedLocked = true;
-                sendUpdatePowerStateLocked();
+                if (!mPendingRequestChangedLocked) {
+                    mPendingRequestChangedLocked = true;
+                    sendUpdatePowerStateLocked();
+                }
             }
 
             return mDisplayReadyLocked;
@@ -758,6 +754,34 @@
         // TODO: b/175821789 - Support high brightness on multiple (folding) displays
     }
 
+    /**
+     * Unregisters all listeners and interrupts all running threads; halting future work.
+     *
+     * This method should be called when the DisplayPowerController is no longer in use; i.e. when
+     * the {@link #mDisplayId display} has been removed.
+     */
+    public void stop() {
+        synchronized (mLock) {
+            mStopped = true;
+            Message msg = mHandler.obtainMessage(MSG_STOP);
+            mHandler.sendMessage(msg);
+
+            if (mDisplayWhiteBalanceController != null) {
+                mDisplayWhiteBalanceController.setEnabled(false);
+            }
+
+            if (mAutomaticBrightnessController != null) {
+                mAutomaticBrightnessController.stop();
+            }
+
+            if (mBrightnessTracker != null) {
+                mBrightnessTracker.stop();
+            }
+
+            mContext.getContentResolver().unregisterContentObserver(mSettingsObserver);
+        }
+    }
+
     private void sendUpdatePowerState() {
         synchronized (mLock) {
             sendUpdatePowerStateLocked();
@@ -765,7 +789,7 @@
     }
 
     private void sendUpdatePowerStateLocked() {
-        if (!mPendingUpdatePowerStateLocked) {
+        if (!mStopped && !mPendingUpdatePowerStateLocked) {
             mPendingUpdatePowerStateLocked = true;
             Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
             mHandler.sendMessage(msg);
@@ -788,7 +812,7 @@
             mColorFadeOffAnimator.addListener(mAnimatorListener);
         }
 
-        mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
+        mScreenBrightnessRampAnimator = new RampAnimator<>(
                 mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS_FLOAT);
         mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);
 
@@ -796,9 +820,8 @@
         noteScreenBrightness(mPowerState.getScreenBrightness());
 
         // Initialize all of the brightness tracking state
-        final float brightness = convertToNits(BrightnessSynchronizer.brightnessFloatToInt(
-                mPowerState.getScreenBrightness()));
-        if (brightness >= 0.0f) {
+        final float brightness = convertToNits(mPowerState.getScreenBrightness());
+        if (brightness >= PowerManager.BRIGHTNESS_MIN) {
             mBrightnessTracker.start(brightness);
         }
 
@@ -829,12 +852,17 @@
         }
     };
 
-    private final RampAnimator.Listener mRampAnimatorListener = new RampAnimator.Listener() {
-        @Override
-        public void onAnimationEnd() {
-            sendUpdatePowerState();
+    private final RampAnimator.Listener mRampAnimatorListener = this::sendUpdatePowerState;
+
+    /** Clean up all resources that are accessed via the {@link #mHandler} thread. */
+    private void cleanupHandlerThreadAfterStop() {
+        setProximitySensorEnabled(false);
+        mHandler.removeCallbacksAndMessages(null);
+        if (mPowerState != null) {
+            mPowerState.stop();
+            mPowerState = null;
         }
-    };
+    }
 
     private void updatePowerState() {
         // Update the power state request.
@@ -844,6 +872,9 @@
         int brightnessAdjustmentFlags = 0;
         mBrightnessReasonTemp.set(null);
         synchronized (mLock) {
+            if (mStopped) {
+                return;
+            }
             mPendingUpdatePowerStateLocked = false;
             if (mPendingRequestLocked == null) {
                 return; // wait until first actual power request
@@ -1103,10 +1134,10 @@
         // Apply dimming by at least some minimum amount when user activity
         // timeout is about to expire.
         if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
-            if (brightnessState > mScreenBrightnessRangeMinimum) {
+            if (brightnessState > PowerManager.BRIGHTNESS_MIN) {
                 brightnessState = Math.max(Math.min(brightnessState
                                 - SCREEN_DIM_MINIMUM_REDUCTION_FLOAT,
-                        mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum);
+                        mScreenBrightnessDimConfig), PowerManager.BRIGHTNESS_MIN);
                 mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_DIMMED);
             }
             if (!mAppliedDimming) {
@@ -1120,12 +1151,11 @@
         // If low power mode is enabled, scale brightness by screenLowPowerBrightnessFactor
         // as long as it is above the minimum threshold.
         if (mPowerRequest.lowPowerMode) {
-            if (brightnessState > mScreenBrightnessRangeMinimum) {
+            if (brightnessState > PowerManager.BRIGHTNESS_MIN) {
                 final float brightnessFactor =
                         Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);
                 final float lowPowerBrightnessFloat = (brightnessState * brightnessFactor);
-                brightnessState = Math.max(lowPowerBrightnessFloat,
-                        mScreenBrightnessRangeMinimum);
+                brightnessState = Math.max(lowPowerBrightnessFloat, PowerManager.BRIGHTNESS_MIN);
                 mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_LOW_POWER);
             }
             if (!mAppliedLowPower) {
@@ -1210,9 +1240,8 @@
                     // slider event so notify as if the system changed the brightness.
                     userInitiatedChange = false;
                 }
-                notifyBrightnessChanged(
-                        BrightnessSynchronizer.brightnessFloatToInt(brightnessState),
-                        userInitiatedChange, hadUserBrightnessPoint);
+                notifyBrightnessChanged(brightnessState, userInitiatedChange,
+                        hadUserBrightnessPoint);
             }
 
         }
@@ -1439,17 +1468,17 @@
 
     private float clampScreenBrightness(float value) {
         if (Float.isNaN(value)) {
-            return mScreenBrightnessRangeMinimum;
+            return PowerManager.BRIGHTNESS_MIN;
         }
         return MathUtils.constrain(
-                value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
+                value, PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX);
     }
 
     // Checks whether the brightness is within the valid brightness range, not including the off or
     // invalid states.
     private boolean isValidBrightnessValue(float brightnessState) {
-        return brightnessState >= mScreenBrightnessRangeMinimum
-                && brightnessState <= mScreenBrightnessRangeMaximum;
+        return brightnessState >= PowerManager.BRIGHTNESS_MIN
+                && brightnessState <= PowerManager.BRIGHTNESS_MAX;
     }
 
     private void animateScreenBrightness(float target, float rate) {
@@ -1826,7 +1855,7 @@
         return true;
     }
 
-    private void notifyBrightnessChanged(int brightness, boolean userInitiated,
+    private void notifyBrightnessChanged(float brightness, boolean userInitiated,
             boolean hadUserDataPoint) {
         final float brightnessInNits = convertToNits(brightness);
         if (mPowerRequest.useAutoBrightness && brightnessInNits >= 0.0f
@@ -1843,9 +1872,9 @@
         }
     }
 
-    private float convertToNits(int backlight) {
+    private float convertToNits(float brightness) {
         if (mBrightnessMapper != null) {
-            return mBrightnessMapper.convertToNits(backlight);
+            return mBrightnessMapper.convertToNits(brightness);
         } else {
             return -1.0f;
         }
@@ -1924,12 +1953,9 @@
 
         pw.println();
         pw.println("Display Power Controller Configuration:");
-        pw.println("  mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
-        pw.println("  mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
         pw.println("  mScreenBrightnessRangeDefault=" + mScreenBrightnessDefault);
         pw.println("  mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig);
         pw.println("  mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
-        pw.println("  mScreenBrightnessDefault=" + mScreenBrightnessDefault);
         pw.println("  mScreenBrightnessForVrRangeMinimum=" + mScreenBrightnessForVrRangeMinimum);
         pw.println("  mScreenBrightnessForVrRangeMaximum=" + mScreenBrightnessForVrRangeMaximum);
         pw.println("  mScreenBrightnessForVrDefault=" + mScreenBrightnessForVrDefault);
@@ -2061,10 +2087,6 @@
         }
     }
 
-    private static int clampAbsoluteBrightness(int value) {
-        return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
-    }
-
     private static float clampAbsoluteBrightness(float value) {
         return MathUtils.constrain(value, PowerManager.BRIGHTNESS_MIN,
                 PowerManager.BRIGHTNESS_MAX);
@@ -2144,6 +2166,10 @@
                 case MSG_IGNORE_PROXIMITY:
                     ignoreProximitySensorUntilChangedInternal();
                     break;
+
+                case MSG_STOP:
+                    cleanupHandlerThreadAfterStop();
+                    break;
             }
         }
     }
diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java
index 1d20d87..77aff5b 100644
--- a/services/core/java/com/android/server/display/DisplayPowerState.java
+++ b/services/core/java/com/android/server/display/DisplayPowerState.java
@@ -72,6 +72,8 @@
 
     private Runnable mCleanListener;
 
+    private volatile boolean mStopped;
+
     DisplayPowerState(
             DisplayBlanker blanker, ColorFade colorFade, int displayId, int displayState) {
         mHandler = new Handler(true /*async*/);
@@ -264,9 +266,24 @@
         }
     }
 
+    /**
+     * Interrupts all running threads; halting future work.
+     *
+     * This method should be called when the DisplayPowerState is no longer in use; i.e. when
+     * the {@link #mDisplayId display} has been removed.
+     */
+    public void stop() {
+        mStopped = true;
+        mPhotonicModulator.interrupt();
+        dismissColorFade();
+        mCleanListener = null;
+        mHandler.removeCallbacksAndMessages(null);
+    }
+
     public void dump(PrintWriter pw) {
         pw.println();
         pw.println("Display Power State:");
+        pw.println("  mStopped=" + mStopped);
         pw.println("  mScreenState=" + Display.stateToString(mScreenState));
         pw.println("  mScreenBrightness=" + mScreenBrightness);
         pw.println("  mScreenReady=" + mScreenReady);
@@ -428,7 +445,11 @@
                     if (!stateChanged && !backlightChanged) {
                         try {
                             mLock.wait();
-                        } catch (InterruptedException ex) { }
+                        } catch (InterruptedException ex) {
+                            if (mStopped) {
+                                return;
+                            }
+                        }
                         continue;
                     }
                     mActualState = state;
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 3b66236..3709963 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -30,7 +30,6 @@
 import android.util.LongSparseArray;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.util.Spline;
 import android.view.Display;
 import android.view.DisplayAddress;
 import android.view.DisplayCutout;
@@ -38,8 +37,8 @@
 import android.view.RoundedCorners;
 import android.view.SurfaceControl;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.display.BrightnessSynchronizer;
-import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.LocalServices;
 import com.android.server.lights.LightsManager;
@@ -72,6 +71,7 @@
 
     private final Injector mInjector;
 
+    private final SurfaceControlProxy mSurfaceControlProxy;
 
     // Called with SyncRoot lock held.
     public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
@@ -79,10 +79,12 @@
         this(syncRoot, context, handler, listener, new Injector());
     }
 
+    @VisibleForTesting
     LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
             Context context, Handler handler, Listener listener, Injector injector) {
         super(syncRoot, context, handler, listener, TAG);
         mInjector = injector;
+        mSurfaceControlProxy = mInjector.getSurfaceControlProxy();
     }
 
     @Override
@@ -92,58 +94,57 @@
         mInjector.setDisplayEventListenerLocked(getHandler().getLooper(),
                 new LocalDisplayEventListener());
 
-        for (long physicalDisplayId : SurfaceControl.getPhysicalDisplayIds()) {
+        for (long physicalDisplayId : mSurfaceControlProxy.getPhysicalDisplayIds()) {
             tryConnectDisplayLocked(physicalDisplayId);
         }
     }
 
     private void tryConnectDisplayLocked(long physicalDisplayId) {
-        final IBinder displayToken = SurfaceControl.getPhysicalDisplayToken(physicalDisplayId);
+        final IBinder displayToken =
+                mSurfaceControlProxy.getPhysicalDisplayToken(physicalDisplayId);
         if (displayToken != null) {
-            SurfaceControl.DisplayInfo info = SurfaceControl.getDisplayInfo(displayToken);
-            if (info == null) {
-                Slog.w(TAG, "No valid info found for display device " + physicalDisplayId);
+            SurfaceControl.StaticDisplayInfo staticInfo =
+                    mSurfaceControlProxy.getStaticDisplayInfo(displayToken);
+            if (staticInfo == null) {
+                Slog.w(TAG, "No valid static info found for display device " + physicalDisplayId);
                 return;
             }
-            SurfaceControl.DisplayMode[] displayModes =
-                    SurfaceControl.getDisplayModes(displayToken);
-            if (displayModes == null) {
+            SurfaceControl.DynamicDisplayInfo dynamicInfo =
+                    mSurfaceControlProxy.getDynamicDisplayInfo(displayToken);
+            if (dynamicInfo == null) {
+                Slog.w(TAG, "No valid dynamic info found for display device " + physicalDisplayId);
+                return;
+            }
+            if (dynamicInfo.supportedDisplayModes == null) {
                 // There are no valid modes for this device, so we can't use it
                 Slog.w(TAG, "No valid modes found for display device " + physicalDisplayId);
                 return;
             }
-            int activeDisplayMode = SurfaceControl.getActiveDisplayMode(displayToken);
-            if (activeDisplayMode < 0) {
+            if (dynamicInfo.activeDisplayModeId < 0) {
                 // There is no active mode, and for now we don't have the
                 // policy to set one.
-                Slog.w(TAG, "No active mode found for display device " + physicalDisplayId);
+                Slog.w(TAG, "No valid active mode found for display device " + physicalDisplayId);
                 return;
             }
-            int activeColorMode = SurfaceControl.getActiveColorMode(displayToken);
-            if (activeColorMode < 0) {
+            if (dynamicInfo.activeColorMode < 0) {
                 // We failed to get the active color mode. We don't bail out here since on the next
                 // configuration pass we'll go ahead and set it to whatever it was set to last (or
                 // COLOR_MODE_NATIVE if this is the first configuration).
-                Slog.w(TAG, "Unable to get active color mode for display device " +
-                        physicalDisplayId);
-                activeColorMode = Display.COLOR_MODE_INVALID;
+                Slog.w(TAG, "No valid active color mode for display device " + physicalDisplayId);
+                dynamicInfo.activeColorMode = Display.COLOR_MODE_INVALID;
             }
-            SurfaceControl.DesiredDisplayModeSpecs modeSpecsSpecs =
-                    SurfaceControl.getDesiredDisplayModeSpecs(displayToken);
-            int[] colorModes = SurfaceControl.getDisplayColorModes(displayToken);
-            Display.HdrCapabilities hdrCapabilities =
-                    SurfaceControl.getHdrCapabilities(displayToken);
+            SurfaceControl.DesiredDisplayModeSpecs modeSpecs =
+                    mSurfaceControlProxy.getDesiredDisplayModeSpecs(displayToken);
             LocalDisplayDevice device = mDevices.get(physicalDisplayId);
             if (device == null) {
                 // Display was added.
                 final boolean isDefaultDisplay = mDevices.size() == 0;
-                device = new LocalDisplayDevice(displayToken, physicalDisplayId, info, displayModes,
-                        activeDisplayMode, modeSpecsSpecs, colorModes, activeColorMode,
-                        hdrCapabilities, isDefaultDisplay);
+                device = new LocalDisplayDevice(displayToken, physicalDisplayId, staticInfo,
+                        dynamicInfo, modeSpecs, isDefaultDisplay);
                 mDevices.put(physicalDisplayId, device);
                 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
-            } else if (device.updateDisplayPropertiesLocked(info, displayModes, activeDisplayMode,
-                    modeSpecsSpecs, colorModes, activeColorMode, hdrCapabilities)) {
+            } else if (device.updateDisplayPropertiesLocked(staticInfo, dynamicInfo,
+                    modeSpecs)) {
                 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
             }
         } else {
@@ -195,7 +196,6 @@
         private DisplayModeDirector.DesiredDisplayModeSpecs mDisplayModeSpecs =
                 new DisplayModeDirector.DesiredDisplayModeSpecs();
         private boolean mDisplayModeSpecsInvalid;
-        private int mActiveDisplayModeId;
         private int mActiveColorMode;
         private Display.HdrCapabilities mHdrCapabilities;
         private boolean mAllmSupported;
@@ -204,33 +204,29 @@
         private boolean mGameContentTypeRequested;
         private boolean mSidekickActive;
         private SidekickInternal mSidekickInternal;
-        private SurfaceControl.DisplayInfo mDisplayInfo;
-        private SurfaceControl.DisplayMode[] mDisplayModes;
-        private Spline mSystemBrightnessToNits;
-        private Spline mNitsToHalBrightness;
+        private SurfaceControl.StaticDisplayInfo mStaticDisplayInfo;
+        // The supported display modes according in SurfaceFlinger
+        private SurfaceControl.DisplayMode[] mSfDisplayModes;
+        // The active display mode in SurfaceFlinger
+        private SurfaceControl.DisplayMode mActiveSfDisplayMode;
         private DisplayDeviceConfig mDisplayDeviceConfig;
 
         private DisplayEventReceiver.FrameRateOverride[] mFrameRateOverrides =
                 new DisplayEventReceiver.FrameRateOverride[0];
 
         LocalDisplayDevice(IBinder displayToken, long physicalDisplayId,
-                SurfaceControl.DisplayInfo info, SurfaceControl.DisplayMode[] displayModes,
-                int activeDisplayModeId, SurfaceControl.DesiredDisplayModeSpecs modeSpecs,
-                int[] colorModes, int activeColorMode, Display.HdrCapabilities hdrCapabilities,
-                boolean isDefaultDisplay) {
-            super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + physicalDisplayId);
+                SurfaceControl.StaticDisplayInfo staticDisplayInfo,
+                SurfaceControl.DynamicDisplayInfo dynamicInfo,
+                SurfaceControl.DesiredDisplayModeSpecs modeSpecs, boolean isDefaultDisplay) {
+            super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + physicalDisplayId,
+                    getContext());
             mPhysicalDisplayId = physicalDisplayId;
             mIsDefaultDisplay = isDefaultDisplay;
-            updateDisplayPropertiesLocked(info, displayModes, activeDisplayModeId, modeSpecs,
-                    colorModes, activeColorMode, hdrCapabilities);
+            updateDisplayPropertiesLocked(staticDisplayInfo, dynamicInfo, modeSpecs);
             mSidekickInternal = LocalServices.getService(SidekickInternal.class);
-            mBacklightAdapter = new BacklightAdapter(displayToken, isDefaultDisplay);
-            mAllmSupported = SurfaceControl.getAutoLowLatencyModeSupport(displayToken);
-            mGameContentTypeSupported = SurfaceControl.getGameContentTypeSupport(displayToken);
+            mBacklightAdapter = new BacklightAdapter(displayToken, isDefaultDisplay,
+                    mSurfaceControlProxy);
             mDisplayDeviceConfig = null;
-            // Defer configuration file loading
-            BackgroundThread.getHandler().sendMessage(PooledLambda.obtainMessage(
-                    LocalDisplayDevice::loadDisplayConfiguration, this));
         }
 
         @Override
@@ -241,15 +237,17 @@
         /**
          * Returns true if there is a change.
          **/
-        public boolean updateDisplayPropertiesLocked(SurfaceControl.DisplayInfo info,
-                SurfaceControl.DisplayMode[] displayModes,
-                int activeDisplayModeId, SurfaceControl.DesiredDisplayModeSpecs modeSpecs,
-                int[] colorModes, int activeColorMode, Display.HdrCapabilities hdrCapabilities) {
+        public boolean updateDisplayPropertiesLocked(SurfaceControl.StaticDisplayInfo staticInfo,
+                SurfaceControl.DynamicDisplayInfo dynamicInfo,
+                SurfaceControl.DesiredDisplayModeSpecs modeSpecs) {
             boolean changed = updateDisplayModesLocked(
-                    displayModes, activeDisplayModeId, modeSpecs);
-            changed |= updateDisplayInfo(info);
-            changed |= updateColorModesLocked(colorModes, activeColorMode);
-            changed |= updateHdrCapabilitiesLocked(hdrCapabilities);
+                    dynamicInfo.supportedDisplayModes, dynamicInfo.activeDisplayModeId, modeSpecs);
+            changed |= updateStaticInfo(staticInfo);
+            changed |= updateColorModesLocked(dynamicInfo.supportedColorModes,
+                    dynamicInfo.activeColorMode);
+            changed |= updateHdrCapabilitiesLocked(dynamicInfo.hdrCapabilities);
+            changed |= updateAllmSupport(dynamicInfo.autoLowLatencyModeSupported);
+            changed |= updateGameContentTypeSupport(dynamicInfo.gameContentTypeSupported);
 
             if (changed) {
                 mHavePendingChanges = true;
@@ -260,8 +258,9 @@
         public boolean updateDisplayModesLocked(
                 SurfaceControl.DisplayMode[] displayModes, int activeDisplayModeId,
                 SurfaceControl.DesiredDisplayModeSpecs modeSpecs) {
-            mDisplayModes = Arrays.copyOf(displayModes, displayModes.length);
-            mActiveDisplayModeId = activeDisplayModeId;
+            mSfDisplayModes = Arrays.copyOf(displayModes, displayModes.length);
+            mActiveSfDisplayMode = getModeById(displayModes, activeDisplayModeId);
+
             // Build an updated list of all existing modes.
             ArrayList<DisplayModeRecord> records = new ArrayList<>();
             boolean modesAdded = false;
@@ -282,7 +281,7 @@
 
                 // First, check to see if we've already added a matching mode. Since not all
                 // configuration options are exposed via Display.Mode, it's possible that we have
-                // multiple DisplayModess that would generate the same Display.Mode.
+                // multiple DisplayModes that would generate the same Display.Mode.
                 boolean existingMode = false;
                 for (DisplayModeRecord record : records) {
                     if (record.hasMatchingMode(mode)
@@ -312,9 +311,8 @@
 
             // Get the currently active mode
             DisplayModeRecord activeRecord = null;
-            for (int i = 0; i < records.size(); i++) {
-                DisplayModeRecord record = records.get(i);
-                if (record.hasMatchingMode(displayModes[activeDisplayModeId])) {
+            for (DisplayModeRecord record : records) {
+                if (record.hasMatchingMode(mActiveSfDisplayMode)) {
                     activeRecord = record;
                     break;
                 }
@@ -340,19 +338,18 @@
                 // If we can't map the defaultMode index to a mode, then the physical display
                 // modes must have changed, and the code below for handling changes to the
                 // list of available modes will take care of updating display mode specs.
-                if (activeBaseMode != NO_DISPLAY_MODE_ID) {
-                    if (mDisplayModeSpecs.baseModeId != activeBaseMode
-                            || mDisplayModeSpecs.primaryRefreshRateRange.min
-                                    != modeSpecs.primaryRefreshRateMin
-                            || mDisplayModeSpecs.primaryRefreshRateRange.max
-                                    != modeSpecs.primaryRefreshRateMax
-                            || mDisplayModeSpecs.appRequestRefreshRateRange.min
-                                    != modeSpecs.appRequestRefreshRateMin
-                            || mDisplayModeSpecs.appRequestRefreshRateRange.max
-                                    != modeSpecs.appRequestRefreshRateMax) {
-                        mDisplayModeSpecsInvalid = true;
-                        sendTraversalRequestLocked();
-                    }
+                if (activeBaseMode == NO_DISPLAY_MODE_ID
+                        || mDisplayModeSpecs.baseModeId != activeBaseMode
+                        || mDisplayModeSpecs.primaryRefreshRateRange.min
+                                != modeSpecs.primaryRefreshRateMin
+                        || mDisplayModeSpecs.primaryRefreshRateRange.max
+                                != modeSpecs.primaryRefreshRateMax
+                        || mDisplayModeSpecs.appRequestRefreshRateRange.min
+                                != modeSpecs.appRequestRefreshRateMin
+                        || mDisplayModeSpecs.appRequestRefreshRateRange.max
+                                != modeSpecs.appRequestRefreshRateMax) {
+                    mDisplayModeSpecsInvalid = true;
+                    sendTraversalRequestLocked();
                 }
             }
 
@@ -370,17 +367,17 @@
             // For a new display, we need to initialize the default mode ID.
             if (mDefaultModeId == NO_DISPLAY_MODE_ID) {
                 mDefaultModeId = activeRecord.mMode.getModeId();
-                mDefaultModeGroup = displayModes[activeDisplayModeId].group;
+                mDefaultModeGroup = mActiveSfDisplayMode.group;
             } else if (modesAdded && activeModeChanged) {
                 Slog.d(TAG, "New display modes are added and the active mode has changed, "
                         + "use active mode as default mode.");
                 mDefaultModeId = activeRecord.mMode.getModeId();
-                mDefaultModeGroup = displayModes[activeDisplayModeId].group;
+                mDefaultModeGroup = mActiveSfDisplayMode.group;
             } else if (findDisplayModeIdLocked(mDefaultModeId, mDefaultModeGroup) < 0) {
                 Slog.w(TAG, "Default display mode no longer available, using currently"
                         + " active mode as default.");
                 mDefaultModeId = activeRecord.mMode.getModeId();
-                mDefaultModeGroup = displayModes[activeDisplayModeId].group;
+                mDefaultModeGroup = mActiveSfDisplayMode.group;
             }
 
             // Determine whether the display mode specs' base mode is still there.
@@ -410,14 +407,14 @@
 
         @Override
         public DisplayDeviceConfig getDisplayDeviceConfig() {
+            if (mDisplayDeviceConfig == null) {
+                loadDisplayDeviceConfig();
+            }
             return mDisplayDeviceConfig;
         }
 
-        private void loadDisplayConfiguration() {
-            Spline nitsToHal = null;
-            Spline sysToNits = null;
-
-            // Load the mapping from nits to HAL brightness range (display-device-config.xml)
+        private void loadDisplayDeviceConfig() {
+            // Load display device config
             final Context context = getOverlayContext();
             mDisplayDeviceConfig = DisplayDeviceConfig.create(context, mPhysicalDisplayId,
                     mIsDefaultDisplay);
@@ -425,40 +422,16 @@
                 return;
             }
 
+            // Load brightness HWC quirk
             mBacklightAdapter.setForceSurfaceControl(mDisplayDeviceConfig.hasQuirk(
                     DisplayDeviceConfig.QUIRK_CAN_SET_BRIGHTNESS_VIA_HWC));
-
-            final float[] halNits = mDisplayDeviceConfig.getNits();
-            final float[] halBrightness = mDisplayDeviceConfig.getBrightness();
-            if (halNits == null || halBrightness == null) {
-                return;
-            }
-            nitsToHal = Spline.createSpline(halNits, halBrightness);
-
-            // Load the mapping from system brightness range to nits (config.xml)
-            final Resources res = context.getResources();
-            final float[] sysNits = BrightnessMappingStrategy.getFloatArray(res.obtainTypedArray(
-                    com.android.internal.R.array.config_screenBrightnessNits));
-            final int[] sysBrightness = res.getIntArray(
-                    com.android.internal.R.array.config_screenBrightnessBacklight);
-            if (sysNits.length == 0 || sysBrightness.length != sysNits.length) {
-                return;
-            }
-            final float[] sysBrightnessFloat = new float[sysBrightness.length];
-            for (int i = 0; i < sysBrightness.length; i++) {
-                sysBrightnessFloat[i] = sysBrightness[i];
-            }
-            sysToNits = Spline.createSpline(sysBrightnessFloat, sysNits);
-
-            mNitsToHalBrightness = nitsToHal;
-            mSystemBrightnessToNits = sysToNits;
         }
 
-        private boolean updateDisplayInfo(SurfaceControl.DisplayInfo info) {
-            if (Objects.equals(mDisplayInfo, info)) {
+        private boolean updateStaticInfo(SurfaceControl.StaticDisplayInfo info) {
+            if (Objects.equals(mStaticDisplayInfo, info)) {
                 return false;
             }
-            mDisplayInfo = info;
+            mStaticDisplayInfo = info;
             return true;
         }
 
@@ -520,6 +493,33 @@
             return true;
         }
 
+        private boolean updateAllmSupport(boolean supported) {
+            if (mAllmSupported == supported) {
+                return false;
+            }
+            mAllmSupported = supported;
+            return true;
+        }
+
+        private boolean updateGameContentTypeSupport(boolean supported) {
+            if (mGameContentTypeSupported == supported) {
+                return false;
+            }
+            mGameContentTypeSupported = supported;
+            return true;
+        }
+
+        private SurfaceControl.DisplayMode getModeById(SurfaceControl.DisplayMode[] supportedModes,
+                int modeId) {
+            for (SurfaceControl.DisplayMode mode : supportedModes) {
+                if (mode.id == modeId) {
+                    return mode;
+                }
+            }
+            Slog.e(TAG, "Can't find display mode with id " + modeId);
+            return null;
+        }
+
         private DisplayModeRecord findDisplayModeRecord(SurfaceControl.DisplayMode mode,
                 List<Float> alternativeRefreshRates) {
             for (int i = 0; i < mSupportedModes.size(); i++) {
@@ -556,10 +556,9 @@
         @Override
         public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
             if (mInfo == null) {
-                SurfaceControl.DisplayMode mode = mDisplayModes[mActiveDisplayModeId];
                 mInfo = new DisplayDeviceInfo();
-                mInfo.width = mode.width;
-                mInfo.height = mode.height;
+                mInfo.width = mActiveSfDisplayMode.width;
+                mInfo.height = mActiveSfDisplayMode.height;
                 mInfo.modeId = mActiveModeId;
                 mInfo.defaultModeId = mDefaultModeId;
                 mInfo.supportedModes = getDisplayModes(mSupportedModes);
@@ -572,21 +571,21 @@
                     mInfo.supportedColorModes[i] = mSupportedColorModes.get(i);
                 }
                 mInfo.hdrCapabilities = mHdrCapabilities;
-                mInfo.appVsyncOffsetNanos = mode.appVsyncOffsetNanos;
-                mInfo.presentationDeadlineNanos = mode.presentationDeadlineNanos;
+                mInfo.appVsyncOffsetNanos = mActiveSfDisplayMode.appVsyncOffsetNanos;
+                mInfo.presentationDeadlineNanos = mActiveSfDisplayMode.presentationDeadlineNanos;
                 mInfo.state = mState;
                 mInfo.uniqueId = getUniqueId();
                 final DisplayAddress.Physical physicalAddress =
                         DisplayAddress.fromPhysicalDisplayId(mPhysicalDisplayId);
                 mInfo.address = physicalAddress;
-                mInfo.densityDpi = (int) (mDisplayInfo.density * 160 + 0.5f);
-                mInfo.xDpi = mode.xDpi;
-                mInfo.yDpi = mode.yDpi;
-                mInfo.deviceProductInfo = mDisplayInfo.deviceProductInfo;
+                mInfo.densityDpi = (int) (mStaticDisplayInfo.density * 160 + 0.5f);
+                mInfo.xDpi = mActiveSfDisplayMode.xDpi;
+                mInfo.yDpi = mActiveSfDisplayMode.yDpi;
+                mInfo.deviceProductInfo = mStaticDisplayInfo.deviceProductInfo;
 
                 // Assume that all built-in displays that have secure output (eg. HDCP) also
                 // support compositing from gralloc protected buffers.
-                if (mDisplayInfo.secure) {
+                if (mStaticDisplayInfo.secure) {
                     mInfo.flags = DisplayDeviceInfo.FLAG_SECURE
                             | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
                 }
@@ -620,7 +619,7 @@
                     }
                 }
 
-                if (mDisplayInfo.isInternal) {
+                if (mStaticDisplayInfo.isInternal) {
                     mInfo.type = Display.TYPE_INTERNAL;
                     mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
                     mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
@@ -637,15 +636,9 @@
 
                 // The display is trusted since it is created by system.
                 mInfo.flags |= DisplayDeviceInfo.FLAG_TRUSTED;
-                if (mDisplayDeviceConfig != null) {
-                    mInfo.brightnessMinimum = mDisplayDeviceConfig.getBrightnessMinimum();
-                    mInfo.brightnessMaximum = mDisplayDeviceConfig.getBrightnessMaximum();
-                    mInfo.brightnessDefault = mDisplayDeviceConfig.getBrightnessDefault();
-                } else {
-                    mInfo.brightnessMinimum = PowerManager.BRIGHTNESS_MIN;
-                    mInfo.brightnessMaximum = PowerManager.BRIGHTNESS_MAX;
-                    mInfo.brightnessDefault = 0.5f;
-                }
+                mInfo.brightnessMinimum = PowerManager.BRIGHTNESS_MIN;
+                mInfo.brightnessMaximum = PowerManager.BRIGHTNESS_MAX;
+                mInfo.brightnessDefault = getDisplayDeviceConfig().getBrightnessDefault();
             }
             return mInfo;
         }
@@ -690,7 +683,12 @@
                                 setDisplayState(Display.STATE_ON);
                                 currentState = Display.STATE_ON;
                             } else {
-                                return; // old state and new state is off
+                                if (oldState == Display.STATE_UNKNOWN) {
+                                    // There's no guarantee about what the initial state is
+                                    // at startup, so we have to set it if previous was UNKNOWN.
+                                    setDisplayState(state);
+                                }
+                                return;
                             }
                         }
 
@@ -749,7 +747,7 @@
                                 + "id=" + physicalDisplayId
                                 + ", state=" + Display.stateToString(state) + ")");
                         try {
-                            SurfaceControl.setDisplayPowerMode(token, mode);
+                            mSurfaceControlProxy.setDisplayPowerMode(token, mode);
                             Trace.traceCounter(Trace.TRACE_TAG_POWER, "DisplayPowerMode", mode);
                         } finally {
                             Trace.traceEnd(Trace.TRACE_TAG_POWER);
@@ -778,8 +776,8 @@
                         Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
                                 + "id=" + physicalDisplayId + ", brightness=" + brightness + ")");
                         try {
-                            brightness = displayBrightnessToHalBrightness(brightness);
-                            mBacklightAdapter.setBrightness(brightness);
+                            float backlight = brightnessToBacklight(brightness);
+                            mBacklightAdapter.setBacklight(backlight);
                             Trace.traceCounter(Trace.TRACE_TAG_POWER,
                                     "ScreenBrightness",
                                     BrightnessSynchronizer.brightnessFloatToInt(brightness));
@@ -788,35 +786,8 @@
                         }
                     }
 
-                    /**
-                     * Converts brightness range from the framework's brightness space to the
-                     * Hal brightness space if the HAL brightness space has been provided via
-                     * a display device configuration file.
-                     */
-                    private float displayBrightnessToHalBrightness(float brightness) {
-                        // TODO: b/171380847 - This needs to be deprecated. The nits-to-brightness
-                        // relationship should be specified in display-config OR config.xml, but not
-                        // both, and no nits-space conversion should be necessary.
-                        //
-                        // Only do a conversion if there exists a unique system brightness and a
-                        // unique HAL brightness-to-nits range defined.
-                        if (mSystemBrightnessToNits == null || mNitsToHalBrightness == null) {
-                            return brightness;
-                        }
-
-                        // Sys brightness in this conversion is always specified in the old 1-255
-                        // range, so convert that here before the translation.
-                        final float brightnessInt =
-                                BrightnessSynchronizer.brightnessFloatToIntRange(brightness);
-
-                        if (BrightnessSynchronizer.floatEquals(
-                                brightnessInt, PowerManager.BRIGHTNESS_OFF)) {
-                            return PowerManager.BRIGHTNESS_OFF_FLOAT;
-                        }
-
-                        final float nits = mSystemBrightnessToNits.interpolate(brightnessInt);
-                        final float halBrightness = mNitsToHalBrightness.interpolate(nits);
-                        return halBrightness;
+                    private float brightnessToBacklight(float brightness) {
+                        return getDisplayDeviceConfig().getBacklightFromBrightness(brightness);
                     }
                 };
             }
@@ -877,10 +848,12 @@
                 SurfaceControl.DesiredDisplayModeSpecs modeSpecs) {
             // Do not lock when calling these SurfaceControl methods because they are sync
             // operations that may block for a while when setting display power mode.
-            SurfaceControl.setDesiredDisplayModeSpecs(displayToken, modeSpecs);
-            final int activeMode = SurfaceControl.getActiveDisplayMode(displayToken);
+            mSurfaceControlProxy.setDesiredDisplayModeSpecs(displayToken, modeSpecs);
+
+            final int sfActiveModeId = mSurfaceControlProxy
+                    .getDynamicDisplayInfo(displayToken).activeDisplayModeId;
             synchronized (getSyncRoot()) {
-                if (updateActiveModeLocked(activeMode)) {
+                if (updateActiveModeLocked(sfActiveModeId)) {
                     updateDeviceInfoLocked();
                 }
             }
@@ -891,8 +864,8 @@
             updateDeviceInfoLocked();
         }
 
-        public void onActiveDisplayModeChangedLocked(int modeId) {
-            if (updateActiveModeLocked(modeId)) {
+        public void onActiveDisplayModeChangedLocked(int sfModeId) {
+            if (updateActiveModeLocked(sfModeId)) {
                 updateDeviceInfoLocked();
             }
         }
@@ -904,15 +877,15 @@
             }
         }
 
-        public boolean updateActiveModeLocked(int activeModeId) {
-            if (mActiveDisplayModeId == activeModeId) {
+        public boolean updateActiveModeLocked(int activeSfModeId) {
+            if (mActiveSfDisplayMode.id == activeSfModeId) {
                 return false;
             }
-            mActiveDisplayModeId = activeModeId;
-            mActiveModeId = findMatchingModeIdLocked(activeModeId);
+            mActiveSfDisplayMode = getModeById(mSfDisplayModes, activeSfModeId);
+            mActiveModeId = findMatchingModeIdLocked(activeSfModeId);
             if (mActiveModeId == NO_DISPLAY_MODE_ID) {
                 Slog.w(TAG, "In unknown mode after setting allowed modes"
-                        + ", activeModeId=" + mActiveDisplayModeId);
+                        + ", activeModeId=" + activeSfModeId);
             }
             return true;
         }
@@ -946,7 +919,7 @@
         private void requestColorModeAsync(IBinder displayToken, int colorMode) {
             // Do not lock when calling this SurfaceControl method because it is a sync operation
             // that may block for a while when setting display power mode.
-            SurfaceControl.setActiveColorMode(displayToken, colorMode);
+            mSurfaceControlProxy.setActiveColorMode(displayToken, colorMode);
             synchronized (getSyncRoot()) {
                 updateDeviceInfoLocked();
             }
@@ -966,7 +939,7 @@
                 return;
             }
 
-            SurfaceControl.setAutoLowLatencyMode(getDisplayTokenLocked(), on);
+            mSurfaceControlProxy.setAutoLowLatencyMode(getDisplayTokenLocked(), on);
         }
 
         @Override
@@ -983,7 +956,7 @@
                 return;
             }
 
-            SurfaceControl.setGameContentType(getDisplayTokenLocked(), on);
+            mSurfaceControlProxy.setGameContentType(getDisplayTokenLocked(), on);
         }
 
         @Override
@@ -992,7 +965,6 @@
             pw.println("mPhysicalDisplayId=" + mPhysicalDisplayId);
             pw.println("mDisplayModeSpecs={" + mDisplayModeSpecs + "}");
             pw.println("mDisplayModeSpecsInvalid=" + mDisplayModeSpecsInvalid);
-            pw.println("mActiveDisplayModeId=" + mActiveDisplayModeId);
             pw.println("mActiveModeId=" + mActiveModeId);
             pw.println("mActiveColorMode=" + mActiveColorMode);
             pw.println("mDefaultModeId=" + mDefaultModeId);
@@ -1003,11 +975,12 @@
             pw.println("mAllmRequested=" + mAllmRequested);
             pw.println("mGameContentTypeSupported=" + mGameContentTypeSupported);
             pw.println("mGameContentTypeRequested=" + mGameContentTypeRequested);
-            pw.println("mDisplayInfo=" + mDisplayInfo);
-            pw.println("mDisplayModes=");
-            for (int i = 0; i < mDisplayModes.length; i++) {
-                pw.println("  " + mDisplayModes[i]);
+            pw.println("mStaticDisplayInfo=" + mStaticDisplayInfo);
+            pw.println("mSfDisplayModes=");
+            for (int i = 0; i < mSfDisplayModes.length; i++) {
+                pw.println("  " + mSfDisplayModes[i]);
             }
+            pw.println("mActiveSfDisplayMode=" + mActiveSfDisplayMode);
             pw.println("mSupportedModes=");
             for (int i = 0; i < mSupportedModes.size(); i++) {
                 pw.println("  " + mSupportedModes.valueAt(i));
@@ -1020,17 +993,16 @@
             int matchingModeId = SurfaceControl.DisplayMode.INVALID_DISPLAY_MODE_ID;
             DisplayModeRecord record = mSupportedModes.get(modeId);
             if (record != null) {
-                for (int i = 0; i < mDisplayModes.length; i++) {
-                    SurfaceControl.DisplayMode mode = mDisplayModes[i];
+                for (SurfaceControl.DisplayMode mode : mSfDisplayModes) {
                     if (record.hasMatchingMode(mode)) {
                         if (matchingModeId
                                 == SurfaceControl.DisplayMode.INVALID_DISPLAY_MODE_ID) {
-                            matchingModeId = i;
+                            matchingModeId = mode.id;
                         }
 
                         // Prefer to return a mode that matches the modeGroup
                         if (mode.group == modeGroup) {
-                            return i;
+                            return mode.id;
                         }
                     }
                 }
@@ -1038,12 +1010,12 @@
             return matchingModeId;
         }
 
-        private int findMatchingModeIdLocked(int modeId) {
-            if (modeId < 0 || modeId >= mDisplayModes.length) {
-                Slog.e(TAG, "Invalid display config index " + modeId);
+        private int findMatchingModeIdLocked(int sfModeId) {
+            SurfaceControl.DisplayMode mode = getModeById(mSfDisplayModes, sfModeId);
+            if (mode == null) {
+                Slog.e(TAG, "Invalid display mode ID " + sfModeId);
                 return NO_DISPLAY_MODE_ID;
             }
-            SurfaceControl.DisplayMode mode = mDisplayModes[modeId];
             for (int i = 0; i < mSupportedModes.size(); i++) {
                 DisplayModeRecord record = mSupportedModes.valueAt(i);
                 if (record.hasMatchingMode(mode)) {
@@ -1128,6 +1100,9 @@
         public void setDisplayEventListenerLocked(Looper looper, DisplayEventListener listener) {
             mReceiver = new ProxyDisplayEventReceiver(looper, listener);
         }
+        public SurfaceControlProxy getSurfaceControlProxy() {
+            return new SurfaceControlProxy();
+        }
     }
 
     public interface DisplayEventListener {
@@ -1219,24 +1194,79 @@
         }
     }
 
+    @VisibleForTesting
+    static class SurfaceControlProxy {
+        public SurfaceControl.DynamicDisplayInfo getDynamicDisplayInfo(IBinder token) {
+            return SurfaceControl.getDynamicDisplayInfo(token);
+        }
+
+        public long[] getPhysicalDisplayIds() {
+            return SurfaceControl.getPhysicalDisplayIds();
+        }
+
+        public IBinder getPhysicalDisplayToken(long physicalDisplayId) {
+            return SurfaceControl.getPhysicalDisplayToken(physicalDisplayId);
+        }
+
+        public SurfaceControl.StaticDisplayInfo getStaticDisplayInfo(IBinder displayToken) {
+            return SurfaceControl.getStaticDisplayInfo(displayToken);
+        }
+
+        public SurfaceControl.DesiredDisplayModeSpecs getDesiredDisplayModeSpecs(
+                IBinder displayToken) {
+            return SurfaceControl.getDesiredDisplayModeSpecs(displayToken);
+        }
+
+        public boolean setDesiredDisplayModeSpecs(IBinder token,
+                SurfaceControl.DesiredDisplayModeSpecs specs) {
+            return SurfaceControl.setDesiredDisplayModeSpecs(token, specs);
+        }
+
+        public void setDisplayPowerMode(IBinder displayToken, int mode) {
+            SurfaceControl.setDisplayPowerMode(displayToken, mode);
+        }
+
+        public boolean setActiveColorMode(IBinder displayToken, int colorMode) {
+            return SurfaceControl.setActiveColorMode(displayToken, colorMode);
+        }
+
+        public void setAutoLowLatencyMode(IBinder displayToken, boolean on) {
+            SurfaceControl.setAutoLowLatencyMode(displayToken, on);
+
+        }
+
+        public void setGameContentType(IBinder displayToken, boolean on) {
+            SurfaceControl.setGameContentType(displayToken, on);
+        }
+
+        public boolean getDisplayBrightnessSupport(IBinder displayToken) {
+            return SurfaceControl.getDisplayBrightnessSupport(displayToken);
+        }
+
+        public boolean setDisplayBrightness(IBinder displayToken, float brightness) {
+            return SurfaceControl.setDisplayBrightness(displayToken, brightness);
+        }
+    }
+
     static class BacklightAdapter {
         private final IBinder mDisplayToken;
         private final LogicalLight mBacklight;
         private final boolean mUseSurfaceControlBrightness;
+        private final SurfaceControlProxy mSurfaceControlProxy;
 
         private boolean mForceSurfaceControl = false;
 
         /**
          * @param displayToken Token for display associated with this backlight.
          * @param isDefaultDisplay {@code true} if it is the default display.
-         * @param forceSurfaceControl {@code true} if brightness should always be
-         *                            set via SurfaceControl API.
          */
-        BacklightAdapter(IBinder displayToken, boolean isDefaultDisplay) {
+        BacklightAdapter(IBinder displayToken, boolean isDefaultDisplay,
+                SurfaceControlProxy surfaceControlProxy) {
             mDisplayToken = displayToken;
+            mSurfaceControlProxy = surfaceControlProxy;
 
-            mUseSurfaceControlBrightness =
-                    SurfaceControl.getDisplayBrightnessSupport(mDisplayToken);
+            mUseSurfaceControlBrightness = mSurfaceControlProxy
+                    .getDisplayBrightnessSupport(mDisplayToken);
 
             if (!mUseSurfaceControlBrightness && isDefaultDisplay) {
                 LightsManager lights = LocalServices.getService(LightsManager.class);
@@ -1246,11 +1276,12 @@
             }
         }
 
-        void setBrightness(float brightness) {
+        // Set backlight within min and max backlight values
+        void setBacklight(float backlight) {
             if (mUseSurfaceControlBrightness || mForceSurfaceControl) {
-                SurfaceControl.setDisplayBrightness(mDisplayToken, brightness);
+                mSurfaceControlProxy.setDisplayBrightness(mDisplayToken, backlight);
             } else if (mBacklight != null) {
-                mBacklight.setBrightness(brightness);
+                mBacklight.setBrightness(backlight);
             }
         }
 
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index a054db5..a3ff534 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -17,7 +17,6 @@
 package com.android.server.display;
 
 import android.content.Context;
-import android.os.Process;
 import android.os.SystemProperties;
 import android.text.TextUtils;
 import android.util.IndentingPrintWriter;
@@ -143,10 +142,6 @@
         return null;
     }
 
-    public int[] getDisplayIdsLocked() {
-        return getDisplayIdsLocked(Process.SYSTEM_UID);
-    }
-
     public int[] getDisplayIdsLocked(int callingUid) {
         final int count = mLogicalDisplays.size();
         int[] displayIds = new int[count];
@@ -171,15 +166,6 @@
         }
     }
 
-    public int getDisplayGroupIdLocked(int displayId) {
-        final DisplayGroup displayGroup = mDisplayIdToGroupMap.get(displayId);
-        if (displayGroup != null) {
-            return displayGroup.getGroupId();
-        }
-
-        return -1;
-    }
-
     public DisplayGroup getDisplayGroupLocked(int groupId) {
         final int size = mDisplayIdToGroupMap.size();
         for (int i = 0; i < size; i++) {
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index 69943e3..330379c 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -281,7 +281,8 @@
                 List<OverlayMode> modes, int activeMode, int defaultMode,
                 float refreshRate, long presentationDeadlineNanos,
                 OverlayFlags flags, int state, SurfaceTexture surfaceTexture, int number) {
-            super(OverlayDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + number);
+            super(OverlayDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + number,
+                    getContext());
             mName = name;
             mRefreshRate = refreshRate;
             mDisplayPresentationDeadlineNanos = presentationDeadlineNanos;
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index ff4717b..52a810b 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -236,7 +236,7 @@
                 int ownerUid, String ownerPackageName, Surface surface, int flags,
                 Callback callback, String uniqueId, int uniqueIndex,
                 VirtualDisplayConfig virtualDisplayConfig) {
-            super(VirtualDisplayAdapter.this, displayToken, uniqueId);
+            super(VirtualDisplayAdapter.this, displayToken, uniqueId, getContext());
             mAppToken = appToken;
             mOwnerUid = ownerUid;
             mOwnerPackageName = ownerPackageName;
diff --git a/services/core/java/com/android/server/display/WifiDisplayAdapter.java b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
index 5732317..d2baaf22 100644
--- a/services/core/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
@@ -598,7 +598,8 @@
         public WifiDisplayDevice(IBinder displayToken, String name,
                 int width, int height, float refreshRate, int flags, String address,
                 Surface surface) {
-            super(WifiDisplayAdapter.this, displayToken, DISPLAY_NAME_PREFIX + address);
+            super(WifiDisplayAdapter.this, displayToken, DISPLAY_NAME_PREFIX + address,
+                    getContext());
             mName = name;
             mWidth = width;
             mHeight = height;
diff --git a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
index 09c0937..01e839d 100644
--- a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
+++ b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
@@ -41,7 +41,6 @@
 import com.android.internal.util.Preconditions;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
-import com.android.server.security.FileIntegrityService;
 import com.android.server.security.VerityUtils;
 
 import java.io.File;
@@ -226,7 +225,7 @@
     @Nullable
     private static UpdatableFontDir createUpdatableFontDir() {
         // If apk verity is supported, fs-verity should be available.
-        if (!FileIntegrityService.isApkVeritySupported()) return null;
+        if (!VerityUtils.isFsVeritySupported()) return null;
         return new UpdatableFontDir(new File(FONT_FILES_DIR),
                 Arrays.asList(new File(SystemFonts.SYSTEM_FONT_DIR),
                         new File(SystemFonts.OEM_FONT_DIR)),
diff --git a/services/core/java/com/android/server/graphics/fonts/PersistentSystemFontConfig.java b/services/core/java/com/android/server/graphics/fonts/PersistentSystemFontConfig.java
index d514aab..62337c7 100644
--- a/services/core/java/com/android/server/graphics/fonts/PersistentSystemFontConfig.java
+++ b/services/core/java/com/android/server/graphics/fonts/PersistentSystemFontConfig.java
@@ -46,7 +46,7 @@
     private static final String ATTR_VALUE = "value";
 
     /* package */ static class Config {
-        public long lastModifiedDate;
+        public long lastModifiedMillis;
         public final Set<String> updatedFontDirs = new ArraySet<>();
         public final List<FontConfig.FontFamily> fontFamilies = new ArrayList<>();
     }
@@ -73,7 +73,7 @@
             } else if (depth == 2) {
                 switch (tag) {
                     case TAG_LAST_MODIFIED_DATE:
-                        out.lastModifiedDate = parseLongAttribute(parser, ATTR_VALUE, 0);
+                        out.lastModifiedMillis = parseLongAttribute(parser, ATTR_VALUE, 0);
                         break;
                     case TAG_UPDATED_FONT_DIR:
                         out.updatedFontDirs.add(getAttribute(parser, ATTR_VALUE));
@@ -101,7 +101,7 @@
 
         out.startTag(null, TAG_ROOT);
         out.startTag(null, TAG_LAST_MODIFIED_DATE);
-        out.attribute(null, ATTR_VALUE, Long.toString(config.lastModifiedDate));
+        out.attribute(null, ATTR_VALUE, Long.toString(config.lastModifiedMillis));
         out.endTag(null, TAG_LAST_MODIFIED_DATE);
         for (String dir : config.updatedFontDirs) {
             out.startTag(null, TAG_UPDATED_FONT_DIR);
diff --git a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
index 08ddc6d..86dbe86 100644
--- a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
+++ b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
@@ -112,7 +112,7 @@
     private final File mConfigFile;
     private final File mTmpConfigFile;
 
-    private long mLastModifiedDate;
+    private long mLastModifiedMillis;
     private int mConfigVersion = 1;
 
     /**
@@ -147,7 +147,7 @@
     /* package */ void loadFontFileMap() {
         mFontFileInfoMap.clear();
         mFontFamilyMap.clear();
-        mLastModifiedDate = 0;
+        mLastModifiedMillis = 0;
         boolean success = false;
         try {
             PersistentSystemFontConfig.Config config = new PersistentSystemFontConfig.Config();
@@ -157,7 +157,7 @@
                 Slog.e(TAG, "Failed to load config xml file", e);
                 return;
             }
-            mLastModifiedDate = config.lastModifiedDate;
+            mLastModifiedMillis = config.lastModifiedMillis;
 
             File[] dirs = mFilesDir.listFiles();
             if (dirs == null) return;
@@ -200,7 +200,7 @@
             if (!success) {
                 mFontFileInfoMap.clear();
                 mFontFamilyMap.clear();
-                mLastModifiedDate = 0;
+                mLastModifiedMillis = 0;
                 FileUtils.deleteContents(mFilesDir);
             }
         }
@@ -211,7 +211,7 @@
         FileUtils.deleteContents(mFilesDir);
         mFontFamilyMap.clear();
 
-        mLastModifiedDate = Instant.now().getEpochSecond();
+        mLastModifiedMillis = System.currentTimeMillis();
         try (FileOutputStream fos = new FileOutputStream(mConfigFile)) {
             PersistentSystemFontConfig.writeToXml(fos, createPersistentConfig());
         } catch (Exception e) {
@@ -231,7 +231,7 @@
         // Backup the mapping for rollback.
         ArrayMap<String, FontFileInfo> backupMap = new ArrayMap<>(mFontFileInfoMap);
         ArrayMap<String, FontConfig.FontFamily> backupFamilies = new ArrayMap<>(mFontFamilyMap);
-        long backupLastModifiedDate = mLastModifiedDate;
+        long backupLastModifiedDate = mLastModifiedMillis;
         boolean success = false;
         try {
             for (FontUpdateRequest request : requests) {
@@ -247,7 +247,7 @@
             }
 
             // Write config file.
-            mLastModifiedDate = Instant.now().getEpochSecond();
+            mLastModifiedMillis = Instant.now().getEpochSecond();
             try (FileOutputStream fos = new FileOutputStream(mTmpConfigFile)) {
                 PersistentSystemFontConfig.writeToXml(fos, createPersistentConfig());
             } catch (Exception e) {
@@ -269,7 +269,7 @@
                 mFontFileInfoMap.putAll(backupMap);
                 mFontFamilyMap.clear();
                 mFontFamilyMap.putAll(backupFamilies);
-                mLastModifiedDate = backupLastModifiedDate;
+                mLastModifiedMillis = backupLastModifiedDate;
             }
         }
     }
@@ -527,7 +527,7 @@
 
     private PersistentSystemFontConfig.Config createPersistentConfig() {
         PersistentSystemFontConfig.Config config = new PersistentSystemFontConfig.Config();
-        config.lastModifiedDate = mLastModifiedDate;
+        config.lastModifiedMillis = mLastModifiedMillis;
         for (FontFileInfo info : mFontFileInfoMap.values()) {
             config.updatedFontDirs.add(info.getRandomizedFontDir().getName());
         }
@@ -560,7 +560,7 @@
         // which will be used as a fallback font without being overridden.
         mergedFamilies.addAll(mFontFamilyMap.values());
         return new FontConfig(
-                mergedFamilies, config.getAliases(), mLastModifiedDate, mConfigVersion);
+                mergedFamilies, config.getAliases(), mLastModifiedMillis, mConfigVersion);
     }
 
     /* package */ int getConfigVersion() {
diff --git a/services/core/java/com/android/server/hdmi/DeviceSelectAction.java b/services/core/java/com/android/server/hdmi/DeviceSelectAction.java
index 86a8e36..983b6b5 100644
--- a/services/core/java/com/android/server/hdmi/DeviceSelectAction.java
+++ b/services/core/java/com/android/server/hdmi/DeviceSelectAction.java
@@ -100,9 +100,9 @@
 
     @Override
     public boolean start() {
-        if (mIsCec20) {
-            sendSetStreamPath();
-        }
+      // Wake-up on <Set Stream Path> was not mandatory before CEC 2.0.
+      // The message is re-sent at the end of the action for devices that don't support 2.0.
+      sendSetStreamPath();
         int targetPowerStatus = localDevice().mService.getHdmiCecNetwork()
                 .getCecDeviceInfo(getTargetAddress()).getDevicePowerStatus();
         if (!mIsCec20 || targetPowerStatus == HdmiControlManager.POWER_STATUS_UNKNOWN) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecConfig.java b/services/core/java/com/android/server/hdmi/HdmiCecConfig.java
index f64efe7..624af30 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecConfig.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecConfig.java
@@ -39,6 +39,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ConcurrentUtils;
 import com.android.server.hdmi.cec.config.CecSettings;
 import com.android.server.hdmi.cec.config.Setting;
 import com.android.server.hdmi.cec.config.Value;
@@ -55,7 +56,9 @@
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map.Entry;
 import java.util.Set;
+import java.util.concurrent.Executor;
 
 import javax.xml.datatype.DatatypeConfigurationException;
 
@@ -99,7 +102,7 @@
     private final Object mLock = new Object();
 
     @GuardedBy("mLock")
-    private final ArrayMap<Setting, Set<SettingChangeListener>>
+    private final ArrayMap<Setting, ArrayMap<SettingChangeListener, Executor>>
             mSettingChangeListeners = new ArrayMap<>();
 
     private SettingsObserver mSettingsObserver;
@@ -292,7 +295,7 @@
             case HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED:
                 return STORAGE_GLOBAL_SETTINGS;
             case HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION:
-                return STORAGE_GLOBAL_SETTINGS;
+                return STORAGE_SHARED_PREFS;
             case HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE:
                 return STORAGE_GLOBAL_SETTINGS;
             case HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE:
@@ -329,7 +332,7 @@
             case HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED:
                 return Global.HDMI_CONTROL_ENABLED;
             case HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION:
-                return Global.HDMI_CEC_VERSION;
+                return setting.getName();
             case HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE:
                 return Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP;
             case HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE:
@@ -402,9 +405,6 @@
             case Global.HDMI_CONTROL_ENABLED:
                 notifySettingChanged(HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED);
                 break;
-            case Global.HDMI_CEC_VERSION:
-                notifySettingChanged(HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION);
-                break;
             case Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP:
                 notifySettingChanged(HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE);
                 break;
@@ -430,12 +430,20 @@
 
     private void notifySettingChanged(@NonNull Setting setting) {
         synchronized (mLock) {
-            Set<SettingChangeListener> listeners = mSettingChangeListeners.get(setting);
+            ArrayMap<SettingChangeListener, Executor> listeners =
+                    mSettingChangeListeners.get(setting);
             if (listeners == null) {
                 return;  // No listeners registered, do nothing.
             }
-            for (SettingChangeListener listener: listeners) {
-                listener.onChange(setting.getName());
+            for (Entry<SettingChangeListener, Executor> entry: listeners.entrySet()) {
+                SettingChangeListener listener = entry.getKey();
+                Executor executor = entry.getValue();
+                executor.execute(new Runnable() {
+                    @Override
+                    public void run() {
+                        listener.onChange(setting.getName());
+                    }
+                });
             }
         }
     }
@@ -450,7 +458,6 @@
         ContentResolver resolver = mContext.getContentResolver();
         String[] settings = new String[] {
                 Global.HDMI_CONTROL_ENABLED,
-                Global.HDMI_CEC_VERSION,
                 Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
                 Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED,
                 Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED,
@@ -471,10 +478,19 @@
     }
 
     /**
-     * Register change listener for a given setting name.
+     * Register change listener for a given setting name using DirectExecutor.
      */
     public void registerChangeListener(@NonNull @CecSettingName String name,
                                        SettingChangeListener listener) {
+        registerChangeListener(name, listener, ConcurrentUtils.DIRECT_EXECUTOR);
+    }
+
+    /**
+     * Register change listener for a given setting name and executor.
+     */
+    public void registerChangeListener(@NonNull @CecSettingName String name,
+                                       SettingChangeListener listener,
+                                       Executor executor) {
         Setting setting = getSetting(name);
         if (setting == null) {
             throw new IllegalArgumentException("Setting '" + name + "' does not exist.");
@@ -486,9 +502,9 @@
         }
         synchronized (mLock) {
             if (!mSettingChangeListeners.containsKey(setting)) {
-                mSettingChangeListeners.put(setting, new HashSet<>());
+                mSettingChangeListeners.put(setting, new ArrayMap<>());
             }
-            mSettingChangeListeners.get(setting).add(listener);
+            mSettingChangeListeners.get(setting).put(listener, executor);
         }
     }
 
@@ -503,7 +519,8 @@
         }
         synchronized (mLock) {
             if (mSettingChangeListeners.containsKey(setting)) {
-                Set<SettingChangeListener> listeners = mSettingChangeListeners.get(setting);
+                ArrayMap<SettingChangeListener, Executor> listeners =
+                        mSettingChangeListeners.get(setting);
                 listeners.remove(listener);
                 if (listeners.isEmpty()) {
                     mSettingChangeListeners.remove(setting);
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index fa1fb48..115cafed 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -108,6 +108,7 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.Executor;
 import java.util.stream.Collectors;
 
 /**
@@ -199,6 +200,13 @@
     public @interface WakeReason {
     }
 
+    private final Executor mServiceThreadExecutor = new Executor() {
+        @Override
+        public void execute(Runnable r) {
+            runOnServiceThread(r);
+        }
+    };
+
     // Logical address of the active source.
     @GuardedBy("mLock")
     protected final ActiveSource mActiveSource = new ActiveSource();
@@ -213,7 +221,7 @@
     private int mHdmiCecVolumeControl;
 
     // Make sure HdmiCecConfig is instantiated and the XMLs are read.
-    private final HdmiCecConfig mHdmiCecConfig;
+    private HdmiCecConfig mHdmiCecConfig;
 
     /**
      * Interface to report send result.
@@ -520,14 +528,14 @@
                                 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED);
                         setControlEnabled(enabled);
                     }
-                });
+                }, mServiceThreadExecutor);
         mHdmiCecConfig.registerChangeListener(HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
                 new HdmiCecConfig.SettingChangeListener() {
                     @Override
                     public void onChange(String setting) {
                         initializeCec(INITIATED_BY_ENABLE_CEC);
                     }
-                });
+                }, mServiceThreadExecutor);
         mHdmiCecConfig.registerChangeListener(
                 HdmiControlManager.CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY,
                 new HdmiCecConfig.SettingChangeListener() {
@@ -537,7 +545,7 @@
                             setCecOption(OptionKey.WAKEUP, tv().getAutoWakeup());
                         }
                     }
-                });
+                }, mServiceThreadExecutor);
     }
 
     private void bootCompleted() {
@@ -572,6 +580,11 @@
         mHdmiCecNetwork = hdmiCecNetwork;
     }
 
+    @VisibleForTesting
+    void setHdmiCecConfig(HdmiCecConfig hdmiCecConfig) {
+        mHdmiCecConfig = hdmiCecConfig;
+    }
+
     public HdmiCecNetwork getHdmiCecNetwork() {
         return mHdmiCecNetwork;
     }
@@ -774,8 +787,14 @@
 
     private void initializeCec(int initiatedBy) {
         mAddressAllocated = false;
-        mCecVersion = getHdmiCecConfig().getIntValue(
+        int settingsCecVersion = getHdmiCecConfig().getIntValue(
                 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION);
+        int supportedCecVersion = mCecController.getVersion();
+
+        // Limit the used CEC version to the highest supported version by HAL and selected
+        // version in settings (but at least v1.4b).
+        mCecVersion = Math.max(HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
+                Math.min(settingsCecVersion, supportedCecVersion));
 
         mCecController.setOption(OptionKey.SYSTEM_CEC_CONTROL, true);
         mCecController.setLanguage(mMenuLanguage);
@@ -2184,6 +2203,7 @@
 
             pw.println("mProhibitMode: " + mProhibitMode);
             pw.println("mPowerStatus: " + mPowerStatusController.getPowerStatus());
+            pw.println("mCecVersion: " + mCecVersion);
 
             // System settings
             pw.println("System_settings:");
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java b/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java
index ee3427f..a1e6136 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java
@@ -70,6 +70,10 @@
         pw.println("                --args <vendor specific arguments>");
         pw.println("                [--id <true if vendor command should be sent with vendor id>]");
         pw.println("      Send a Vendor Command to the given target device");
+        pw.println("  cec_setting get <setting name>");
+        pw.println("      Get the current value of a CEC setting");
+        pw.println("  cec_setting set <setting name> <value>");
+        pw.println("      Set the value of a CEC setting");
     }
 
     private int handleShellCommand(String cmd) throws RemoteException {
@@ -81,6 +85,8 @@
                 return oneTouchPlay(pw);
             case "vendorcommand":
                 return vendorCommand(pw);
+            case "cec_setting":
+                return cecSetting(pw);
         }
 
         getErrPrintWriter().println("Unhandled command: " + cmd);
@@ -157,4 +163,39 @@
         mBinderService.sendVendorCommand(deviceType, destination, params, hasVendorId);
         return 0;
     }
+
+    private int cecSetting(PrintWriter pw) throws RemoteException {
+        if (getRemainingArgsCount() < 1) {
+            throw new IllegalArgumentException("Expected at least 1 argument (operation).");
+        }
+        String operation = getNextArgRequired();
+        switch (operation) {
+            case "get": {
+                String setting = getNextArgRequired();
+                try {
+                    String value = mBinderService.getCecSettingStringValue(setting);
+                    pw.println(setting + " = " + value);
+                } catch (IllegalArgumentException e) {
+                    int intValue = mBinderService.getCecSettingIntValue(setting);
+                    pw.println(setting + " = " + intValue);
+                }
+                return 0;
+            }
+            case "set": {
+                String setting = getNextArgRequired();
+                String value = getNextArgRequired();
+                try {
+                    mBinderService.setCecSettingStringValue(setting, value);
+                    pw.println(setting + " = " + value);
+                } catch (IllegalArgumentException e) {
+                    int intValue = Integer.parseInt(value);
+                    mBinderService.setCecSettingIntValue(setting, intValue);
+                    pw.println(setting + " = " + intValue);
+                }
+                return 0;
+            }
+            default:
+                throw new IllegalArgumentException("Unknown operation: " + operation);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
index a7f34ed..4c4c978 100644
--- a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
+++ b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
@@ -259,7 +259,7 @@
     }
 
     private void mayDisableSystemAudioAndARC(int address) {
-        if (HdmiUtils.isEligibleAddressForDevice(HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM, address)) {
+        if (!HdmiUtils.isEligibleAddressForDevice(HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM, address)) {
             return;
         }
 
diff --git a/services/core/java/com/android/server/hdmi/cec_key_handling.md b/services/core/java/com/android/server/hdmi/cec_key_handling.md
index 1b41a67..69877be 100644
--- a/services/core/java/com/android/server/hdmi/cec_key_handling.md
+++ b/services/core/java/com/android/server/hdmi/cec_key_handling.md
@@ -1,36 +1,37 @@
 # CEC Key Handling
 
-The mapping of CEC key codes to Android key codes are at
-[HdmiCecKeycode](HdmiCecKeycode.java)
+The mapping of CEC keycodes to Android keycodes is done at [HdmiCecKeycode](HdmiCecKeycode.java).
 
 # Android TV
 
-Android TV requires special handling of some keys.
+Android TV (ATV) requires special handling of some keys.
 
-The general action for key handling is described in the table
+The general action for key handling is described in the table below.
 
 | Android Key | TV Panel                                               | OTT                        | Soundbar                                               |
 | ----------- | -----------------                                      | -------------------        | -------------------                                    |
-| general     | Send to active source                                  | handle on device           | handle on device                                       |
 | POWER       | Toggle the device power state  | Toggle the OTT power state, TV power state follows | Toggle the soundbar power state, TV power state follows|
 | TV_POWER    | Toggle the device power state  | Toggle the TV power state, OTT power state follows | Toggle the TV power state, soundbar power state follows|
 | HOME        | Turn on TV, Set active Source to TV, go to home screen | OTP, and go to home screen | OTP, and go to home screen                             |
-| volume keys | Handle on device or send to soundbar                   | Send to TV or soundbar     | Handle on device or send to TV                         |
+| Volume keys | Handle on device or send to soundbar                   | Send to TV or soundbar     | Handle on device or send to TV                         |
+| Other keys  | Forward to active source                               | Handle on device           | Handle on device                                       |
 
-Special cases and flags for each key are described below
+Special cases and flags per key are described below.
 
-## POWER
+## TV_POWER
 
 ### TV Panel
 
-TODO
+For ATV TV panel devices, TV_POWER is an alias of POWER.
 
-### OTT
+### Source Devices (OTT and Soundbar)
 
-TODO
+For ATV source devices with POWER_CONTROL_MODE set to none or CEC control disabled, TV_POWER is an alias of POWER.
 
-### Soundbar
+For all other source devices, TV_POWER toggles the TV power state and makes the OTT power state follow.
 
-TODO
+### Other Devices
+
+For any device that is not connected to a TV via HDMI and not an ATV device, TV_POWER is ignored.
 
 
diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
index bd577f3..016c5ed 100644
--- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
+++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
@@ -1052,6 +1052,9 @@
         public void onChange(boolean selfChange, Uri uri, @UserIdInt int userId) {
             if (verbose) Slog.v(mTag, "onChange(): uri=" + uri + ", userId=" + userId);
             final String property = uri.getLastPathSegment();
+            if (property == null) {
+                return;
+            }
             if (property.equals(getServiceSettingsProperty())
                     || property.equals(Settings.Secure.USER_SETUP_COMPLETE)) {
                 synchronized (mLock) {
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 4e97411..edb5d97 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -17,6 +17,7 @@
 package com.android.server.input;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -37,6 +38,7 @@
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.database.ContentObserver;
+import android.graphics.Rect;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayViewport;
 import android.hardware.input.IInputDevicesChangedListener;
@@ -50,6 +52,8 @@
 import android.hardware.input.InputSensorInfo;
 import android.hardware.input.KeyboardLayout;
 import android.hardware.input.TouchCalibration;
+import android.hardware.lights.Light;
+import android.hardware.lights.LightState;
 import android.media.AudioManager;
 import android.os.Binder;
 import android.os.Bundle;
@@ -69,6 +73,7 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.VibrationEffect;
 import android.provider.DeviceConfig;
@@ -168,6 +173,9 @@
     /** TODO(b/169067926): Remove this. */
     private static final boolean UNTRUSTED_TOUCHES_TOAST = false;
 
+    public static final boolean ENABLE_PER_WINDOW_INPUT_ROTATION =
+            SystemProperties.getBoolean("persist.debug.per_window_input_rotation", false);
+
     // Pointer to native input manager service object.
     private final long mPtr;
 
@@ -232,9 +240,21 @@
     // List of vibrator states by device id.
     @GuardedBy("mVibratorLock")
     private final SparseBooleanArray mIsVibrating = new SparseBooleanArray();
+    private Object mLightLock = new Object();
+    // State for light tokens. A light token marks a lights manager session, it is generated
+    // by light session open() and deleted in session close().
+    // When lights session requests light states, the token will be used to find the light session.
+    @GuardedBy("mLightLock")
+    private final ArrayMap<IBinder, LightSession> mLightSessions =
+            new ArrayMap<IBinder, LightSession>();
 
     // State for lid switch
+    // Lock for the lid switch state. Held when triggering callbacks to guarantee lid switch events
+    // are delivered in order. For ex, when a new lid switch callback is registered the lock is held
+    // while the callback is processing the initial lid switch event which guarantees that any
+    // events that occur at the same time are delivered after the callback has returned.
     private final Object mLidSwitchLock = new Object();
+    @GuardedBy("mLidSwitchLock")
     private List<LidSwitchCallback> mLidSwitchCallbacks = new ArrayList<>();
 
     // State for the currently installed input filter.
@@ -298,6 +318,12 @@
     private static native int[] nativeGetVibratorIds(long ptr, int deviceId);
     private static native int nativeGetBatteryCapacity(long ptr, int deviceId);
     private static native int nativeGetBatteryStatus(long ptr, int deviceId);
+    private static native List<Light> nativeGetLights(long ptr, int deviceId);
+    private static native int nativeGetLightPlayerId(long ptr, int deviceId, int lightId);
+    private static native int nativeGetLightColor(long ptr, int deviceId, int lightId);
+    private static native void nativeSetLightPlayerId(long ptr, int deviceId, int lightId,
+            int playerId);
+    private static native void nativeSetLightColor(long ptr, int deviceId, int lightId, int color);
     private static native void nativeReloadKeyboardLayouts(long ptr);
     private static native void nativeReloadDeviceAliases(long ptr);
     private static native String nativeDump(long ptr);
@@ -382,9 +408,6 @@
     public static final int SW_CAMERA_LENS_COVER_BIT = 1 << SW_CAMERA_LENS_COVER;
     public static final int SW_MUTE_DEVICE_BIT = 1 << SW_MUTE_DEVICE;
 
-    /** Indicates an open state for the lid switch. */
-    public static final int SW_STATE_LID_OPEN = 0;
-
     /** Whether to use the dev/input/event or uevent subsystem for the audio jack. */
     final boolean mUseDevInputEventForAudioJack;
 
@@ -420,13 +443,18 @@
     }
 
     void registerLidSwitchCallbackInternal(@NonNull LidSwitchCallback callback) {
-        boolean lidOpen;
         synchronized (mLidSwitchLock) {
             mLidSwitchCallbacks.add(callback);
-            lidOpen = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY, SW_LID)
-                    == SW_STATE_LID_OPEN;
+
+            // Skip triggering the initial callback if the system is not yet ready as the switch
+            // state will be reported as KEY_STATE_UNKNOWN. The callback will be triggered in
+            // systemRunning().
+            if (mSystemReady) {
+                boolean lidOpen = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY, SW_LID)
+                        == KEY_STATE_UP;
+                callback.notifyLidSwitchChanged(0 /* whenNanos */, lidOpen);
+            }
         }
-        callback.notifyLidSwitchChanged(0 /* whenNanos */, lidOpen);
     }
 
     void unregisterLidSwitchCallbackInternal(@NonNull LidSwitchCallback callback) {
@@ -474,7 +502,18 @@
         }
         mNotificationManager = (NotificationManager)mContext.getSystemService(
                 Context.NOTIFICATION_SERVICE);
-        mSystemReady = true;
+
+        synchronized (mLidSwitchLock) {
+            mSystemReady = true;
+
+            // Send the initial lid switch state to any callback registered before the system was
+            // ready.
+            int switchState = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY, SW_LID);
+            for (int i = 0; i < mLidSwitchCallbacks.size(); i++) {
+                LidSwitchCallback callback = mLidSwitchCallbacks.get(i);
+                callback.notifyLidSwitchChanged(0 /* whenNanos */, switchState == KEY_STATE_UP);
+            }
+        }
 
         IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
         filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -518,8 +557,54 @@
         nativeReloadDeviceAliases(mPtr);
     }
 
+    /** Rotates CCW by `delta` 90-degree increments. */
+    private static void rotateBounds(Rect inOutBounds, int parentW, int parentH, int delta) {
+        int rdelta = ((delta % 4) + 4) % 4;
+        int origLeft = inOutBounds.left;
+        switch (rdelta) {
+            case 0:
+                return;
+            case 1:
+                inOutBounds.left = inOutBounds.top;
+                inOutBounds.top = parentW - inOutBounds.right;
+                inOutBounds.right = inOutBounds.bottom;
+                inOutBounds.bottom = parentW - origLeft;
+                return;
+            case 2:
+                inOutBounds.left = parentW - inOutBounds.right;
+                inOutBounds.right = parentW - origLeft;
+                return;
+            case 3:
+                inOutBounds.left = parentH - inOutBounds.bottom;
+                inOutBounds.bottom = inOutBounds.right;
+                inOutBounds.right = parentH - inOutBounds.top;
+                inOutBounds.top = origLeft;
+                return;
+        }
+    }
+
     private void setDisplayViewportsInternal(List<DisplayViewport> viewports) {
-        nativeSetDisplayViewports(mPtr, viewports.toArray(new DisplayViewport[0]));
+        final DisplayViewport[] vArray = new DisplayViewport[viewports.size()];
+        if (ENABLE_PER_WINDOW_INPUT_ROTATION) {
+            // Remove all viewport operations. They will be built-into the window transforms.
+            for (int i = viewports.size() - 1; i >= 0; --i) {
+                final DisplayViewport v = vArray[i] = viewports.get(i).makeCopy();
+                // deviceWidth/Height are apparently in "rotated" space, so flip them if needed.
+                if (v.orientation % 2 != 0) {
+                    final int dw = v.deviceWidth;
+                    v.deviceWidth = v.deviceHeight;
+                    v.deviceHeight = dw;
+                }
+                v.logicalFrame.set(0, 0, v.deviceWidth, v.deviceHeight);
+                v.physicalFrame.set(0, 0, v.deviceWidth, v.deviceHeight);
+                v.orientation = 0;
+            }
+        } else {
+            for (int i = viewports.size() - 1; i >= 0; --i) {
+                vArray[i] = viewports.get(i);
+            }
+        }
+        nativeSetDisplayViewports(mPtr, vArray);
     }
 
     /**
@@ -2246,6 +2331,151 @@
         }
     }
 
+    /**
+     * LightSession represents a light session for lights manager.
+     */
+    private final class LightSession implements DeathRecipient {
+        private final int mDeviceId;
+        private final IBinder mToken;
+        private final String mOpPkg;
+        // The light ids and states that are requested by the light seesion
+        private int[] mLightIds;
+        private LightState[] mLightStates;
+
+        LightSession(int deviceId, String opPkg, IBinder token) {
+            mDeviceId = deviceId;
+            mOpPkg = opPkg;
+            mToken = token;
+        }
+
+        @Override
+        public void binderDied() {
+            if (DEBUG) {
+                Slog.d(TAG, "Light token died.");
+            }
+            synchronized (mLightLock) {
+                closeLightSession(mDeviceId, mToken);
+                mLightSessions.remove(mToken);
+            }
+        }
+    }
+
+    /**
+     * Returns the lights available for apps to control on the specified input device.
+     * Only lights that aren't reserved for system use are available to apps.
+     */
+    @Override // Binder call
+    public List<Light> getLights(int deviceId) {
+        return nativeGetLights(mPtr, deviceId);
+    }
+
+    /**
+     * Set specified light state with for a specific input device.
+     */
+    private void setLightStateInternal(int deviceId, Light light, LightState lightState) {
+        Preconditions.checkNotNull(light, "light does not exist");
+        if (DEBUG) {
+            Slog.d(TAG, "setLightStateInternal device " + deviceId + " light " + light
+                    + "lightState " + lightState);
+        }
+        if (light.getType() == Light.LIGHT_TYPE_INPUT_PLAYER_ID) {
+            nativeSetLightPlayerId(mPtr, deviceId, light.getId(), lightState.getPlayerId());
+        } else if (light.getType() == Light.LIGHT_TYPE_INPUT_SINGLE
+                || light.getType() == Light.LIGHT_TYPE_INPUT_RGB) {
+            // Set ARGB format color to input device light
+            // Refer to https://developer.android.com/reference/kotlin/android/graphics/Color
+            nativeSetLightColor(mPtr, deviceId, light.getId(), lightState.getColor());
+        } else {
+            Slog.e(TAG, "setLightStates for unsupported light type " + light.getType());
+        }
+    }
+
+    /**
+     * Set multiple light states with multiple light ids for a specific input device.
+     */
+    private void setLightStatesInternal(int deviceId, int[] lightIds, LightState[] lightStates) {
+        final List<Light> lights = nativeGetLights(mPtr, deviceId);
+        SparseArray<Light> lightArray = new SparseArray<>();
+        for (int i = 0; i < lights.size(); i++) {
+            lightArray.put(lights.get(i).getId(), lights.get(i));
+        }
+        for (int i = 0; i < lightIds.length; i++) {
+            if (lightArray.contains(lightIds[i])) {
+                setLightStateInternal(deviceId, lightArray.get(lightIds[i]), lightStates[i]);
+            }
+        }
+    }
+
+    /**
+     * Set states for multiple lights for an opened light session.
+     */
+    @Override
+    public void setLightStates(int deviceId, int[] lightIds, LightState[] lightStates,
+            IBinder token) {
+        Preconditions.checkArgument(lightIds.length == lightStates.length,
+                "lights and light states are not same length");
+        synchronized (mLightLock) {
+            LightSession lightSession = mLightSessions.get(token);
+            Preconditions.checkArgument(lightSession != null, "not registered");
+            Preconditions.checkState(lightSession.mDeviceId == deviceId, "Incorrect device ID");
+            lightSession.mLightIds = lightIds.clone();
+            lightSession.mLightStates = lightStates.clone();
+            if (DEBUG) {
+                Slog.d(TAG, "setLightStates for " + lightSession.mOpPkg + " device " + deviceId);
+            }
+        }
+        setLightStatesInternal(deviceId, lightIds, lightStates);
+    }
+
+    @Override
+    public @Nullable LightState getLightState(int deviceId, int lightId) {
+        synchronized (mLightLock) {
+            int color = nativeGetLightColor(mPtr, deviceId, lightId);
+            int playerId = nativeGetLightPlayerId(mPtr, deviceId, lightId);
+
+            return new LightState(color, playerId);
+        }
+    }
+
+    @Override
+    public void openLightSession(int deviceId, String opPkg, IBinder token) {
+        Preconditions.checkNotNull(token);
+        synchronized (mLightLock) {
+            Preconditions.checkState(mLightSessions.get(token) == null, "already registered");
+            LightSession lightSession = new LightSession(deviceId, opPkg, token);
+            try {
+                token.linkToDeath(lightSession, 0);
+            } catch (RemoteException ex) {
+                // give up
+                ex.rethrowAsRuntimeException();
+            }
+            mLightSessions.put(token, lightSession);
+            if (DEBUG) {
+                Slog.d(TAG, "Open light session for " + opPkg + " device " + deviceId);
+            }
+        }
+    }
+
+    @Override
+    public void closeLightSession(int deviceId, IBinder token) {
+        Preconditions.checkNotNull(token);
+        synchronized (mLightLock) {
+            LightSession lightSession = mLightSessions.get(token);
+            Preconditions.checkState(lightSession != null, "not registered");
+            // Turn off the lights that were previously requested by the session to be closed.
+            Arrays.fill(lightSession.mLightStates, new LightState(0));
+            setLightStatesInternal(deviceId, lightSession.mLightIds,
+                    lightSession.mLightStates);
+            mLightSessions.remove(token);
+            // If any other session is still pending with light request, apply the first session's
+            // request.
+            if (!mLightSessions.isEmpty()) {
+                LightSession nextSession = mLightSessions.valueAt(0);
+                setLightStatesInternal(deviceId, nextSession.mLightIds, nextSession.mLightStates);
+            }
+        }
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
@@ -2331,14 +2561,13 @@
 
         if ((switchMask & SW_LID_BIT) != 0) {
             final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0);
-
-            ArrayList<LidSwitchCallback> callbacksCopy;
             synchronized (mLidSwitchLock) {
-                callbacksCopy = new ArrayList<>(mLidSwitchCallbacks);
-            }
-            for (int i = 0; i < callbacksCopy.size(); i++) {
-                LidSwitchCallback callbacks = callbacksCopy.get(i);
-                callbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
+                if (mSystemReady) {
+                    for (int i = 0; i < mLidSwitchCallbacks.size(); i++) {
+                        LidSwitchCallback callbacks = mLidSwitchCallbacks.get(i);
+                        callbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
+                    }
+                }
             }
         }
 
diff --git a/services/core/java/com/android/server/input/InputShellCommand.java b/services/core/java/com/android/server/input/InputShellCommand.java
index d08980c..720be82 100644
--- a/services/core/java/com/android/server/input/InputShellCommand.java
+++ b/services/core/java/com/android/server/input/InputShellCommand.java
@@ -29,6 +29,7 @@
 import android.view.ViewConfiguration;
 
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -199,6 +200,8 @@
                 runRoll(inputSource, displayId);
             }  else if ("motionevent".equals(arg)) {
                 runMotionEvent(inputSource, displayId);
+            } else if ("keycombination".equals(arg)) {
+                runKeyCombination(inputSource, displayId);
             } else {
                 handleDefaultCommands(arg);
             }
@@ -224,7 +227,7 @@
             out.println();
             out.println("The commands and default sources are:");
             out.println("      text <string> (Default: touchscreen)");
-            out.println("      keyevent [--longpress] <key code number or name> ..."
+            out.println("      keyevent [--longpress|--doubletap] <key code number or name> ..."
                     + " (Default: keyboard)");
             out.println("      tap <x> <y> (Default: touchscreen)");
             out.println("      swipe <x1> <y1> <x2> <y2> [duration(ms)]"
@@ -234,6 +237,8 @@
             out.println("      press (Default: trackball)");
             out.println("      roll <dx> <dy> (Default: trackball)");
             out.println("      motionevent <DOWN|UP|MOVE|CANCEL> <x> <y> (Default: touchscreen)");
+            out.println("      keycombination <key code 1> <key code 2> ..."
+                    + " (Default: keyboard)");
         }
     }
 
@@ -282,6 +287,14 @@
         final boolean longpress = "--longpress".equals(arg);
         if (longpress) {
             arg = getNextArgRequired();
+        } else {
+            final boolean doubleTap = "--doubletap".equals(arg);
+            if (doubleTap) {
+                arg = getNextArgRequired();
+                final int keycode = KeyEvent.keyCodeFromString(arg);
+                sendKeyDoubleTap(inputSource, keycode, displayId);
+                return;
+            }
         }
 
         do {
@@ -292,22 +305,32 @@
 
     private void sendKeyEvent(int inputSource, int keyCode, boolean longpress, int displayId) {
         final long now = SystemClock.uptimeMillis();
-        int repeatCount = 0;
 
-        KeyEvent event = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, repeatCount,
+        KeyEvent event = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0 /* repeatCount */,
                 0 /*metaState*/, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/, 0 /*flags*/,
                 inputSource);
         event.setDisplayId(displayId);
 
         injectKeyEvent(event);
         if (longpress) {
-            repeatCount++;
-            injectKeyEvent(KeyEvent.changeTimeRepeat(event, now, repeatCount,
+            // Some long press behavior would check the event time, we set a new event time here.
+            final long nextEventTime = now + ViewConfiguration.getGlobalActionKeyTimeout();
+            injectKeyEvent(KeyEvent.changeTimeRepeat(event, nextEventTime, 1 /* repeatCount */,
                     KeyEvent.FLAG_LONG_PRESS));
         }
         injectKeyEvent(KeyEvent.changeAction(event, KeyEvent.ACTION_UP));
     }
 
+    private void sendKeyDoubleTap(int inputSource, int keyCode, int displayId) {
+        sendKeyEvent(inputSource, keyCode, false, displayId);
+        try {
+            Thread.sleep(ViewConfiguration.getDoubleTapMinTime());
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        sendKeyEvent(inputSource, keyCode, false, displayId);
+    }
+
     private void runTap(int inputSource, int displayId) {
         inputSource = getSource(inputSource, InputDevice.SOURCE_TOUCHSCREEN);
         sendTap(inputSource, Float.parseFloat(getNextArgRequired()),
@@ -440,4 +463,59 @@
         final long now = SystemClock.uptimeMillis();
         injectMotionEvent(inputSource, action, now, now, x, y, pressure, displayId);
     }
+
+    private void runKeyCombination(int inputSource, int displayId) {
+        String arg = getNextArgRequired();
+        ArrayList<Integer> keyCodes = new ArrayList<>();
+
+        while (arg != null) {
+            final int keyCode = KeyEvent.keyCodeFromString(arg);
+            if (keyCode == KeyEvent.KEYCODE_UNKNOWN) {
+                throw new IllegalArgumentException("Unknown keycode: " + arg);
+            }
+            keyCodes.add(keyCode);
+            arg = getNextArg();
+        }
+
+        // At least 2 keys.
+        if (keyCodes.size() < 2) {
+            throw new IllegalArgumentException("keycombination requires at least 2 keycodes");
+        }
+
+        sendKeyCombination(inputSource, keyCodes, displayId);
+    }
+
+    private void injectKeyEventAsync(KeyEvent event) {
+        InputManager.getInstance().injectInputEvent(event,
+                InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
+    }
+
+    private void sendKeyCombination(int inputSource, ArrayList<Integer> keyCodes, int displayId) {
+        final long now = SystemClock.uptimeMillis();
+        final int count = keyCodes.size();
+        final KeyEvent[] events = new KeyEvent[count];
+        for (int i = 0; i < count; i++) {
+            final KeyEvent event = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCodes.get(i), 0,
+                    0 /*metaState*/, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/, 0 /*flags*/,
+                    inputSource);
+            event.setDisplayId(displayId);
+            events[i] = event;
+        }
+
+        for (KeyEvent event: events) {
+            // Use async inject so interceptKeyBeforeQueueing or interceptKeyBeforeDispatching could
+            // handle keys.
+            injectKeyEventAsync(event);
+        }
+
+        try {
+            Thread.sleep(ViewConfiguration.getTapTimeout());
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+
+        for (KeyEvent event: events) {
+            injectKeyEventAsync(KeyEvent.changeAction(event, KeyEvent.ACTION_UP));
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/input/OWNERS b/services/core/java/com/android/server/input/OWNERS
index 0313a40..82c6ee1 100644
--- a/services/core/java/com/android/server/input/OWNERS
+++ b/services/core/java/com/android/server/input/OWNERS
@@ -1,2 +1,3 @@
+lzye@google.com
 michaelwr@google.com
 svv@google.com
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 0754df0..d41f4c7 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -3646,12 +3646,9 @@
                         hideCurrentInputLocked(mCurFocusedWindow, 0, null,
                                 SoftInputShowHideReason.HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR);
                     }
-                    res = startInputUncheckedLocked(cs, inputContext, missingMethods, attribute,
-                            startInputFlags, startInputReason);
-                } else {
-                    res = startInputUncheckedLocked(cs, inputContext, missingMethods, attribute,
-                            startInputFlags, startInputReason);
                 }
+                res = startInputUncheckedLocked(cs, inputContext, missingMethods, attribute,
+                        startInputFlags, startInputReason);
             } else {
                 res = InputBindResult.NULL_EDITOR_INFO;
             }
@@ -5412,37 +5409,38 @@
         @BinderThread
         @ShellCommandResult
         private int onCommandWithSystemIdentity(@Nullable String cmd) {
-            if ("get-last-switch-user-id".equals(cmd)) {
-                return mService.getLastSwitchUserId(this);
-            }
-
-            // For existing "adb shell ime <command>".
-            if ("ime".equals(cmd)) {
-                final String imeCommand = getNextArg();
-                if (imeCommand == null || "help".equals(imeCommand) || "-h".equals(imeCommand)) {
-                    onImeCommandHelp();
-                    return ShellCommandResult.SUCCESS;
+            switch (TextUtils.emptyIfNull(cmd)) {
+                case "get-last-switch-user-id":
+                    return mService.getLastSwitchUserId(this);
+                case "tracing":
+                    return mService.handleShellCommandTraceInputMethod(this);
+                case "ime": {  // For "adb shell ime <command>".
+                    final String imeCommand = TextUtils.emptyIfNull(getNextArg());
+                    switch (imeCommand) {
+                        case "":
+                        case "-h":
+                        case "help":
+                            return onImeCommandHelp();
+                        case "list":
+                            return mService.handleShellCommandListInputMethods(this);
+                        case "enable":
+                            return mService.handleShellCommandEnableDisableInputMethod(this, true);
+                        case "disable":
+                            return mService.handleShellCommandEnableDisableInputMethod(this, false);
+                        case "set":
+                            return mService.handleShellCommandSetInputMethod(this);
+                        case "reset":
+                            return mService.handleShellCommandResetInputMethod(this);
+                        case "tracing":  // TODO(b/180765389): Unsupport "adb shell ime tracing"
+                            return mService.handleShellCommandTraceInputMethod(this);
+                        default:
+                            getOutPrintWriter().println("Unknown command: " + imeCommand);
+                            return ShellCommandResult.FAILURE;
+                    }
                 }
-                switch (imeCommand) {
-                    case "list":
-                        return mService.handleShellCommandListInputMethods(this);
-                    case "enable":
-                        return mService.handleShellCommandEnableDisableInputMethod(this, true);
-                    case "disable":
-                        return mService.handleShellCommandEnableDisableInputMethod(this, false);
-                    case "set":
-                        return mService.handleShellCommandSetInputMethod(this);
-                    case "reset":
-                        return mService.handleShellCommandResetInputMethod(this);
-                    case "tracing":
-                        return mService.handleShellCommandTraceInputMethod(this);
-                    default:
-                        getOutPrintWriter().println("Unknown command: " + imeCommand);
-                        return ShellCommandResult.FAILURE;
-                }
+                default:
+                    return handleDefaultCommands(cmd);
             }
-
-            return handleDefaultCommands(cmd);
         }
 
         @BinderThread
@@ -5456,10 +5454,16 @@
                 pw.println("    Synonym of dumpsys.");
                 pw.println("  ime <command> [options]");
                 pw.println("    Manipulate IMEs.  Run \"ime help\" for details.");
+                pw.println("  tracing <command>");
+                pw.println("    start: Start tracing.");
+                pw.println("    stop : Stop tracing.");
+                pw.println("    help : Show help.");
             }
         }
 
-        private void onImeCommandHelp() {
+        @BinderThread
+        @ShellCommandResult
+        private int onImeCommandHelp() {
             try (IndentingPrintWriter pw =
                          new IndentingPrintWriter(getOutPrintWriter(), "  ", 100)) {
                 pw.println("ime <command>:");
@@ -5514,6 +5518,7 @@
 
                 pw.decreaseIndent();
             }
+            return ShellCommandResult.SUCCESS;
         }
     }
 
diff --git a/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java b/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java
index 7b400b6..6ea4bd2 100644
--- a/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java
+++ b/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java
@@ -17,7 +17,6 @@
 package com.android.server.location;
 
 import android.annotation.Nullable;
-import android.content.ComponentName;
 import android.content.Context;
 import android.hardware.location.ActivityRecognitionHardware;
 import android.hardware.location.IActivityRecognitionHardwareClient;
@@ -27,6 +26,7 @@
 import android.util.Log;
 
 import com.android.server.ServiceWatcher;
+import com.android.server.ServiceWatcher.BoundService;
 
 /**
  * Proxy class to bind GmsCore to the ActivityRecognitionHardware.
@@ -82,7 +82,7 @@
         return resolves;
     }
 
-    private void onBind(IBinder binder, ComponentName service) throws RemoteException {
+    private void onBind(IBinder binder, BoundService service) throws RemoteException {
         String descriptor = binder.getInterfaceDescriptor();
 
         if (IActivityRecognitionHardwareWatcher.class.getCanonicalName().equals(descriptor)) {
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index 6deb19a..2920ddb 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -52,6 +52,7 @@
 import android.location.GnssMeasurementCorrections;
 import android.location.GnssMeasurementRequest;
 import android.location.IGeocodeListener;
+import android.location.IGnssAntennaInfoListener;
 import android.location.IGnssMeasurementsListener;
 import android.location.IGnssNavigationMessageListener;
 import android.location.IGnssNmeaListener;
@@ -63,6 +64,7 @@
 import android.location.Location;
 import android.location.LocationManager;
 import android.location.LocationManagerInternal;
+import android.location.LocationManagerInternal.OnProviderLocationTagsChangeListener;
 import android.location.LocationProvider;
 import android.location.LocationRequest;
 import android.location.LocationTime;
@@ -70,6 +72,7 @@
 import android.location.provider.ProviderProperties;
 import android.location.util.identity.CallerIdentity;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.ICancellationSignal;
 import android.os.ParcelFileDescriptor;
@@ -81,6 +84,7 @@
 import android.provider.Settings;
 import android.stats.location.LocationStatsEnums;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.IndentingPrintWriter;
 import android.util.Log;
 
@@ -251,9 +255,12 @@
 
     // @GuardedBy("mProviderManagers")
     // hold lock for writes, no lock necessary for simple reads
-    private final CopyOnWriteArrayList<LocationProviderManager> mProviderManagers =
+    final CopyOnWriteArrayList<LocationProviderManager> mProviderManagers =
             new CopyOnWriteArrayList<>();
 
+    @GuardedBy("mLock")
+    private @Nullable OnProviderLocationTagsChangeListener mOnProviderLocationTagsChangeListener;
+
     LocationManagerService(Context context, Injector injector, LocationEventLog eventLog) {
         mContext = context.createAttributionContext(ATTRIBUTION_TAG);
         mInjector = injector;
@@ -283,7 +290,7 @@
     }
 
     @Nullable
-    private LocationProviderManager getLocationProviderManager(String providerName) {
+    LocationProviderManager getLocationProviderManager(String providerName) {
         if (providerName == null) {
             return null;
         }
@@ -318,8 +325,9 @@
             Preconditions.checkState(getLocationProviderManager(manager.getName()) == null);
 
             manager.startManager();
+            manager.setOnProviderLocationTagsChangeListener(
+                    mOnProviderLocationTagsChangeListener);
             if (realProvider != null) {
-
                 // custom logic wrapping all non-passive providers
                 if (manager != mPassiveManager) {
                     boolean enableStationaryThrottling = Settings.Global.getInt(
@@ -330,7 +338,6 @@
                                 mInjector, realProvider, mEventLog);
                     }
                 }
-
                 manager.setRealProvider(realProvider);
             }
             mProviderManagers.add(manager);
@@ -350,6 +357,22 @@
     void onSystemReady() {
         mInjector.getSettingsHelper().addOnLocationEnabledChangedListener(
                 this::onLocationModeChanged);
+
+        if (Build.IS_DEBUGGABLE) {
+            // on debug builds, watch for location noteOps while location is off. there are some
+            // scenarios (emergency location) where this is expected, but generally this should
+            // rarely occur, and may indicate bugs. dump occurrences to logs for further evaluation
+            AppOpsManager appOps = Objects.requireNonNull(
+                    mContext.getSystemService(AppOpsManager.class));
+            appOps.startWatchingNoted(
+                    new int[]{AppOpsManager.OP_FINE_LOCATION, AppOpsManager.OP_COARSE_LOCATION},
+                    (code, uid, packageName, attributionTag, flags, result) -> {
+                        if (!isLocationEnabledForUser(UserHandle.getUserId(uid))) {
+                            Log.w(TAG, "location noteOp with location off - "
+                                    + CallerIdentity.forTest(uid, 0, packageName, attributionTag));
+                        }
+                    });
+        }
     }
 
     void onSystemThirdPartyAppsCanStart() {
@@ -439,8 +462,9 @@
                     .setPowerUsage(Integer.parseInt(fragments[8]))
                     .setAccuracy(Integer.parseInt(fragments[9]))
                     .build();
-            getOrAddLocationProviderManager(name).setMockProvider(
-                    new MockLocationProvider(properties, CallerIdentity.fromContext(mContext)));
+            final LocationProviderManager manager = getOrAddLocationProviderManager(name);
+            manager.setMockProvider(new MockLocationProvider(properties,
+                    CallerIdentity.fromContext(mContext), Collections.emptySet()));
         }
     }
 
@@ -479,7 +503,7 @@
 
     @Override
     public void startGnssBatch(long periodNanos, ILocationListener listener, String packageName,
-            String attributionTag, String listenerId) {
+            @Nullable String attributionTag, String listenerId) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
 
         if (mGnssManagerService == null) {
@@ -616,7 +640,7 @@
     @Nullable
     @Override
     public ICancellationSignal getCurrentLocation(String provider, LocationRequest request,
-            ILocationCallback consumer, String packageName, String attributionTag,
+            ILocationCallback consumer, String packageName, @Nullable String attributionTag,
             String listenerId) {
         CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag,
                 listenerId);
@@ -640,7 +664,7 @@
     @Override
     public void registerLocationListener(String provider, LocationRequest request,
             ILocationListener listener, String packageName, @Nullable String attributionTag,
-            @Nullable String listenerId) {
+            String listenerId) {
         CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag,
                 listenerId);
         int permissionLevel = LocationPermissions.getPermissionLevel(mContext, identity.getUid(),
@@ -791,7 +815,7 @@
 
     @Override
     public Location getLastLocation(String provider, LastLocationRequest request,
-            String packageName, String attributionTag) {
+            String packageName, @Nullable String attributionTag) {
         CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag);
         int permissionLevel = LocationPermissions.getPermissionLevel(mContext, identity.getUid(),
                 identity.getPid());
@@ -858,9 +882,10 @@
 
     @Override
     public void registerGnssStatusCallback(IGnssStatusListener listener, String packageName,
-            String attributionTag) {
+            @Nullable String attributionTag, String listenerId) {
         if (mGnssManagerService != null) {
-            mGnssManagerService.registerGnssStatusCallback(listener, packageName, attributionTag);
+            mGnssManagerService.registerGnssStatusCallback(listener, packageName, attributionTag,
+                    listenerId);
         }
     }
 
@@ -873,9 +898,10 @@
 
     @Override
     public void registerGnssNmeaCallback(IGnssNmeaListener listener, String packageName,
-            String attributionTag) {
+            @Nullable String attributionTag, String listenerId) {
         if (mGnssManagerService != null) {
-            mGnssManagerService.registerGnssNmeaCallback(listener, packageName, attributionTag);
+            mGnssManagerService.registerGnssNmeaCallback(listener, packageName, attributionTag,
+                    listenerId);
         }
     }
 
@@ -887,11 +913,12 @@
     }
 
     @Override
-    public void addGnssMeasurementsListener(@Nullable GnssMeasurementRequest request,
-            IGnssMeasurementsListener listener, String packageName, String attributionTag) {
+    public void addGnssMeasurementsListener(GnssMeasurementRequest request,
+            IGnssMeasurementsListener listener, String packageName, @Nullable String attributionTag,
+            String listenerId) {
         if (mGnssManagerService != null) {
             mGnssManagerService.addGnssMeasurementsListener(request, listener, packageName,
-                    attributionTag);
+                    attributionTag, listenerId);
         }
     }
 
@@ -904,6 +931,22 @@
     }
 
     @Override
+    public void addGnssAntennaInfoListener(IGnssAntennaInfoListener listener, String packageName,
+            @Nullable String attributionTag, String listenerId) {
+        if (mGnssManagerService != null) {
+            mGnssManagerService.addGnssAntennaInfoListener(listener, packageName, attributionTag,
+                    listenerId);
+        }
+    }
+
+    @Override
+    public void removeGnssAntennaInfoListener(IGnssAntennaInfoListener listener) {
+        if (mGnssManagerService != null) {
+            mGnssManagerService.removeGnssAntennaInfoListener(listener);
+        }
+    }
+
+    @Override
     public void addProviderRequestListener(IProviderRequestListener listener) {
         for (LocationProviderManager manager : mProviderManagers) {
             manager.addProviderRequestListener(listener);
@@ -937,10 +980,10 @@
 
     @Override
     public void addGnssNavigationMessageListener(IGnssNavigationMessageListener listener,
-            String packageName, String attributionTag) {
+            String packageName, @Nullable String attributionTag, String listenerId) {
         if (mGnssManagerService != null) {
             mGnssManagerService.addGnssNavigationMessageListener(listener, packageName,
-                    attributionTag);
+                    attributionTag, listenerId);
         }
     }
 
@@ -1127,15 +1170,16 @@
 
     @Override
     public void addTestProvider(String provider, ProviderProperties properties,
-            String packageName, String attributionTag) {
+            List<String> extraAttributionTags, String packageName, String attributionTag) {
         // unsafe is ok because app ops will verify the package name
         CallerIdentity identity = CallerIdentity.fromBinderUnsafe(packageName, attributionTag);
         if (!mInjector.getAppOpsHelper().noteOp(AppOpsManager.OP_MOCK_LOCATION, identity)) {
             return;
         }
 
-        getOrAddLocationProviderManager(provider).setMockProvider(
-                new MockLocationProvider(properties, identity));
+        final LocationProviderManager manager = getOrAddLocationProviderManager(provider);
+        manager.setMockProvider(new MockLocationProvider(properties, identity,
+                new ArraySet<>(extraAttributionTags)));
     }
 
     @Override
@@ -1268,13 +1312,13 @@
 
         ipw.println("Historical Aggregate Location Provider Data:");
         ipw.increaseIndent();
-        ArrayMap<String, ArrayMap<String, LocationEventLog.AggregateStats>> aggregateStats =
+        ArrayMap<String, ArrayMap<CallerIdentity, LocationEventLog.AggregateStats>> aggregateStats =
                 mEventLog.copyAggregateStats();
         for (int i = 0; i < aggregateStats.size(); i++) {
             ipw.print(aggregateStats.keyAt(i));
             ipw.println(":");
             ipw.increaseIndent();
-            ArrayMap<String, LocationEventLog.AggregateStats> providerStats =
+            ArrayMap<CallerIdentity, LocationEventLog.AggregateStats> providerStats =
                     aggregateStats.valueAt(i);
             for (int j = 0; j < providerStats.size(); j++) {
                 ipw.print(providerStats.keyAt(j));
@@ -1342,7 +1386,7 @@
                 if (provider != null && !provider.equals(manager.getName())) {
                     continue;
                 }
-                if (identity.equalsIgnoringListenerId(manager.getIdentity())) {
+                if (identity.equals(manager.getIdentity())) {
                     return true;
                 }
             }
@@ -1372,6 +1416,19 @@
 
             return new LocationTime(location.getTime(), location.getElapsedRealtimeNanos());
         }
+
+        @Override
+        public void setOnProviderLocationTagsChangeListener(
+                @Nullable OnProviderLocationTagsChangeListener listener) {
+            synchronized (mLock) {
+                mOnProviderLocationTagsChangeListener = listener;
+                final int providerCount = mProviderManagers.size();
+                for (int i = 0; i < providerCount; i++) {
+                    final LocationProviderManager manager = mProviderManagers.get(i);
+                    manager.setOnProviderLocationTagsChangeListener(listener);
+                }
+            }
+        }
     }
 
     private static class SystemInjector implements Injector {
diff --git a/services/core/java/com/android/server/location/LocationShellCommand.java b/services/core/java/com/android/server/location/LocationShellCommand.java
index f0dd8b5..5dc3ed8 100644
--- a/services/core/java/com/android/server/location/LocationShellCommand.java
+++ b/services/core/java/com/android/server/location/LocationShellCommand.java
@@ -26,6 +26,8 @@
 
 import java.io.PrintWriter;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -50,15 +52,11 @@
 
         switch (cmd) {
             case "is-location-enabled": {
-                int userId = parseUserId();
-                boolean enabled = mService.isLocationEnabledForUser(userId);
-                getOutPrintWriter().println(enabled);
+                handleIsLocationEnabled();
                 return 0;
             }
             case "set-location-enabled": {
-                int userId = parseUserId();
-                boolean enabled = Boolean.parseBoolean(getNextArgRequired());
-                mService.setLocationEnabledForUser(enabled, userId);
+                handleSetLocationEnabled();
                 return 0;
             }
             case "providers": {
@@ -73,36 +71,23 @@
     private int parseProvidersCommand(String cmd) {
         switch (cmd) {
             case "add-test-provider": {
-                String provider = getNextArgRequired();
-                ProviderProperties properties = parseTestProviderProviderProperties();
-                mService.addTestProvider(provider, properties, mContext.getOpPackageName(),
-                        mContext.getFeatureId());
+                handleAddTestProvider();
                 return 0;
             }
             case "remove-test-provider": {
-                String provider = getNextArgRequired();
-                mService.removeTestProvider(provider, mContext.getOpPackageName(),
-                        mContext.getFeatureId());
+                handleRemoveTestProvider();
                 return 0;
             }
             case "set-test-provider-enabled": {
-                String provider = getNextArgRequired();
-                boolean enabled = Boolean.parseBoolean(getNextArgRequired());
-                mService.setTestProviderEnabled(provider, enabled, mContext.getOpPackageName(),
-                        mContext.getFeatureId());
+                handleSetTestProviderEnabled();
                 return 0;
             }
             case "set-test-provider-location": {
-                String provider = getNextArgRequired();
-                Location location = parseTestProviderLocation(provider);
-                mService.setTestProviderLocation(provider, location, mContext.getOpPackageName(),
-                        mContext.getFeatureId());
+                handleSetTestProviderLocation();
                 return 0;
             }
             case "send-extra-command": {
-                String provider = getNextArgRequired();
-                String command = getNextArgRequired();
-                mService.sendExtraCommand(provider, command, null);
+                handleSendExtraCommand();
                 return 0;
             }
             default:
@@ -110,21 +95,47 @@
         }
     }
 
-    private int parseUserId() {
-        final String option = getNextOption();
-        if (option != null) {
-            if (option.equals("--user")) {
-                return UserHandle.parseUserArg(getNextArgRequired());
-            } else {
-                throw new IllegalArgumentException(
-                        "Expected \"--user\" option, but got \"" + option + "\" instead");
-            }
-        }
+    private void handleIsLocationEnabled() {
+        int userId = UserHandle.USER_CURRENT_OR_SELF;
 
-        return UserHandle.USER_CURRENT_OR_SELF;
+        do {
+            String option = getNextOption();
+            if (option == null) {
+                break;
+            }
+            if ("--user".equals(option)) {
+                userId = UserHandle.parseUserArg(getNextArgRequired());
+            } else {
+                throw new IllegalArgumentException("Unknown option: " + option);
+            }
+        } while (true);
+
+        getOutPrintWriter().println(mService.isLocationEnabledForUser(userId));
     }
 
-    private ProviderProperties parseTestProviderProviderProperties() {
+    private void handleSetLocationEnabled() {
+        boolean enabled = Boolean.parseBoolean(getNextArgRequired());
+
+        int userId = UserHandle.USER_CURRENT_OR_SELF;
+
+        do {
+            String option = getNextOption();
+            if (option == null) {
+                break;
+            }
+            if ("--user".equals(option)) {
+                userId = UserHandle.parseUserArg(getNextArgRequired());
+            } else {
+                throw new IllegalArgumentException("Unknown option: " + option);
+            }
+        } while (true);
+
+        mService.setLocationEnabledForUser(enabled, userId);
+    }
+
+    private void handleAddTestProvider() {
+        String provider = getNextArgRequired();
+
         boolean requiresNetwork = false;
         boolean requiresSatellite = false;
         boolean requiresCell = false;
@@ -135,8 +146,13 @@
         int powerRequirement = Criteria.POWER_LOW;
         int accuracy = Criteria.ACCURACY_FINE;
 
-        String option = getNextOption();
-        while (option != null) {
+        List<String> extraAttributionTags = Collections.emptyList();
+
+        do {
+            String option = getNextOption();
+            if (option == null) {
+                break;
+            }
             switch (option) {
                 case "--requiresNetwork": {
                     requiresNetwork = true;
@@ -174,12 +190,15 @@
                     accuracy = Integer.parseInt(getNextArgRequired());
                     break;
                 }
+                case "--extraAttributionTags": {
+                    extraAttributionTags = Arrays.asList(getNextArgRequired().split(","));
+                    break;
+                }
                 default:
                     throw new IllegalArgumentException(
                             "Received unexpected option: " + option);
             }
-            option = getNextOption();
-        }
+        } while(true);
 
         ProviderProperties properties = new ProviderProperties.Builder()
                 .setHasNetworkRequirement(requiresNetwork)
@@ -192,30 +211,50 @@
                 .setPowerUsage(powerRequirement)
                 .setAccuracy(accuracy)
                 .build();
-
-        return properties;
+        mService.addTestProvider(provider, properties, extraAttributionTags,
+                mContext.getOpPackageName(), mContext.getAttributionTag());
     }
 
-    private Location parseTestProviderLocation(String provider) {
-        boolean hasLatitude = false;
-        boolean hasLongitude = false;
+    private void handleRemoveTestProvider() {
+        String provider = getNextArgRequired();
+        mService.removeTestProvider(provider, mContext.getOpPackageName(),
+                mContext.getAttributionTag());
+    }
+
+    private void handleSetTestProviderEnabled() {
+        String provider = getNextArgRequired();
+        boolean enabled = Boolean.parseBoolean(getNextArgRequired());
+        mService.setTestProviderEnabled(provider, enabled, mContext.getOpPackageName(),
+                mContext.getAttributionTag());
+    }
+
+    private void handleSetTestProviderLocation() {
+        String provider = getNextArgRequired();
+
+        boolean hasLatLng = false;
 
         Location location = new Location(provider);
         location.setAccuracy(DEFAULT_TEST_LOCATION_ACCURACY);
         location.setTime(System.currentTimeMillis());
+        location.setElapsedRealtimeNanos(System.nanoTime());
 
-        String option = getNextOption();
-        while (option != null) {
+        do {
+            String option = getNextOption();
+            if (option == null) {
+                break;
+            }
             switch (option) {
                 case "--location": {
                     String[] locationInput = getNextArgRequired().split(",");
                     if (locationInput.length != 2) {
-                        throw new IllegalArgumentException(
-                                "Unexpected location format: " + Arrays.toString(locationInput));
+                        throw new IllegalArgumentException("Location argument must be in the form "
+                                + "of \"<LATITUDE>,<LONGITUDE>\", not "
+                                + Arrays.toString(locationInput));
                     }
 
                     location.setLatitude(Double.parseDouble(locationInput[0]));
                     location.setLongitude(Double.parseDouble(locationInput[1]));
+                    hasLatLng = true;
                     break;
                 }
                 case "--accuracy": {
@@ -227,15 +266,22 @@
                     break;
                 }
                 default:
-                    throw new IllegalArgumentException(
-                            "Received unexpected option: " + option);
+                    throw new IllegalArgumentException("Unknown option: " + option);
             }
-            option = getNextOption();
+        } while (true);
+
+        if (!hasLatLng) {
+            throw new IllegalArgumentException("Option \"--location\" is required");
         }
 
-        location.setElapsedRealtimeNanos(System.nanoTime());
+        mService.setTestProviderLocation(provider, location, mContext.getOpPackageName(),
+                mContext.getAttributionTag());
+    }
 
-        return location;
+    private void handleSendExtraCommand() {
+        String provider = getNextArgRequired();
+        String command = getNextArgRequired();
+        mService.sendExtraCommand(provider, command, null);
     }
 
     @Override
@@ -245,24 +291,29 @@
         pw.println("  help or -h");
         pw.println("    Print this help text.");
         pw.println("  is-location-enabled [--user <USER_ID>]");
-        pw.println("    Gets the master location switch enabled state.");
-        pw.println("  set-location-enabled [--user <USER_ID>] true|false");
-        pw.println("    Sets the master location switch enabled state.");
+        pw.println("    Gets the master location switch enabled state. If no user is specified,");
+        pw.println("    the current user is assumed.");
+        pw.println("  set-location-enabled true|false [--user <USER_ID>]");
+        pw.println("    Sets the master location switch enabled state. If no user is specified,");
+        pw.println("    the current user is assumed.");
         pw.println("  providers");
+        pw.println("    The providers command is followed by a subcommand, as listed below:");
+        pw.println();
         pw.println("    add-test-provider <PROVIDER> [--requiresNetwork] [--requiresSatellite]");
         pw.println("      [--requiresCell] [--hasMonetaryCost] [--supportsAltitude]");
         pw.println("      [--supportsSpeed] [--supportsBearing]");
         pw.println("      [--powerRequirement <POWER_REQUIREMENT>]");
+        pw.println("      [--extraAttributionTags <TAG>,<TAG>,...]");
         pw.println("      Add the given test provider. Requires MOCK_LOCATION permissions which");
         pw.println("      can be enabled by running \"adb shell appops set <uid>");
         pw.println("      android:mock_location allow\". There are optional flags that can be");
-        pw.println("      used to configure the provider properties. If no flags are included,");
-        pw.println("      then default values will be used.");
+        pw.println("      used to configure the provider properties and additional arguments. If");
+        pw.println("      no flags are included, then default values will be used.");
         pw.println("    remove-test-provider <PROVIDER>");
         pw.println("      Remove the given test provider.");
         pw.println("    set-test-provider-enabled <PROVIDER> true|false");
         pw.println("      Sets the given test provider enabled state.");
-        pw.println("    set-test-provider-location <PROVIDER> [--location <LATITUDE>,<LONGITUDE>]");
+        pw.println("    set-test-provider-location <PROVIDER> --location <LATITUDE>,<LONGITUDE>");
         pw.println("      [--accuracy <ACCURACY>] [--time <TIME>]");
         pw.println("      Set location for given test provider. Accuracy and time are optional.");
         pw.println("    send-extra-command <PROVIDER> <COMMAND>");
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java b/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java
index 6249a06..e1c011d 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java
@@ -46,6 +46,7 @@
 
 import com.android.server.location.ClientBrokerProto;
 
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -101,6 +102,11 @@
     private static final String TAG = "ContextHubClientBroker";
 
     /**
+     * Internal only authorization value used when the auth state is unknown.
+     */
+    private static final int AUTHORIZATION_UNKNOWN = -1;
+
+    /**
      * Message used by noteOp when this client receives a message from a nanoapp.
      */
     private static final String RECEIVE_MSG_NOTE = "NanoappMessageDelivery ";
@@ -227,7 +233,7 @@
                         if (mMessageChannelNanoappIdMap.containsKey(state.getNanoAppId())) {
                             List<String> permissions = state.getNanoAppPermissions();
                             updateNanoAppAuthState(state.getNanoAppId(),
-                                    hasPermissions(permissions), false /* gracePeriodExpired */);
+                                    permissions, false /* gracePeriodExpired */);
                         }
                     }
                 }
@@ -344,32 +350,13 @@
     public int sendMessageToNanoApp(NanoAppMessage message) {
         ContextHubServiceUtil.checkPermissions(mContext);
 
-        int authState;
-        synchronized (mMessageChannelNanoappIdMap) {
-            // Default to the granted auth state. The true auth state will be checked async if it's
-            // not denied.
-            authState = mMessageChannelNanoappIdMap.getOrDefault(
-                    message.getNanoAppId(), AUTHORIZATION_GRANTED);
-            if (authState == AUTHORIZATION_DENIED) {
-                return ContextHubTransaction.RESULT_FAILED_PERMISSION_DENIED;
-            }
-        }
-
         int result;
         if (isRegistered()) {
-            // Even though the auth state is currently not denied, query the nanoapp permissions
-            // async and verify that the host app currently holds all the requisite permissions.
-            // This can't be done synchronously due to the async query that needs to be performed to
-            // obtain the nanoapp permissions.
-            boolean initialNanoappMessage = false;
-            synchronized (mMessageChannelNanoappIdMap) {
-                if (mMessageChannelNanoappIdMap.get(message.getNanoAppId()) == null) {
-                    mMessageChannelNanoappIdMap.put(message.getNanoAppId(), AUTHORIZATION_GRANTED);
-                    initialNanoappMessage = true;
-                }
-            }
-
-            if (initialNanoappMessage) {
+            int authState = mMessageChannelNanoappIdMap.getOrDefault(
+                    message.getNanoAppId(), AUTHORIZATION_UNKNOWN);
+            if (authState == AUTHORIZATION_DENIED) {
+                return ContextHubTransaction.RESULT_FAILED_PERMISSION_DENIED;
+            } else if (authState == AUTHORIZATION_UNKNOWN) {
                 // Only check permissions the first time a nanoapp is queried since nanoapp
                 // permissions don't currently change at runtime. If the host permission changes
                 // later, that'll be checked by onOpChanged.
@@ -472,7 +459,8 @@
             List<String> messagePermissions) {
         long nanoAppId = message.getNanoAppId();
 
-        int authState = mMessageChannelNanoappIdMap.getOrDefault(nanoAppId, AUTHORIZATION_GRANTED);
+        int authState = updateNanoAppAuthState(nanoAppId, nanoappPermissions,
+                false /* gracePeriodExpired */);
 
         // If in the grace period, the host may not receive any messages containing permissions
         // covered data.
@@ -482,7 +470,9 @@
             return;
         }
 
-        if (authState == AUTHORIZATION_DENIED || !hasPermissions(nanoappPermissions)
+        // If in the grace period, don't check permissions state since it'll cause cleanup
+        // messages to be dropped.
+        if (authState == AUTHORIZATION_DENIED
                 || !notePermissions(messagePermissions, RECEIVE_MSG_NOTE + nanoAppId)) {
             Log.e(TAG, "Dropping message from " + Long.toHexString(nanoAppId) + ". " + mPackage
                     + " doesn't have permission");
@@ -629,7 +619,8 @@
 
         if (timer != null) {
             updateNanoAppAuthState(
-                    nanoAppId, false /* hasPermissions */, true /* gracePeriodExpired */);
+                    nanoAppId, Collections.emptyList() /* nanoappPermissions */,
+                    true /* gracePeriodExpired */);
         }
     }
 
@@ -643,24 +634,43 @@
         mTransactionManager.addTransaction(transaction);
     }
 
-    /**
-     * Updates the latest authentication state for this client to be able to communicate with the
-     * given nanoapp.
-     */
-    private void updateNanoAppAuthState(
-            long nanoAppId, boolean hasPermissions, boolean gracePeriodExpired) {
-        updateNanoAppAuthState(
-                nanoAppId, hasPermissions, gracePeriodExpired, false /* forceDenied */);
+    private int updateNanoAppAuthState(
+            long nanoAppId, List<String> nanoappPermissions, boolean gracePeriodExpired) {
+        return updateNanoAppAuthState(
+                nanoAppId, nanoappPermissions, gracePeriodExpired, false /* forceDenied */);
     }
 
-    /* package */ void updateNanoAppAuthState(
-            long nanoAppId, boolean hasPermissions, boolean gracePeriodExpired,
+    /**
+     * Updates the latest authenticatication state for the given nanoapp.
+     *
+     * @param nanoAppId the nanoapp that's auth state is being updated
+     * @param nanoappPermissions the Android permissions required to communicate with the nanoapp
+     * @param gracePeriodExpired indicates whether this invocation is a result of the grace period
+     *         expiring
+     * @param forceDenied indicates that no matter what auth state is asssociated with this nanoapp
+     *         it should transition to denied
+     * @return the latest auth state as of the completion of this method.
+     */
+    /* package */ int updateNanoAppAuthState(
+            long nanoAppId, List<String> nanoappPermissions, boolean gracePeriodExpired,
             boolean forceDenied) {
         int curAuthState;
         int newAuthState;
         synchronized (mMessageChannelNanoappIdMap) {
+            // Check permission granted state synchronously since this method can be invoked from
+            // multiple threads.
+            boolean hasPermissions = hasPermissions(nanoappPermissions);
+
             curAuthState = mMessageChannelNanoappIdMap.getOrDefault(
-                    nanoAppId, AUTHORIZATION_GRANTED);
+                    nanoAppId, AUTHORIZATION_UNKNOWN);
+            if (curAuthState == AUTHORIZATION_UNKNOWN) {
+                // If there's never been an auth check performed, start the state as granted so the
+                // appropriate state transitions occur below and clients don't receive a granted
+                // callback if they're determined to be in the granted state initially.
+                curAuthState = AUTHORIZATION_GRANTED;
+                mMessageChannelNanoappIdMap.put(nanoAppId, AUTHORIZATION_GRANTED);
+            }
+
             newAuthState = curAuthState;
             // The below logic ensures that only the following transitions are possible:
             // GRANTED -> DENIED_GRACE_PERIOD only if permissions have been lost
@@ -701,6 +711,7 @@
             // Don't send the callback in the synchronized block or it could end up in a deadlock.
             sendAuthStateCallback(nanoAppId, newAuthState);
         }
+        return newAuthState;
     }
 
     private void sendAuthStateCallback(long nanoAppId, int authState) {
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
index 0737db7..dde45c4 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
@@ -124,9 +124,6 @@
     // True if WiFi is available for the Context Hub
     private boolean mIsWifiAvailable = false;
 
-    // True if audio is disabled for the ContextHub
-    private boolean mIsAudioDisabled = false;
-
     // Lock object for sendWifiSettingUpdate()
     private final Object mSendWifiSettingUpdateLock = new Object();
 
@@ -298,7 +295,7 @@
                 };
             SensorPrivacyManager manager = SensorPrivacyManager.getInstance(mContext);
             manager.addSensorPrivacyListener(
-                    SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE, listener);
+                    SensorPrivacyManager.Sensors.MICROPHONE, listener);
         }
     }
 
@@ -945,8 +942,8 @@
         mClientManager.forEachClientOfHub(contextHubId, client -> {
             if (client.getPackageName().equals(packageName)) {
                 client.updateNanoAppAuthState(
-                        nanoAppId, false /* hasPermissions */, false /* gracePeriodExpired */,
-                        true /* forceDenied */);
+                        nanoAppId, Collections.emptyList() /* nanoappPermissions */,
+                        false /* gracePeriodExpired */, true /* forceDenied */);
             }
         });
     }
@@ -1082,12 +1079,10 @@
      */
     private void sendMicrophoneDisableSettingUpdate() {
         SensorPrivacyManager manager = SensorPrivacyManager.getInstance(mContext);
-        boolean disabled = manager.isIndividualSensorPrivacyEnabled(
-                SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE);
-        if (mIsAudioDisabled != disabled) {
-            mIsAudioDisabled = disabled;
-            mContextHubWrapper.onMicrophoneDisableSettingChanged(disabled);
-        }
+        boolean disabled = manager.isSensorPrivacyEnabled(
+                SensorPrivacyManager.Sensors.MICROPHONE);
+        Log.d(TAG, "Mic Disabled Setting: " + disabled);
+        mContextHubWrapper.onMicrophoneDisableSettingChanged(disabled);
     }
 
 
diff --git a/services/core/java/com/android/server/location/countrydetector/ComprehensiveCountryDetector.java b/services/core/java/com/android/server/location/countrydetector/ComprehensiveCountryDetector.java
index af3907e..dda502b 100644
--- a/services/core/java/com/android/server/location/countrydetector/ComprehensiveCountryDetector.java
+++ b/services/core/java/com/android/server/location/countrydetector/ComprehensiveCountryDetector.java
@@ -320,13 +320,15 @@
                         "(source: " + detectedCountry.getSource()
                         + ", countryISO: " + detectedCountry.getCountryIso() + ")")
                     + " isAirplaneModeOff()=" + isAirplaneModeOff()
+                    + " isWifiOn()=" + isWifiOn()
                     + " mListener=" + mListener
                     + " isGeoCoderImplemnted()=" + isGeoCoderImplemented());
         }
 
         if (startLocationBasedDetection && (detectedCountry == null
                 || detectedCountry.getSource() > Country.COUNTRY_SOURCE_LOCATION)
-                && isAirplaneModeOff() && mListener != null && isGeoCoderImplemented()) {
+                && (isAirplaneModeOff() || isWifiOn()) && mListener != null
+                && isGeoCoderImplemented()) {
             if (DEBUG) Slog.d(TAG, "run startLocationBasedDetector()");
             // Start finding location when the source is less reliable than the
             // location and the airplane mode is off (as geocoder will not
@@ -387,6 +389,11 @@
                 mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) == 0;
     }
 
+    protected boolean isWifiOn() {
+        return Settings.Global.getInt(
+                mContext.getContentResolver(), Settings.Global.WIFI_ON, 0) != 0;
+    }
+
     /**
      * Notify the country change.
      */
diff --git a/services/core/java/com/android/server/location/eventlog/LocationEventLog.java b/services/core/java/com/android/server/location/eventlog/LocationEventLog.java
index dbfd0a5..29ce378 100644
--- a/services/core/java/com/android/server/location/eventlog/LocationEventLog.java
+++ b/services/core/java/com/android/server/location/eventlog/LocationEventLog.java
@@ -64,16 +64,17 @@
     private static final int EVENT_LOCATION_POWER_SAVE_MODE_CHANGE = 10;
 
     @GuardedBy("mAggregateStats")
-    private final ArrayMap<String, ArrayMap<String, AggregateStats>> mAggregateStats;
+    private final ArrayMap<String, ArrayMap<CallerIdentity, AggregateStats>> mAggregateStats;
 
     public LocationEventLog() {
         super(getLogSize());
         mAggregateStats = new ArrayMap<>(4);
     }
 
-    public ArrayMap<String, ArrayMap<String, AggregateStats>> copyAggregateStats() {
+    /** Copies out all aggregated stats. */
+    public ArrayMap<String, ArrayMap<CallerIdentity, AggregateStats>> copyAggregateStats() {
         synchronized (mAggregateStats) {
-            ArrayMap<String, ArrayMap<String, AggregateStats>> copy = new ArrayMap<>(
+            ArrayMap<String, ArrayMap<CallerIdentity, AggregateStats>> copy = new ArrayMap<>(
                     mAggregateStats);
             for (int i = 0; i < copy.size(); i++) {
                 copy.setValueAt(i, new ArrayMap<>(copy.valueAt(i)));
@@ -82,17 +83,18 @@
         }
     }
 
-    private AggregateStats getAggregateStats(String provider, String packageName) {
+    private AggregateStats getAggregateStats(String provider, CallerIdentity identity) {
         synchronized (mAggregateStats) {
-            ArrayMap<String, AggregateStats> packageMap = mAggregateStats.get(provider);
+            ArrayMap<CallerIdentity, AggregateStats> packageMap = mAggregateStats.get(provider);
             if (packageMap == null) {
                 packageMap = new ArrayMap<>(2);
                 mAggregateStats.put(provider, packageMap);
             }
-            AggregateStats stats = packageMap.get(packageName);
+            CallerIdentity stripped = identity.stripListenerId();
+            AggregateStats stats = packageMap.get(stripped);
             if (stats == null) {
                 stats = new AggregateStats();
-                packageMap.put(packageName, stats);
+                packageMap.put(stripped, stats);
             }
             return stats;
         }
@@ -117,34 +119,33 @@
     public void logProviderClientRegistered(String provider, CallerIdentity identity,
             LocationRequest request) {
         addLogEvent(EVENT_PROVIDER_REGISTER_CLIENT, provider, identity, request);
-        getAggregateStats(provider, identity.getPackageName())
-                .markRequestAdded(request.getIntervalMillis());
+        getAggregateStats(provider, identity).markRequestAdded(request.getIntervalMillis());
     }
 
     /** Logs a client unregistration for a location provider. */
     public void logProviderClientUnregistered(String provider, CallerIdentity identity) {
         addLogEvent(EVENT_PROVIDER_UNREGISTER_CLIENT, provider, identity);
-        getAggregateStats(provider, identity.getPackageName()).markRequestRemoved();
+        getAggregateStats(provider, identity).markRequestRemoved();
     }
 
     /** Logs a client for a location provider entering the active state. */
     public void logProviderClientActive(String provider, CallerIdentity identity) {
-        getAggregateStats(provider, identity.getPackageName()).markRequestActive();
+        getAggregateStats(provider, identity).markRequestActive();
     }
 
     /** Logs a client for a location provider leaving the active state. */
     public void logProviderClientInactive(String provider, CallerIdentity identity) {
-        getAggregateStats(provider, identity.getPackageName()).markRequestInactive();
+        getAggregateStats(provider, identity).markRequestInactive();
     }
 
     /** Logs a client for a location provider entering the foreground state. */
     public void logProviderClientForeground(String provider, CallerIdentity identity) {
-        getAggregateStats(provider, identity.getPackageName()).markRequestForeground();
+        getAggregateStats(provider, identity).markRequestForeground();
     }
 
     /** Logs a client for a location provider leaving the foreground state. */
     public void logProviderClientBackground(String provider, CallerIdentity identity) {
-        getAggregateStats(provider, identity.getPackageName()).markRequestBackground();
+        getAggregateStats(provider, identity).markRequestBackground();
     }
 
     /** Logs a change to the provider request for a location provider. */
@@ -165,7 +166,7 @@
         if (Build.IS_DEBUGGABLE || D) {
             addLogEvent(EVENT_PROVIDER_DELIVER_LOCATION, provider, numLocations, identity);
         }
-        getAggregateStats(provider, identity.getPackageName()).markLocationDelivered();
+        getAggregateStats(provider, identity).markLocationDelivered();
     }
 
     /** Logs that a provider has entered or exited stationary throttling. */
@@ -218,7 +219,7 @@
 
         protected final String mProvider;
 
-        protected ProviderEvent(long timeDelta, String provider) {
+        ProviderEvent(long timeDelta, String provider) {
             super(timeDelta);
             mProvider = provider;
         }
@@ -234,7 +235,7 @@
         private final int mUserId;
         private final boolean mEnabled;
 
-        protected ProviderEnabledEvent(long timeDelta, String provider, int userId,
+        ProviderEnabledEvent(long timeDelta, String provider, int userId,
                 boolean enabled) {
             super(timeDelta, provider);
             mUserId = userId;
@@ -252,7 +253,7 @@
 
         private final boolean mMocked;
 
-        protected ProviderMockedEvent(long timeDelta, String provider, boolean mocked) {
+        ProviderMockedEvent(long timeDelta, String provider, boolean mocked) {
             super(timeDelta, provider);
             mMocked = mocked;
         }
@@ -273,7 +274,7 @@
         private final CallerIdentity mIdentity;
         @Nullable private final LocationRequest mLocationRequest;
 
-        private ProviderRegisterEvent(long timeDelta, String provider, boolean registered,
+        ProviderRegisterEvent(long timeDelta, String provider, boolean registered,
                 CallerIdentity identity, @Nullable LocationRequest locationRequest) {
             super(timeDelta, provider);
             mRegistered = registered;
@@ -296,7 +297,7 @@
 
         private final ProviderRequest mRequest;
 
-        private ProviderUpdateEvent(long timeDelta, String provider, ProviderRequest request) {
+        ProviderUpdateEvent(long timeDelta, String provider, ProviderRequest request) {
             super(timeDelta, provider);
             mRequest = request;
         }
@@ -311,7 +312,7 @@
 
         private final int mNumLocations;
 
-        private ProviderReceiveLocationEvent(long timeDelta, String provider, int numLocations) {
+        ProviderReceiveLocationEvent(long timeDelta, String provider, int numLocations) {
             super(timeDelta, provider);
             mNumLocations = numLocations;
         }
@@ -327,7 +328,7 @@
         private final int mNumLocations;
         @Nullable private final CallerIdentity mIdentity;
 
-        private ProviderDeliverLocationEvent(long timeDelta, String provider, int numLocations,
+        ProviderDeliverLocationEvent(long timeDelta, String provider, int numLocations,
                 @Nullable CallerIdentity identity) {
             super(timeDelta, provider);
             mNumLocations = numLocations;
@@ -345,7 +346,7 @@
 
         private final boolean mStationaryThrottled;
 
-        private ProviderStationaryThrottledEvent(long timeDelta, String provider,
+        ProviderStationaryThrottledEvent(long timeDelta, String provider,
                 boolean stationaryThrottled) {
             super(timeDelta, provider);
             mStationaryThrottled = stationaryThrottled;
@@ -363,7 +364,7 @@
         @LocationPowerSaveMode
         private final int mLocationPowerSaveMode;
 
-        private LocationPowerSaveModeEvent(long timeDelta,
+        LocationPowerSaveModeEvent(long timeDelta,
                 @LocationPowerSaveMode int locationPowerSaveMode) {
             super(timeDelta);
             mLocationPowerSaveMode = locationPowerSaveMode;
@@ -401,7 +402,7 @@
         private final int mUserId;
         private final boolean mEnabled;
 
-        private LocationEnabledEvent(long timeDelta, int userId, boolean enabled) {
+        LocationEnabledEvent(long timeDelta, int userId, boolean enabled) {
             super(timeDelta);
             mUserId = userId;
             mEnabled = enabled;
diff --git a/services/core/java/com/android/server/location/gnss/GnssAntennaInfoProvider.java b/services/core/java/com/android/server/location/gnss/GnssAntennaInfoProvider.java
new file mode 100644
index 0000000..1967e02
--- /dev/null
+++ b/services/core/java/com/android/server/location/gnss/GnssAntennaInfoProvider.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.location.gnss;
+
+import static com.android.server.location.gnss.GnssManagerService.TAG;
+
+import android.annotation.Nullable;
+import android.location.GnssAntennaInfo;
+import android.location.IGnssAntennaInfoListener;
+import android.location.util.identity.CallerIdentity;
+import android.os.Binder;
+import android.os.IBinder;
+
+import com.android.server.location.gnss.hal.GnssNative;
+import com.android.server.location.listeners.BinderListenerRegistration;
+import com.android.server.location.listeners.ListenerMultiplexer;
+import com.android.server.location.listeners.ListenerRegistration;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Antenna info HAL module and listener multiplexer.
+ */
+public class GnssAntennaInfoProvider extends
+        ListenerMultiplexer<IBinder, IGnssAntennaInfoListener,
+                ListenerRegistration<IGnssAntennaInfoListener>, Void> implements
+        GnssNative.BaseCallbacks, GnssNative.AntennaInfoCallbacks {
+
+    /**
+     * Registration object for GNSS listeners.
+     */
+    protected class AntennaInfoListenerRegistration extends
+            BinderListenerRegistration<Void, IGnssAntennaInfoListener> {
+
+        protected AntennaInfoListenerRegistration(CallerIdentity callerIdentity,
+                IGnssAntennaInfoListener listener) {
+            super(null, callerIdentity, listener);
+        }
+
+        @Override
+        protected GnssAntennaInfoProvider getOwner() {
+            return GnssAntennaInfoProvider.this;
+        }
+    }
+
+    private final GnssNative mGnssNative;
+
+    private volatile @Nullable List<GnssAntennaInfo> mAntennaInfos;
+
+    GnssAntennaInfoProvider(GnssNative gnssNative) {
+        mGnssNative = gnssNative;
+        mGnssNative.addBaseCallbacks(this);
+        mGnssNative.addAntennaInfoCallbacks(this);
+    }
+
+    @Nullable List<GnssAntennaInfo> getAntennaInfos() {
+        return mAntennaInfos;
+    }
+
+    @Override
+    public String getTag() {
+        return TAG;
+    }
+
+    public boolean isSupported() {
+        return mGnssNative.isAntennaInfoSupported();
+    }
+
+    public void addListener(CallerIdentity callerIdentity, IGnssAntennaInfoListener listener) {
+        long identity = Binder.clearCallingIdentity();
+        try {
+            putRegistration(listener.asBinder(),
+                    new AntennaInfoListenerRegistration(callerIdentity, listener));
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    public void removeListener(IGnssAntennaInfoListener listener) {
+        long identity = Binder.clearCallingIdentity();
+        try {
+            removeRegistration(listener.asBinder());
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    protected boolean registerWithService(Void merged,
+            Collection<ListenerRegistration<IGnssAntennaInfoListener>> listenerRegistrations) {
+        return true;
+    }
+
+    @Override
+    protected void unregisterWithService() {}
+
+    @Override
+    protected boolean isActive(ListenerRegistration<IGnssAntennaInfoListener> registration) {
+        return true;
+    }
+
+    @Override
+    protected Void mergeRegistrations(
+            Collection<ListenerRegistration<IGnssAntennaInfoListener>> listenerRegistrations) {
+        return null;
+    }
+
+    @Override
+    public void onHalStarted() {
+        mGnssNative.startAntennaInfoListening();
+    }
+
+    @Override
+    public void onHalRestarted() {
+        mGnssNative.startAntennaInfoListening();
+    }
+
+    @Override
+    public void onReportAntennaInfo(List<GnssAntennaInfo> antennaInfos) {
+        if (antennaInfos.equals(mAntennaInfos)) {
+            return;
+        }
+
+        mAntennaInfos = antennaInfos;
+        deliverToListeners(listener -> {
+            listener.onGnssAntennaInfoChanged(antennaInfos);
+        });
+    }
+}
diff --git a/services/core/java/com/android/server/location/gnss/GnssListenerMultiplexer.java b/services/core/java/com/android/server/location/gnss/GnssListenerMultiplexer.java
index 87e6ef4..5e6ae68 100644
--- a/services/core/java/com/android/server/location/gnss/GnssListenerMultiplexer.java
+++ b/services/core/java/com/android/server/location/gnss/GnssListenerMultiplexer.java
@@ -229,7 +229,7 @@
      * registrations will be treated as inactive and the backing service will never be registered.
      *
      */
-    protected boolean isServiceSupported() {
+    public boolean isSupported() {
         return true;
     }
 
@@ -276,7 +276,7 @@
 
     @Override
     protected boolean isActive(GnssListenerRegistration registration) {
-        if (!isServiceSupported()) {
+        if (!isSupported()) {
             return false;
         }
 
@@ -339,7 +339,7 @@
 
     @Override
     protected void onRegister() {
-        if (!isServiceSupported()) {
+        if (!isSupported()) {
             return;
         }
 
@@ -356,7 +356,7 @@
 
     @Override
     protected void onUnregister() {
-        if (!isServiceSupported()) {
+        if (!isSupported()) {
             return;
         }
 
@@ -404,7 +404,7 @@
 
     @Override
     protected String getServiceState() {
-        if (!isServiceSupported()) {
+        if (!isSupported()) {
             return "unsupported";
         } else {
             return super.getServiceState();
diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
index 9216a6b..1df29ab 100644
--- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
@@ -103,6 +103,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
@@ -371,7 +372,8 @@
 
     public GnssLocationProvider(Context context, Injector injector, GnssNative gnssNative,
             GnssMetrics gnssMetrics) {
-        super(FgThread.getExecutor(), CallerIdentity.fromContext(context), PROPERTIES);
+        super(FgThread.getExecutor(), CallerIdentity.fromContext(context), PROPERTIES,
+                Collections.emptySet());
 
         mContext = context;
         mGnssNative = gnssNative;
diff --git a/services/core/java/com/android/server/location/gnss/GnssManagerService.java b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
index b6695c2..bcdfed4 100644
--- a/services/core/java/com/android/server/location/gnss/GnssManagerService.java
+++ b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
@@ -27,6 +27,7 @@
 import android.location.GnssCapabilities;
 import android.location.GnssMeasurementCorrections;
 import android.location.GnssMeasurementRequest;
+import android.location.IGnssAntennaInfoListener;
 import android.location.IGnssMeasurementsListener;
 import android.location.IGnssNavigationMessageListener;
 import android.location.IGnssNmeaListener;
@@ -49,7 +50,6 @@
 import com.android.server.location.injector.Injector;
 
 import java.io.FileDescriptor;
-import java.util.ArrayList;
 import java.util.List;
 
 /** Manages Gnss providers and related Gnss functions for LocationManagerService. */
@@ -60,7 +60,7 @@
 
     private static final String ATTRIBUTION_ID = "GnssService";
 
-    private final Context mContext;
+    final Context mContext;
     private final GnssNative mGnssNative;
 
     private final GnssLocationProvider mGnssLocationProvider;
@@ -68,11 +68,11 @@
     private final GnssNmeaProvider mGnssNmeaProvider;
     private final GnssMeasurementsProvider mGnssMeasurementsProvider;
     private final GnssNavigationMessageProvider mGnssNavigationMessageProvider;
+    private final GnssAntennaInfoProvider mGnssAntennaInfoProvider;
     private final IGpsGeofenceHardware mGnssGeofenceProxy;
 
     private final GnssGeofenceHalModule mGeofenceHalModule;
     private final GnssCapabilitiesHalModule mCapabilitiesHalModule;
-    private final GnssAntennaInfoHalModule mAntennaInfoHalModule;
 
     private final GnssMetrics mGnssMetrics;
 
@@ -89,11 +89,11 @@
         mGnssNmeaProvider = new GnssNmeaProvider(injector, mGnssNative);
         mGnssMeasurementsProvider = new GnssMeasurementsProvider(injector, mGnssNative);
         mGnssNavigationMessageProvider = new GnssNavigationMessageProvider(injector, mGnssNative);
+        mGnssAntennaInfoProvider = new GnssAntennaInfoProvider(mGnssNative);
         mGnssGeofenceProxy = new GnssGeofenceProxy(mGnssNative);
 
         mGeofenceHalModule = new GnssGeofenceHalModule(mGnssNative);
         mCapabilitiesHalModule = new GnssCapabilitiesHalModule(mGnssNative);
-        mAntennaInfoHalModule = new GnssAntennaInfoHalModule(mGnssNative);
 
         // allow gnss access to begin - we must assume that callbacks can start immediately
         mGnssNative.register();
@@ -140,7 +140,7 @@
      * Get GNSS antenna information.
      */
     public @Nullable List<GnssAntennaInfo> getGnssAntennaInfos() {
-        return mAntennaInfoHalModule.getAntennaInfos();
+        return mGnssAntennaInfoProvider.getAntennaInfos();
     }
 
     /**
@@ -154,10 +154,11 @@
      * Registers listener for GNSS status changes.
      */
     public void registerGnssStatusCallback(IGnssStatusListener listener, String packageName,
-            @Nullable String attributionTag) {
+            @Nullable String attributionTag, String listenerId) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
 
-        CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag);
+        CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag,
+                listenerId);
         mGnssStatusProvider.addListener(identity, listener);
     }
 
@@ -172,10 +173,11 @@
      * Registers listener for GNSS NMEA messages.
      */
     public void registerGnssNmeaCallback(IGnssNmeaListener listener, String packageName,
-            @Nullable String attributionTag) {
+            @Nullable String attributionTag, String listenerId) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
 
-        CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag);
+        CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag,
+                listenerId);
         mGnssNmeaProvider.addListener(identity, listener);
     }
 
@@ -191,12 +193,13 @@
      */
     public void addGnssMeasurementsListener(GnssMeasurementRequest request,
             IGnssMeasurementsListener listener, String packageName,
-            @Nullable String attributionTag) {
+            @Nullable String attributionTag, String listenerId) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
         if (request.isCorrelationVectorOutputsEnabled()) {
             mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
         }
-        CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag);
+        CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag,
+                listenerId);
         mGnssMeasurementsProvider.addListener(request, identity, listener);
     }
 
@@ -223,10 +226,11 @@
      * Adds a GNSS navigation message listener.
      */
     public void addGnssNavigationMessageListener(IGnssNavigationMessageListener listener,
-            String packageName, @Nullable String attributionTag) {
+            String packageName, @Nullable String attributionTag, String listenerId) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
 
-        CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag);
+        CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag,
+                listenerId);
         mGnssNavigationMessageProvider.addListener(identity, listener);
     }
 
@@ -238,6 +242,24 @@
     }
 
     /**
+     * Adds a GNSS antenna info listener.
+     */
+    public void addGnssAntennaInfoListener(IGnssAntennaInfoListener listener, String packageName,
+            @Nullable String attributionTag, String listenerId) {
+
+        CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag,
+                listenerId);
+        mGnssAntennaInfoProvider.addListener(identity, listener);
+    }
+
+    /**
+     * Removes a GNSS antenna info listener.
+     */
+    public void removeGnssAntennaInfoListener(IGnssAntennaInfoListener listener) {
+        mGnssAntennaInfoProvider.removeListener(listener);
+    }
+
+    /**
      * Send Ni Response, indicating a location request initiated by a network carrier.
      */
     public void sendNiResponse(int notifId, int userResponse) {
@@ -259,25 +281,34 @@
 
         ipw.println("Capabilities: " + mGnssNative.getCapabilities());
 
-        List<GnssAntennaInfo> infos = mAntennaInfoHalModule.getAntennaInfos();
-        if (infos != null) {
-            ipw.println("Antenna Infos: " + infos);
+        if (mGnssStatusProvider.isSupported()) {
+            ipw.println("Status Provider:");
+            ipw.increaseIndent();
+            mGnssStatusProvider.dump(fd, ipw, args);
+            ipw.decreaseIndent();
         }
 
-        ipw.println("Measurements Provider:");
-        ipw.increaseIndent();
-        mGnssMeasurementsProvider.dump(fd, ipw, args);
-        ipw.decreaseIndent();
+        if (mGnssMeasurementsProvider.isSupported()) {
+            ipw.println("Measurements Provider:");
+            ipw.increaseIndent();
+            mGnssMeasurementsProvider.dump(fd, ipw, args);
+            ipw.decreaseIndent();
+        }
 
-        ipw.println("Navigation Message Provider:");
-        ipw.increaseIndent();
-        mGnssNavigationMessageProvider.dump(fd, ipw, args);
-        ipw.decreaseIndent();
+        if (mGnssNavigationMessageProvider.isSupported()) {
+            ipw.println("Navigation Message Provider:");
+            ipw.increaseIndent();
+            mGnssNavigationMessageProvider.dump(fd, ipw, args);
+            ipw.decreaseIndent();
+        }
 
-        ipw.println("Status Provider:");
-        ipw.increaseIndent();
-        mGnssStatusProvider.dump(fd, ipw, args);
-        ipw.decreaseIndent();
+        if (mGnssAntennaInfoProvider.isSupported()) {
+            ipw.println("Navigation Message Provider:");
+            ipw.increaseIndent();
+            ipw.println("Antenna Infos: " + mGnssAntennaInfoProvider.getAntennaInfos());
+            mGnssAntennaInfoProvider.dump(fd, ipw, args);
+            ipw.decreaseIndent();
+        }
 
         GnssPowerStats powerStats = mGnssNative.getPowerStats();
         if (powerStats != null) {
@@ -395,53 +426,4 @@
             }
         }
     }
-
-    private class GnssAntennaInfoHalModule implements GnssNative.BaseCallbacks,
-            GnssNative.AntennaInfoCallbacks {
-
-        private final GnssNative mGnssNative;
-
-        private volatile @Nullable List<GnssAntennaInfo> mAntennaInfos;
-
-        GnssAntennaInfoHalModule(GnssNative gnssNative) {
-            mGnssNative = gnssNative;
-            mGnssNative.addBaseCallbacks(this);
-            mGnssNative.addAntennaInfoCallbacks(this);
-        }
-
-        @Nullable List<GnssAntennaInfo> getAntennaInfos() {
-            return mAntennaInfos;
-        }
-
-        @Override
-        public void onHalStarted() {
-            mGnssNative.startAntennaInfoListening();
-        }
-
-        @Override
-        public void onHalRestarted() {
-            mGnssNative.startAntennaInfoListening();
-        }
-
-        @Override
-        public void onReportAntennaInfo(List<GnssAntennaInfo> antennaInfos) {
-            if (antennaInfos.equals(mAntennaInfos)) {
-                return;
-            }
-
-            mAntennaInfos = antennaInfos;
-
-            long ident = Binder.clearCallingIdentity();
-            try {
-                Intent intent = new Intent(LocationManager.ACTION_GNSS_ANTENNA_INFOS_CHANGED)
-                        .putParcelableArrayListExtra(LocationManager.EXTRA_GNSS_ANTENNA_INFOS,
-                                new ArrayList<>(antennaInfos))
-                        .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
-                        .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-                mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
-        }
-    }
 }
diff --git a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
index 305bc9b..b3119d7 100644
--- a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
@@ -99,7 +99,7 @@
     }
 
     @Override
-    protected boolean isServiceSupported() {
+    public boolean isSupported() {
         return mGnssNative.isMeasurementSupported();
     }
 
diff --git a/services/core/java/com/android/server/location/gnss/GnssNavigationMessageProvider.java b/services/core/java/com/android/server/location/gnss/GnssNavigationMessageProvider.java
index ff9ad65..e9fce05 100644
--- a/services/core/java/com/android/server/location/gnss/GnssNavigationMessageProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssNavigationMessageProvider.java
@@ -70,7 +70,7 @@
     }
 
     @Override
-    protected boolean isServiceSupported() {
+    public boolean isSupported() {
         return mGnssNative.isNavigationMessageCollectionSupported();
     }
 
diff --git a/services/core/java/com/android/server/location/gnss/hal/GnssNative.java b/services/core/java/com/android/server/location/gnss/hal/GnssNative.java
index 7e2f089..f275663 100644
--- a/services/core/java/com/android/server/location/gnss/hal/GnssNative.java
+++ b/services/core/java/com/android/server/location/gnss/hal/GnssNative.java
@@ -699,11 +699,11 @@
     }
 
     /**
-     * Returns true if antenna info listening is supported.
+     * Returns true if antenna info is supported.
      */
-    public boolean isAntennaInfoListeningSupported() {
+    public boolean isAntennaInfoSupported() {
         Preconditions.checkState(mRegistered);
-        return mGnssHal.isAntennaInfoListeningSupported();
+        return mGnssHal.isAntennaInfoSupported();
     }
 
     /**
@@ -1259,7 +1259,7 @@
             return native_stop_navigation_message_collection();
         }
 
-        protected boolean isAntennaInfoListeningSupported() {
+        protected boolean isAntennaInfoSupported() {
             return native_is_antenna_info_supported();
         }
 
diff --git a/services/core/java/com/android/server/location/provider/AbstractLocationProvider.java b/services/core/java/com/android/server/location/provider/AbstractLocationProvider.java
index 4e0a0b8..ba7f44f 100644
--- a/services/core/java/com/android/server/location/provider/AbstractLocationProvider.java
+++ b/services/core/java/com/android/server/location/provider/AbstractLocationProvider.java
@@ -28,7 +28,9 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.Collections;
 import java.util.Objects;
+import java.util.Set;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.UnaryOperator;
@@ -65,9 +67,10 @@
 
         /**
          * Default state value for a location provider that is disabled with no properties and an
-         * empty provider package list.
+         * empty extra attribution tag set.
          */
-        public static final State EMPTY_STATE = new State(false, null, null);
+        public static final State EMPTY_STATE = new State(false, null, null,
+                Collections.emptySet());
 
         /**
          * The provider's allowed state.
@@ -84,10 +87,18 @@
          */
         @Nullable public final CallerIdentity identity;
 
-        private State(boolean allowed, ProviderProperties properties, CallerIdentity identity) {
+        /**
+         * A set of attribution tags also associated with this provider - these attribution tags may
+         * be afforded special privileges.
+         */
+        public final Set<String> extraAttributionTags;
+
+        private State(boolean allowed, ProviderProperties properties, CallerIdentity identity,
+                Set<String> extraAttributionTags) {
             this.allowed = allowed;
             this.properties = properties;
             this.identity = identity;
+            this.extraAttributionTags = Objects.requireNonNull(extraAttributionTags);
         }
 
         /**
@@ -97,7 +108,7 @@
             if (allowed == this.allowed) {
                 return this;
             } else {
-                return new State(allowed, properties, identity);
+                return new State(allowed, properties, identity, extraAttributionTags);
             }
         }
 
@@ -108,7 +119,7 @@
             if (Objects.equals(properties, this.properties)) {
                 return this;
             } else {
-                return new State(allowed, properties, identity);
+                return new State(allowed, properties, identity, extraAttributionTags);
             }
         }
 
@@ -119,10 +130,22 @@
             if (Objects.equals(identity, this.identity)) {
                 return this;
             } else {
-                return new State(allowed, properties, identity);
+                return new State(allowed, properties, identity, extraAttributionTags);
             }
         }
 
+        /**
+         * Returns a state the same as the current but with extra attribution tags set as specified.
+         */
+        public State withExtraAttributionTags(Set<String> extraAttributionTags) {
+            if (extraAttributionTags.equals(this.extraAttributionTags)) {
+                return this;
+            } else {
+                return new State(allowed, properties, identity, extraAttributionTags);
+            }
+        }
+
+
         @Override
         public boolean equals(Object o) {
             if (this == o) {
@@ -133,12 +156,13 @@
             }
             State state = (State) o;
             return allowed == state.allowed && properties == state.properties
-                    && Objects.equals(identity, state.identity);
+                    && Objects.equals(identity, state.identity)
+                    && extraAttributionTags.equals(state.extraAttributionTags);
         }
 
         @Override
         public int hashCode() {
-            return Objects.hash(allowed, properties, identity);
+            return Objects.hash(allowed, properties, identity, extraAttributionTags);
         }
     }
 
@@ -195,10 +219,14 @@
      * An optional identity and properties may be provided to initialize the location provider.
      */
     protected AbstractLocationProvider(Executor executor, @Nullable CallerIdentity identity,
-            @Nullable ProviderProperties properties) {
-        mExecutor = executor;
+            @Nullable ProviderProperties properties, Set<String> extraAttributionTags) {
+        Preconditions.checkArgument(identity == null || identity.getListenerId() == null);
+        mExecutor = Objects.requireNonNull(executor);
         mInternalState = new AtomicReference<>(new InternalState(null,
-                State.EMPTY_STATE.withIdentity(identity).withProperties(properties)));
+                State.EMPTY_STATE
+                        .withIdentity(identity)
+                        .withProperties(properties)
+                        .withExtraAttributionTags(extraAttributionTags)));
         mController = new Controller();
     }
 
@@ -270,13 +298,21 @@
     }
 
     /**
-     * Call this method to report a change in provider packages.
+     * Call this method to report a change in the provider's identity.
      */
     protected void setIdentity(@Nullable CallerIdentity identity) {
+        Preconditions.checkArgument(identity == null || identity.getListenerId() == null);
         setState(state -> state.withIdentity(identity));
     }
 
     /**
+     * Call this method to report a change in the provider's extra attribution tags.
+     */
+    protected void setExtraAttributionTags(Set<String> extraAttributionTags) {
+        setState(state -> state.withExtraAttributionTags(extraAttributionTags));
+    }
+
+    /**
      * Call this method to report a new location.
      */
     protected void reportLocation(LocationResult locationResult) {
@@ -335,6 +371,8 @@
 
         private boolean mStarted = false;
 
+        Controller() {}
+
         @Override
         public State setListener(@Nullable Listener listener) {
             InternalState oldInternalState = mInternalState.getAndUpdate(
diff --git a/services/core/java/com/android/server/location/provider/DelegateLocationProvider.java b/services/core/java/com/android/server/location/provider/DelegateLocationProvider.java
index a3ec867..423f833 100644
--- a/services/core/java/com/android/server/location/provider/DelegateLocationProvider.java
+++ b/services/core/java/com/android/server/location/provider/DelegateLocationProvider.java
@@ -24,6 +24,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.Collections;
 import java.util.concurrent.Executor;
 
 /**
@@ -40,7 +41,7 @@
     private boolean mInitialized = false;
 
     DelegateLocationProvider(Executor executor, AbstractLocationProvider delegate) {
-        super(executor, null, null);
+        super(executor, null, null, Collections.emptySet());
 
         mDelegate = delegate;
     }
diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
index 388b5a4..2aa6f28 100644
--- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
@@ -29,6 +29,8 @@
 import static android.os.PowerManager.LOCATION_MODE_FOREGROUND_ONLY;
 import static android.os.PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF;
 import static android.os.PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF;
+import static android.os.PowerWhitelistManager.REASON_LOCATION_PROVIDER;
+import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
 
 import static com.android.server.location.LocationManagerService.D;
 import static com.android.server.location.LocationManagerService.TAG;
@@ -52,6 +54,8 @@
 import android.location.Location;
 import android.location.LocationManager;
 import android.location.LocationManagerInternal;
+import android.location.LocationManagerInternal.LocationTagInfo;
+import android.location.LocationManagerInternal.OnProviderLocationTagsChangeListener;
 import android.location.LocationManagerInternal.ProviderEnabledListener;
 import android.location.LocationRequest;
 import android.location.LocationResult;
@@ -85,6 +89,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
 import com.android.server.location.LocationPermissions;
@@ -117,6 +122,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Objects;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.function.Predicate;
@@ -223,7 +229,10 @@
             BroadcastOptions options = BroadcastOptions.makeBasic();
             options.setDontSendToRestrictedApps(true);
             // allows apps to start a fg service in response to a location PI
-            options.setTemporaryAppWhitelistDuration(TEMPORARY_APP_ALLOWLIST_DURATION_MS);
+            options.setTemporaryAppAllowlist(TEMPORARY_APP_ALLOWLIST_DURATION_MS,
+                    TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+                    REASON_LOCATION_PROVIDER,
+                    "");
 
             Intent intent = new Intent().putExtra(KEY_LOCATION_CHANGED,
                     locationResult.getLastLocation());
@@ -304,6 +313,7 @@
                 LocationTransport transport, @PermissionLevel int permissionLevel) {
             super(Objects.requireNonNull(request), identity, transport);
 
+            Preconditions.checkArgument(identity.getListenerId() != null);
             Preconditions.checkArgument(permissionLevel > PERMISSION_NONE);
             Preconditions.checkArgument(!request.getWorkSource().isEmpty());
 
@@ -1287,6 +1297,9 @@
     @GuardedBy("mLock")
     private @Nullable OnAlarmListener mDelayedRegister;
 
+    @GuardedBy("mLock")
+    private @Nullable OnProviderLocationTagsChangeListener mOnLocationTagsChangeListener;
+
     public LocationProviderManager(Context context, Injector injector, LocationEventLog eventLog,
             String name, @Nullable PassiveLocationProviderManager passiveManager) {
         mContext = context;
@@ -1447,6 +1460,19 @@
         }
     }
 
+    /**
+     * Registers a listener for the location tags of the provider.
+     *
+     * @param listener The listener
+     */
+    public void setOnProviderLocationTagsChangeListener(
+            @Nullable OnProviderLocationTagsChangeListener listener) {
+        Preconditions.checkArgument(mOnLocationTagsChangeListener == null || listener == null);
+        synchronized (mLock) {
+            mOnLocationTagsChangeListener = listener;
+        }
+    }
+
     public void setMockProvider(@Nullable MockLocationProvider provider) {
         synchronized (mLock) {
             Preconditions.checkState(mState != STATE_STOPPED);
@@ -2243,6 +2269,27 @@
         if (oldState.allowed != newState.allowed) {
             onEnabledChanged(UserHandle.USER_ALL);
         }
+
+        if (mOnLocationTagsChangeListener != null) {
+            if (!oldState.extraAttributionTags.equals(newState.extraAttributionTags)) {
+                if (oldState.identity != null) {
+                    FgThread.getHandler().sendMessage(PooledLambda.obtainMessage(
+                            OnProviderLocationTagsChangeListener::onLocationTagsChanged,
+                            mOnLocationTagsChangeListener, new LocationTagInfo(
+                                    oldState.identity.getUid(), oldState.identity.getPackageName(),
+                                    Collections.emptySet())
+                            ));
+                }
+                if (newState.identity != null) {
+                    FgThread.getHandler().sendMessage(PooledLambda.obtainMessage(
+                            OnProviderLocationTagsChangeListener::onLocationTagsChanged,
+                            mOnLocationTagsChangeListener, new LocationTagInfo(
+                                    newState.identity.getUid(), newState.identity.getPackageName(),
+                                    newState.extraAttributionTags)
+                            ));
+                }
+            }
+        }
     }
 
     @GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/location/provider/MockLocationProvider.java b/services/core/java/com/android/server/location/provider/MockLocationProvider.java
index 0d8f643..52b04d4 100644
--- a/services/core/java/com/android/server/location/provider/MockLocationProvider.java
+++ b/services/core/java/com/android/server/location/provider/MockLocationProvider.java
@@ -28,6 +28,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.Set;
 
 /**
  * A mock location provider used by LocationManagerService to implement test providers.
@@ -38,9 +39,10 @@
 
     @Nullable private Location mLocation;
 
-    public MockLocationProvider(ProviderProperties properties, CallerIdentity identity) {
+    public MockLocationProvider(ProviderProperties properties, CallerIdentity identity,
+            Set<String> extraAttributionTags) {
         // using a direct executor is ok because this class has no locks that could deadlock
-        super(DIRECT_EXECUTOR, identity, properties);
+        super(DIRECT_EXECUTOR, identity, properties, extraAttributionTags);
     }
 
     /** Sets the allowed state of this mock provider. */
diff --git a/services/core/java/com/android/server/location/provider/MockableLocationProvider.java b/services/core/java/com/android/server/location/provider/MockableLocationProvider.java
index cb7264e..8193644 100644
--- a/services/core/java/com/android/server/location/provider/MockableLocationProvider.java
+++ b/services/core/java/com/android/server/location/provider/MockableLocationProvider.java
@@ -31,6 +31,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.Collections;
 
 /**
  * Represents a location provider that may switch between a mock implementation and a real
@@ -75,7 +76,7 @@
     public MockableLocationProvider(Object ownerLock) {
         // using a direct executor is acceptable because all inbound calls are delegated to the
         // actual provider implementations which will use their own executors
-        super(DIRECT_EXECUTOR, null, null);
+        super(DIRECT_EXECUTOR, null, null, Collections.emptySet());
         mOwnerLock = ownerLock;
         mRequest = ProviderRequest.EMPTY_REQUEST;
     }
diff --git a/services/core/java/com/android/server/location/provider/PassiveLocationProvider.java b/services/core/java/com/android/server/location/provider/PassiveLocationProvider.java
index a5758a3..68ede88 100644
--- a/services/core/java/com/android/server/location/provider/PassiveLocationProvider.java
+++ b/services/core/java/com/android/server/location/provider/PassiveLocationProvider.java
@@ -30,6 +30,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.Collections;
 
 /**
  * A passive location provider reports locations received from other providers
@@ -47,7 +48,8 @@
 
     public PassiveLocationProvider(Context context) {
         // using a direct executor is ok because this class has no locks that could deadlock
-        super(DIRECT_EXECUTOR, CallerIdentity.fromContext(context), PROPERTIES);
+        super(DIRECT_EXECUTOR, CallerIdentity.fromContext(context), PROPERTIES,
+                Collections.emptySet());
         setAllowed(true);
     }
 
diff --git a/services/core/java/com/android/server/location/provider/proxy/ProxyLocationProvider.java b/services/core/java/com/android/server/location/provider/proxy/ProxyLocationProvider.java
index 4c97f64..44b62b3 100644
--- a/services/core/java/com/android/server/location/provider/proxy/ProxyLocationProvider.java
+++ b/services/core/java/com/android/server/location/provider/proxy/ProxyLocationProvider.java
@@ -32,15 +32,18 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.util.ArraySet;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.ServiceWatcher;
+import com.android.server.ServiceWatcher.BoundService;
 import com.android.server.location.provider.AbstractLocationProvider;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 
@@ -49,6 +52,9 @@
  */
 public class ProxyLocationProvider extends AbstractLocationProvider {
 
+    private static final String KEY_EXTRA_ATTRIBUTION_TAGS = "android:location_allow_listed_tags";
+    private static final String EXTRA_ATTRIBUTION_TAGS_SEPARATOR = ";";
+
     /**
      * Creates and registers this proxy. If no suitable service is available for the proxy, returns
      * null.
@@ -84,7 +90,7 @@
             int nonOverlayPackageResId) {
         // safe to use direct executor since our locks are not acquired in a code path invoked by
         // our owning provider
-        super(DIRECT_EXECUTOR, null, null);
+        super(DIRECT_EXECUTOR, null, null, Collections.emptySet());
 
         mContext = context;
         mServiceWatcher = new ServiceWatcher(context, action, this::onBind,
@@ -98,12 +104,22 @@
         return mServiceWatcher.checkServiceResolves();
     }
 
-    private void onBind(IBinder binder, ComponentName service) throws RemoteException {
+    private void onBind(IBinder binder, BoundService boundService) throws RemoteException {
         ILocationProvider provider = ILocationProvider.Stub.asInterface(binder);
 
         synchronized (mLock) {
             mProxy = new Proxy();
-            mService = service;
+            mService = boundService.component;
+
+            // update extra attribution tag info from manifest
+            if (boundService.metadata != null) {
+                String tagsList = boundService.metadata.getString(KEY_EXTRA_ATTRIBUTION_TAGS);
+                if (tagsList != null) {
+                    setExtraAttributionTags(
+                            new ArraySet<>(tagsList.split(EXTRA_ATTRIBUTION_TAGS_SEPARATOR)));
+                }
+            }
+
             provider.setLocationProviderManager(mProxy);
 
             ProviderRequest request = mRequest;
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 8da2d67..43c7365 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -88,6 +88,7 @@
 import android.provider.Settings;
 import android.provider.Settings.Secure;
 import android.provider.Settings.SettingNotFoundException;
+import android.security.AndroidKeyStoreMaintenance;
 import android.security.Authorization;
 import android.security.KeyStore;
 import android.security.keystore.AndroidKeyStoreProvider;
@@ -224,7 +225,6 @@
     private final SyntheticPasswordManager mSpManager;
 
     private final KeyStore mKeyStore;
-
     private final RecoverableKeyStoreManager mRecoverableKeyStoreManager;
     private ManagedProfilePasswordCache mManagedProfilePasswordCache;
 
@@ -479,8 +479,8 @@
             return KeyStore.getInstance();
         }
 
-        public RecoverableKeyStoreManager getRecoverableKeyStoreManager(KeyStore keyStore) {
-            return RecoverableKeyStoreManager.getInstance(mContext, keyStore);
+        public RecoverableKeyStoreManager getRecoverableKeyStoreManager() {
+            return RecoverableKeyStoreManager.getInstance(mContext);
         }
 
         public IStorageManager getStorageManager() {
@@ -561,7 +561,7 @@
         mInjector = injector;
         mContext = injector.getContext();
         mKeyStore = injector.getKeyStore();
-        mRecoverableKeyStoreManager = injector.getRecoverableKeyStoreManager(mKeyStore);
+        mRecoverableKeyStoreManager = injector.getRecoverableKeyStoreManager();
         mHandler = injector.getHandler(injector.getServiceThread());
         mStrongAuth = injector.getStrongAuth();
         mActivityManager = injector.getActivityManager();
@@ -795,6 +795,7 @@
             if (Intent.ACTION_USER_ADDED.equals(intent.getAction())) {
                 // Notify keystore that a new user was added.
                 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+                AndroidKeyStoreMaintenance.onUserAdded(userHandle);
                 final KeyStore ks = KeyStore.getInstance();
                 final UserInfo parentInfo = mUserManager.getProfileParent(userHandle);
                 final int parentHandle = parentInfo != null ? parentInfo.id : -1;
@@ -1266,6 +1267,7 @@
     }
 
     private void setKeystorePassword(byte[] password, int userHandle) {
+        AndroidKeyStoreMaintenance.onUserPasswordChanged(userHandle, password);
         final KeyStore ks = KeyStore.getInstance();
         // TODO(b/120484642): Update keystore to accept byte[] passwords
         String passwordString = password == null ? null : new String(password);
@@ -1274,7 +1276,7 @@
 
     private void unlockKeystore(byte[] password, int userHandle) {
         if (DEBUG) Slog.v(TAG, "Unlock keystore for user: " + userHandle);
-        new Authorization().onLockScreenEvent(false, userHandle, password);
+        Authorization.onLockScreenEvent(false, userHandle, password);
         // TODO(b/120484642): Update keystore to accept byte[] passwords
         String passwordString = password == null ? null : new String(password);
         final KeyStore ks = KeyStore.getInstance();
@@ -2292,6 +2294,7 @@
         mSpManager.removeUser(userId);
         mStrongAuth.removeUser(userId);
 
+        AndroidKeyStoreMaintenance.onUserRemoved(userId);
         final KeyStore ks = KeyStore.getInstance();
         ks.onUserRemoved(userId);
         mManagedProfilePasswordCache.removePassword(userId);
diff --git a/services/core/java/com/android/server/locksettings/OWNERS b/services/core/java/com/android/server/locksettings/OWNERS
index 08b8a8c..7577ee5 100644
--- a/services/core/java/com/android/server/locksettings/OWNERS
+++ b/services/core/java/com/android/server/locksettings/OWNERS
@@ -1,3 +1,4 @@
 jaggies@google.com
 kchyn@google.com
 rubinxu@google.com
+xunchang@google.com
diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
index 30ea555..7e00fd6 100644
--- a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
+++ b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
@@ -194,7 +194,9 @@
         }
 
         public void reportMetric(boolean success) {
-            FrameworkStatsLog.write(FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED, success);
+            // TODO(b/179105110) design error code; and report the true value for other fields.
+            FrameworkStatsLog.write(FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED, 0, 1, 1,
+                    -1, 0);
         }
 
         public RebootEscrowEventLog getEventLog() {
diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowProviderServerBasedImpl.java b/services/core/java/com/android/server/locksettings/RebootEscrowProviderServerBasedImpl.java
index b3b4546..697bf08 100644
--- a/services/core/java/com/android/server/locksettings/RebootEscrowProviderServerBasedImpl.java
+++ b/services/core/java/com/android/server/locksettings/RebootEscrowProviderServerBasedImpl.java
@@ -44,7 +44,7 @@
      * Use the default lifetime of 10 minutes. The lifetime covers the following activities:
      * Server wrap secret -> device reboot -> server unwrap blob.
      */
-    private static final long DEFAULT_SERVER_BLOB_LIFETIME_IN_MILLIS = 600_1000;
+    private static final long DEFAULT_SERVER_BLOB_LIFETIME_IN_MILLIS = 600_000;
 
     private final LockSettingsStorage mStorage;
 
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java
index 6d420a9..35e6489 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java
@@ -18,7 +18,6 @@
 
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyProtection;
-import android.security.keystore2.AndroidKeyStoreProvider;
 import android.util.Slog;
 
 import java.io.ByteArrayOutputStream;
@@ -141,19 +140,8 @@
         }
     }
 
-    /**
-     * TODO This function redirects keystore access to the legacy keystore during a transitional
-     *      phase during which not all calling code has been adjusted to use Keystore 2.0.
-     *      This can be reverted to a constant of "AndroidKeyStore" when b/171305684 is complete.
-     *      The specific bug for this component is b/171305115.
-     */
     static String androidKeystoreProviderName() {
-        if (AndroidKeyStoreProvider.isInstalled()) {
-            return "AndroidKeyStoreLegacy";
-        } else {
-            return "AndroidKeystore";
-        }
-
+        return "AndroidKeyStore";
     }
 
     public static byte[] decryptBlob(String keyAlias, byte[] blob, byte[] applicationId) {
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeyStoreProxyImpl.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeyStoreProxyImpl.java
index 9857fb6..f594136 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeyStoreProxyImpl.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeyStoreProxyImpl.java
@@ -16,8 +16,6 @@
 
 package com.android.server.locksettings.recoverablekeystore;
 
-import android.security.keystore2.AndroidKeyStoreProvider;
-
 import java.io.IOException;
 import java.security.Key;
 import java.security.KeyStore;
@@ -31,24 +29,11 @@
  */
 public class KeyStoreProxyImpl implements KeyStoreProxy {
 
+    public static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore";
+
     private final KeyStore mKeyStore;
 
     /**
-     * TODO This function redirects keystore access to the legacy keystore during a transitional
-     *      phase during which not all calling code has been adjusted to use Keystore 2.0.
-     *      This can be reverted to a constant of "AndroidKeyStore" when b/171305684 is complete.
-     *      The specific bug for this component is b/171305545.
-     */
-    static String androidKeystoreProviderName() {
-        if (AndroidKeyStoreProvider.isInstalled()) {
-            return "AndroidKeyStoreLegacy";
-        } else {
-            return "AndroidKeyStore";
-        }
-
-    }
-
-    /**
      * A new instance, delegating to {@code keyStore}.
      */
     public KeyStoreProxyImpl(KeyStore keyStore) {
@@ -84,7 +69,7 @@
      * @throws KeyStoreException if there was a problem getting or initializing the key store.
      */
     public static KeyStore getAndLoadAndroidKeyStore() throws KeyStoreException {
-        KeyStore keyStore = KeyStore.getInstance(androidKeystoreProviderName());
+        KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER);
         try {
             keyStore.load(/*param=*/ null);
         } catch (CertificateException | IOException | NoSuchAlgorithmException e) {
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
index dff1df7..f448a6e 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
@@ -470,7 +470,7 @@
      * @throws KeyStoreException if there was a problem getting or initializing the key store.
      */
     private static KeyStore getAndLoadAndroidKeyStore() throws KeyStoreException {
-        KeyStore keyStore = KeyStore.getInstance(KeyStoreProxyImpl.androidKeystoreProviderName());
+        KeyStore keyStore = KeyStore.getInstance(KeyStoreProxyImpl.ANDROID_KEY_STORE_PROVIDER);
         try {
             keyStore.load(/*param=*/ null);
         } catch (CertificateException | IOException | NoSuchAlgorithmException e) {
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
index 6d97ed7..b49bced 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -34,7 +34,6 @@
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
 import android.os.UserHandle;
-import android.security.KeyStore;
 import android.security.keystore.recovery.KeyChainProtectionParams;
 import android.security.keystore.recovery.KeyChainSnapshot;
 import android.security.keystore.recovery.RecoveryCertPath;
@@ -110,14 +109,14 @@
      * @hide
      */
     public static synchronized RecoverableKeyStoreManager
-            getInstance(Context context, KeyStore keystore) {
+            getInstance(Context context) {
         if (mInstance == null) {
             RecoverableKeyStoreDb db = RecoverableKeyStoreDb.newInstance(context);
             PlatformKeyManager platformKeyManager;
             ApplicationKeyStorage applicationKeyStorage;
             try {
                 platformKeyManager = PlatformKeyManager.getInstance(context, db);
-                applicationKeyStorage = ApplicationKeyStorage.getInstance(keystore);
+                applicationKeyStorage = ApplicationKeyStorage.getInstance();
             } catch (NoSuchAlgorithmException e) {
                 // Impossible: all algorithms must be supported by AOSP
                 throw new RuntimeException(e);
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/ApplicationKeyStorage.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/ApplicationKeyStorage.java
index 84ddbf7..2398f56 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/ApplicationKeyStorage.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/ApplicationKeyStorage.java
@@ -21,9 +21,13 @@
 import android.annotation.Nullable;
 import android.os.ServiceSpecificException;
 import android.security.Credentials;
+import android.security.KeyStore;
+import android.security.KeyStore2;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyProtection;
-import android.security.KeyStore;
+import android.system.keystore2.Domain;
+import android.system.keystore2.KeyDescriptor;
+import android.system.keystore2.KeyPermission;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -47,32 +51,37 @@
 
     private static final String APPLICATION_KEY_ALIAS_PREFIX =
             "com.android.server.locksettings.recoverablekeystore/application/";
+    private static final String APPLICATION_KEY_GRANT_PREFIX = "recoverable_key:";
 
     private final KeyStoreProxy mKeyStore;
-    private final KeyStore mKeystoreService;
 
-    public static ApplicationKeyStorage getInstance(KeyStore keystoreService)
+    /**
+     * Creates a new instance.
+     */
+    public static ApplicationKeyStorage getInstance()
             throws KeyStoreException {
         return new ApplicationKeyStorage(
-                new KeyStoreProxyImpl(KeyStoreProxyImpl.getAndLoadAndroidKeyStore()),
-                keystoreService);
+                new KeyStoreProxyImpl(KeyStoreProxyImpl.getAndLoadAndroidKeyStore()));
     }
 
     @VisibleForTesting
-    ApplicationKeyStorage(KeyStoreProxy keyStore, KeyStore keystoreService) {
+    ApplicationKeyStorage(KeyStoreProxy keyStore) {
         mKeyStore = keyStore;
-        mKeystoreService = keystoreService;
     }
 
     /**
-     * Returns grant alias, valid in Applications namespace.
+     * Returns String representation of {@code KeyDescriptor} valid in application's namespace.
      */
     public @Nullable String getGrantAlias(int userId, int uid, String alias) {
-        // Aliases used by {@link KeyStore} are different than used by public API.
-        // {@code USER_PRIVATE_KEY} prefix is used secret keys.
         Log.i(TAG, String.format(Locale.US, "Get %d/%d/%s", userId, uid, alias));
-        String keystoreAlias = Credentials.USER_PRIVATE_KEY + getInternalAlias(userId, uid, alias);
-        return mKeystoreService.grant(keystoreAlias, uid);
+        String keystoreAlias = getInternalAlias(userId, uid, alias);
+        if (useKeyStore2()) {
+            return makeKeystoreEngineGrantString(uid, keystoreAlias);
+        } else {
+            // Aliases used by {@link KeyStore} are different than used by public API.
+            // {@code USER_PRIVATE_KEY} prefix is used secret keys.
+            return KeyStore.getInstance().grant(Credentials.USER_PRIVATE_KEY + keystoreAlias, uid);
+        }
     }
 
     public void setSymmetricKeyEntry(int userId, int uid, String alias, byte[] secretKey)
@@ -117,4 +126,31 @@
     private String getInternalAlias(int userId, int uid, String alias) {
         return APPLICATION_KEY_ALIAS_PREFIX + userId + "/" + uid + "/" + alias;
     }
+
+    private String makeKeystoreEngineGrantString(int uid, String alias) {
+        if (alias == null) {
+            return null;
+        }
+
+        KeyDescriptor key = new KeyDescriptor();
+        key.domain = Domain.APP;
+        key.nspace = KeyProperties.NAMESPACE_APPLICATION;
+        key.alias = alias;
+        key.blob = null;
+
+        int grantAccessVector = KeyPermission.USE | KeyPermission.GET_INFO | KeyPermission.DELETE;
+
+        try {
+            key = KeyStore2.getInstance().grant(key, uid, grantAccessVector);
+        } catch (android.security.KeyStoreException e) {
+            Log.e(TAG, "Failed to get grant for KeyStore key.", e);
+            throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage());
+        }
+        return String.format("%s%016X", APPLICATION_KEY_GRANT_PREFIX, key.nspace);
+    }
+
+    private static boolean useKeyStore2() {
+        return android.security.keystore2.AndroidKeyStoreProvider.isInstalled();
+    }
+
 }
diff --git a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
index 87e170a..cb0a6688 100644
--- a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
+++ b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
@@ -29,6 +29,7 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.os.Handler;
+import android.os.PowerWhitelistManager;
 import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
@@ -195,8 +196,9 @@
         mediaButtonIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, callingPackageName);
 
         final BroadcastOptions options = BroadcastOptions.makeBasic();
-        options.setTemporaryAppWhitelistDuration(
-                FGS_STARTS_TEMP_ALLOWLIST_DURATION_MS);
+        options.setTemporaryAppAllowlist(FGS_STARTS_TEMP_ALLOWLIST_DURATION_MS,
+                PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+                PowerWhitelistManager.REASON_MEDIA_BUTTON, "");
         if (mPendingIntent != null) {
             if (DEBUG_KEY_EVENT) {
                 Log.d(TAG, "Sending " + keyEvent + " to the last known PendingIntent "
diff --git a/services/core/java/com/android/server/media/MediaKeyDispatcher.java b/services/core/java/com/android/server/media/MediaKeyDispatcher.java
index 7ef4924..55511ad 100644
--- a/services/core/java/com/android/server/media/MediaKeyDispatcher.java
+++ b/services/core/java/com/android/server/media/MediaKeyDispatcher.java
@@ -77,7 +77,7 @@
         mOverriddenKeyEvents.put(KeyEvent.KEYCODE_VOLUME_MUTE, 0);
     }
 
-    // TODO: Move this method into SessionPolicyProvider.java for better readability.
+    // TODO: Move this method into MediaSessionPolicyProvider.java for better readability.
     /**
      * Implement this to customize the logic for which MediaSession should consume which key event.
      *
diff --git a/services/core/java/com/android/server/media/SessionPolicyProvider.java b/services/core/java/com/android/server/media/MediaSessionPolicyProvider.java
similarity index 95%
rename from services/core/java/com/android/server/media/SessionPolicyProvider.java
rename to services/core/java/com/android/server/media/MediaSessionPolicyProvider.java
index 332c85a..ceadb59 100644
--- a/services/core/java/com/android/server/media/SessionPolicyProvider.java
+++ b/services/core/java/com/android/server/media/MediaSessionPolicyProvider.java
@@ -31,7 +31,7 @@
  * without any parameters.
  */
 // TODO: Move this class to apex/media/
-public abstract class SessionPolicyProvider {
+public abstract class MediaSessionPolicyProvider {
     @IntDef(value = {
             SESSION_POLICY_IGNORE_BUTTON_RECEIVER,
             SESSION_POLICY_IGNORE_BUTTON_SESSION
@@ -55,7 +55,7 @@
      */
     static final int SESSION_POLICY_IGNORE_BUTTON_SESSION = 1 << 1;
 
-    public SessionPolicyProvider(Context context) {
+    public MediaSessionPolicyProvider(Context context) {
         // Constructor used for reflection
     }
 
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index c462a92..0a074e1 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -895,7 +895,7 @@
                 throws RemoteException {
             final long token = Binder.clearCallingIdentity();
             try {
-                if ((mPolicies & SessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_RECEIVER)
+                if ((mPolicies & MediaSessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_RECEIVER)
                         != 0) {
                     return;
                 }
@@ -911,7 +911,7 @@
         public void setMediaButtonBroadcastReceiver(ComponentName receiver) throws RemoteException {
             final long token = Binder.clearCallingIdentity();
             try {
-                if ((mPolicies & SessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_RECEIVER)
+                if ((mPolicies & MediaSessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_RECEIVER)
                         != 0) {
                     return;
                 }
diff --git a/services/core/java/com/android/server/media/MediaSessionRecordImpl.java b/services/core/java/com/android/server/media/MediaSessionRecordImpl.java
index 032523e..3c50597 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecordImpl.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecordImpl.java
@@ -20,7 +20,7 @@
 import android.os.ResultReceiver;
 import android.view.KeyEvent;
 
-import com.android.server.media.SessionPolicyProvider.SessionPolicy;
+import com.android.server.media.MediaSessionPolicyProvider.SessionPolicy;
 
 import java.io.PrintWriter;
 
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 6c1d399..23d8429 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -40,10 +40,10 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
-import android.content.pm.ParceledListSlice;
 import android.media.AudioManager;
 import android.media.AudioPlaybackConfiguration;
 import android.media.IRemoteSessionCallback;
+import android.media.MediaCommunicationManager;
 import android.media.Session2Token;
 import android.media.session.IActiveSessionsListener;
 import android.media.session.IOnMediaKeyEventDispatchedListener;
@@ -148,9 +148,28 @@
     final RemoteCallbackList<IRemoteSessionCallback> mRemoteVolumeControllers =
             new RemoteCallbackList<>();
 
-    private SessionPolicyProvider mCustomSessionPolicyProvider;
+    private MediaSessionPolicyProvider mCustomMediaSessionPolicyProvider;
     private MediaKeyDispatcher mCustomMediaKeyDispatcher;
 
+    private MediaCommunicationManager mCommunicationManager;
+    private final MediaCommunicationManager.SessionCallback mSession2TokenCallback =
+            new MediaCommunicationManager.SessionCallback() {
+                @Override
+                public void onSession2TokenCreated(Session2Token token) {
+                    if (DEBUG) {
+                        Log.d(TAG, "Session2 is created " + token);
+                    }
+                    MediaSession2Record record = new MediaSession2Record(token,
+                            MediaSessionService.this, mRecordThread.getLooper(), 0);
+                    synchronized (mLock) {
+                        FullUserRecord user = getFullUserRecordLocked(record.getUserId());
+                        if (user != null) {
+                            user.mPriorityStack.addSession(record);
+                        }
+                    }
+                }
+            };
+
     public MediaSessionService(Context context) {
         super(context);
         mContext = context;
@@ -191,8 +210,10 @@
 
         updateUser();
 
-        instantiateCustomProvider(null);
-        instantiateCustomDispatcher(null);
+        instantiateCustomProvider(mContext.getResources().getString(
+                R.string.config_customMediaSessionPolicyProvider));
+        instantiateCustomDispatcher(mContext.getResources().getString(
+                R.string.config_customMediaKeyDispatcher));
         mRecordThread.start();
 
         final IntentFilter filter = new IntentFilter(
@@ -200,6 +221,19 @@
         mContext.registerReceiver(mNotificationListenerEnabledChangedReceiver, filter);
     }
 
+    @Override
+    public void onBootPhase(int phase) {
+        super.onBootPhase(phase);
+        switch (phase) {
+            // This ensures MediaCommunicationService is started
+            case PHASE_BOOT_COMPLETED:
+                mCommunicationManager = mContext.getSystemService(MediaCommunicationManager.class);
+                mCommunicationManager.registerSessionCallback(new HandlerExecutor(mHandler),
+                        mSession2TokenCallback);
+                break;
+        }
+    }
+
     private final BroadcastReceiver mNotificationListenerEnabledChangedReceiver =
             new BroadcastReceiver() {
                 @Override
@@ -589,8 +623,8 @@
             String callerPackageName, ISessionCallback cb, String tag, Bundle sessionInfo) {
         synchronized (mLock) {
             int policies = 0;
-            if (mCustomSessionPolicyProvider != null) {
-                policies = mCustomSessionPolicyProvider.getSessionPoliciesForApplication(
+            if (mCustomMediaSessionPolicyProvider != null) {
+                policies = mCustomMediaSessionPolicyProvider.getSessionPoliciesForApplication(
                         callerUid, callerPackageName);
             }
 
@@ -778,16 +812,13 @@
         return null;
     }
 
-    private void instantiateCustomDispatcher(String nameFromTesting) {
+    private void instantiateCustomDispatcher(String componentName) {
         synchronized (mLock) {
             mCustomMediaKeyDispatcher = null;
 
-            String customDispatcherClassName = (nameFromTesting == null)
-                    ? mContext.getResources().getString(R.string.config_customMediaKeyDispatcher)
-                    : nameFromTesting;
             try {
-                if (!TextUtils.isEmpty(customDispatcherClassName)) {
-                    Class customDispatcherClass = Class.forName(customDispatcherClassName);
+                if (componentName != null && !TextUtils.isEmpty(componentName)) {
+                    Class customDispatcherClass = Class.forName(componentName);
                     Constructor constructor =
                             customDispatcherClass.getDeclaredConstructor(Context.class);
                     mCustomMediaKeyDispatcher =
@@ -801,20 +832,17 @@
         }
     }
 
-    private void instantiateCustomProvider(String nameFromTesting) {
+    private void instantiateCustomProvider(String componentName) {
         synchronized (mLock) {
-            mCustomSessionPolicyProvider = null;
+            mCustomMediaSessionPolicyProvider = null;
 
-            String customProviderClassName = (nameFromTesting == null)
-                    ? mContext.getResources().getString(R.string.config_customSessionPolicyProvider)
-                    : nameFromTesting;
             try {
-                if (!TextUtils.isEmpty(customProviderClassName)) {
-                    Class customProviderClass = Class.forName(customProviderClassName);
+                if (componentName != null && !TextUtils.isEmpty(componentName)) {
+                    Class customProviderClass = Class.forName(componentName);
                     Constructor constructor =
                             customProviderClass.getDeclaredConstructor(Context.class);
-                    mCustomSessionPolicyProvider =
-                            (SessionPolicyProvider) constructor.newInstance(mContext);
+                    mCustomMediaSessionPolicyProvider =
+                            (MediaSessionPolicyProvider) constructor.newInstance(mContext);
                 }
             } catch (ClassNotFoundException | InstantiationException | InvocationTargetException
                     | IllegalAccessException | NoSuchMethodException e) {
@@ -1143,31 +1171,6 @@
         }
 
         @Override
-        public void notifySession2Created(Session2Token sessionToken) throws RemoteException {
-            final int pid = Binder.getCallingPid();
-            final int uid = Binder.getCallingUid();
-            final long token = Binder.clearCallingIdentity();
-            try {
-                if (DEBUG) {
-                    Log.d(TAG, "Session2 is created " + sessionToken);
-                }
-                if (uid != sessionToken.getUid()) {
-                    throw new SecurityException("Unexpected Session2Token's UID, expected=" + uid
-                            + " but actually=" + sessionToken.getUid());
-                }
-                MediaSession2Record record = new MediaSession2Record(sessionToken,
-                        MediaSessionService.this, mRecordThread.getLooper(), 0);
-                synchronized (mLock) {
-                    FullUserRecord user = getFullUserRecordLocked(record.getUserId());
-                    user.mPriorityStack.addSession(record);
-                }
-                // Do not immediately notify changes -- do so when framework can dispatch command
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
         public List<MediaSession.Token> getSessions(ComponentName componentName, int userId) {
             final int pid = Binder.getCallingPid();
             final int uid = Binder.getCallingUid();
@@ -1189,26 +1192,6 @@
         }
 
         @Override
-        public ParceledListSlice getSession2Tokens(int userId) {
-            final int pid = Binder.getCallingPid();
-            final int uid = Binder.getCallingUid();
-            final long token = Binder.clearCallingIdentity();
-
-            try {
-                // Check that they can make calls on behalf of the user and get the final user id
-                int resolvedUserId = handleIncomingUser(pid, uid, userId, null);
-                List<Session2Token> result;
-                synchronized (mLock) {
-                    FullUserRecord user = getFullUserRecordLocked(userId);
-                    result = user.mPriorityStack.getSession2Tokens(resolvedUserId);
-                }
-                return new ParceledListSlice(result);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
         public void addSessionsListener(IActiveSessionsListener listener,
                 ComponentName componentName, int userId) throws RemoteException {
             final int pid = Binder.getCallingPid();
@@ -1933,16 +1916,30 @@
         }
 
         @Override
-        public void setCustomMediaKeyDispatcherForTesting(String name) {
+        public void setCustomMediaKeyDispatcher(String name) {
             instantiateCustomDispatcher(name);
         }
 
         @Override
-        public void setCustomSessionPolicyProviderForTesting(String name) {
+        public void setCustomMediaSessionPolicyProvider(String name) {
             instantiateCustomProvider(name);
         }
 
         @Override
+        public boolean hasCustomMediaKeyDispatcher(String componentName) {
+            return mCustomMediaKeyDispatcher == null ? false
+                    : TextUtils.equals(componentName,
+                            mCustomMediaKeyDispatcher.getClass().getName());
+        }
+
+        @Override
+        public boolean hasCustomMediaSessionPolicyProvider(String componentName) {
+            return mCustomMediaSessionPolicyProvider == null ? false
+                    : TextUtils.equals(componentName,
+                            mCustomMediaSessionPolicyProvider.getClass().getName());
+        }
+
+        @Override
         public int getSessionPolicies(MediaSession.Token token) {
             synchronized (mLock) {
                 MediaSessionRecord record = getMediaSessionRecordLocked(token);
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index f8ff5b5..50eed19 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -16,7 +16,7 @@
 
 package com.android.server.media;
 
-import static com.android.server.media.SessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_SESSION;
+import static com.android.server.media.MediaSessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_SESSION;
 
 import android.media.Session2Token;
 import android.media.session.MediaSession;
diff --git a/services/core/java/com/android/server/net/NetworkIdentitySet.java b/services/core/java/com/android/server/net/NetworkIdentitySet.java
index bce8069..22ed781 100644
--- a/services/core/java/com/android/server/net/NetworkIdentitySet.java
+++ b/services/core/java/com/android/server/net/NetworkIdentitySet.java
@@ -40,6 +40,7 @@
     private static final int VERSION_ADD_NETWORK_ID = 3;
     private static final int VERSION_ADD_METERED = 4;
     private static final int VERSION_ADD_DEFAULT_NETWORK = 5;
+    private static final int VERSION_ADD_OEM_MANAGED_NETWORK = 6;
 
     public NetworkIdentitySet() {
     }
@@ -84,13 +85,20 @@
                 defaultNetwork = true;
             }
 
+            final int oemNetCapabilities;
+            if (version >= VERSION_ADD_OEM_MANAGED_NETWORK) {
+                oemNetCapabilities = in.readInt();
+            } else {
+                oemNetCapabilities = NetworkIdentity.OEM_NONE;
+            }
+
             add(new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered,
-                    defaultNetwork));
+                    defaultNetwork, oemNetCapabilities));
         }
     }
 
     public void writeToStream(DataOutput out) throws IOException {
-        out.writeInt(VERSION_ADD_DEFAULT_NETWORK);
+        out.writeInt(VERSION_ADD_OEM_MANAGED_NETWORK);
         out.writeInt(size());
         for (NetworkIdentity ident : this) {
             out.writeInt(ident.getType());
@@ -100,6 +108,7 @@
             out.writeBoolean(ident.getRoaming());
             out.writeBoolean(ident.getMetered());
             out.writeBoolean(ident.getDefaultNetwork());
+            out.writeInt(ident.getOemManaged());
         }
     }
 
diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
index 676f421..4b41466 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
@@ -29,6 +29,7 @@
 import static android.os.Process.INVALID_UID;
 
 import android.app.ActivityManager;
+import android.app.ActivityManager.ProcessCapability;
 import android.net.NetworkPolicyManager;
 import android.os.UserHandle;
 import android.util.Log;
@@ -97,13 +98,15 @@
         }
     }
 
-    void uidStateChanged(int uid, int procState, long procStateSeq) {
+    void uidStateChanged(int uid, int procState, long procStateSeq,
+            @ProcessCapability int capability) {
         synchronized (mLock) {
             if (LOGV || uid == mDebugUid) {
                 Slog.v(TAG, uid + " state changed to "
-                        + ProcessList.makeProcStateString(procState) + " with seq=" + procStateSeq);
+                        + ProcessList.makeProcStateString(procState) + ",seq=" + procStateSeq
+                        + ",cap=" + ActivityManager.getCapabilitiesSummary(capability));
             }
-            mUidStateChangeBuffer.uidStateChanged(uid, procState, procStateSeq);
+            mUidStateChangeBuffer.uidStateChanged(uid, procState, procStateSeq, capability);
         }
     }
 
@@ -373,7 +376,8 @@
             super(Data.class, capacity);
         }
 
-        public void uidStateChanged(int uid, int procState, long procStateSeq) {
+        public void uidStateChanged(int uid, int procState, long procStateSeq,
+                @ProcessCapability int capability) {
             final Data data = getNextSlot();
             if (data == null) return;
 
@@ -381,6 +385,7 @@
             data.type = EVENT_UID_STATE_CHANGED;
             data.ifield1 = uid;
             data.ifield2 = procState;
+            data.ifield3 = capability;
             data.lfield1 = procStateSeq;
             data.timeStamp = System.currentTimeMillis();
         }
@@ -546,8 +551,9 @@
                 case EVENT_NETWORK_BLOCKED:
                     return data.ifield1 + "-" + getBlockedReason(data.ifield2);
                 case EVENT_UID_STATE_CHANGED:
-                    return data.ifield1 + "-" + ProcessList.makeProcStateString(data.ifield2)
-                            + "-" + data.lfield1;
+                    return data.ifield1 + ":" + ProcessList.makeProcStateString(data.ifield2)
+                            + ":" + ActivityManager.getCapabilitiesSummary(data.ifield3)
+                            + ":" + data.lfield1;
                 case EVENT_POLICIES_CHANGED:
                     return getPolicyChangedLog(data.ifield1, data.ifield2, data.ifield3);
                 case EVENT_METEREDNESS_CHANGED:
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index aa7da54..067c5c0e 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -54,6 +54,7 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkIdentity.OEM_NONE;
 import static android.net.NetworkPolicy.LIMIT_DISABLED;
 import static android.net.NetworkPolicy.SNOOZE_NEVER;
 import static android.net.NetworkPolicy.WARNING_DISABLED;
@@ -131,6 +132,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.ActivityManager.ProcessCapability;
 import android.app.ActivityManagerInternal;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
@@ -166,6 +168,7 @@
 import android.net.NetworkIdentity;
 import android.net.NetworkPolicy;
 import android.net.NetworkPolicyManager;
+import android.net.NetworkPolicyManager.UidState;
 import android.net.NetworkQuotaInfo;
 import android.net.NetworkRequest;
 import android.net.NetworkSpecifier;
@@ -557,7 +560,7 @@
 
     /** Foreground at UID granularity. */
     @GuardedBy("mUidRulesFirstLock")
-    final SparseIntArray mUidState = new SparseIntArray();
+    final SparseArray<UidState> mUidState = new SparseArray<UidState>();
 
     /** Map from network ID to last observed meteredness state */
     @GuardedBy("mNetworkPoliciesSecondLock")
@@ -880,9 +883,10 @@
 
             mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
             try {
+                // TODO: There shouldn't be a need to receive callback for all changes.
                 mActivityManager.registerUidObserver(mUidObserver,
                         ActivityManager.UID_OBSERVER_PROCSTATE|ActivityManager.UID_OBSERVER_GONE,
-                        NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE, "android");
+                        ActivityManager.PROCESS_STATE_UNKNOWN, "android");
                 mNetworkManager.registerObserver(mAlertObserver);
             } catch (RemoteException e) {
                 // ignored; both services live in system_server
@@ -988,9 +992,12 @@
 
     final private IUidObserver mUidObserver = new IUidObserver.Stub() {
         @Override public void onUidStateChanged(int uid, int procState, long procStateSeq,
-                int capability) {
+                @ProcessCapability int capability) {
+            // TODO: Avoid creating a new UidStateCallbackInfo object every time
+            // we get a callback for an uid
             mUidEventHandler.obtainMessage(UID_MSG_STATE_CHANGED,
-                    uid, procState, procStateSeq).sendToTarget();
+                    new UidStateCallbackInfo(uid, procState, procStateSeq, capability))
+                            .sendToTarget();
         }
 
         @Override public void onUidGone(int uid, boolean disabled) {
@@ -1007,6 +1014,22 @@
         }
     };
 
+    private static final class UidStateCallbackInfo {
+        public final int uid;
+        public final int procState;
+        public final long procStateSeq;
+        @ProcessCapability
+        public final int capability;
+
+        UidStateCallbackInfo(int uid, int procState, long procStateSeq,
+                @ProcessCapability int capability) {
+            this.uid = uid;
+            this.procState = procState;
+            this.procStateSeq = procStateSeq;
+            this.capability = capability;
+        }
+    }
+
     final private BroadcastReceiver mPowerSaveWhitelistReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -1382,7 +1405,11 @@
             final String subscriberId = mSubIdToSubscriberId.valueAt(i);
             final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
                     TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true,
-                    true);
+                    true, OEM_NONE);
+            /* While OEM_NONE indicates "any non OEM managed network", OEM_NONE is meant to be a
+             * placeholder value here. The probeIdent is matched against a NetworkTemplate which
+             * should have its OEM managed value set to OEM_MANAGED_ALL, which will cause the
+             * template to match probeIdent without regard to OEM managed status. */
             if (template.matches(probeIdent)) {
                 return subId;
             }
@@ -1612,7 +1639,8 @@
         // find and update the mobile NetworkPolicy for this subscriber id
         boolean policyUpdated = false;
         final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
-                TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true, true);
+                TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true, true,
+                OEM_NONE);
         for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) {
             final NetworkTemplate template = mNetworkPolicy.keyAt(i);
             if (template.matches(probeIdent)) {
@@ -1841,7 +1869,7 @@
 
                     final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
                             TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true,
-                            true);
+                            true, OEM_NONE);
                     // Template is matched when subscriber id matches.
                     if (template.matches(probeIdent)) {
                         matchingSubIds.add(subId);
@@ -2156,7 +2184,8 @@
     private boolean ensureActiveMobilePolicyAL(int subId, String subscriberId) {
         // Poke around to see if we already have a policy
         final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
-                TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true, true);
+                TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true, true,
+                OEM_NONE);
         for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) {
             final NetworkTemplate template = mNetworkPolicy.keyAt(i);
             if (template.matches(probeIdent)) {
@@ -3718,14 +3747,12 @@
                     fout.print("UID=");
                     fout.print(uid);
 
-                    final int state = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
-                    fout.print(" state=");
-                    fout.print(state);
-                    if (state <= ActivityManager.PROCESS_STATE_TOP) {
-                        fout.print(" (fg)");
+                    final UidState uidState = mUidState.get(uid);
+                    if (uidState == null) {
+                        fout.print(" state={null}");
                     } else {
-                        fout.print(state <= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
-                                ? " (fg svc)" : " (bg)");
+                        fout.print(" state=");
+                        fout.print(uidState.toString());
                     }
 
                     final int uidRules = mUidRules.get(uid, RULE_NONE);
@@ -3783,26 +3810,20 @@
     @VisibleForTesting
     boolean isUidForeground(int uid) {
         synchronized (mUidRulesFirstLock) {
-            return isUidStateForeground(
-                    mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY));
+            return isProcStateAllowedWhileIdleOrPowerSaveMode(mUidState.get(uid));
         }
     }
 
     @GuardedBy("mUidRulesFirstLock")
     private boolean isUidForegroundOnRestrictBackgroundUL(int uid) {
-        final int procState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
-        return isProcStateAllowedWhileOnRestrictBackground(procState);
+        final UidState uidState = mUidState.get(uid);
+        return isProcStateAllowedWhileOnRestrictBackground(uidState);
     }
 
     @GuardedBy("mUidRulesFirstLock")
     private boolean isUidForegroundOnRestrictPowerUL(int uid) {
-        final int procState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
-        return isProcStateAllowedWhileIdleOrPowerSaveMode(procState);
-    }
-
-    private boolean isUidStateForeground(int state) {
-        // only really in foreground when screen is also on
-        return state <= NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE;
+        final UidState uidState = mUidState.get(uid);
+        return isProcStateAllowedWhileIdleOrPowerSaveMode(uidState);
     }
 
     /**
@@ -3811,16 +3832,18 @@
      * {@link #updateRulesForPowerRestrictionsUL(int)}. Returns true if the state was updated.
      */
     @GuardedBy("mUidRulesFirstLock")
-    private boolean updateUidStateUL(int uid, int uidState) {
+    private boolean updateUidStateUL(int uid, int procState, @ProcessCapability int capability) {
         Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateUidStateUL");
         try {
-            final int oldUidState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
-            if (oldUidState != uidState) {
+            final UidState oldUidState = mUidState.get(uid);
+            if (oldUidState == null || oldUidState.procState != procState
+                    || oldUidState.capability != capability) {
+                final UidState newUidState = new UidState(uid, procState, capability);
                 // state changed, push updated rules
-                mUidState.put(uid, uidState);
-                updateRestrictBackgroundRulesOnUidStatusChangedUL(uid, oldUidState, uidState);
+                mUidState.put(uid, newUidState);
+                updateRestrictBackgroundRulesOnUidStatusChangedUL(uid, oldUidState, newUidState);
                 if (isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState)
-                        != isProcStateAllowedWhileIdleOrPowerSaveMode(uidState) ) {
+                        != isProcStateAllowedWhileIdleOrPowerSaveMode(newUidState)) {
                     updateRuleForAppIdleUL(uid);
                     if (mDeviceIdleMode) {
                         updateRuleForDeviceIdleUL(uid);
@@ -3842,11 +3865,10 @@
     private boolean removeUidStateUL(int uid) {
         final int index = mUidState.indexOfKey(uid);
         if (index >= 0) {
-            final int oldUidState = mUidState.valueAt(index);
+            final UidState oldUidState = mUidState.valueAt(index);
             mUidState.removeAt(index);
-            if (oldUidState != ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
-                updateRestrictBackgroundRulesOnUidStatusChangedUL(uid, oldUidState,
-                        ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+            if (oldUidState != null) {
+                updateRestrictBackgroundRulesOnUidStatusChangedUL(uid, oldUidState, null);
                 if (mDeviceIdleMode) {
                     updateRuleForDeviceIdleUL(uid);
                 }
@@ -3873,8 +3895,8 @@
         }
     }
 
-    private void updateRestrictBackgroundRulesOnUidStatusChangedUL(int uid, int oldUidState,
-            int newUidState) {
+    private void updateRestrictBackgroundRulesOnUidStatusChangedUL(int uid,
+            @Nullable UidState oldUidState, @Nullable UidState newUidState) {
         final boolean oldForeground =
                 isProcStateAllowedWhileOnRestrictBackground(oldUidState);
         final boolean newForeground =
@@ -4979,11 +5001,14 @@
         public boolean handleMessage(Message msg) {
             switch (msg.what) {
                 case UID_MSG_STATE_CHANGED: {
-                    final int uid = msg.arg1;
-                    final int procState = msg.arg2;
-                    final long procStateSeq = (Long) msg.obj;
+                    final UidStateCallbackInfo uidStateCallbackInfo =
+                            (UidStateCallbackInfo) msg.obj;
+                    final int uid = uidStateCallbackInfo.uid;
+                    final int procState = uidStateCallbackInfo.procState;
+                    final long procStateSeq = uidStateCallbackInfo.procStateSeq;
+                    final int capability = uidStateCallbackInfo.capability;
 
-                    handleUidChanged(uid, procState, procStateSeq);
+                    handleUidChanged(uid, procState, procStateSeq, capability);
                     return true;
                 }
                 case UID_MSG_GONE: {
@@ -4998,23 +5023,24 @@
         }
     };
 
-    void handleUidChanged(int uid, int procState, long procStateSeq) {
+    void handleUidChanged(int uid, int procState, long procStateSeq,
+            @ProcessCapability int capability) {
         Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "onUidStateChanged");
         try {
             boolean updated;
             synchronized (mUidRulesFirstLock) {
                 // We received a uid state change callback, add it to the history so that it
                 // will be useful for debugging.
-                mLogger.uidStateChanged(uid, procState, procStateSeq);
+                mLogger.uidStateChanged(uid, procState, procStateSeq, capability);
                 // Now update the network policy rules as per the updated uid state.
-                updated = updateUidStateUL(uid, procState);
+                updated = updateUidStateUL(uid, procState, capability);
                 // Updating the network rules is done, so notify AMS about this.
                 mActivityManagerInternal.notifyNetworkPolicyRulesUpdated(uid, procStateSeq);
             }
             // Do this without the lock held. handleUidChanged() and handleUidGone() are
             // called from the handler, so there's no multi-threading issue.
             if (updated) {
-                updateNetworkStats(uid, isUidStateForeground(procState));
+                updateNetworkStats(uid, isProcStateAllowedWhileOnRestrictBackground(procState));
             }
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
@@ -5349,6 +5375,13 @@
         }
     }
 
+    private static void collectKeys(SparseArray<UidState> source, SparseBooleanArray target) {
+        final int size = source.size();
+        for (int i = 0; i < size; i++) {
+            target.put(source.keyAt(i), true);
+        }
+    }
+
     @Override
     public void factoryReset(String subscriber) {
         mContext.enforceCallingOrSelfPermission(NETWORK_SETTINGS, TAG);
diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java
index 6aefe41..557fa89 100644
--- a/services/core/java/com/android/server/net/NetworkStatsCollection.java
+++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java
@@ -54,6 +54,8 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.FastDataInput;
+import com.android.internal.util.FastDataOutput;
 import com.android.internal.util.FileRotator;
 import com.android.internal.util.IndentingPrintWriter;
 
@@ -89,6 +91,9 @@
     /** File header magic number: "ANET" */
     private static final int FILE_MAGIC = 0x414E4554;
 
+    /** Default buffer size from BufferedInputStream */
+    private static final int BUFFER_SIZE = 8192;
+
     private static final int VERSION_NETWORK_INIT = 1;
 
     private static final int VERSION_UID_INIT = 1;
@@ -434,7 +439,8 @@
 
     @Override
     public void read(InputStream in) throws IOException {
-        read((DataInput) new DataInputStream(in));
+        final FastDataInput dataIn = new FastDataInput(in, BUFFER_SIZE);
+        read(dataIn);
     }
 
     private void read(DataInput in) throws IOException {
@@ -473,8 +479,9 @@
 
     @Override
     public void write(OutputStream out) throws IOException {
-        write((DataOutput) new DataOutputStream(out));
-        out.flush();
+        final FastDataOutput dataOut = new FastDataOutput(out, BUFFER_SIZE);
+        write(dataOut);
+        dataOut.flush();
     }
 
     private void write(DataOutput out) throws IOException {
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 9706bce..5b9a11b 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -1319,7 +1319,7 @@
                     NetworkIdentity vtIdent = new NetworkIdentity(ident.getType(),
                             ident.getSubType(), ident.getSubscriberId(), ident.getNetworkId(),
                             ident.getRoaming(), true /* metered */,
-                            true /* onDefaultNetwork */);
+                            true /* onDefaultNetwork */, ident.getOemManaged());
                     findOrCreateNetworkIdentitySet(mActiveIfaces, IFACE_VT).add(vtIdent);
                     findOrCreateNetworkIdentitySet(mActiveUidIfaces, IFACE_VT).add(vtIdent);
                 }
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index 1051423..afb47e8 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -18,6 +18,7 @@
 
 import android.app.Notification;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.UserHandle;
 import android.service.notification.NotificationStats;
 
@@ -31,7 +32,7 @@
     void onNotificationActionClick(int callingUid, int callingPid, String key, int actionIndex,
             Notification.Action action, NotificationVisibility nv, boolean generatedByAssistant);
     void onNotificationClear(int callingUid, int callingPid,
-            String pkg, String tag, int id, int userId, String key,
+            String pkg, int userId, String key,
             @NotificationStats.DismissalSurface int dismissalSurface,
             @NotificationStats.DismissalSentiment int dismissalSentiment,
             NotificationVisibility nv);
@@ -88,5 +89,13 @@
     void onNotificationSmartReplySent(String key, int clickedIndex, CharSequence reply,
             int notificationLocation, boolean modifiedBeforeSending);
 
+    /**
+     * Notifies a user feedback is provided.
+     *
+     * @param key the notification key
+     * @param feedback the feedback detail
+     */
+    void onNotificationFeedbackReceived(String key, Bundle feedback);
+
     void prepareForPossibleShutdown();
 }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 917be29..73db705 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -64,6 +64,8 @@
 import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
+import static android.os.PowerWhitelistManager.REASON_NOTIFICATION_SERVICE;
+import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
 import static android.os.UserHandle.USER_NULL;
 import static android.os.UserHandle.USER_SYSTEM;
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ALERTING;
@@ -73,6 +75,8 @@
 import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS;
 import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS;
 import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS;
+import static android.service.notification.NotificationListenerService.META_DATA_DEFAULT_FILTER_TYPES;
+import static android.service.notification.NotificationListenerService.META_DATA_DISABLED_FILTER_TYPES;
 import static android.service.notification.NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED;
 import static android.service.notification.NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED;
 import static android.service.notification.NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED;
@@ -172,7 +176,6 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.ParceledListSlice;
-import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutServiceInternal;
@@ -215,7 +218,6 @@
 import android.provider.Settings;
 import android.service.notification.Adjustment;
 import android.service.notification.Condition;
-import android.service.notification.ConditionProviderService;
 import android.service.notification.ConversationChannelWrapper;
 import android.service.notification.IConditionProvider;
 import android.service.notification.INotificationListener;
@@ -383,7 +385,8 @@
             Adjustment.KEY_TEXT_REPLIES,
             Adjustment.KEY_NOT_CONVERSATION,
             Adjustment.KEY_IMPORTANCE,
-            Adjustment.KEY_RANKING_SCORE};
+            Adjustment.KEY_RANKING_SCORE
+    };
 
     static final String[] NON_BLOCKABLE_DEFAULT_ROLES = new String[] {
             RoleManager.ROLE_DIALER,
@@ -432,8 +435,6 @@
     private static final String SCHEME_TIMEOUT = "timeout";
     private static final String EXTRA_KEY = "key";
 
-    private static final String FEEDBACK_KEY = "feedback_key";
-
     private static final int NOTIFICATION_INSTANCE_ID_MAX = (1 << 13);
 
     /**
@@ -1020,30 +1021,26 @@
                     return;
                 }
                 final long now = System.currentTimeMillis();
-                //TODO(b/154257994): remove this when feedback apis are in place
-                boolean isFeedback = action.getExtras().containsKey(FEEDBACK_KEY);
-                if (!isFeedback) {
-                    MetricsLogger.action(r.getLogMaker(now)
-                            .setCategory(MetricsEvent.NOTIFICATION_ITEM_ACTION)
-                            .setType(MetricsEvent.TYPE_ACTION)
-                            .setSubtype(actionIndex)
-                            .addTaggedData(MetricsEvent.NOTIFICATION_SHADE_INDEX, nv.rank)
-                            .addTaggedData(MetricsEvent.NOTIFICATION_SHADE_COUNT, nv.count)
-                            .addTaggedData(MetricsEvent.NOTIFICATION_ACTION_IS_SMART,
-                                    action.isContextual() ? 1 : 0)
-                            .addTaggedData(
-                                    MetricsEvent.NOTIFICATION_SMART_SUGGESTION_ASSISTANT_GENERATED,
-                                    generatedByAssistant ? 1 : 0)
-                            .addTaggedData(MetricsEvent.NOTIFICATION_LOCATION,
-                                    nv.location.toMetricsEventEnum()));
-                    mNotificationRecordLogger.log(
-                            NotificationRecordLogger.NotificationEvent.fromAction(actionIndex,
-                                    generatedByAssistant, action.isContextual()), r);
-                    EventLogTags.writeNotificationActionClicked(key, actionIndex,
-                            r.getLifespanMs(now), r.getFreshnessMs(now), r.getExposureMs(now),
-                            nv.rank, nv.count);
-                    nv.recycle();
-                }
+                MetricsLogger.action(r.getLogMaker(now)
+                        .setCategory(MetricsEvent.NOTIFICATION_ITEM_ACTION)
+                        .setType(MetricsEvent.TYPE_ACTION)
+                        .setSubtype(actionIndex)
+                        .addTaggedData(MetricsEvent.NOTIFICATION_SHADE_INDEX, nv.rank)
+                        .addTaggedData(MetricsEvent.NOTIFICATION_SHADE_COUNT, nv.count)
+                        .addTaggedData(MetricsEvent.NOTIFICATION_ACTION_IS_SMART,
+                                action.isContextual() ? 1 : 0)
+                        .addTaggedData(
+                                MetricsEvent.NOTIFICATION_SMART_SUGGESTION_ASSISTANT_GENERATED,
+                                generatedByAssistant ? 1 : 0)
+                        .addTaggedData(MetricsEvent.NOTIFICATION_LOCATION,
+                                nv.location.toMetricsEventEnum()));
+                mNotificationRecordLogger.log(
+                        NotificationRecordLogger.NotificationEvent.fromAction(actionIndex,
+                                generatedByAssistant, action.isContextual()), r);
+                EventLogTags.writeNotificationActionClicked(key, actionIndex,
+                        r.getLifespanMs(now), r.getFreshnessMs(now), r.getExposureMs(now),
+                        nv.rank, nv.count);
+                nv.recycle();
                 reportUserInteraction(r);
                 mAssistants.notifyAssistantActionClicked(r, action, generatedByAssistant);
             }
@@ -1051,15 +1048,19 @@
 
         @Override
         public void onNotificationClear(int callingUid, int callingPid,
-                String pkg, String tag, int id, int userId, String key,
+                String pkg, int userId, String key,
                 @NotificationStats.DismissalSurface int dismissalSurface,
                 @NotificationStats.DismissalSentiment int dismissalSentiment,
                 NotificationVisibility nv) {
+            String tag = null;
+            int id = 0;
             synchronized (mNotificationLock) {
                 NotificationRecord r = mNotificationsByKey.get(key);
                 if (r != null) {
                     r.recordDismissalSurface(dismissalSurface);
                     r.recordDismissalSentiment(dismissalSentiment);
+                    tag = r.getSbn().getTag();
+                    id = r.getSbn().getId();
                 }
             }
             cancelNotification(callingUid, callingPid, pkg, tag, id, 0,
@@ -1386,6 +1387,20 @@
                 }
             }
         }
+
+        @Override
+        public void onNotificationFeedbackReceived(String key, Bundle feedback) {
+            exitIdle();
+            synchronized (mNotificationLock) {
+                NotificationRecord r = mNotificationsByKey.get(key);
+                if (r == null) {
+                    if (DBG) Slog.w(TAG, "No notification with key: " + key);
+                    return;
+                }
+                mAssistants.notifyAssistantFeedbackReceived(r, feedback);
+            }
+        }
+
     };
 
     @VisibleForTesting
@@ -5990,10 +6005,11 @@
                 for (int i = 0; i < intentCount; i++) {
                     PendingIntent pendingIntent = notification.allPendingIntents.valueAt(i);
                     if (pendingIntent != null) {
-                        am.setPendingIntentWhitelistDuration(pendingIntent.getTarget(),
+                        am.setPendingIntentAllowlistDuration(pendingIntent.getTarget(),
                                 ALLOWLIST_TOKEN, duration,
-                                BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED
-                        );
+                                TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+                                REASON_NOTIFICATION_SERVICE,
+                                "NotificationManagerService");
                         am.setPendingIntentAllowBgActivityStarts(pendingIntent.getTarget(),
                                 ALLOWLIST_TOKEN, (FLAG_ACTIVITY_SENDER | FLAG_BROADCAST_SENDER
                                         | FLAG_SERVICE_SENDER));
@@ -9505,6 +9521,26 @@
                     });
         }
 
+        @GuardedBy("mNotificationLock")
+        void notifyAssistantFeedbackReceived(final NotificationRecord r, Bundle feedback) {
+            final StatusBarNotification sbn = r.getSbn();
+
+            for (final ManagedServiceInfo info : NotificationAssistants.this.getServices()) {
+                boolean sbnVisible = isVisibleToListener(
+                        sbn, r.getNotificationType(), info)
+                        && info.isSameUser(r.getUserId());
+                if (sbnVisible) {
+                    final INotificationListener assistant = (INotificationListener) info.service;
+                    try {
+                        final NotificationRankingUpdate update = makeRankingUpdateLocked(info);
+                        assistant.onNotificationFeedbackReceived(sbn.getKey(), update, feedback);
+                    } catch (RemoteException ex) {
+                        Slog.e(TAG, "unable to notify assistant (feedback): " + assistant, ex);
+                    }
+                }
+            }
+        }
+
         /**
          * Notifies the assistant something about the specified notification, only assistant
          * that is visible to the notification will be notified.
@@ -9832,33 +9868,54 @@
             Pair listener = Pair.create(si.getComponentName(), userId);
             NotificationListenerFilter existingNlf =
                     mRequestedNotificationListeners.get(listener);
-            if (existingNlf  == null) {
-                // no stored filters for this listener; see if they provided a default
-                if (si.metaData != null) {
-                    String typeList = si.metaData.getString(
-                            NotificationListenerService.META_DATA_DEFAULT_FILTER_TYPES);
-                    if (typeList != null) {
-                        int types = 0;
-                        String[] typeStrings = typeList.split(XML_SEPARATOR);
-                        for (int i = 0; i < typeStrings.length; i++) {
-                            if (TextUtils.isEmpty(typeStrings[i])) {
-                                continue;
-                            }
-                            try {
-                                types |= Integer.parseInt(typeStrings[i]);
-                            } catch (NumberFormatException e) {
-                                // skip
-                            }
+            if (si.metaData != null) {
+                if (existingNlf  == null) {
+                    // no stored filters for this listener; see if they provided a default
+                    if (si.metaData.containsKey(META_DATA_DEFAULT_FILTER_TYPES)) {
+                        String typeList =
+                                si.metaData.get(META_DATA_DEFAULT_FILTER_TYPES).toString();
+                        if (typeList != null) {
+                            int types = getTypesFromStringList(typeList);
+                            NotificationListenerFilter nlf =
+                                    new NotificationListenerFilter(types, new ArraySet<>());
+                            mRequestedNotificationListeners.put(listener, nlf);
                         }
+                    }
+                }
 
-                         NotificationListenerFilter nlf =
-                                 new NotificationListenerFilter(types, new ArraySet<>());
+                // also check the types they never want bridged
+                if (si.metaData.containsKey(META_DATA_DISABLED_FILTER_TYPES)) {
+                    int neverBridge = getTypesFromStringList(si.metaData.get(
+                            META_DATA_DISABLED_FILTER_TYPES).toString());
+                    if (neverBridge != 0) {
+                        NotificationListenerFilter nlf =
+                                mRequestedNotificationListeners.getOrDefault(
+                                        listener, new NotificationListenerFilter());
+                        nlf.setTypes(nlf.getTypes() & ~neverBridge);
                         mRequestedNotificationListeners.put(listener, nlf);
                     }
                 }
             }
         }
 
+        private int getTypesFromStringList(String typeList) {
+            int types = 0;
+            if (typeList != null) {
+                String[] typeStrings = typeList.split(XML_SEPARATOR);
+                for (int i = 0; i < typeStrings.length; i++) {
+                    if (TextUtils.isEmpty(typeStrings[i])) {
+                        continue;
+                    }
+                    try {
+                        types |= Integer.parseInt(typeStrings[i]);
+                    } catch (NumberFormatException e) {
+                        // skip
+                    }
+                }
+            }
+            return types;
+        }
+
         @GuardedBy("mNotificationLock")
         public void setOnNotificationPostedTrimLocked(ManagedServiceInfo info, int trim) {
             if (trim == TRIM_LIGHT) {
diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java
index f078242..4500bbc 100644
--- a/services/core/java/com/android/server/notification/SnoozeHelper.java
+++ b/services/core/java/com/android/server/notification/SnoozeHelper.java
@@ -39,6 +39,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.util.XmlUtils;
+import com.android.server.pm.PackageManagerService;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -465,6 +466,7 @@
         return PendingIntent.getBroadcast(mContext,
                 REQUEST_CODE_REPOST,
                 new Intent(REPOST_ACTION)
+                        .setPackage(PackageManagerService.PLATFORM_PACKAGE_NAME)
                         .setData(new Uri.Builder().scheme(REPOST_SCHEME).appendPath(key).build())
                         .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
                         .putExtra(EXTRA_KEY, key)
diff --git a/services/core/java/com/android/server/om/OverlayActorEnforcer.java b/services/core/java/com/android/server/om/OverlayActorEnforcer.java
index 2d540de..c4b6485 100644
--- a/services/core/java/com/android/server/om/OverlayActorEnforcer.java
+++ b/services/core/java/com/android/server/om/OverlayActorEnforcer.java
@@ -23,6 +23,7 @@
 import android.os.Process;
 import android.text.TextUtils;
 import android.util.Pair;
+import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
@@ -42,9 +43,6 @@
  */
 public class OverlayActorEnforcer {
 
-    // By default, the reason is not logged to prevent leaks of why it failed
-    private static final boolean DEBUG_REASON = false;
-
     private final PackageManagerHelper mPackageManager;
 
     /**
@@ -85,17 +83,18 @@
 
     void enforceActor(@NonNull OverlayInfo overlayInfo, @NonNull String methodName,
             int callingUid, int userId) throws SecurityException {
-        ActorState actorState = isAllowedActor(methodName, overlayInfo, callingUid, userId);
+        final ActorState actorState = isAllowedActor(methodName, overlayInfo, callingUid, userId);
         if (actorState == ActorState.ALLOWED) {
             return;
         }
 
-        String targetOverlayableName = overlayInfo.targetOverlayableName;
-        throw new SecurityException("UID" + callingUid + " is not allowed to call "
-                + methodName + " for "
+        final String targetOverlayableName = overlayInfo.targetOverlayableName;
+        final String errorMessage = "UID" + callingUid + " is not allowed to call " + methodName
+                + " for "
                 + (TextUtils.isEmpty(targetOverlayableName) ? "" : (targetOverlayableName + " in "))
-                + overlayInfo.targetPackageName + (DEBUG_REASON ? (" because " + actorState) : "")
-        );
+                + overlayInfo.targetPackageName + " for user " + userId;
+        Slog.w(OverlayManagerService.TAG, errorMessage + " because " + actorState);
+        throw new SecurityException(errorMessage);
     }
 
     /**
diff --git a/services/core/java/com/android/server/os/NativeTombstoneManager.java b/services/core/java/com/android/server/os/NativeTombstoneManager.java
index a83edb7..9c4c510 100644
--- a/services/core/java/com/android/server/os/NativeTombstoneManager.java
+++ b/services/core/java/com/android/server/os/NativeTombstoneManager.java
@@ -16,24 +16,38 @@
 
 package com.android.server.os;
 
+import static android.app.ApplicationExitInfo.REASON_CRASH_NATIVE;
+import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
 import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
 import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
 
 import android.annotation.AppIdInt;
+import android.annotation.CurrentTimeMillisLong;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
+import android.app.ActivityManager.RunningAppProcessInfo;
+import android.app.ApplicationExitInfo;
+import android.app.IParcelFileDescriptorRetriever;
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.os.FileObserver;
 import android.os.Handler;
 import android.os.ParcelFileDescriptor;
 import android.os.UserHandle;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.StructStat;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.proto.ProtoInputStream;
+import android.util.proto.ProtoParseException;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.server.BootReceiver;
 import com.android.server.ServiceThread;
+import com.android.server.os.TombstoneProtos.Cause;
 import com.android.server.os.TombstoneProtos.Tombstone;
 
 import libcore.io.IoUtils;
@@ -42,7 +56,11 @@
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
 
 /**
  * A class to manage native tombstones.
@@ -75,6 +93,9 @@
     }
 
     void onSystemReady() {
+        registerForUserRemoval();
+        registerForPackageRemoval();
+
         // Scan existing tombstones.
         mHandler.post(() -> {
             final File[] tombstoneFiles = TOMBSTONE_DIR.listFiles();
@@ -94,8 +115,9 @@
 
         if (filename.endsWith(".pb")) {
             handleProtoTombstone(path);
+            BootReceiver.addTombstoneToDropBox(mContext, path, true);
         } else {
-            BootReceiver.addTombstoneToDropBox(mContext, path);
+            BootReceiver.addTombstoneToDropBox(mContext, path, false);
         }
     }
 
@@ -145,18 +167,164 @@
         }
     }
 
+    /**
+     * Remove native tombstones matching a user and/or app.
+     *
+     * @param userId user id to filter by, selects all users if empty
+     * @param appId app id to filter by, selects all users if empty
+     */
+    public void purge(Optional<Integer> userId, Optional<Integer> appId) {
+        mHandler.post(() -> {
+            synchronized (mLock) {
+                for (int i = mTombstones.size() - 1; i >= 0; --i) {
+                    TombstoneFile tombstone = mTombstones.valueAt(i);
+                    if (tombstone.matches(userId, appId)) {
+                        tombstone.purge();
+                        mTombstones.removeAt(i);
+                    }
+                }
+            }
+        });
+    }
+
+    private void purgePackage(int uid, boolean allUsers) {
+        final int appId = UserHandle.getAppId(uid);
+        Optional<Integer> userId;
+        if (allUsers) {
+            userId = Optional.empty();
+        } else {
+            userId = Optional.of(UserHandle.getUserId(uid));
+        }
+        purge(userId, Optional.of(appId));
+    }
+
+    private void purgeUser(int uid) {
+        purge(Optional.of(uid), Optional.empty());
+    }
+
+    private void registerForPackageRemoval() {
+        final IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
+        filter.addDataScheme("package");
+        mContext.registerReceiverForAllUsers(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                final int uid = intent.getIntExtra(Intent.EXTRA_UID, UserHandle.USER_NULL);
+                if (uid == UserHandle.USER_NULL) return;
+
+                final boolean allUsers = intent.getBooleanExtra(
+                        Intent.EXTRA_REMOVED_FOR_ALL_USERS, false);
+
+                purgePackage(uid, allUsers);
+            }
+        }, filter, null, mHandler);
+    }
+
+    private void registerForUserRemoval() {
+        final IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_USER_REMOVED);
+        mContext.registerReceiverForAllUsers(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+                if (userId < 1) return;
+
+                purgeUser(userId);
+            }
+        }, filter, null, mHandler);
+    }
+
+    /**
+     * Collect native tombstones.
+     *
+     * @param output list to append to
+     * @param callingUid POSIX uid to filter by
+     * @param pid pid to filter by, ignored if zero
+     * @param maxNum maximum number of elements in output
+     */
+    public void collectTombstones(ArrayList<ApplicationExitInfo> output, int callingUid, int pid,
+            int maxNum) {
+        CompletableFuture<Object> future = new CompletableFuture<>();
+
+        if (!UserHandle.isApp(callingUid)) {
+            return;
+        }
+
+        final int userId = UserHandle.getUserId(callingUid);
+        final int appId = UserHandle.getAppId(callingUid);
+
+        mHandler.post(() -> {
+            boolean appendedTombstones = false;
+
+            synchronized (mLock) {
+                final int tombstonesSize = mTombstones.size();
+
+            tombstoneIter:
+                for (int i = 0; i < tombstonesSize; ++i) {
+                    TombstoneFile tombstone = mTombstones.valueAt(i);
+                    if (tombstone.matches(Optional.of(userId), Optional.of(appId))) {
+                        if (pid != 0 && tombstone.mPid != pid) {
+                            continue;
+                        }
+
+                        // Try to attach to an existing REASON_CRASH_NATIVE.
+                        final int outputSize = output.size();
+                        for (int j = 0; j < outputSize; ++j) {
+                            ApplicationExitInfo exitInfo = output.get(j);
+                            if (tombstone.matches(exitInfo)) {
+                                exitInfo.setNativeTombstoneRetriever(tombstone.getPfdRetriever());
+                                continue tombstoneIter;
+                            }
+                        }
+
+                        if (output.size() < maxNum) {
+                            appendedTombstones = true;
+                            output.add(tombstone.toAppExitInfo());
+                        }
+                    }
+                }
+            }
+
+            if (appendedTombstones) {
+                Collections.sort(output, (lhs, rhs) -> {
+                    // Reports should be ordered with newest reports first.
+                    long diff = rhs.getTimestamp() - lhs.getTimestamp();
+                    if (diff < 0) {
+                        return -1;
+                    } else if (diff == 0) {
+                        return 0;
+                    } else {
+                        return 1;
+                    }
+                });
+            }
+            future.complete(null);
+        });
+
+        try {
+            future.get();
+        } catch (ExecutionException | InterruptedException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
     static class TombstoneFile {
         final ParcelFileDescriptor mPfd;
 
-        final @UserIdInt int mUserId;
-        final @AppIdInt int mAppId;
+        @UserIdInt int mUserId;
+        @AppIdInt int mAppId;
+
+        int mPid;
+        int mUid;
+        String mProcessName;
+        @CurrentTimeMillisLong long mTimestampMs;
+        String mCrashReason;
 
         boolean mPurged = false;
+        final IParcelFileDescriptorRetriever mRetriever = new ParcelFileDescriptorRetriever();
 
-        TombstoneFile(ParcelFileDescriptor pfd, @UserIdInt int userId, @AppIdInt int appId) {
+        TombstoneFile(ParcelFileDescriptor pfd) {
             mPfd = pfd;
-            mUserId = userId;
-            mAppId = appId;
         }
 
         public boolean matches(Optional<Integer> userId, Optional<Integer> appId) {
@@ -175,24 +343,90 @@
             return true;
         }
 
+        public boolean matches(ApplicationExitInfo exitInfo) {
+            if (exitInfo.getReason() != REASON_CRASH_NATIVE) {
+                return false;
+            }
+
+            if (exitInfo.getPid() != mPid) {
+                return false;
+            }
+
+            if (exitInfo.getRealUid() != mUid) {
+                return false;
+            }
+
+            if (Math.abs(exitInfo.getTimestamp() - mTimestampMs) > 1000) {
+                return false;
+            }
+
+            return true;
+        }
+
         public void dispose() {
             IoUtils.closeQuietly(mPfd);
         }
 
+        public void purge() {
+            if (!mPurged) {
+                // There's no way to atomically unlink a specific file for which we have an fd from
+                // a path, which means that we can't safely delete a tombstone without coordination
+                // with tombstoned (which has a risk of deadlock if for example, system_server hangs
+                // with a flock). Do the next best thing, and just truncate the file.
+                //
+                // We don't have to worry about inflicting a SIGBUS on a process that has the
+                // tombstone mmaped, because we only clear if the package has been removed, which
+                // means no one with access to the tombstone should be left.
+                try {
+                    Os.ftruncate(mPfd.getFileDescriptor(), 0);
+                } catch (ErrnoException ex) {
+                    Slog.e(TAG, "Failed to truncate tombstone", ex);
+                }
+                mPurged = true;
+            }
+        }
+
         static Optional<TombstoneFile> parse(ParcelFileDescriptor pfd) {
             final FileInputStream is = new FileInputStream(pfd.getFileDescriptor());
             final ProtoInputStream stream = new ProtoInputStream(is);
 
+            int pid = 0;
             int uid = 0;
+            String processName = "";
+            String crashReason = "";
             String selinuxLabel = "";
 
             try {
                 while (stream.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
                     switch (stream.getFieldNumber()) {
+                        case (int) Tombstone.PID:
+                            pid = stream.readInt(Tombstone.PID);
+                            break;
+
                         case (int) Tombstone.UID:
                             uid = stream.readInt(Tombstone.UID);
                             break;
 
+                        case (int) Tombstone.PROCESS_NAME:
+                            processName = stream.readString(Tombstone.PROCESS_NAME);
+                            break;
+
+                        case (int) Tombstone.CAUSE:
+                            long token = stream.start(Tombstone.CAUSE);
+                        cause:
+                            while (stream.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+                                switch (stream.getFieldNumber()) {
+                                    case (int) Cause.HUMAN_READABLE:
+                                        crashReason = stream.readString(Cause.HUMAN_READABLE);
+                                        break cause;
+
+                                    default:
+                                        break;
+                                }
+                            }
+                            stream.end(token);
+                            break;
+
                         case (int) Tombstone.SELINUX_LABEL:
                             selinuxLabel = stream.readString(Tombstone.SELINUX_LABEL);
                             break;
@@ -201,7 +435,7 @@
                             break;
                     }
                 }
-            } catch (IOException ex) {
+            } catch (IOException | ProtoParseException ex) {
                 Slog.e(TAG, "Failed to parse tombstone", ex);
                 return Optional.empty();
             }
@@ -211,6 +445,14 @@
                 return Optional.empty();
             }
 
+            long timestampMs = 0;
+            try {
+                StructStat stat = Os.fstat(pfd.getFileDescriptor());
+                timestampMs = stat.st_atim.tv_sec * 1000 + stat.st_atim.tv_nsec / 1000000;
+            } catch (ErrnoException ex) {
+                Slog.e(TAG, "Failed to get timestamp of tombstone", ex);
+            }
+
             final int userId = UserHandle.getUserId(uid);
             final int appId = UserHandle.getAppId(uid);
 
@@ -219,7 +461,74 @@
                 return Optional.empty();
             }
 
-            return Optional.of(new TombstoneFile(pfd, userId, appId));
+            TombstoneFile result = new TombstoneFile(pfd);
+
+            result.mUserId = userId;
+            result.mAppId = appId;
+            result.mPid = pid;
+            result.mUid = uid;
+            result.mProcessName = processName;
+            result.mTimestampMs = timestampMs;
+            result.mCrashReason = crashReason;
+
+            return Optional.of(result);
+        }
+
+        public IParcelFileDescriptorRetriever getPfdRetriever() {
+            return mRetriever;
+        }
+
+        public ApplicationExitInfo toAppExitInfo() {
+            ApplicationExitInfo info = new ApplicationExitInfo();
+            info.setPid(mPid);
+            info.setRealUid(mUid);
+            info.setPackageUid(mUid);
+            info.setDefiningUid(mUid);
+            info.setProcessName(mProcessName);
+            info.setReason(ApplicationExitInfo.REASON_CRASH_NATIVE);
+
+            // Signal numbers are architecture-specific!
+            // We choose to provide nothing here, to avoid leading users astray.
+            info.setStatus(0);
+
+            // No way for us to find out.
+            info.setImportance(RunningAppProcessInfo.IMPORTANCE_GONE);
+            info.setPackageName("");
+            info.setProcessStateSummary(null);
+
+            // We could find out, but they didn't get OOM-killed...
+            info.setPss(0);
+            info.setRss(0);
+
+            info.setTimestamp(mTimestampMs);
+            info.setDescription(mCrashReason);
+
+            info.setSubReason(ApplicationExitInfo.SUBREASON_UNKNOWN);
+            info.setNativeTombstoneRetriever(mRetriever);
+
+            return info;
+        }
+
+
+        class ParcelFileDescriptorRetriever extends IParcelFileDescriptorRetriever.Stub {
+            ParcelFileDescriptorRetriever() {}
+
+            public @Nullable ParcelFileDescriptor getPfd() {
+                if (mPurged) {
+                    return null;
+                }
+
+                // Reopen the file descriptor as read-only.
+                try {
+                    final String path = "/proc/self/fd/" + mPfd.getFd();
+                    ParcelFileDescriptor pfd = ParcelFileDescriptor.open(new File(path),
+                            MODE_READ_ONLY);
+                    return pfd;
+                } catch (FileNotFoundException ex) {
+                    Slog.e(TAG, "failed to reopen file descriptor as read-only", ex);
+                    return null;
+                }
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 5d7c41c..1acbabd 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -69,6 +69,7 @@
 import java.util.Set;
 import java.util.StringTokenizer;
 import java.util.concurrent.Executor;
+import java.util.function.Function;
 
 /**
  * The entity responsible for filtering visibility between apps based on declarations in their
@@ -1354,14 +1355,13 @@
     }
 
     public void dumpQueries(
-            PrintWriter pw, PackageManagerService pms, @Nullable Integer filteringAppId,
-            DumpState dumpState,
-            int[] users) {
+            PrintWriter pw, @Nullable Integer filteringAppId, DumpState dumpState, int[] users,
+            Function<Integer, String[]> getPackagesForUid) {
         final SparseArray<String> cache = new SparseArray<>();
         ToString<Integer> expandPackages = input -> {
             String cachedValue = cache.get(input);
             if (cachedValue == null) {
-                final String[] packagesForUid = pms.getPackagesForUid(input);
+                final String[] packagesForUid = getPackagesForUid.apply(input);
                 if (packagesForUid == null) {
                     cachedValue = "[unknown app id " + input + "]";
                 } else {
diff --git a/services/core/java/com/android/server/pm/DataLoaderManagerService.java b/services/core/java/com/android/server/pm/DataLoaderManagerService.java
index 308e815..9a9b14c 100644
--- a/services/core/java/com/android/server/pm/DataLoaderManagerService.java
+++ b/services/core/java/com/android/server/pm/DataLoaderManagerService.java
@@ -171,7 +171,7 @@
         }
     }
 
-    private class DataLoaderServiceConnection implements ServiceConnection {
+    private class DataLoaderServiceConnection implements ServiceConnection, IBinder.DeathRecipient {
         final int mId;
         final IDataLoaderStatusListener mListener;
         IDataLoader mDataLoader;
@@ -194,6 +194,13 @@
                 mContext.unbindService(this);
                 return;
             }
+            try {
+                service.linkToDeath(this, /*flags=*/0);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to link to DataLoader's death: " + mId, e);
+                onBindingDied(className);
+                return;
+            }
             callListener(IDataLoaderStatusListener.DATA_LOADER_BOUND);
         }
 
@@ -218,6 +225,13 @@
             destroy();
         }
 
+        @Override
+        public void binderDied() {
+            Slog.i(TAG, "DataLoader " + mId + " died");
+            callListener(IDataLoaderStatusListener.DATA_LOADER_DESTROYED);
+            destroy();
+        }
+
         IDataLoader getDataLoader() {
             return mDataLoader;
         }
diff --git a/services/core/java/com/android/server/pm/DumpState.java b/services/core/java/com/android/server/pm/DumpState.java
index 2a1fc87..6875b8a 100644
--- a/services/core/java/com/android/server/pm/DumpState.java
+++ b/services/core/java/com/android/server/pm/DumpState.java
@@ -55,6 +55,10 @@
     private int mOptions;
 
     private boolean mTitlePrinted;
+    private boolean mFullPreferred;
+    private boolean mCheckIn;
+
+    private String mTargetPackageName;
 
     private SharedUserSetting mSharedUser;
 
@@ -99,4 +103,28 @@
     public void setSharedUser(SharedUserSetting user) {
         mSharedUser = user;
     }
+
+    public String getTargetPackageName() {
+        return mTargetPackageName;
+    }
+
+    public void setTargetPackageName(String packageName) {
+        mTargetPackageName = packageName;
+    }
+
+    public boolean isFullPreferred() {
+        return mFullPreferred;
+    }
+
+    public void setFullPreferred(boolean fullPreferred) {
+        mFullPreferred = fullPreferred;
+    }
+
+    public boolean isCheckIn() {
+        return mCheckIn;
+    }
+
+    public void setCheckIn(boolean checkIn) {
+        mCheckIn = checkIn;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index b9e3e0f..0a443f3 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -780,7 +780,8 @@
         return getOatDir(codePath).getAbsolutePath();
     }
 
-    static File getOatDir(File codePath) {
+    /** Returns the oat dir for the given code path */
+    public static File getOatDir(File codePath) {
         return new File(codePath, OAT_DIR_NAME);
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 2812830..a5e28f1 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -530,14 +530,6 @@
             throw new SecurityException("User restriction prevents installing");
         }
 
-        if (params.dataLoaderParams != null
-                && mContext.checkCallingOrSelfPermission(Manifest.permission.USE_INSTALLER_V2)
-                        != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("You need the "
-                    + "com.android.permission.USE_INSTALLER_V2 permission "
-                    + "to use a data loader");
-        }
-
         // INSTALL_REASON_ROLLBACK allows an app to be rolled back without requiring the ROLLBACK
         // capability; ensure if this is set as the install reason the app has one of the necessary
         // signature permissions to perform the rollback.
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 0ce2673..460b2f2 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -70,6 +70,7 @@
 import android.content.pm.IPackageInstallObserver2;
 import android.content.pm.IPackageInstallerSession;
 import android.content.pm.IPackageInstallerSessionFileSystemConnector;
+import android.content.pm.IPackageLoadingProgressCallback;
 import android.content.pm.InstallationFile;
 import android.content.pm.InstallationFileParcel;
 import android.content.pm.PackageInfo;
@@ -321,6 +322,8 @@
     private float mProgress = 0;
     @GuardedBy("mLock")
     private float mReportedProgress = -1;
+    @GuardedBy("mLock")
+    private float mIncrementalProgress = 0;
 
     /** State of the session. */
     @GuardedBy("mLock")
@@ -778,7 +781,7 @@
     @GuardedBy("mLock")
     private File mInheritedFilesBase;
     @GuardedBy("mLock")
-    private boolean mVerityFound;
+    private boolean mVerityFoundForApks;
 
     /**
      * Both flags should be guarded with mLock whenever changes need to be in lockstep.
@@ -1007,9 +1010,14 @@
                 throw new IllegalArgumentException(
                         "DataLoader installation of APEX modules is not allowed.");
             }
+
             if (this.params.dataLoaderParams.getComponentName().getPackageName()
-                    == SYSTEM_DATA_LOADER_PACKAGE) {
-                assertShellOrSystemCalling("System data loaders");
+                    == SYSTEM_DATA_LOADER_PACKAGE && mContext.checkCallingOrSelfPermission(
+                    Manifest.permission.USE_SYSTEM_DATA_LOADERS)
+                    != PackageManager.PERMISSION_GRANTED) {
+                throw new SecurityException("You need the "
+                        + "com.android.permission.USE_SYSTEM_DATA_LOADERS permission "
+                        + "to use system data loaders");
             }
         }
 
@@ -1199,8 +1207,13 @@
 
     @GuardedBy("mLock")
     private void computeProgressLocked(boolean forcePublish) {
-        mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f)
-                + MathUtils.constrain(mInternalProgress * 0.2f, 0f, 0.2f);
+        if (!mCommitted) {
+            mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f)
+                    + MathUtils.constrain(mInternalProgress * 0.2f, 0f, 0.2f);
+        } else {
+            // For incremental installs, continue publishing the install progress during committing.
+            mProgress = mIncrementalProgress;
+        }
 
         // Only publish when meaningful change
         if (forcePublish || Math.abs(mProgress - mReportedProgress) >= 0.01) {
@@ -1936,9 +1949,11 @@
                     throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
                             "Session destroyed");
                 }
-                // Client staging is fully done at this point
-                mClientProgress = 1f;
-                computeProgressLocked(true);
+                if (!isIncrementalInstallation()) {
+                    // For non-incremental installs, client staging is fully done at this point
+                    mClientProgress = 1f;
+                    computeProgressLocked(true);
+                }
 
                 // This ongoing commit should keep session active, even though client
                 // will probably close their end.
@@ -2714,8 +2729,8 @@
             throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
                     "Missing existing base package");
         }
-        // Default to require only if existing base has fs-verity.
-        mVerityFound = PackageManagerServiceUtils.isApkVerityEnabled()
+        // Default to require only if existing base apk has fs-verity.
+        mVerityFoundForApks = PackageManagerServiceUtils.isApkVerityEnabled()
                 && params.mode == SessionParams.MODE_INHERIT_EXISTING
                 && VerityUtils.hasFsverity(pkgInfo.applicationInfo.getBaseCodePath());
 
@@ -3010,34 +3025,18 @@
     }
 
     @GuardedBy("mLock")
-    private void maybeStageFsveritySignatureLocked(File origFile, File targetFile)
-            throws PackageManagerException {
+    private void maybeStageFsveritySignatureLocked(File origFile, File targetFile,
+            boolean fsVerityRequired) throws PackageManagerException {
         final File originalSignature = new File(
                 VerityUtils.getFsveritySignatureFilePath(origFile.getPath()));
-        // Make sure .fsv_sig exists when it should, then resolve and stage it.
         if (originalSignature.exists()) {
-            // mVerityFound can only change from false to true here during the staging loop. Since
-            // all or none of files should have .fsv_sig, this should only happen in the first time
-            // (or never), otherwise bail out.
-            if (!mVerityFound) {
-                mVerityFound = true;
-                if (mResolvedStagedFiles.size() > 1) {
-                    throw new PackageManagerException(INSTALL_FAILED_BAD_SIGNATURE,
-                            "Some file is missing fs-verity signature");
-                }
-            }
-        } else {
-            if (!mVerityFound) {
-                return;
-            }
+            final File stagedSignature = new File(
+                    VerityUtils.getFsveritySignatureFilePath(targetFile.getPath()));
+            stageFileLocked(originalSignature, stagedSignature);
+        } else if (fsVerityRequired) {
             throw new PackageManagerException(INSTALL_FAILED_BAD_SIGNATURE,
                     "Missing corresponding fs-verity signature to " + origFile);
         }
-
-        final File stagedSignature = new File(
-                VerityUtils.getFsveritySignatureFilePath(targetFile.getPath()));
-
-        stageFileLocked(originalSignature, stagedSignature);
     }
 
     @GuardedBy("mLock")
@@ -3056,7 +3055,11 @@
                 DexMetadataHelper.buildDexMetadataPathForApk(targetFile.getName()));
 
         stageFileLocked(dexMetadataFile, targetDexMetadataFile);
-        maybeStageFsveritySignatureLocked(dexMetadataFile, targetDexMetadataFile);
+
+        // Also stage .dm.fsv_sig. .dm may be required to install with fs-verity signature on
+        // supported on older devices.
+        maybeStageFsveritySignatureLocked(dexMetadataFile, targetDexMetadataFile,
+                VerityUtils.isFsVeritySupported() && DexMetadataHelper.isFsVerityRequired());
     }
 
     private void storeBytesToInstallationFile(final String localPath, final String absolutePath,
@@ -3118,13 +3121,45 @@
     }
 
     @GuardedBy("mLock")
+    private boolean isFsVerityRequiredForApk(File origFile, File targetFile)
+            throws PackageManagerException {
+        if (mVerityFoundForApks) {
+            return true;
+        }
+
+        // We haven't seen .fsv_sig for any APKs. Treat it as not required until we see one.
+        final File originalSignature = new File(
+                VerityUtils.getFsveritySignatureFilePath(origFile.getPath()));
+        if (!originalSignature.exists()) {
+            return false;
+        }
+        mVerityFoundForApks = true;
+
+        // When a signature is found, also check any previous staged APKs since they also need to
+        // have fs-verity signature consistently.
+        for (File file : mResolvedStagedFiles) {
+            if (!file.getName().endsWith(".apk")) {
+                continue;
+            }
+            // Ignore the current targeting file.
+            if (targetFile.getName().equals(file.getName())) {
+                continue;
+            }
+            throw new PackageManagerException(INSTALL_FAILED_BAD_SIGNATURE,
+                    "Previously staged apk is missing fs-verity signature");
+        }
+        return true;
+    }
+
+    @GuardedBy("mLock")
     private void resolveAndStageFileLocked(File origFile, File targetFile, String splitName)
             throws PackageManagerException {
         stageFileLocked(origFile, targetFile);
 
-        // Stage fsverity signature if present.
-        maybeStageFsveritySignatureLocked(origFile, targetFile);
-        // Stage dex metadata (.dm) if present.
+        // Stage APK's fs-verity signature if present.
+        maybeStageFsveritySignatureLocked(origFile, targetFile,
+                isFsVerityRequiredForApk(origFile, targetFile));
+        // Stage dex metadata (.dm) and corresponding fs-verity signature if present.
         maybeStageDexMetadataLocked(origFile, targetFile);
         // Stage checksums (.digests) if present.
         maybeStageDigestsLocked(origFile, targetFile, splitName);
@@ -3512,14 +3547,12 @@
 
     @Override
     public DataLoaderParamsParcel getDataLoaderParams() {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.USE_INSTALLER_V2, null);
         return params.dataLoaderParams != null ? params.dataLoaderParams.getData() : null;
     }
 
     @Override
     public void addFile(int location, String name, long lengthBytes, byte[] metadata,
             byte[] signature) {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.USE_INSTALLER_V2, null);
         if (!isDataLoaderInstallation()) {
             throw new IllegalStateException(
                     "Cannot add files to non-data loader installation session.");
@@ -3552,7 +3585,6 @@
 
     @Override
     public void removeFile(int location, String name) {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.USE_INSTALLER_V2, null);
         if (!isDataLoaderInstallation()) {
             throw new IllegalStateException(
                     "Cannot add files to non-data loader installation session.");
@@ -3770,7 +3802,16 @@
 
                 mIncrementalFileStorages = IncrementalFileStorages.initialize(mContext, stageDir,
                         inheritedDir, params, statusListener, healthCheckParams, healthListener,
-                        addedFiles, perUidReadTimeouts);
+                        addedFiles, perUidReadTimeouts,
+                        new IPackageLoadingProgressCallback.Stub() {
+                            @Override
+                            public void onPackageLoadingProgressChanged(float progress) {
+                                synchronized (mLock) {
+                                    mIncrementalProgress = progress;
+                                    computeProgressLocked(true);
+                                }
+                            }
+                        });
                 return false;
             } catch (IOException e) {
                 throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE, e.getMessage(),
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e6789d4..e3f925a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -97,6 +97,10 @@
 import static android.content.pm.PackageManagerInternal.LAST_KNOWN_PACKAGE;
 import static android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V4;
 import static android.content.pm.parsing.ApkLiteParseUtils.isApkFile;
+import static android.os.PowerWhitelistManager.REASON_LOCKED_BOOT_COMPLETED;
+import static android.os.PowerWhitelistManager.REASON_PACKAGE_REPLACED;
+import static android.os.PowerWhitelistManager.REASON_PACKAGE_VERIFIER;
+import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
 import static android.os.incremental.IncrementalManager.isIncrementalPath;
 import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
@@ -270,6 +274,7 @@
 import android.os.ParcelableException;
 import android.os.PatternMatcher;
 import android.os.PersistableBundle;
+import android.os.PowerWhitelistManager;
 import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
@@ -316,7 +321,6 @@
 import android.util.IntArray;
 import android.util.Log;
 import android.util.LogPrinter;
-import android.util.LongSparseArray;
 import android.util.LongSparseLongArray;
 import android.util.MathUtils;
 import android.util.PackageUtils;
@@ -370,6 +374,7 @@
 import com.android.server.pm.Settings.DatabaseVersion;
 import com.android.server.pm.Settings.VersionInfo;
 import com.android.server.pm.dex.ArtManagerService;
+import com.android.server.pm.dex.ArtUtils;
 import com.android.server.pm.dex.DexManager;
 import com.android.server.pm.dex.DexoptOptions;
 import com.android.server.pm.dex.PackageDexUsage;
@@ -389,6 +394,7 @@
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
 import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
 import com.android.server.pm.verify.domain.DomainVerificationService;
+import com.android.server.pm.verify.domain.DomainVerificationUtils;
 import com.android.server.pm.verify.domain.proxy.DomainVerificationProxy;
 import com.android.server.pm.verify.domain.proxy.DomainVerificationProxyV1;
 import com.android.server.pm.verify.domain.proxy.DomainVerificationProxyV2;
@@ -400,6 +406,7 @@
 import com.android.server.utils.Watchable;
 import com.android.server.utils.Watched;
 import com.android.server.utils.WatchedArrayMap;
+import com.android.server.utils.WatchedLongSparseArray;
 import com.android.server.utils.WatchedSparseBooleanArray;
 import com.android.server.utils.Watcher;
 import com.android.server.wm.ActivityTaskManagerInternal;
@@ -1401,10 +1408,10 @@
 
     // Currently known shared libraries.
     @Watched
-    final WatchedArrayMap<String, LongSparseArray<SharedLibraryInfo>> mSharedLibraries =
-            new WatchedArrayMap<>();
+    final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>
+            mSharedLibraries = new WatchedArrayMap<>();
     @Watched
-    final WatchedArrayMap<String, LongSparseArray<SharedLibraryInfo>>
+    final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>
             mStaticLibsByDeclaringPackage = new WatchedArrayMap<>();
 
     // Mapping from instrumentation class names to info about them.
@@ -1755,6 +1762,11 @@
         public boolean filterAppAccess(String packageName, int callingUid, int userId) {
             return mPmInternal.filterAppAccess(packageName, callingUid, userId);
         }
+
+        @Override
+        public int[] getAllUserIds() {
+            return mUserManager.getUserIds();
+        }
     }
 
     /**
@@ -1785,8 +1797,8 @@
         public final Settings settings;
         public final SparseIntArray isolatedOwners;
         public final WatchedArrayMap<String, AndroidPackage> packages;
-        public final WatchedArrayMap<String, LongSparseArray<SharedLibraryInfo>> sharedLibs;
-        public final WatchedArrayMap<String, LongSparseArray<SharedLibraryInfo>> staticLibs;
+        public final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>> sharedLibs;
+        public final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>> staticLibs;
         public final WatchedArrayMap<ComponentName, ParsedInstrumentation> instrumentation;
         public final WatchedSparseBooleanArray webInstantAppsDisabled;
         public final ComponentName resolveComponentName;
@@ -1954,9 +1966,10 @@
         boolean isInstantAppInternal(String packageName, @UserIdInt int userId, int callingUid);
         boolean isInstantAppInternalBody(String packageName, @UserIdInt int userId, int callingUid);
         boolean isInstantAppResolutionAllowed(Intent intent, List<ResolveInfo> resolvedActivities,
-                int userId, boolean skipPackageCheck);
+                int userId, boolean skipPackageCheck, int flags);
         boolean isInstantAppResolutionAllowedBody(Intent intent,
-                List<ResolveInfo> resolvedActivities, int userId, boolean skipPackageCheck);
+                List<ResolveInfo> resolvedActivities, int userId, boolean skipPackageCheck,
+                int flags);
         boolean isPersistentPreferredActivitySetByDpm(Intent intent, int userId,
                 String resolvedType, int flags);
         boolean isRecentsAccessingChildProfiles(int callingUid, int targetUserId);
@@ -1988,6 +2001,7 @@
         SigningDetails getSigningDetails(int uid);
         boolean filterAppAccess(AndroidPackage pkg, int callingUid, int userId);
         boolean filterAppAccess(String packageName, int callingUid, int userId);
+        void dump(int type, FileDescriptor fd, PrintWriter pw, DumpState dumpState);
     }
 
     /**
@@ -2004,9 +2018,9 @@
         private final WatchedArrayMap<String, AndroidPackage> mPackages;
         private final WatchedArrayMap<ComponentName, ParsedInstrumentation>
                 mInstrumentation;
-        private final WatchedArrayMap<String, LongSparseArray<SharedLibraryInfo>>
+        private final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>
                 mStaticLibsByDeclaringPackage;
-        private final WatchedArrayMap<String, LongSparseArray<SharedLibraryInfo>>
+        private final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>
                 mSharedLibraries;
         private final ComponentName mLocalResolveComponentName;
         private final ActivityInfo mResolveActivity;
@@ -2031,6 +2045,9 @@
         private final InstantAppResolverConnection mInstantAppResolverConnection;
         private final DefaultAppProvider mDefaultAppProvider;
         private final DomainVerificationManagerInternal mDomainVerificationManager;
+        private final PackageDexOptimizer mPackageDexOptimizer;
+        private final DexManager mDexManager;
+        private final CompilerStats mCompilerStats;
 
         // PackageManagerService attributes that are primitives are referenced through the
         // pms object directly.  Primitives are the only attributes so referenced.
@@ -2077,6 +2094,9 @@
             mInstantAppResolverConnection = args.service.mInstantAppResolverConnection;
             mDefaultAppProvider = args.service.mDefaultAppProvider;
             mDomainVerificationManager = args.service.mDomainVerificationManager;
+            mPackageDexOptimizer = args.service.mPackageDexOptimizer;
+            mDexManager = args.service.mDexManager;
+            mCompilerStats = args.service.mCompilerStats;
 
             // Used to reference PMS attributes that are primitives and which are not
             // updated under control of the PMS lock.
@@ -2308,7 +2328,7 @@
                 result = filterIfNotSystemUser(mComponentResolver.queryActivities(
                         intent, resolvedType, flags, userId), userId);
                 addInstant = isInstantAppResolutionAllowed(intent, result, userId,
-                        false /*skipPackageCheck*/);
+                        false /*skipPackageCheck*/, flags);
                 // Check for cross profile results.
                 boolean hasNonNegativePriorityResult = hasNonNegativePriority(result);
                 xpResolveInfo = queryCrossProfileIntents(
@@ -2373,8 +2393,8 @@
                 if (result == null || result.size() == 0) {
                     // the caller wants to resolve for a particular package; however, there
                     // were no installed results, so, try to find an ephemeral result
-                    addInstant = isInstantAppResolutionAllowed(
-                                    intent, null /*result*/, userId, true /*skipPackageCheck*/);
+                    addInstant = isInstantAppResolutionAllowed(intent, null /*result*/, userId,
+                            true /*skipPackageCheck*/, flags);
                     if (result == null) {
                         result = new ArrayList<>();
                     }
@@ -2587,40 +2607,69 @@
                 CrossProfileDomainInfo xpDomainInfo, int userId, boolean debug) {
             final ArrayList<ResolveInfo> result = new ArrayList<>();
             final ArrayList<ResolveInfo> matchAllList = new ArrayList<>();
+            final ArrayList<ResolveInfo> undefinedList = new ArrayList<>();
+
+            // Blocking instant apps is usually done in applyPostResolutionFilter, but since
+            // domain verification can resolve to a single result, which can be an instant app,
+            // it will then be filtered to an empty list in that method. Instead, do blocking
+            // here so that instant apps can be ignored for approval filtering and a lower
+            // priority result chosen instead.
+            final boolean blockInstant = intent.isWebIntent() && areWebInstantAppsDisabled(userId);
 
             final int count = candidates.size();
             // First, try to use approved apps.
             for (int n = 0; n < count; n++) {
                 ResolveInfo info = candidates.get(n);
+                if (blockInstant && (info.isInstantAppAvailable
+                        || isInstantApp(info.activityInfo.packageName, userId))) {
+                    continue;
+                }
+
                 // Add to the special match all list (Browser use case)
                 if (info.handleAllWebDataURI) {
                     matchAllList.add(info);
+                } else {
+                    undefinedList.add(info);
                 }
             }
 
-            Pair<List<ResolveInfo>, Integer> infosAndLevel = mDomainVerificationManager
-                    .filterToApprovedApp(intent, candidates, userId, mSettings::getPackageLPr);
-            List<ResolveInfo> approvedInfos = infosAndLevel.first;
-            Integer highestApproval = infosAndLevel.second;
-
             // We'll want to include browser possibilities in a few cases
             boolean includeBrowser = false;
 
-            // If no apps are approved for the domain, resolve only to browsers
-            if (approvedInfos.isEmpty()) {
-                // If the other profile has a result, include that and delegate to ResolveActivity
+            if (!DomainVerificationUtils.isDomainVerificationIntent(intent, candidates,
+                            matchFlags)) {
+                result.addAll(undefinedList);
+                // Maybe add one for the other profile.
                 if (xpDomainInfo != null && xpDomainInfo.highestApprovalLevel
                         > DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE) {
                     result.add(xpDomainInfo.resolveInfo);
-                } else {
-                    includeBrowser = true;
                 }
+                includeBrowser = true;
             } else {
-                result.addAll(approvedInfos);
+                Pair<List<ResolveInfo>, Integer> infosAndLevel = mDomainVerificationManager
+                        .filterToApprovedApp(intent, undefinedList, userId,
+                                mSettings::getPackageLPr);
+                List<ResolveInfo> approvedInfos = infosAndLevel.first;
+                Integer highestApproval = infosAndLevel.second;
 
-                // If the other profile has an app that's of equal or higher approval, add it
-                if (xpDomainInfo != null && xpDomainInfo.highestApprovalLevel >= highestApproval) {
-                    result.add(xpDomainInfo.resolveInfo);
+                // If no apps are approved for the domain, resolve only to browsers
+                if (approvedInfos.isEmpty()) {
+                    // If the other profile has a result, include that and delegate to
+                    // ResolveActivity
+                    if (xpDomainInfo != null && xpDomainInfo.highestApprovalLevel
+                            > DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE) {
+                        result.add(xpDomainInfo.resolveInfo);
+                    } else {
+                        includeBrowser = true;
+                    }
+                } else {
+                    result.addAll(approvedInfos);
+
+                    // If the other profile has an app that's of equal or higher approval, add it
+                    if (xpDomainInfo != null
+                            && xpDomainInfo.highestApprovalLevel >= highestApproval) {
+                        result.add(xpDomainInfo.resolveInfo);
+                    }
                 }
             }
 
@@ -2772,8 +2821,8 @@
                 }
 
                 result.highestApprovalLevel = Math.max(mDomainVerificationManager
-                        .approvalLevelForDomain(ps, intent, riTargetUser.targetUserId),
-                        result.highestApprovalLevel);
+                        .approvalLevelForDomain(ps, intent, resultTargetUser, flags,
+                                riTargetUser.targetUserId), result.highestApprovalLevel);
             }
             if (result != null && result.highestApprovalLevel
                     <= DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE) {
@@ -3020,7 +3069,7 @@
                     final PackageSetting ps = mSettings.getPackageLPr(packageName);
                     if (ps.getInstantApp(userId)) {
                         if (hasAnyDomainApproval(mDomainVerificationManager, ps, intent,
-                                userId)) {
+                                instantApps, flags, userId)) {
                             if (DEBUG_INSTANT) {
                                 Slog.v(TAG, "Instant app approved for intent; pkg: "
                                         + packageName);
@@ -3529,7 +3578,7 @@
             packageName = normalizedPackageName != null ? normalizedPackageName : packageName;
 
             // Is this a static library?
-            LongSparseArray<SharedLibraryInfo> versionedLib =
+            WatchedLongSparseArray<SharedLibraryInfo> versionedLib =
                     mStaticLibsByDeclaringPackage.get(packageName);
             if (versionedLib == null || versionedLib.size() <= 0) {
                 return packageName;
@@ -3898,7 +3947,7 @@
 
         public boolean isInstantAppResolutionAllowed(
                 Intent intent, List<ResolveInfo> resolvedActivities, int userId,
-                boolean skipPackageCheck) {
+                boolean skipPackageCheck, int flags) {
             if (mInstantAppResolverConnection == null) {
                 return false;
             }
@@ -3931,14 +3980,14 @@
             // Deny ephemeral apps if the user chose _ALWAYS or _ALWAYS_ASK for intent resolution.
             // Or if there's already an ephemeral app installed that handles the action
             return isInstantAppResolutionAllowedBody(intent, resolvedActivities, userId,
-                                                       skipPackageCheck);
+                                                       skipPackageCheck, flags);
         }
 
         // Deny ephemeral apps if the user chose _ALWAYS or _ALWAYS_ASK for intent resolution.
         // Or if there's already an ephemeral app installed that handles the action
         public boolean isInstantAppResolutionAllowedBody(
                 Intent intent, List<ResolveInfo> resolvedActivities, int userId,
-                boolean skipPackageCheck) {
+                boolean skipPackageCheck, int flags) {
             final int count = (resolvedActivities == null ? 0 : resolvedActivities.size());
             for (int n = 0; n < count; n++) {
                 final ResolveInfo info = resolvedActivities.get(n);
@@ -3948,7 +3997,7 @@
                     // only check domain verification status if the app is not a browser
                     if (!info.handleAllWebDataURI) {
                         if (hasAnyDomainApproval(mDomainVerificationManager, ps, intent,
-                                userId)) {
+                                resolvedActivities, flags, userId)) {
                             if (DEBUG_INSTANT) {
                                 Slog.v(TAG, "DENY instant app;" + " pkg: " + packageName
                                         + ", approved");
@@ -4371,6 +4420,194 @@
                     userId);
         }
 
+        public void dump(int type, FileDescriptor fd, PrintWriter pw, DumpState dumpState) {
+            final String packageName = dumpState.getTargetPackageName();
+            final boolean checkin = dumpState.isCheckIn();
+
+            switch (type) {
+                case DumpState.DUMP_VERSION:
+                {
+                    if (dumpState.onTitlePrinted()) {
+                        pw.println();
+                    }
+                    pw.println("Database versions:");
+                    mSettings.dumpVersionLPr(new IndentingPrintWriter(pw, "  "));
+                    break;
+                }
+
+                case DumpState.DUMP_LIBS:
+                {
+                    boolean printedHeader = false;
+                    final int numSharedLibraries = mSharedLibraries.size();
+                    for (int index = 0; index < numSharedLibraries; index++) {
+                        final String libName = mSharedLibraries.keyAt(index);
+                        final WatchedLongSparseArray<SharedLibraryInfo> versionedLib =
+                                mSharedLibraries.get(libName);
+                        if (versionedLib == null) {
+                            continue;
+                        }
+                        final int versionCount = versionedLib.size();
+                        for (int i = 0; i < versionCount; i++) {
+                            SharedLibraryInfo libraryInfo = versionedLib.valueAt(i);
+                            if (!checkin) {
+                                if (!printedHeader) {
+                                    if (dumpState.onTitlePrinted()) {
+                                        pw.println();
+                                    }
+                                    pw.println("Libraries:");
+                                    printedHeader = true;
+                                }
+                                pw.print("  ");
+                            } else {
+                                pw.print("lib,");
+                            }
+                            pw.print(libraryInfo.getName());
+                            if (libraryInfo.isStatic()) {
+                                pw.print(" version=" + libraryInfo.getLongVersion());
+                            }
+                            if (!checkin) {
+                                pw.print(" -> ");
+                            }
+                            if (libraryInfo.getPath() != null) {
+                                if (libraryInfo.isNative()) {
+                                    pw.print(" (so) ");
+                                } else {
+                                    pw.print(" (jar) ");
+                                }
+                                pw.print(libraryInfo.getPath());
+                            } else {
+                                pw.print(" (apk) ");
+                                pw.print(libraryInfo.getPackageName());
+                            }
+                            pw.println();
+                        }
+                    }
+                    break;
+                }
+
+                case DumpState.DUMP_PREFERRED_XML:
+                {
+                    pw.flush();
+                    FileOutputStream fout = new FileOutputStream(fd);
+                    BufferedOutputStream str = new BufferedOutputStream(fout);
+                    TypedXmlSerializer serializer = Xml.newFastSerializer();
+                    try {
+                        serializer.setOutput(str, StandardCharsets.UTF_8.name());
+                        serializer.startDocument(null, true);
+                        serializer.setFeature(
+                                "http://xmlpull.org/v1/doc/features.html#indent-output", true);
+                        mSettings.writePreferredActivitiesLPr(serializer, 0,
+                                dumpState.isFullPreferred());
+                        serializer.endDocument();
+                        serializer.flush();
+                    } catch (IllegalArgumentException e) {
+                        pw.println("Failed writing: " + e);
+                    } catch (IllegalStateException e) {
+                        pw.println("Failed writing: " + e);
+                    } catch (IOException e) {
+                        pw.println("Failed writing: " + e);
+                    }
+                    break;
+                }
+
+                case DumpState.DUMP_QUERIES:
+                {
+                    final PackageSetting setting = mSettings.getPackageLPr(packageName);
+                    Integer filteringAppId = setting == null ? null : setting.appId;
+                    mAppsFilter.dumpQueries(
+                            pw, filteringAppId, dumpState, mUserManager.getUserIds(),
+                            this::getPackagesForUid);
+                    break;
+                }
+
+                case DumpState.DUMP_DOMAIN_PREFERRED:
+                {
+                    final android.util.IndentingPrintWriter writer =
+                            new android.util.IndentingPrintWriter(pw);
+                    if (dumpState.onTitlePrinted()) pw.println();
+
+                    writer.println("Domain verification status:");
+                    writer.increaseIndent();
+                    try {
+                        mDomainVerificationManager.printState(writer, packageName,
+                                UserHandle.USER_ALL, mSettings::getPackageLPr);
+                    } catch (PackageManager.NameNotFoundException e) {
+                        pw.println("Failure printing domain verification information");
+                        Slog.e(TAG, "Failure printing domain verification information", e);
+                    }
+                    writer.decreaseIndent();
+                    break;
+                }
+
+                case DumpState.DUMP_DEXOPT:
+                {
+                    final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
+                    ipw.println();
+                    ipw.println("Dexopt state:");
+                    ipw.increaseIndent();
+                    Collection<PackageSetting> pkgSettings;
+                    if (packageName != null) {
+                        PackageSetting targetPkgSetting = mSettings.getPackageLPr(packageName);
+                        if (targetPkgSetting != null) {
+                            pkgSettings = Collections.singletonList(targetPkgSetting);
+                        } else {
+                            ipw.println("Unable to find package: " + packageName);
+                            return;
+                        }
+                    } else {
+                        pkgSettings = mSettings.getPackagesLocked().values();
+                    }
+
+                    for (PackageSetting pkgSetting : pkgSettings) {
+                        final AndroidPackage pkg = pkgSetting.getPkg();
+                        if (pkg == null) {
+                            continue;
+                        }
+                        ipw.println("[" + pkgSetting.name + "]");
+                        ipw.increaseIndent();
+                        mPackageDexOptimizer.dumpDexoptState(ipw, pkg, pkgSetting,
+                                mDexManager.getPackageUseInfoOrDefault(pkg.getPackageName()));
+                        ipw.decreaseIndent();
+                    }
+                    break;
+                }
+
+                case DumpState.DUMP_COMPILER_STATS:
+                {
+                    final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
+                    ipw.println();
+                    ipw.println("Compiler stats:");
+                    ipw.increaseIndent();
+                    Collection<AndroidPackage> packages;
+                    if (packageName != null) {
+                        AndroidPackage targetPackage = mPackages.get(packageName);
+                        if (targetPackage != null) {
+                            packages = Collections.singletonList(targetPackage);
+                        } else {
+                            ipw.println("Unable to find package: " + packageName);
+                            return;
+                        }
+                    } else {
+                        packages = mPackages.values();
+                    }
+
+                    for (AndroidPackage pkg : packages) {
+                        final String pkgName = pkg.getPackageName();
+                        ipw.println("[" + pkgName + "]");
+                        ipw.increaseIndent();
+
+                        CompilerStats.PackageStats stats = mCompilerStats.getPackageStats(pkgName);
+                        if (stats == null) {
+                            ipw.println("(No recorded stats)");
+                        } else {
+                            stats.dump(ipw);
+                        }
+                        ipw.decreaseIndent();
+                    }
+                    break;
+                }
+            } // switch
+        }
     }
 
     /**
@@ -4398,7 +4635,7 @@
      * computer engine.  This is required because there are no locks taken in
      * the engine itself.
      */
-    private static class ComputerLocked extends ComputerEngine {
+    private static class ComputerLocked extends ComputerEngineLive {
         private final Object mLock;
 
         ComputerLocked(Snapshot args) {
@@ -4406,16 +4643,6 @@
             mLock = mService.mLock;
         }
 
-        protected ComponentName resolveComponentName() {
-            return mService.mResolveComponentName;
-        }
-        protected ActivityInfo instantAppInstallerActivity() {
-            return mService.mInstantAppInstallerActivity;
-        }
-        protected ApplicationInfo androidApplication() {
-            return mService.mAndroidApplication;
-        }
-
         public @NonNull List<ResolveInfo> queryIntentServicesInternalBody(Intent intent,
                 String resolvedType, int flags, int userId, int callingUid,
                 String instantAppPkgName) {
@@ -4509,10 +4736,11 @@
             }
         }
         public boolean isInstantAppResolutionAllowedBody(Intent intent,
-                List<ResolveInfo> resolvedActivities, int userId, boolean skipPackageCheck) {
+                List<ResolveInfo> resolvedActivities, int userId, boolean skipPackageCheck,
+                int flags) {
             synchronized (mLock) {
                 return super.isInstantAppResolutionAllowedBody(intent, resolvedActivities, userId,
-                        skipPackageCheck);
+                        skipPackageCheck, flags);
             }
         }
         public int getPackageUidInternal(String packageName, int flags, int userId,
@@ -4544,8 +4772,9 @@
     }
 
 
-    // Compute read-only functions, based on live data.
-    private final Computer mLiveComputer;
+    // Compute read-only functions, based on live data.  This attribute may be modified multiple
+    // times during the PackageManagerService constructor but it should not be modified thereafter.
+    private Computer mLiveComputer;
     // A lock-free cache for frequently called functions.
     private volatile Computer mSnapshotComputer;
     // If true, the snapshot is invalid (stale).  The attribute is static since it may be
@@ -4684,6 +4913,10 @@
     // and an image with the flag set false does not use snapshots.
     private static final boolean SNAPSHOT_ENABLED = true;
 
+    // The per-instance snapshot disable/enable flag.  This is generally set to false in
+    // test instances and set to SNAPSHOT_ENABLED in operational instances.
+    private final boolean mSnapshotEnabled;
+
     /**
      * Return the live computer.
      */
@@ -4696,7 +4929,7 @@
      * The live computer will be returned if snapshots are disabled.
      */
     private Computer snapshotComputer() {
-        if (!SNAPSHOT_ENABLED) {
+        if (!mSnapshotEnabled) {
             return mLiveComputer;
         }
         if (Thread.holdsLock(mLock)) {
@@ -4868,23 +5101,12 @@
                         InstallArgs args = data.args;
                         PackageInstalledInfo parentRes = data.res;
 
-                        final boolean grantPermissions = (args.installFlags
-                                & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0;
                         final boolean killApp = (args.installFlags
                                 & PackageManager.INSTALL_DONT_KILL_APP) == 0;
                         final boolean virtualPreload = ((args.installFlags
                                 & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
-                        final String[] grantedPermissions = args.installGrantPermissions;
-                        final List<String> whitelistedRestrictedPermissions = ((args.installFlags
-                                & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS) != 0
-                                    && parentRes.pkg != null)
-                                ? parentRes.pkg.getRequestedPermissions()
-                                : args.whitelistedRestrictedPermissions;
-                        int autoRevokePermissionsMode = args.autoRevokePermissionsMode;
 
-                        handlePackagePostInstall(parentRes, grantPermissions,
-                                killApp, virtualPreload, grantedPermissions,
-                                whitelistedRestrictedPermissions, autoRevokePermissionsMode,
+                        handlePackagePostInstall(parentRes, killApp, virtualPreload,
                                 didRestore, args.installSource.installerPackageName, args.observer,
                                 args.mDataLoaderType);
 
@@ -5163,11 +5385,8 @@
         }
     }
 
-    private void handlePackagePostInstall(PackageInstalledInfo res, boolean grantPermissions,
-            boolean killApp, boolean virtualPreload,
-            String[] grantedPermissions, List<String> allowlistedRestrictedPermissions,
-            int autoRevokePermissionsMode,
-            boolean launchedForRestore, String installerPackage,
+    private void handlePackagePostInstall(PackageInstalledInfo res, boolean killApp,
+            boolean virtualPreload, boolean launchedForRestore, String installerPackage,
             IPackageInstallObserver2 installObserver, int dataLoaderType) {
         boolean succeeded = res.returnCode == PackageManager.INSTALL_SUCCEEDED;
         final boolean update = res.removedInfo != null && res.removedInfo.removedPackage != null;
@@ -5198,29 +5417,6 @@
                 res.removedInfo.sendPackageRemovedBroadcasts(killApp, false /*removedBySystem*/);
             }
 
-            final PermissionManagerServiceInternal.PackageInstalledParams.Builder
-                    permissionParamsBuilder =
-                    new PermissionManagerServiceInternal.PackageInstalledParams.Builder();
-            final List<String> grantedPermissionsList;
-            if (grantPermissions) {
-                if (grantedPermissions != null) {
-                    permissionParamsBuilder.setGrantedPermissions(Arrays.asList(
-                            grantedPermissions));
-                } else {
-                    permissionParamsBuilder.setGrantedPermissions(
-                            res.pkg.getRequestedPermissions());
-                }
-            }
-            if (allowlistedRestrictedPermissions != null) {
-                permissionParamsBuilder.setAllowlistedRestrictedPermissions(
-                        allowlistedRestrictedPermissions);
-            }
-            permissionParamsBuilder.setAutoRevokePermissionsMode(autoRevokePermissionsMode);
-            for (final int userId : res.newUsers) {
-                mPermissionManager.onPackageInstalled(res.pkg, permissionParamsBuilder.build(),
-                        userId);
-            }
-
             final String installerPackageName =
                     res.installerPackageName != null
                             ? res.installerPackageName
@@ -5353,7 +5549,8 @@
                             packageName /*targetPackage*/,
                             null /*finishedReceiver*/, updateUserIds, instantUserIds,
                             null /*broadcastAllowList*/,
-                            getTemporaryAppWhitelistBroadcastOptions().toBundle());
+                            getTemporaryAppAllowlistBroadcastOptions(REASON_PACKAGE_REPLACED)
+                                    .toBundle());
                 } else if (launchedForRestore && !res.pkg.isSystem()) {
                     // First-install and we did a restore, so we're responsible for the
                     // first-launch broadcast.
@@ -6031,15 +6228,12 @@
         mOverlayConfigSignaturePackage = testParams.overlayConfigSignaturePackage;
         mResolveComponentName = testParams.resolveComponentName;
 
-        // Create the computer as soon as the state objects have been installed.  The
-        // cached computer is the same as the live computer until the end of the
-        // constructor, at which time the invalidation method updates it.  The cache is
-        // corked initially to ensure a cached computer is not built until the end of the
-        // constructor.
-        sSnapshotCorked = true;
+        // Disable snapshots in this instance of PackageManagerService, which is only used
+        // for testing.  The instance still needs a live computer.  The snapshot computer
+        // is set to null since it must never be used by this instance.
+        mSnapshotEnabled = false;
         mLiveComputer = createLiveComputer();
-        mSnapshotComputer = mLiveComputer;
-        registerObserver();
+        mSnapshotComputer = null;
 
         mPackages.putAll(testParams.packages);
         mEnableFreeCacheV2 = testParams.enableFreeCacheV2;
@@ -6052,7 +6246,6 @@
         mIncrementalVersion = testParams.incrementalVersion;
 
         invalidatePackageInfoCache();
-        sSnapshotCorked = false;
     }
 
     public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,
@@ -6198,9 +6391,11 @@
         // constructor, at which time the invalidation method updates it.  The cache is
         // corked initially to ensure a cached computer is not built until the end of the
         // constructor.
+        mSnapshotEnabled = SNAPSHOT_ENABLED;
         sSnapshotCorked = true;
+        sSnapshotInvalid = true;
         mLiveComputer = createLiveComputer();
-        mSnapshotComputer = mLiveComputer;
+        mSnapshotComputer = null;
         registerObserver();
 
         // CHECKSTYLE:OFF IndentationCheck
@@ -6879,6 +7074,10 @@
                         BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_INIT_TIME,
                         SystemClock.uptimeMillis() - startTime);
             }
+
+            // Rebild the live computer since some attributes have been rebuilt.
+            mLiveComputer = createLiveComputer();
+
         } // synchronized (mLock)
         } // synchronized (mInstallLock)
         // CHECKSTYLE:ON IndentationCheck
@@ -8021,7 +8220,7 @@
             final int[] allUsers = mUserManager.getUserIds();
             final int libCount = mSharedLibraries.size();
             for (int i = 0; i < libCount; i++) {
-                final LongSparseArray<SharedLibraryInfo> versionedLib
+                final WatchedLongSparseArray<SharedLibraryInfo> versionedLib
                         = mSharedLibraries.valueAt(i);
                 if (versionedLib == null) {
                     continue;
@@ -8286,7 +8485,8 @@
 
             final int libCount = mSharedLibraries.size();
             for (int i = 0; i < libCount; i++) {
-                LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.valueAt(i);
+                WatchedLongSparseArray<SharedLibraryInfo> versionedLib =
+                        mSharedLibraries.valueAt(i);
                 if (versionedLib == null) {
                     continue;
                 }
@@ -8355,7 +8555,8 @@
 
             int libraryCount = mSharedLibraries.size();
             for (int i = 0; i < libraryCount; i++) {
-                LongSparseArray<SharedLibraryInfo> versionedLibrary = mSharedLibraries.valueAt(i);
+                WatchedLongSparseArray<SharedLibraryInfo> versionedLibrary =
+                        mSharedLibraries.valueAt(i);
                 if (versionedLibrary == null) {
                     continue;
                 }
@@ -8516,7 +8717,8 @@
             Set<String> libs = null;
             final int libCount = mSharedLibraries.size();
             for (int i = 0; i < libCount; i++) {
-                LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.valueAt(i);
+                WatchedLongSparseArray<SharedLibraryInfo> versionedLib =
+                        mSharedLibraries.valueAt(i);
                 if (versionedLib == null) {
                     continue;
                 }
@@ -8942,6 +9144,10 @@
 
     @Override
     public List<String> getAllPackages() {
+        // Allow iorapd to call this method.
+        if (Binder.getCallingUid() != Process.IORAPD_UID) {
+            enforceSystemOrRootOrShell("getAllPackages is limited to privileged callers");
+        }
         final int callingUid = Binder.getCallingUid();
         final int callingUserId = UserHandle.getUserId(callingUid);
         synchronized (mLock) {
@@ -8992,6 +9198,11 @@
      */
     @Override
     public String[] getPackagesForUid(int uid) {
+        final int callingUid = Binder.getCallingUid();
+        final int userId = UserHandle.getUserId(uid);
+        enforceCrossUserOrProfilePermission(callingUid, userId,
+                /* requireFullPermission */ false,
+                /* checkShell */ false, "getPackagesForUid");
         return snapshotComputer().getPackagesForUid(uid);
     }
 
@@ -9295,20 +9506,20 @@
 
     private boolean isInstantAppResolutionAllowed(
             Intent intent, List<ResolveInfo> resolvedActivities, int userId,
-            boolean skipPackageCheck) {
+            boolean skipPackageCheck, int flags) {
         return liveComputer().isInstantAppResolutionAllowed(
             intent, resolvedActivities, userId,
-            skipPackageCheck);
+            skipPackageCheck, flags);
     }
 
     // Deny ephemeral apps if the user chose _ALWAYS or _ALWAYS_ASK for intent resolution.
     // Or if there's already an ephemeral app installed that handles the action
     private boolean isInstantAppResolutionAllowedBody(
             Intent intent, List<ResolveInfo> resolvedActivities, int userId,
-            boolean skipPackageCheck) {
+            boolean skipPackageCheck, int flags) {
         return liveComputer().isInstantAppResolutionAllowedBody(
             intent, resolvedActivities, userId,
-            skipPackageCheck);
+            skipPackageCheck, flags);
     }
 
     private void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj,
@@ -9365,7 +9576,7 @@
                         final String packageName = ri.activityInfo.packageName;
                         final PackageSetting ps = mSettings.getPackageLPr(packageName);
                         if (ps != null && hasAnyDomainApproval(mDomainVerificationManager, ps,
-                                intent, userId)) {
+                                intent, query, flags, userId)) {
                             return ri;
                         }
                     }
@@ -9422,9 +9633,10 @@
      */
     private static boolean hasAnyDomainApproval(
             @NonNull DomainVerificationManagerInternal manager, @NonNull PackageSetting pkgSetting,
-            @NonNull Intent intent, @UserIdInt int userId) {
-        return manager.approvalLevelForDomain(pkgSetting, intent, userId)
-                > DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE;
+            @NonNull Intent intent, @NonNull List<ResolveInfo> candidates,
+            @PackageManager.ResolveInfoFlags int resolveInfoFlags, @UserIdInt int userId) {
+        return manager.approvalLevelForDomain(pkgSetting, intent, candidates, resolveInfoFlags,
+                userId) > DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE;
     }
 
     /**
@@ -9820,7 +10032,7 @@
 
     private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
             String resolvedType, int flags, int userId) {
-        return liveComputer().queryIntentActivitiesInternal(intent,
+        return snapshotComputer().queryIntentActivitiesInternal(intent,
                 resolvedType, flags, userId);
     }
 
@@ -10307,7 +10519,7 @@
     private @NonNull List<ResolveInfo> queryIntentServicesInternal(Intent intent,
             String resolvedType, int flags, int userId, int callingUid,
             boolean includeInstantApps) {
-        return liveComputer().queryIntentServicesInternal(intent,
+        return snapshotComputer().queryIntentServicesInternal(intent,
                 resolvedType, flags, userId, callingUid,
                 includeInstantApps);
     }
@@ -12181,10 +12393,10 @@
 
     @Nullable
     private static SharedLibraryInfo getSharedLibraryInfo(String name, long version,
-            Map<String, LongSparseArray<SharedLibraryInfo>> existingLibraries,
-            @Nullable Map<String, LongSparseArray<SharedLibraryInfo>> newLibraries) {
+            Map<String, WatchedLongSparseArray<SharedLibraryInfo>> existingLibraries,
+            @Nullable Map<String, WatchedLongSparseArray<SharedLibraryInfo>> newLibraries) {
         if (newLibraries != null) {
-            final LongSparseArray<SharedLibraryInfo> versionedLib = newLibraries.get(name);
+            final WatchedLongSparseArray<SharedLibraryInfo> versionedLib = newLibraries.get(name);
             SharedLibraryInfo info = null;
             if (versionedLib != null) {
                 info = versionedLib.get(version);
@@ -12193,7 +12405,7 @@
                 return info;
             }
         }
-        final LongSparseArray<SharedLibraryInfo> versionedLib = existingLibraries.get(name);
+        final WatchedLongSparseArray<SharedLibraryInfo> versionedLib = existingLibraries.get(name);
         if (versionedLib == null) {
             return null;
         }
@@ -12201,7 +12413,7 @@
     }
 
     private SharedLibraryInfo getLatestSharedLibraVersionLPr(AndroidPackage pkg) {
-        LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(
+        WatchedLongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(
                 pkg.getStaticSharedLibName());
         if (versionedLib == null) {
             return null;
@@ -12506,8 +12718,8 @@
 
     private static ArrayList<SharedLibraryInfo> collectSharedLibraryInfos(AndroidPackage pkg,
             Map<String, AndroidPackage> availablePackages,
-            @NonNull final Map<String, LongSparseArray<SharedLibraryInfo>> existingLibraries,
-            @Nullable final Map<String, LongSparseArray<SharedLibraryInfo>> newLibraries)
+            @NonNull final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> existingLibraries,
+            @Nullable final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> newLibraries)
             throws PackageManagerException {
         if (pkg == null) {
             return null;
@@ -12604,8 +12816,8 @@
             @NonNull String packageName, boolean required, int targetSdk,
             @Nullable ArrayList<SharedLibraryInfo> outUsedLibraries,
             @NonNull final Map<String, AndroidPackage> availablePackages,
-            @NonNull final Map<String, LongSparseArray<SharedLibraryInfo>> existingLibraries,
-            @Nullable final Map<String, LongSparseArray<SharedLibraryInfo>> newLibraries)
+            @NonNull final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> existingLibraries,
+            @Nullable final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> newLibraries)
             throws PackageManagerException {
         final int libCount = requestedLibraries.size();
         for (int i = 0; i < libCount; i++) {
@@ -14026,7 +14238,7 @@
                 long minVersionCode = Long.MIN_VALUE;
                 long maxVersionCode = Long.MAX_VALUE;
 
-                LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(
+                WatchedLongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(
                         pkg.getStaticSharedLibName());
                 if (versionedLib != null) {
                     final int versionCount = versionedLib.size();
@@ -14254,8 +14466,8 @@
     }
 
     private static boolean sharedLibExists(final String name, final long version,
-            Map<String, LongSparseArray<SharedLibraryInfo>> librarySource) {
-        LongSparseArray<SharedLibraryInfo> versionedLib = librarySource.get(name);
+            Map<String, WatchedLongSparseArray<SharedLibraryInfo>> librarySource) {
+        WatchedLongSparseArray<SharedLibraryInfo> versionedLib = librarySource.get(name);
         if (versionedLib != null && versionedLib.indexOfKey(version) >= 0) {
             return true;
         }
@@ -14265,9 +14477,9 @@
     @GuardedBy("mLock")
     private void commitSharedLibraryInfoLocked(SharedLibraryInfo libraryInfo) {
         final String name = libraryInfo.getName();
-        LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
+        WatchedLongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
         if (versionedLib == null) {
-            versionedLib = new LongSparseArray<>();
+            versionedLib = new WatchedLongSparseArray<>();
             mSharedLibraries.put(name, versionedLib);
         }
         final String declaringPackageName = libraryInfo.getDeclaringPackage().getPackageName();
@@ -14278,7 +14490,7 @@
     }
 
     private boolean removeSharedLibraryLPw(String name, long version) {
-        LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
+        WatchedLongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
         if (versionedLib == null) {
             return false;
         }
@@ -14984,7 +15196,8 @@
                 lockedBcIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
             }
             final String[] requiredPermissions = {Manifest.permission.RECEIVE_BOOT_COMPLETED};
-            final BroadcastOptions bOptions = getTemporaryAppWhitelistBroadcastOptions();
+            final BroadcastOptions bOptions = getTemporaryAppAllowlistBroadcastOptions(
+                    REASON_LOCKED_BOOT_COMPLETED);
             am.broadcastIntentWithFeature(null, null, lockedBcIntent, null, null, 0, null, null,
                     requiredPermissions, android.app.AppOpsManager.OP_NONE, bOptions.toBundle(),
                     false, false,
@@ -17373,7 +17586,9 @@
                         mInjector.getLocalService(DeviceIdleInternal.class);
                 final long idleDuration = getVerificationTimeout();
                 final BroadcastOptions options = BroadcastOptions.makeBasic();
-                options.setTemporaryAppWhitelistDuration(idleDuration);
+                options.setTemporaryAppAllowlist(idleDuration,
+                        TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+                        REASON_PACKAGE_VERIFIER, "");
 
                 /*
                  * If any sufficient verifiers were listed in the package
@@ -17389,7 +17604,8 @@
                             final ComponentName verifierComponent = sufficientVerifiers.get(i);
                             idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
                                     verifierComponent.getPackageName(), idleDuration,
-                                    verifierUser.getIdentifier(), false, "package verifier");
+                                    verifierUser.getIdentifier(), false,
+                                    REASON_PACKAGE_VERIFIER,"package verifier");
 
                             final Intent sufficientIntent = new Intent(verification);
                             sufficientIntent.setComponent(verifierComponent);
@@ -17411,7 +17627,8 @@
                     verification.setComponent(requiredVerifierComponent);
                     idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
                             mRequiredVerifierPackage, idleDuration,
-                            verifierUser.getIdentifier(), false, "package verifier");
+                            verifierUser.getIdentifier(), false,
+                            REASON_PACKAGE_VERIFIER, "package verifier");
                     mContext.sendOrderedBroadcastAsUser(verification, verifierUser,
                             android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
                             /* appOp= */ AppOpsManager.OP_NONE,
@@ -18211,6 +18428,37 @@
                 }
 
                 mSettings.writeKernelMappingLPr(ps);
+
+                final PermissionManagerServiceInternal.PackageInstalledParams.Builder
+                        permissionParamsBuilder =
+                        new PermissionManagerServiceInternal.PackageInstalledParams.Builder();
+                final boolean grantPermissions = (installArgs.installFlags
+                        & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0;
+                if (grantPermissions) {
+                    final List<String> grantedPermissions =
+                            installArgs.installGrantPermissions != null
+                                    ? Arrays.asList(installArgs.installGrantPermissions)
+                                    : pkg.getRequestedPermissions();
+                    permissionParamsBuilder.setGrantedPermissions(grantedPermissions);
+                }
+                final boolean allowlistAllRestrictedPermissions =
+                        (installArgs.installFlags
+                                & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS) != 0;
+                final List<String> allowlistedRestrictedPermissions =
+                        allowlistAllRestrictedPermissions ? pkg.getRequestedPermissions()
+                        : installArgs.whitelistedRestrictedPermissions;
+                if (allowlistedRestrictedPermissions != null) {
+                    permissionParamsBuilder.setAllowlistedRestrictedPermissions(
+                            allowlistedRestrictedPermissions);
+                }
+                final int autoRevokePermissionsMode = installArgs.autoRevokePermissionsMode;
+                permissionParamsBuilder.setAutoRevokePermissionsMode(autoRevokePermissionsMode);
+                for (int currentUserId : allUsersList) {
+                    if (ps.getInstalled(currentUserId)) {
+                        mPermissionManager.onPackageInstalled(pkg, permissionParamsBuilder.build(),
+                                currentUserId);
+                    }
+                }
             }
             res.name = pkgName;
             res.uid = pkg.getUid();
@@ -18273,7 +18521,7 @@
         public final Map<String, ScanResult> scannedPackages;
 
         public final Map<String, AndroidPackage> allPackages;
-        public final Map<String, LongSparseArray<SharedLibraryInfo>> sharedLibrarySource;
+        public final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> sharedLibrarySource;
         public final Map<String, InstallArgs> installArgs;
         public final Map<String, PackageInstalledInfo> installResults;
         public final Map<String, PrepareResult> preparedPackages;
@@ -18284,7 +18532,7 @@
                 Map<String, InstallArgs> installArgs,
                 Map<String, PackageInstalledInfo> installResults,
                 Map<String, PrepareResult> preparedPackages,
-                Map<String, LongSparseArray<SharedLibraryInfo>> sharedLibrarySource,
+                Map<String, WatchedLongSparseArray<SharedLibraryInfo>> sharedLibrarySource,
                 Map<String, AndroidPackage> allPackages,
                 Map<String, VersionInfo> versionInfos,
                 Map<String, PackageSetting> lastStaticSharedLibSettings) {
@@ -18299,7 +18547,7 @@
         }
 
         private ReconcileRequest(Map<String, ScanResult> scannedPackages,
-                Map<String, LongSparseArray<SharedLibraryInfo>> sharedLibrarySource,
+                Map<String, WatchedLongSparseArray<SharedLibraryInfo>> sharedLibrarySource,
                 Map<String, AndroidPackage> allPackages,
                 Map<String, VersionInfo> versionInfos,
                 Map<String, PackageSetting> lastStaticSharedLibSettings) {
@@ -18396,7 +18644,7 @@
 
         combinedPackages.putAll(request.allPackages);
 
-        final Map<String, LongSparseArray<SharedLibraryInfo>> incomingSharedLibraries =
+        final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> incomingSharedLibraries =
                 new ArrayMap<>();
 
         for (String installPackageName : scannedPackages.keySet()) {
@@ -18620,7 +18868,7 @@
      */
     private static List<SharedLibraryInfo> getAllowedSharedLibInfos(
             ScanResult scanResult,
-            Map<String, LongSparseArray<SharedLibraryInfo>> existingSharedLibraries) {
+            Map<String, WatchedLongSparseArray<SharedLibraryInfo>> existingSharedLibraries) {
         // Let's used the parsed package as scanResult.pkgSetting may be null
         final ParsedPackage parsedPackage = scanResult.request.parsedPackage;
         if (scanResult.staticSharedLibraryInfo == null
@@ -18690,7 +18938,7 @@
      * added.
      */
     private static boolean addSharedLibraryToPackageVersionMap(
-            Map<String, LongSparseArray<SharedLibraryInfo>> target,
+            Map<String, WatchedLongSparseArray<SharedLibraryInfo>> target,
             SharedLibraryInfo library) {
         final String name = library.getName();
         if (target.containsKey(name)) {
@@ -18702,7 +18950,7 @@
                 return false;
             }
         } else {
-            target.put(name, new LongSparseArray<>());
+            target.put(name, new WatchedLongSparseArray<>());
         }
         target.get(name).put(library.getLongVersion(), library);
         return true;
@@ -20731,7 +20979,7 @@
                     extras, 0, null /*targetPackage*/, null, null, null, broadcastAllowList, null);
             packageSender.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null, null, 0,
                     removedPackage, null, null, null, null /* broadcastAllowList */,
-                    getTemporaryAppWhitelistBroadcastOptions().toBundle());
+                    getTemporaryAppAllowlistBroadcastOptions(REASON_PACKAGE_REPLACED).toBundle());
             if (installerPackageName != null) {
                 packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
                         removedPackage, extras, 0 /*flags*/,
@@ -22439,7 +22687,7 @@
         }
         final Intent intent = getHomeIntent();
         final List<ResolveInfo> resolveInfos = queryIntentActivitiesInternal(intent, null,
-                PackageManager.GET_META_DATA, userId);
+                MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, userId);
         final ResolveInfo preferredResolveInfo = findPreferredActivityNotLocked(
                 intent, null, 0, resolveInfos, 0, true, false, false, userId);
         final String packageName = preferredResolveInfo != null
@@ -23524,10 +23772,6 @@
         if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
 
         DumpState dumpState = new DumpState();
-        boolean fullPreferred = false;
-        boolean checkin = false;
-
-        String packageName = null;
         ArraySet<String> permissionNames = null;
 
         int opti = 0;
@@ -23577,7 +23821,7 @@
                 pw.println("    <package.name>: info about given package");
                 return;
             } else if ("--checkin".equals(opt)) {
-                checkin = true;
+                dumpState.setCheckIn(true);
             } else if ("--all-components".equals(opt)) {
                 dumpState.setOptionEnabled(DumpState.OPTION_DUMP_ALL_COMPONENTS);
             } else if ("-f".equals(opt)) {
@@ -23596,7 +23840,7 @@
             opti++;
             // Is this a package name?
             if ("android".equals(cmd) || cmd.contains(".")) {
-                packageName = cmd;
+                dumpState.setTargetPackageName(cmd);
                 // When dumping a single package, we always dump all of its
                 // filter information since the amount of data will be reasonable.
                 dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS);
@@ -23677,7 +23921,7 @@
             } else if ("preferred-xml".equals(cmd)) {
                 dumpState.setDump(DumpState.DUMP_PREFERRED_XML);
                 if (opti < args.length && "--full".equals(args[opti])) {
-                    fullPreferred = true;
+                    dumpState.setFullPreferred(true);
                     opti++;
                 }
             } else if ("d".equals(cmd) || "domain-preferred-apps".equals(cmd)) {
@@ -23730,257 +23974,205 @@
             }
         }
 
+        final String packageName = dumpState.getTargetPackageName();
+        final boolean checkin = dumpState.isCheckIn();
         if (checkin) {
             pw.println("vers,1");
         }
 
         // reader
-        synchronized (mLock) {
-            if (dumpState.isDumping(DumpState.DUMP_VERSION) && packageName == null) {
-                if (!checkin) {
-                    if (dumpState.onTitlePrinted())
-                        pw.println();
-                    pw.println("Database versions:");
-                    mSettings.dumpVersionLPr(new IndentingPrintWriter(pw, "  "));
-                }
+        if (dumpState.isDumping(DumpState.DUMP_VERSION) && packageName == null) {
+            if (!checkin) {
+                dump(DumpState.DUMP_VERSION, fd, pw, dumpState);
             }
+        }
 
-            if (!checkin
-                    && dumpState.isDumping(DumpState.DUMP_KNOWN_PACKAGES)
-                    && packageName == null) {
-                if (dumpState.onTitlePrinted()) {
-                    pw.println();
-                }
-                final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ", 120);
-                ipw.println("Known Packages:");
+        if (!checkin
+                && dumpState.isDumping(DumpState.DUMP_KNOWN_PACKAGES)
+                && packageName == null) {
+            if (dumpState.onTitlePrinted()) {
+                pw.println();
+            }
+            final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ", 120);
+            ipw.println("Known Packages:");
+            ipw.increaseIndent();
+            for (int i = 0; i <= LAST_KNOWN_PACKAGE; i++) {
+                final String knownPackage = mPmInternal.knownPackageToString(i);
+                ipw.print(knownPackage);
+                ipw.println(":");
+                final String[] pkgNames = mPmInternal.getKnownPackageNames(i,
+                        UserHandle.USER_SYSTEM);
                 ipw.increaseIndent();
-                for (int i = 0; i <= LAST_KNOWN_PACKAGE; i++) {
-                    final String knownPackage = mPmInternal.knownPackageToString(i);
-                    ipw.print(knownPackage);
-                    ipw.println(":");
-                    final String[] pkgNames = mPmInternal.getKnownPackageNames(i,
-                            UserHandle.USER_SYSTEM);
-                    ipw.increaseIndent();
-                    if (ArrayUtils.isEmpty(pkgNames)) {
-                        ipw.println("none");
-                    } else {
-                        for (String name : pkgNames) {
-                            ipw.println(name);
-                        }
+                if (ArrayUtils.isEmpty(pkgNames)) {
+                    ipw.println("none");
+                } else {
+                    for (String name : pkgNames) {
+                        ipw.println(name);
                     }
-                    ipw.decreaseIndent();
                 }
                 ipw.decreaseIndent();
             }
+            ipw.decreaseIndent();
+        }
 
-            if (dumpState.isDumping(DumpState.DUMP_VERIFIERS) && packageName == null) {
+        if (dumpState.isDumping(DumpState.DUMP_VERIFIERS) && packageName == null) {
+            final String requiredVerifierPackage = mRequiredVerifierPackage;
+            if (!checkin) {
+                if (dumpState.onTitlePrinted()) {
+                    pw.println();
+                }
+                pw.println("Verifiers:");
+                pw.print("  Required: ");
+                pw.print(requiredVerifierPackage);
+                pw.print(" (uid=");
+                pw.print(getPackageUid(requiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
+                        UserHandle.USER_SYSTEM));
+                pw.println(")");
+            } else if (requiredVerifierPackage != null) {
+                pw.print("vrfy,"); pw.print(requiredVerifierPackage);
+                pw.print(",");
+                pw.println(getPackageUid(requiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
+                        UserHandle.USER_SYSTEM));
+            }
+        }
+
+        if (dumpState.isDumping(DumpState.DUMP_DOMAIN_VERIFIER) && packageName == null) {
+            final DomainVerificationProxy proxy = mDomainVerificationManager.getProxy();
+            final ComponentName verifierComponent = proxy.getComponentName();
+            if (verifierComponent != null) {
+                String verifierPackageName = verifierComponent.getPackageName();
                 if (!checkin) {
                     if (dumpState.onTitlePrinted())
                         pw.println();
-                    pw.println("Verifiers:");
-                    pw.print("  Required: ");
-                    pw.print(mRequiredVerifierPackage);
+                    pw.println("Domain Verifier:");
+                    pw.print("  Using: ");
+                    pw.print(verifierPackageName);
                     pw.print(" (uid=");
-                    pw.print(getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
+                    pw.print(getPackageUid(verifierPackageName, MATCH_DEBUG_TRIAGED_MISSING,
                             UserHandle.USER_SYSTEM));
                     pw.println(")");
-                } else if (mRequiredVerifierPackage != null) {
-                    pw.print("vrfy,"); pw.print(mRequiredVerifierPackage);
+                } else if (verifierPackageName != null) {
+                    pw.print("dv,"); pw.print(verifierPackageName);
                     pw.print(",");
-                    pw.println(getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
+                    pw.println(getPackageUid(verifierPackageName, MATCH_DEBUG_TRIAGED_MISSING,
                             UserHandle.USER_SYSTEM));
                 }
+            } else {
+                pw.println();
+                pw.println("No Domain Verifier available!");
+            }
+        }
+
+        if (dumpState.isDumping(DumpState.DUMP_LIBS) && packageName == null) {
+            dump(DumpState.DUMP_LIBS, fd, pw, dumpState);
+        }
+
+        if (dumpState.isDumping(DumpState.DUMP_FEATURES) && packageName == null) {
+            if (dumpState.onTitlePrinted()) {
+                pw.println();
+            }
+            if (!checkin) {
+                pw.println("Features:");
             }
 
-            if (dumpState.isDumping(DumpState.DUMP_DOMAIN_VERIFIER) &&
-                    packageName == null) {
-                DomainVerificationProxy proxy = mDomainVerificationManager.getProxy();
-                ComponentName verifierComponent = proxy.getComponentName();
-                if (verifierComponent != null) {
-                    String verifierPackageName = verifierComponent.getPackageName();
-                    if (!checkin) {
-                        if (dumpState.onTitlePrinted())
-                            pw.println();
-                        pw.println("Domain Verifier:");
-                        pw.print("  Using: ");
-                        pw.print(verifierPackageName);
-                        pw.print(" (uid=");
-                        pw.print(getPackageUid(verifierPackageName, MATCH_DEBUG_TRIAGED_MISSING,
-                                UserHandle.USER_SYSTEM));
-                        pw.println(")");
-                    } else if (verifierPackageName != null) {
-                        pw.print("dv,"); pw.print(verifierPackageName);
+            synchronized (mAvailableFeatures) {
+                for (FeatureInfo feat : mAvailableFeatures.values()) {
+                    if (checkin) {
+                        pw.print("feat,");
+                        pw.print(feat.name);
                         pw.print(",");
-                        pw.println(getPackageUid(verifierPackageName, MATCH_DEBUG_TRIAGED_MISSING,
-                                UserHandle.USER_SYSTEM));
-                    }
-                } else {
-                    pw.println();
-                    pw.println("No Domain Verifier available!");
-                }
-            }
-
-            if (dumpState.isDumping(DumpState.DUMP_LIBS) && packageName == null) {
-                boolean printedHeader = false;
-                final int numSharedLibraries = mSharedLibraries.size();
-                for (int index = 0; index < numSharedLibraries; index++) {
-                    final String libName = mSharedLibraries.keyAt(index);
-                    LongSparseArray<SharedLibraryInfo> versionedLib
-                            = mSharedLibraries.get(libName);
-                    if (versionedLib == null) {
-                        continue;
-                    }
-                    final int versionCount = versionedLib.size();
-                    for (int i = 0; i < versionCount; i++) {
-                        SharedLibraryInfo libraryInfo = versionedLib.valueAt(i);
-                        if (!checkin) {
-                            if (!printedHeader) {
-                                if (dumpState.onTitlePrinted())
-                                    pw.println();
-                                pw.println("Libraries:");
-                                printedHeader = true;
-                            }
-                            pw.print("  ");
-                        } else {
-                            pw.print("lib,");
-                        }
-                        pw.print(libraryInfo.getName());
-                        if (libraryInfo.isStatic()) {
-                            pw.print(" version=" + libraryInfo.getLongVersion());
-                        }
-                        if (!checkin) {
-                            pw.print(" -> ");
-                        }
-                        if (libraryInfo.getPath() != null) {
-                            if (libraryInfo.isNative()) {
-                                pw.print(" (so) ");
-                            } else {
-                                pw.print(" (jar) ");
-                            }
-                            pw.print(libraryInfo.getPath());
-                        } else {
-                            pw.print(" (apk) ");
-                            pw.print(libraryInfo.getPackageName());
+                        pw.println(feat.version);
+                    } else {
+                        pw.print("  ");
+                        pw.print(feat.name);
+                        if (feat.version > 0) {
+                            pw.print(" version=");
+                            pw.print(feat.version);
                         }
                         pw.println();
                     }
                 }
             }
+        }
 
-            if (dumpState.isDumping(DumpState.DUMP_FEATURES) && packageName == null) {
-                if (dumpState.onTitlePrinted())
-                    pw.println();
-                if (!checkin) {
-                    pw.println("Features:");
-                }
-
-                synchronized (mAvailableFeatures) {
-                    for (FeatureInfo feat : mAvailableFeatures.values()) {
-                        if (checkin) {
-                            pw.print("feat,");
-                            pw.print(feat.name);
-                            pw.print(",");
-                            pw.println(feat.version);
-                        } else {
-                            pw.print("  ");
-                            pw.print(feat.name);
-                            if (feat.version > 0) {
-                                pw.print(" version=");
-                                pw.print(feat.version);
-                            }
-                            pw.println();
-                        }
-                    }
-                }
-            }
-
-            if (!checkin && dumpState.isDumping(DumpState.DUMP_ACTIVITY_RESOLVERS)) {
+        if (!checkin && dumpState.isDumping(DumpState.DUMP_ACTIVITY_RESOLVERS)) {
+            synchronized (mLock) {
                 mComponentResolver.dumpActivityResolvers(pw, dumpState, packageName);
             }
-            if (!checkin && dumpState.isDumping(DumpState.DUMP_RECEIVER_RESOLVERS)) {
+        }
+        if (!checkin && dumpState.isDumping(DumpState.DUMP_RECEIVER_RESOLVERS)) {
+            synchronized (mLock) {
                 mComponentResolver.dumpReceiverResolvers(pw, dumpState, packageName);
             }
-            if (!checkin && dumpState.isDumping(DumpState.DUMP_SERVICE_RESOLVERS)) {
+        }
+        if (!checkin && dumpState.isDumping(DumpState.DUMP_SERVICE_RESOLVERS)) {
+            synchronized (mLock) {
                 mComponentResolver.dumpServiceResolvers(pw, dumpState, packageName);
             }
-            if (!checkin && dumpState.isDumping(DumpState.DUMP_CONTENT_RESOLVERS)) {
+        }
+        if (!checkin && dumpState.isDumping(DumpState.DUMP_CONTENT_RESOLVERS)) {
+            synchronized (mLock) {
                 mComponentResolver.dumpProviderResolvers(pw, dumpState, packageName);
             }
+        }
 
-            if (!checkin && dumpState.isDumping(DumpState.DUMP_PREFERRED)) {
+        if (!checkin && dumpState.isDumping(DumpState.DUMP_PREFERRED)) {
+            // TODO: This cannot be moved to ComputerEngine since some variables with collections
+            //  types in IntentResolver such as mTypeToFilter do not have a copy of `F[]`.
+            synchronized (mLock) {
                 mSettings.dumpPreferred(pw, dumpState, packageName);
             }
+        }
 
-            if (!checkin && dumpState.isDumping(DumpState.DUMP_PREFERRED_XML)) {
-                pw.flush();
-                FileOutputStream fout = new FileOutputStream(fd);
-                BufferedOutputStream str = new BufferedOutputStream(fout);
-                TypedXmlSerializer serializer = Xml.newFastSerializer();
-                try {
-                    serializer.setOutput(str, StandardCharsets.UTF_8.name());
-                    serializer.startDocument(null, true);
-                    serializer.setFeature(
-                            "http://xmlpull.org/v1/doc/features.html#indent-output", true);
-                    mSettings.writePreferredActivitiesLPr(serializer, 0, fullPreferred);
-                    serializer.endDocument();
-                    serializer.flush();
-                } catch (IllegalArgumentException e) {
-                    pw.println("Failed writing: " + e);
-                } catch (IllegalStateException e) {
-                    pw.println("Failed writing: " + e);
-                } catch (IOException e) {
-                    pw.println("Failed writing: " + e);
-                }
-            }
+        if (!checkin && dumpState.isDumping(DumpState.DUMP_PREFERRED_XML)) {
+            dump(DumpState.DUMP_PREFERRED_XML, fd, pw, dumpState);
+        }
 
-            if (!checkin && dumpState.isDumping(DumpState.DUMP_DOMAIN_PREFERRED)) {
-                android.util.IndentingPrintWriter writer =
-                        new android.util.IndentingPrintWriter(pw);
-                if (dumpState.onTitlePrinted()) pw.println();
+        if (!checkin && dumpState.isDumping(DumpState.DUMP_DOMAIN_PREFERRED)) {
+            dump(DumpState.DUMP_DOMAIN_PREFERRED, fd, pw, dumpState);
+        }
 
-                writer.println("Domain verification status:");
-                writer.increaseIndent();
-                try {
-                    mDomainVerificationManager.printState(writer, packageName, UserHandle.USER_ALL,
-                            mSettings::getPackageLPr);
-                } catch (PackageManager.NameNotFoundException e) {
-                    pw.println("Failure printing domain verification information");
-                    Slog.e(TAG, "Failure printing domain verification information", e);
-                }
-                writer.decreaseIndent();
-            }
+        if (!checkin && dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) {
+            mSettings.dumpPermissions(pw, packageName, permissionNames, dumpState);
+        }
 
-            if (!checkin && dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) {
-                mSettings.dumpPermissionsLPr(pw, packageName, permissionNames, dumpState);
-            }
-
-            if (!checkin && dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
+        if (!checkin && dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
+            synchronized (mLock) {
                 mComponentResolver.dumpContentProviders(pw, dumpState, packageName);
             }
+        }
 
-            if (!checkin && dumpState.isDumping(DumpState.DUMP_KEYSETS)) {
+        if (!checkin && dumpState.isDumping(DumpState.DUMP_KEYSETS)) {
+            synchronized (mLock) {
                 mSettings.getKeySetManagerService().dumpLPr(pw, packageName, dumpState);
             }
+        }
 
-            if (dumpState.isDumping(DumpState.DUMP_PACKAGES)) {
+        if (dumpState.isDumping(DumpState.DUMP_PACKAGES)) {
+            // This cannot be moved to ComputerEngine since some variables of the collections
+            // in PackageUserState such as suspendParams, disabledComponents and enabledComponents
+            // do not have a copy.
+            synchronized (mLock) {
                 mSettings.dumpPackagesLPr(pw, packageName, permissionNames, dumpState, checkin);
             }
+        }
 
-            if (dumpState.isDumping(DumpState.DUMP_QUERIES)) {
-                final PackageSetting setting = mSettings.getPackageLPr(packageName);
-                Integer filteringAppId = setting == null ? null : setting.appId;
-                mAppsFilter.dumpQueries(
-                        pw, this, filteringAppId, dumpState,
-                        mUserManager.getUserIds());
-            }
+        if (dumpState.isDumping(DumpState.DUMP_QUERIES)) {
+            dump(DumpState.DUMP_QUERIES, fd, pw, dumpState);
+        }
 
-            if (dumpState.isDumping(DumpState.DUMP_SHARED_USERS)) {
+        if (dumpState.isDumping(DumpState.DUMP_SHARED_USERS)) {
+            // This cannot be moved to ComputerEngine since the set of packages in the
+            // SharedUserSetting do not have a copy.
+            synchronized (mLock) {
                 mSettings.dumpSharedUsersLPr(pw, packageName, permissionNames, dumpState, checkin);
             }
+        }
 
-            if (dumpState.isDumping(DumpState.DUMP_CHANGES)) {
-                if (dumpState.onTitlePrinted()) pw.println();
-                pw.println("Package Changes:");
+        if (dumpState.isDumping(DumpState.DUMP_CHANGES)) {
+            if (dumpState.onTitlePrinted()) pw.println();
+            pw.println("Package Changes:");
+            synchronized (mLock) {
                 pw.print("  Sequence number="); pw.println(mChangedPackagesSequenceNumber);
                 final int K = mChangedPackages.size();
                 for (int i = 0; i < K; i++) {
@@ -24002,16 +24194,18 @@
                     }
                 }
             }
+        }
 
-            if (!checkin && dumpState.isDumping(DumpState.DUMP_FROZEN) && packageName == null) {
-                // XXX should handle packageName != null by dumping only install data that
-                // the given package is involved with.
-                if (dumpState.onTitlePrinted()) pw.println();
+        if (!checkin && dumpState.isDumping(DumpState.DUMP_FROZEN) && packageName == null) {
+            // XXX should handle packageName != null by dumping only install data that
+            // the given package is involved with.
+            if (dumpState.onTitlePrinted()) pw.println();
 
-                final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ", 120);
-                ipw.println();
-                ipw.println("Frozen packages:");
-                ipw.increaseIndent();
+            final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ", 120);
+            ipw.println();
+            ipw.println("Frozen packages:");
+            ipw.increaseIndent();
+            synchronized (mLock) {
                 if (mFrozenPackages.size() == 0) {
                     ipw.println("(none)");
                 } else {
@@ -24019,16 +24213,18 @@
                         ipw.println(mFrozenPackages.valueAt(i));
                     }
                 }
-                ipw.decreaseIndent();
             }
+            ipw.decreaseIndent();
+        }
 
-            if (!checkin && dumpState.isDumping(DumpState.DUMP_VOLUMES) && packageName == null) {
-                if (dumpState.onTitlePrinted()) pw.println();
+        if (!checkin && dumpState.isDumping(DumpState.DUMP_VOLUMES) && packageName == null) {
+            if (dumpState.onTitlePrinted()) pw.println();
 
-                final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ", 120);
-                ipw.println();
-                ipw.println("Loaded volumes:");
-                ipw.increaseIndent();
+            final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ", 120);
+            ipw.println();
+            ipw.println("Loaded volumes:");
+            ipw.increaseIndent();
+            synchronized (mLoadedVolumes) {
                 if (mLoadedVolumes.size() == 0) {
                     ipw.println("(none)");
                 } else {
@@ -24036,36 +24232,39 @@
                         ipw.println(mLoadedVolumes.valueAt(i));
                     }
                 }
-                ipw.decreaseIndent();
             }
+            ipw.decreaseIndent();
+        }
 
-            if (!checkin && dumpState.isDumping(DumpState.DUMP_SERVICE_PERMISSIONS)
-                    && packageName == null) {
+        if (!checkin && dumpState.isDumping(DumpState.DUMP_SERVICE_PERMISSIONS)
+                && packageName == null) {
+            synchronized (mLock) {
                 mComponentResolver.dumpServicePermissions(pw, dumpState);
             }
+        }
 
-            if (!checkin && dumpState.isDumping(DumpState.DUMP_DEXOPT)) {
-                if (dumpState.onTitlePrinted()) pw.println();
-                dumpDexoptStateLPr(pw, packageName);
-            }
+        if (!checkin && dumpState.isDumping(DumpState.DUMP_DEXOPT)) {
+            if (dumpState.onTitlePrinted()) pw.println();
+            dump(DumpState.DUMP_DEXOPT, fd, pw, dumpState);
+        }
 
-            if (!checkin && dumpState.isDumping(DumpState.DUMP_COMPILER_STATS)) {
-                if (dumpState.onTitlePrinted()) pw.println();
-                dumpCompilerStatsLPr(pw, packageName);
-            }
+        if (!checkin && dumpState.isDumping(DumpState.DUMP_COMPILER_STATS)) {
+            if (dumpState.onTitlePrinted()) pw.println();
+            dump(DumpState.DUMP_COMPILER_STATS, fd, pw, dumpState);
+        }
 
-            if (!checkin && dumpState.isDumping(DumpState.DUMP_MESSAGES) && packageName == null) {
-                if (dumpState.onTitlePrinted()) pw.println();
+        if (!checkin && dumpState.isDumping(DumpState.DUMP_MESSAGES) && packageName == null) {
+            if (dumpState.onTitlePrinted()) pw.println();
+            synchronized (mLock) {
                 mSettings.dumpReadMessagesLPr(pw, dumpState);
-
-                pw.println();
-                pw.println("Package warning messages:");
-                dumpCriticalInfo(pw, null);
             }
+            pw.println();
+            pw.println("Package warning messages:");
+            dumpCriticalInfo(pw, null);
+        }
 
-            if (checkin && dumpState.isDumping(DumpState.DUMP_MESSAGES)) {
-                dumpCriticalInfo(pw, "msg,");
-            }
+        if (checkin && dumpState.isDumping(DumpState.DUMP_MESSAGES)) {
+            dumpCriticalInfo(pw, "msg,");
         }
 
         // PackageInstaller should be called outside of mPackages lock
@@ -24100,6 +24299,14 @@
         }
     }
 
+    /**
+     * Dump package manager states to the file according to a given dumping type of
+     * {@link DumpState}.
+     */
+    private void dump(int type, FileDescriptor fd, PrintWriter pw, DumpState dumpState) {
+        snapshotComputer().dump(type, fd, pw, dumpState);
+    }
+
     //TODO: b/111402650
     private void disableSkuSpecificApps() {
         String apkList[] = mContext.getResources().getStringArray(
@@ -24174,7 +24381,7 @@
         final int count = mSharedLibraries.size();
         for (int i = 0; i < count; i++) {
             final String libName = mSharedLibraries.keyAt(i);
-            LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(libName);
+            WatchedLongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(libName);
             if (versionedLib == null) {
                 continue;
             }
@@ -24198,72 +24405,6 @@
         }
     }
 
-    @GuardedBy("mLock")
-    @SuppressWarnings("resource")
-    private void dumpDexoptStateLPr(PrintWriter pw, String packageName) {
-        final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
-        ipw.println();
-        ipw.println("Dexopt state:");
-        ipw.increaseIndent();
-        Collection<PackageSetting> pkgSettings;
-        if (packageName != null) {
-            PackageSetting targetPkgSetting = mSettings.getPackageLPr(packageName);
-            if (targetPkgSetting != null) {
-                pkgSettings = Collections.singletonList(targetPkgSetting);
-            } else {
-                ipw.println("Unable to find package: " + packageName);
-                return;
-            }
-        } else {
-            pkgSettings = mSettings.getPackagesLocked().values();
-        }
-
-        for (PackageSetting pkgSetting : pkgSettings) {
-            if (pkgSetting.pkg == null) {
-                continue;
-            }
-            ipw.println("[" + pkgSetting.name + "]");
-            ipw.increaseIndent();
-            mPackageDexOptimizer.dumpDexoptState(ipw, pkgSetting.pkg, pkgSetting,
-                    mDexManager.getPackageUseInfoOrDefault(pkgSetting.pkg.getPackageName()));
-            ipw.decreaseIndent();
-        }
-    }
-
-    @GuardedBy("mLock")
-    @SuppressWarnings("resource")
-    private void dumpCompilerStatsLPr(PrintWriter pw, String packageName) {
-        final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
-        ipw.println();
-        ipw.println("Compiler stats:");
-        ipw.increaseIndent();
-        Collection<AndroidPackage> packages;
-        if (packageName != null) {
-            AndroidPackage targetPackage = mPackages.get(packageName);
-            if (targetPackage != null) {
-                packages = Collections.singletonList(targetPackage);
-            } else {
-                ipw.println("Unable to find package: " + packageName);
-                return;
-            }
-        } else {
-            packages = mPackages.values();
-        }
-
-        for (AndroidPackage pkg : packages) {
-            ipw.println("[" + pkg.getPackageName() + "]");
-            ipw.increaseIndent();
-
-            CompilerStats.PackageStats stats = getCompilerPackageStats(pkg.getPackageName());
-            if (stats == null) {
-                ipw.println("(No recorded stats)");
-            } else {
-                stats.dump(ipw);
-            }
-            ipw.decreaseIndent();
-        }
-    }
-
     // ------- apps on sdcard specific code -------
     static final boolean DEBUG_SD_INSTALL = false;
 
@@ -24422,7 +24563,9 @@
 
         if (DEBUG_INSTALL) Slog.d(TAG, "Loaded packages " + loaded);
         sendResourcesChangedBroadcast(true, false, loaded, null);
-        mLoadedVolumes.add(vol.getId());
+        synchronized (mLoadedVolumes) {
+            mLoadedVolumes.add(vol.getId());
+        }
     }
 
     private void unloadPrivatePackages(final VolumeInfo vol) {
@@ -24470,7 +24613,9 @@
 
         if (DEBUG_INSTALL) Slog.d(TAG, "Unloaded packages " + unloaded);
         sendResourcesChangedBroadcast(false, false, unloaded, null);
-        mLoadedVolumes.remove(vol.getId());
+        synchronized (mLoadedVolumes) {
+            mLoadedVolumes.remove(vol.getId());
+        }
 
         // Try very hard to release any references to this path so we don't risk
         // the system server being killed due to open FDs
@@ -25973,6 +26118,11 @@
             return PackageManagerService.this.hasSigningCertificate(
                 packageName, certificate, CERT_INPUT_SHA256);
         }
+
+        @Override
+        public boolean hasSystemFeature(String featureName, int version) {
+            return PackageManagerService.this.hasSystemFeature(featureName, version);
+        }
     }
 
     private AndroidPackage getPackage(String packageName) {
@@ -27402,43 +27552,14 @@
         }
     }
 
-    private String getOatDir(AndroidPackage pkg, @NonNull PackageSetting pkgSetting) {
-        if (!AndroidPackageUtils.canHaveOatDir(pkg,
-                pkgSetting.getPkgState().isUpdatedSystemApp())) {
-            return null;
-        }
-        File codePath = new File(pkg.getPath());
-        if (codePath.isDirectory()) {
-            return PackageDexOptimizer.getOatDir(codePath).getAbsolutePath();
-        }
-        return null;
-    }
-
     void deleteOatArtifactsOfPackage(String packageName) {
-        final String[] instructionSets;
-        final List<String> codePaths;
-        final String oatDir;
         final AndroidPackage pkg;
         final PackageSetting pkgSetting;
         synchronized (mLock) {
             pkg = mPackages.get(packageName);
             pkgSetting = mSettings.getPackageLPr(packageName);
         }
-        instructionSets = getAppDexInstructionSets(
-                AndroidPackageUtils.getPrimaryCpuAbi(pkg, pkgSetting),
-                AndroidPackageUtils.getSecondaryCpuAbi(pkg, pkgSetting));
-        codePaths = AndroidPackageUtils.getAllCodePaths(pkg);
-        oatDir = getOatDir(pkg, pkgSetting);
-
-        for (String codePath : codePaths) {
-            for (String isa : instructionSets) {
-                try {
-                    mInstaller.deleteOdex(codePath, isa, oatDir);
-                } catch (InstallerException e) {
-                    Log.e(TAG, "Failed deleting oat files for " + codePath, e);
-                }
-            }
-        }
+        mDexManager.deleteOptimizedFiles(ArtUtils.createArtPackageInfo(pkg, pkgSetting));
     }
 
     Set<String> getUnusedPackages(long downgradeTimeThresholdMillis) {
@@ -27710,7 +27831,8 @@
         return result.toArray(new PerUidReadTimeouts[result.size()]);
     }
 
-    static @NonNull BroadcastOptions getTemporaryAppWhitelistBroadcastOptions() {
+    static @NonNull BroadcastOptions getTemporaryAppAllowlistBroadcastOptions(
+            @PowerWhitelistManager.ReasonCode int reasonCode) {
         long duration = 10_000;
         final ActivityManagerInternal amInternal =
                 LocalServices.getService(ActivityManagerInternal.class);
@@ -27718,9 +27840,9 @@
             duration = amInternal.getBootTimeTempAllowListDuration();
         }
         final BroadcastOptions bOptions = BroadcastOptions.makeBasic();
-        bOptions.setTemporaryAppWhitelistDuration(
-                BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
-                duration);
+        bOptions.setTemporaryAppAllowlist(duration,
+                TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+                reasonCode, "");
         return bOptions;
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index a83a3f8..38e100e 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -787,6 +787,10 @@
         return firstInstallTime;
     }
 
+    public String getName() {
+        return name;
+    }
+
     protected PackageSettingBase updateFrom(PackageSettingBase other) {
         super.copyFrom(other);
         setPath(other.getPath());
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 2112247..ec7b451 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -40,7 +40,6 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ComponentInfo;
 import android.content.pm.IntentFilterVerificationInfo;
-import android.content.pm.overlay.OverlayPaths;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageUserState;
@@ -72,6 +71,7 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.incremental.IncrementalManager;
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
 import android.service.pm.PackageServiceDumpProto;
@@ -1028,6 +1028,9 @@
                 pkgSetting.legacyNativeLibraryPathString = legacyNativeLibraryPath;
             }
             pkgSetting.setPath(codePath);
+            if (IncrementalManager.isIncrementalPath(codePath.getAbsolutePath())) {
+                pkgSetting.incrementalStates = new IncrementalStates();
+            }
         }
         // If what we are scanning is a system (and possibly privileged) package,
         // then make it so, regardless of whether it was previously installed only
@@ -4877,7 +4880,7 @@
         }
     }
 
-    void dumpPermissionsLPr(PrintWriter pw, String packageName, ArraySet<String> permissionNames,
+    void dumpPermissions(PrintWriter pw, String packageName, ArraySet<String> permissionNames,
             DumpState dumpState) {
         LegacyPermissionSettings.dumpPermissions(pw, packageName, permissionNames,
                 mPermissionDataProvider.getLegacyPermissions(),
diff --git a/services/core/java/com/android/server/pm/ShortcutBitmapSaver.java b/services/core/java/com/android/server/pm/ShortcutBitmapSaver.java
index 1c5f0a7..f411c98 100644
--- a/services/core/java/com/android/server/pm/ShortcutBitmapSaver.java
+++ b/services/core/java/com/android/server/pm/ShortcutBitmapSaver.java
@@ -280,7 +280,8 @@
                     IoUtils.closeQuietly(out);
                 }
 
-                shortcut.setBitmapPath(file.getAbsolutePath());
+                final String path = file.getAbsolutePath();
+                mService.postValue(shortcut, si -> si.setBitmapPath(path));
 
             } catch (IOException | RuntimeException e) {
                 Slog.e(ShortcutService.TAG, "Unable to write bitmap to file", e);
@@ -295,12 +296,14 @@
                 Slog.d(TAG, "Saved bitmap.");
             }
             if (shortcut != null) {
-                if (shortcut.getBitmapPath() == null) {
-                    removeIcon(shortcut);
-                }
+                mService.postValue(shortcut, si -> {
+                    if (si.getBitmapPath() == null) {
+                        removeIcon(si);
+                    }
 
-                // Whatever happened, remove this flag.
-                shortcut.clearFlags(ShortcutInfo.FLAG_ICON_FILE_PENDING_SAVE);
+                    // Whatever happened, remove this flag.
+                    si.clearFlags(ShortcutInfo.FLAG_ICON_FILE_PENDING_SAVE);
+                });
             }
         }
         return true;
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index bb4ec16..302e657 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -19,15 +19,22 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.Person;
+import android.app.appsearch.AppSearchManager;
+import android.app.appsearch.AppSearchSession;
+import android.app.appsearch.PackageIdentifier;
+import android.app.appsearch.SetSchemaRequest;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.LocusId;
+import android.content.pm.AppSearchPerson;
+import android.content.pm.AppSearchShortcutInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutManager;
 import android.content.res.Resources;
 import android.graphics.drawable.Icon;
+import android.os.Binder;
 import android.os.PersistableBundle;
 import android.text.format.Formatter;
 import android.util.ArrayMap;
@@ -39,9 +46,11 @@
 import android.util.TypedXmlSerializer;
 import android.util.Xml;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.CollectionUtils;
+import com.android.internal.util.ConcurrentUtils;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
 import com.android.server.pm.ShortcutService.DumpFilter;
@@ -64,8 +73,12 @@
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.function.Consumer;
+import java.util.function.Function;
 import java.util.function.Predicate;
 
 /**
@@ -155,6 +168,16 @@
 
     private long mLastKnownForegroundElapsedTime;
 
+    private final Object mLock = new Object();
+
+    /**
+     * All external packages that have gained access to the shortcuts from this package
+     */
+    private final Map<String, PackageIdentifier> mPackageIdentifiers = new ArrayMap<>(0);
+
+    @GuardedBy("mLock")
+    private AppSearchSession mAppSearchSession;
+
     private ShortcutPackage(ShortcutUser shortcutUser,
             int packageUserId, String packageName, ShortcutPackageInfo spi) {
         super(shortcutUser, packageUserId, packageName,
@@ -200,12 +223,14 @@
         // - Disable if needed.
         for (int i = mShortcuts.size() - 1; i >= 0; i--) {
             ShortcutInfo si = mShortcuts.valueAt(i);
-            si.clearFlags(ShortcutInfo.FLAG_SHADOW);
+            mutateShortcut(si.getId(), si, shortcut -> {
+                shortcut.clearFlags(ShortcutInfo.FLAG_SHADOW);
 
-            si.setDisabledReason(restoreBlockReason);
-            if (restoreBlockReason != ShortcutInfo.DISABLED_REASON_NOT_DISABLED) {
-                si.addFlags(ShortcutInfo.FLAG_DISABLED);
-            }
+                shortcut.setDisabledReason(restoreBlockReason);
+                if (restoreBlockReason != ShortcutInfo.DISABLED_REASON_NOT_DISABLED) {
+                    shortcut.addFlags(ShortcutInfo.FLAG_DISABLED);
+                }
+            });
         }
         // Because some launchers may not have been restored (e.g. allowBackup=false),
         // we need to re-calculate the pinned shortcuts.
@@ -437,9 +462,11 @@
             if (si.isDynamic() && (!ignoreInvisible || si.isVisibleToPublisher())) {
                 changed = true;
 
-                si.setTimestamp(now);
-                si.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
-                si.setRank(0); // It may still be pinned, so clear the rank.
+                mutateShortcut(si.getId(), si, shortcut -> {
+                    shortcut.setTimestamp(now);
+                    shortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
+                    shortcut.setRank(0); // It may still be pinned, so clear the rank.
+                });
             }
         }
         if (changed) {
@@ -483,7 +510,7 @@
     public ShortcutInfo deleteLongLivedWithId(@NonNull String shortcutId, boolean ignoreInvisible) {
         final ShortcutInfo shortcut = mShortcuts.get(shortcutId);
         if (shortcut != null) {
-            shortcut.clearFlags(ShortcutInfo.FLAG_CACHED_ALL);
+            mutateShortcut(shortcutId, null, si -> si.clearFlags(ShortcutInfo.FLAG_CACHED_ALL));
         }
         return deleteOrDisableWithId(
                 shortcutId, /* disable =*/ false, /* overrideImmutable=*/ false, ignoreInvisible,
@@ -504,15 +531,16 @@
                 overrideImmutable, ignoreInvisible, disabledReason);
 
         // If disabled id still exists, it is pinned and we need to update the disabled message.
-        final ShortcutInfo disabled = mShortcuts.get(shortcutId);
-        if (disabled != null) {
-            if (disabledMessage != null) {
-                disabled.setDisabledMessage(disabledMessage);
-            } else if (disabledMessageResId != 0) {
-                disabled.setDisabledMessageResId(disabledMessageResId);
-                mShortcutUser.mService.fixUpShortcutResourceNamesAndValues(disabled);
+        mutateShortcut(shortcutId, null, disabled -> {
+            if (disabled != null) {
+                if (disabledMessage != null) {
+                    disabled.setDisabledMessage(disabledMessage);
+                } else if (disabledMessageResId != 0) {
+                    disabled.setDisabledMessageResId(disabledMessageResId);
+                    mShortcutUser.mService.fixUpShortcutResourceNamesAndValues(disabled);
+                }
             }
-        }
+        });
 
         return deleted;
     }
@@ -534,21 +562,23 @@
         }
         if (oldShortcut.isPinned() || oldShortcut.isCached()) {
 
-            oldShortcut.setRank(0);
-            oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST);
-            if (disable) {
-                oldShortcut.addFlags(ShortcutInfo.FLAG_DISABLED);
-                // Do not overwrite the disabled reason if one is alreay set.
-                if (oldShortcut.getDisabledReason() == ShortcutInfo.DISABLED_REASON_NOT_DISABLED) {
-                    oldShortcut.setDisabledReason(disabledReason);
+            mutateShortcut(oldShortcut.getId(), oldShortcut, si -> {
+                si.setRank(0);
+                si.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST);
+                if (disable) {
+                    si.addFlags(ShortcutInfo.FLAG_DISABLED);
+                    // Do not overwrite the disabled reason if one is alreay set.
+                    if (si.getDisabledReason() == ShortcutInfo.DISABLED_REASON_NOT_DISABLED) {
+                        si.setDisabledReason(disabledReason);
+                    }
                 }
-            }
-            oldShortcut.setTimestamp(mShortcutUser.mService.injectCurrentTimeMillis());
+                si.setTimestamp(mShortcutUser.mService.injectCurrentTimeMillis());
 
-            // See ShortcutRequestPinProcessor.directPinShortcut().
-            if (mShortcutUser.mService.isDummyMainActivity(oldShortcut.getActivity())) {
-                oldShortcut.setActivity(null);
-            }
+                // See ShortcutRequestPinProcessor.directPinShortcut().
+                if (mShortcutUser.mService.isDummyMainActivity(si.getActivity())) {
+                    si.setActivity(null);
+                }
+            });
 
             return null;
         } else {
@@ -558,12 +588,11 @@
     }
 
     public void enableWithId(@NonNull String shortcutId) {
-        final ShortcutInfo shortcut = mShortcuts.get(shortcutId);
-        if (shortcut != null) {
-            ensureNotImmutable(shortcut, /*ignoreInvisible=*/ true);
-            shortcut.clearFlags(ShortcutInfo.FLAG_DISABLED);
-            shortcut.setDisabledReason(ShortcutInfo.DISABLED_REASON_NOT_DISABLED);
-        }
+        mutateShortcut(shortcutId, null, si -> {
+            ensureNotImmutable(si, /*ignoreInvisible=*/ true);
+            si.clearFlags(ShortcutInfo.FLAG_DISABLED);
+            si.setDisabledReason(ShortcutInfo.DISABLED_REASON_NOT_DISABLED);
+        });
     }
 
     public void updateInvisibleShortcutForPinRequestWith(@NonNull ShortcutInfo shortcut) {
@@ -586,22 +615,25 @@
      * <p>Then remove all shortcuts that are not dynamic and no longer pinned either.
      */
     public void refreshPinnedFlags() {
-        // First, un-pin all shortcuts
-        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
-            mShortcuts.valueAt(i).clearFlags(ShortcutInfo.FLAG_PINNED);
+        // TODO: rewrite this function with proper query (i.e. fetch only pinned shortcuts and
+        //  unpin if it's no longer pinned by any launcher and vice versa)
+        final List<ShortcutInfo> shortcuts = new ArrayList<>(mShortcuts.values());
+        final Map<String, ShortcutInfo> shortcutMap = new ArrayMap<>(shortcuts.size());
+        for (ShortcutInfo si : shortcuts) {
+            shortcutMap.put(si.getId(), si);
         }
+        final Set<String> pinnedShortcuts = new ArraySet<>();
 
-        // Then, for the pinned set for each launcher, set the pin flag one by one.
+        // First, for the pinned set for each launcher, keep track of their id one by one.
         mShortcutUser.forAllLaunchers(launcherShortcuts -> {
             final ArraySet<String> pinned = launcherShortcuts.getPinnedShortcutIds(
                     getPackageName(), getPackageUserId());
-
             if (pinned == null || pinned.size() == 0) {
                 return;
             }
             for (int i = pinned.size() - 1; i >= 0; i--) {
                 final String id = pinned.valueAt(i);
-                final ShortcutInfo si = mShortcuts.get(id);
+                final ShortcutInfo si = shortcutMap.get(id);
                 if (si == null) {
                     // This happens if a launcher pinned shortcuts from this package, then backup&
                     // restored, but this package doesn't allow backing up.
@@ -609,9 +641,21 @@
                     // That's fine, when the launcher is restored, we'll fix it.
                     continue;
                 }
-                si.addFlags(ShortcutInfo.FLAG_PINNED);
+                pinnedShortcuts.add(si.getId());
             }
         });
+        // Then, update the pinned state if necessary
+        for (int i = shortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo si = shortcuts.get(i);
+            if (pinnedShortcuts.contains(si.getId()) && !si.isPinned()) {
+                mutateShortcut(si.getId(), si,
+                        shortcut -> shortcut.addFlags(ShortcutInfo.FLAG_PINNED));
+            }
+            if (!pinnedShortcuts.contains(si.getId()) && si.isPinned()) {
+                mutateShortcut(si.getId(), si, shortcut ->
+                        shortcut.clearFlags(ShortcutInfo.FLAG_PINNED));
+            }
+        }
 
         // Lastly, remove the ones that are no longer pinned, cached nor dynamic.
         removeOrphans();
@@ -1011,8 +1055,10 @@
                 continue;
             }
             Slog.i(TAG, String.format("Restoring shortcut: %s", si.getId()));
-            si.clearFlags(ShortcutInfo.FLAG_DISABLED);
-            si.setDisabledReason(ShortcutInfo.DISABLED_REASON_NOT_DISABLED);
+            mutateShortcut(si.getId(), si, shortcut -> {
+                shortcut.clearFlags(ShortcutInfo.FLAG_DISABLED);
+                shortcut.setDisabledReason(ShortcutInfo.DISABLED_REASON_NOT_DISABLED);
+            });
         }
 
         // For existing shortcuts, update timestamps if they have any resources.
@@ -1042,21 +1088,24 @@
                 }
 
                 if (si.hasAnyResources()) {
-                    if (!si.isOriginallyFromManifest()) {
+                    if (publisherRes == null) {
+                        publisherRes = getPackageResources();
                         if (publisherRes == null) {
-                            publisherRes = getPackageResources();
-                            if (publisherRes == null) {
-                                break; // Resources couldn't be loaded.
-                            }
+                            break; // Resources couldn't be loaded.
+                        }
+                    }
+
+                    final Resources res = publisherRes;
+                    mutateShortcut(si.getId(), si, shortcut -> {
+                        if (!shortcut.isOriginallyFromManifest()) {
+                            shortcut.lookupAndFillInResourceIds(res);
                         }
 
-                        // TODO: update resource strings in AppSearch
                         // If this shortcut is not from a manifest, then update all resource IDs
                         // from resource names.  (We don't allow resource strings for
                         // non-manifest at the moment, but icons can still be resources.)
-                        si.lookupAndFillInResourceIds(publisherRes);
-                    }
-                    si.setTimestamp(s.injectCurrentTimeMillis());
+                        shortcut.setTimestamp(s.injectCurrentTimeMillis());
+                    });
                 }
             }
         }
@@ -1359,8 +1408,11 @@
                     }
                 }
 
-                si.resolveResourceStrings(publisherRes);
-                si.setTimestamp(s.injectCurrentTimeMillis());
+                final Resources res = publisherRes;
+                mutateShortcut(si.getId(), si, shortcut -> {
+                    shortcut.resolveResourceStrings(res);
+                    shortcut.setTimestamp(s.injectCurrentTimeMillis());
+                });
 
                 if (changedShortcuts == null) {
                     changedShortcuts = new ArrayList<>(1);
@@ -1377,7 +1429,7 @@
     public void clearAllImplicitRanks() {
         for (int i = mShortcuts.size() - 1; i >= 0; i--) {
             final ShortcutInfo si = mShortcuts.valueAt(i);
-            si.clearImplicitRankAndRankChangedFlag();
+            mutateShortcut(si.getId(), si, ShortcutInfo::clearImplicitRankAndRankChangedFlag);
         }
     }
 
@@ -1422,8 +1474,10 @@
             final ShortcutInfo si = mShortcuts.valueAt(i);
             if (si.isFloating()) {
                 if (si.getRank() != 0) {
-                    si.setTimestamp(now);
-                    si.setRank(0);
+                    mutateShortcut(si.getId(), si, shortcut -> {
+                        shortcut.setTimestamp(now);
+                        shortcut.setRank(0);
+                    });
                 }
             }
         }
@@ -1456,8 +1510,10 @@
                 }
                 final int thisRank = rank++;
                 if (si.getRank() != thisRank) {
-                    si.setTimestamp(now);
-                    si.setRank(thisRank);
+                    mutateShortcut(si.getId(), si, shortcut -> {
+                        shortcut.setTimestamp(now);
+                        shortcut.setRank(thisRank);
+                    });
                 }
             }
         }
@@ -2140,6 +2196,41 @@
         }
     }
 
+    void updateVisibility(String packageName, byte[] certificate, boolean visible) {
+        if (visible) {
+            mPackageIdentifiers.put(packageName, new PackageIdentifier(packageName, certificate));
+        } else {
+            mPackageIdentifiers.remove(packageName);
+        }
+        resetAppSearch(null);
+    }
+
+    void mutateShortcut(@NonNull final String id, @Nullable final ShortcutInfo shortcut,
+            @NonNull final Consumer<ShortcutInfo> transform) {
+        Objects.requireNonNull(id);
+        Objects.requireNonNull(transform);
+        synchronized (mLock) {
+            if (shortcut != null) {
+                transform.accept(shortcut);
+            } else {
+                transform.accept(findShortcutById(id));
+            }
+            // TODO: Load ShortcutInfo from AppSearch, apply transformation logic and save
+        }
+    }
+
+    /**
+     * Removes shortcuts from AppSearch.
+     */
+    void removeShortcuts() {
+    }
+
+    /**
+     * Merge/replace shortcuts parsed from xml file.
+     */
+    void restoreParsedShortcuts(final boolean replace) {
+    }
+
     private boolean verifyRanksSequential(List<ShortcutInfo> list) {
         boolean failed = false;
 
@@ -2153,4 +2244,128 @@
         }
         return failed;
     }
+
+    private void runInAppSearch(
+            Function<SearchSessionObservable, Consumer<AppSearchSession>>... observers) {
+        if (mShortcutUser == null) {
+            Slog.w(TAG, "shortcut user is null");
+            return;
+        }
+        synchronized (mLock) {
+            if (mAppSearchSession != null) {
+                final CountDownLatch latch = new CountDownLatch(1);
+                final long callingIdentity = Binder.clearCallingIdentity();
+                try {
+                    final SearchSessionObservable upstream =
+                            new SearchSessionObservable(mAppSearchSession, latch);
+                    for (Function<SearchSessionObservable, Consumer<AppSearchSession>> observer
+                            : observers) {
+                        upstream.map(observer);
+                    }
+                    upstream.next();
+                } finally {
+                    Binder.restoreCallingIdentity(callingIdentity);
+                }
+                ConcurrentUtils.waitForCountDownNoInterrupt(latch, 500,
+                        "timeout accessing shortcut");
+            } else {
+                resetAppSearch(observers);
+            }
+        }
+    }
+
+    private void resetAppSearch(
+            Function<SearchSessionObservable, Consumer<AppSearchSession>>... observers) {
+        final CountDownLatch latch = new CountDownLatch(1);
+        final AppSearchManager.SearchContext searchContext =
+                new AppSearchManager.SearchContext.Builder()
+                        .setDatabaseName(getPackageName()).build();
+        mShortcutUser.runInAppSearch(searchContext, result -> {
+            if (!result.isSuccess()) {
+                Slog.e(TAG, "error getting search session during lazy init, "
+                        + result.getErrorMessage());
+                latch.countDown();
+                return;
+            }
+            // TODO: Flatten callback chain with proper async framework
+            final SearchSessionObservable upstream =
+                    new SearchSessionObservable(result.getResultValue(), latch)
+                            .map(this::setupSchema);
+            if (observers != null) {
+                for (Function<SearchSessionObservable, Consumer<AppSearchSession>> observer
+                        : observers) {
+                    upstream.map(observer);
+                }
+            }
+            upstream.map(observable -> session -> {
+                mAppSearchSession = session;
+                observable.next();
+            });
+            upstream.next();
+        });
+        ConcurrentUtils.waitForCountDownNoInterrupt(latch, 1500,
+                "timeout accessing shortcut during lazy initialization");
+    }
+
+    /**
+     * creates the schema for shortcut in the database
+     */
+    private Consumer<AppSearchSession> setupSchema(SearchSessionObservable observable) {
+        return session -> {
+            SetSchemaRequest.Builder schemaBuilder = new SetSchemaRequest.Builder()
+                            .addSchemas(AppSearchPerson.SCHEMA, AppSearchShortcutInfo.SCHEMA);
+            for (PackageIdentifier pi : mPackageIdentifiers.values()) {
+                schemaBuilder = schemaBuilder
+                        .setSchemaTypeVisibilityForPackage(
+                                AppSearchPerson.SCHEMA_TYPE, true, pi)
+                        .setSchemaTypeVisibilityForPackage(
+                                AppSearchShortcutInfo.SCHEMA_TYPE, true, pi);
+            }
+            session.setSchema(schemaBuilder.build(), mShortcutUser.mExecutor, result -> {
+                if (!result.isSuccess()) {
+                    observable.error("failed to instantiate app search schema: "
+                            + result.getErrorMessage());
+                    return;
+                }
+                observable.next();
+            });
+        };
+    }
+
+    /**
+     * TODO: Replace this temporary implementation with proper async framework
+     */
+    private class SearchSessionObservable {
+
+        final AppSearchSession mSession;
+        final CountDownLatch mLatch;
+        final ArrayList<Consumer<AppSearchSession>> mObservers = new ArrayList<>(1);
+
+        SearchSessionObservable(@NonNull final AppSearchSession session,
+                @NonNull final CountDownLatch latch) {
+            mSession = session;
+            mLatch = latch;
+        }
+
+        SearchSessionObservable map(
+                Function<SearchSessionObservable, Consumer<AppSearchSession>> observer) {
+            mObservers.add(observer.apply(this));
+            return this;
+        }
+
+        void next() {
+            if (mObservers.isEmpty()) {
+                mLatch.countDown();
+                return;
+            }
+            mObservers.remove(0).accept(mSession);
+        }
+
+        void error(@Nullable final String errorMessage) {
+            if (errorMessage != null) {
+                Slog.e(TAG, errorMessage);
+            }
+            mLatch.countDown();
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 4d8abea..f84eb44 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -662,7 +662,7 @@
     /** lifecycle event */
     void handleUnlockUser(int userId) {
         if (DEBUG) {
-        Slog.d(TAG, "handleUnlockUser: user=" + userId);
+            Slog.d(TAG, "handleUnlockUser: user=" + userId);
         }
         synchronized (mUnlockedUsers) {
             mUnlockedUsers.put(userId, true);
@@ -1179,6 +1179,14 @@
         }
     }
 
+    void postValue(@NonNull final ShortcutInfo shortcutInfo,
+            @NonNull final Consumer<ShortcutInfo> cb) {
+        final String pkg = shortcutInfo.getPackage();
+        final int userId = shortcutInfo.getUserId();
+        final String id = shortcutInfo.getId();
+        getPackageShortcutsLocked(pkg, userId).mutateShortcut(id, shortcutInfo, cb);
+    }
+
     /** Return the last reset time. */
     @GuardedBy("mLock")
     long getLastResetTimeLocked() {
@@ -1566,7 +1574,6 @@
      * resource-based strings.
      */
     void fixUpShortcutResourceNamesAndValues(ShortcutInfo si) {
-        // TODO: update resource names in AppSearch
         final Resources publisherRes = injectGetResourcesForApplicationAsUser(
                 si.getPackage(), si.getUserId());
         if (publisherRes != null) {
@@ -1947,7 +1954,7 @@
         final boolean unlimited = injectHasUnlimitedShortcutsApiCallsPermission(
                 injectBinderCallingPid(), injectBinderCallingUid());
 
-        List<ShortcutInfo> changedShortcuts = null;
+        final List<ShortcutInfo> changedShortcuts = new ArrayList<>(1);
 
         synchronized (mLock) {
             throwIfUserLockedL(userId);
@@ -1975,59 +1982,57 @@
                 final ShortcutInfo source = newShortcuts.get(i);
                 fixUpIncomingShortcutInfo(source, /* forUpdate= */ true);
 
-                final ShortcutInfo target = ps.findShortcutById(source.getId());
+                ps.mutateShortcut(source.getId(), null, target -> {
+                    // Invisible shortcuts can't be updated.
+                    if (target == null || !target.isVisibleToPublisher()) {
+                        return;
+                    }
 
-                // Invisible shortcuts can't be updated.
-                if (target == null || !target.isVisibleToPublisher()) {
-                    continue;
-                }
+                    if (target.isEnabled() != source.isEnabled()) {
+                        Slog.w(TAG,
+                                "ShortcutInfo.enabled cannot be changed with updateShortcuts()");
+                    }
 
-                if (target.isEnabled() != source.isEnabled()) {
-                    Slog.w(TAG,
-                            "ShortcutInfo.enabled cannot be changed with updateShortcuts()");
-                }
+                    if (target.isLongLived() != source.isLongLived()) {
+                        Slog.w(TAG,
+                                "ShortcutInfo.longLived cannot be changed with updateShortcuts()");
+                    }
 
-                if (target.isLongLived() != source.isLongLived()) {
-                    Slog.w(TAG,
-                            "ShortcutInfo.longLived cannot be changed with updateShortcuts()");
-                }
+                    // When updating the rank, we need to insert between existing ranks, so set
+                    // this setRankChanged, and also copy the implicit rank fo adjustRanks().
+                    if (source.hasRank()) {
+                        target.setRankChanged();
+                        target.setImplicitRank(source.getImplicitRank());
+                    }
 
-                // When updating the rank, we need to insert between existing ranks, so set
-                // this setRankChanged, and also copy the implicit rank fo adjustRanks().
-                if (source.hasRank()) {
-                    target.setRankChanged();
-                    target.setImplicitRank(source.getImplicitRank());
-                }
+                    final boolean replacingIcon = (source.getIcon() != null);
+                    if (replacingIcon) {
+                        removeIconLocked(target);
+                    }
 
-                final boolean replacingIcon = (source.getIcon() != null);
-                if (replacingIcon) {
-                    removeIconLocked(target);
-                }
+                    // Note copyNonNullFieldsFrom() does the "updatable with?" check too.
+                    target.copyNonNullFieldsFrom(source);
+                    target.setTimestamp(injectCurrentTimeMillis());
 
-                // Note copyNonNullFieldsFrom() does the "updatable with?" check too.
-                target.copyNonNullFieldsFrom(source);
-                target.setTimestamp(injectCurrentTimeMillis());
+                    if (replacingIcon) {
+                        saveIconAndFixUpShortcutLocked(target);
+                    }
 
-                if (replacingIcon) {
-                    saveIconAndFixUpShortcutLocked(target);
-                }
+                    // When we're updating any resource related fields, re-extract the res names and
+                    // the values.
+                    if (replacingIcon || source.hasStringResources()) {
+                        fixUpShortcutResourceNamesAndValues(target);
+                    }
 
-                // When we're updating any resource related fields, re-extract the res names and
-                // the values.
-                if (replacingIcon || source.hasStringResources()) {
-                    fixUpShortcutResourceNamesAndValues(target);
-                }
-
-                if (changedShortcuts == null) {
-                    changedShortcuts = new ArrayList<>(1);
-                }
-                changedShortcuts.add(target);
+                    changedShortcuts.add(target);
+                });
             }
 
             // Lastly, adjust the ranks.
             ps.adjustRanks();
         }
-        packageShortcutsChanged(packageName, userId, changedShortcuts, null);
+        packageShortcutsChanged(packageName, userId,
+                changedShortcuts.isEmpty() ? null : changedShortcuts, null);
 
         verifyStates();
 
@@ -2150,6 +2155,15 @@
     }
 
     @Override
+    public void updateShortcutVisibility(String callingPkg, String packageName, byte[] certificate,
+            boolean visible, int userId) {
+        synchronized (mLock) {
+            getPackageShortcutsForPublisherLocked(callingPkg, userId)
+                    .updateVisibility(packageName, certificate, visible);
+        }
+    }
+
+    @Override
     public boolean requestPinShortcut(String packageName, ShortcutInfo shortcut,
             IntentSender resultIntent, int userId) {
         Objects.requireNonNull(shortcut);
@@ -3105,7 +3119,8 @@
 
                     if (doCache) {
                         if (si.isLongLived()) {
-                            si.addFlags(cacheFlags);
+                            sp.mutateShortcut(si.getId(), si,
+                                    shortcut -> shortcut.addFlags(cacheFlags));
                             if (changedShortcuts == null) {
                                 changedShortcuts = new ArrayList<>(1);
                             }
@@ -3116,7 +3131,8 @@
                         }
                     } else {
                         ShortcutInfo removed = null;
-                        si.clearFlags(cacheFlags);
+                        sp.mutateShortcut(si.getId(), si, shortcut ->
+                                shortcut.clearFlags(cacheFlags));
                         if (!si.isDynamic() && !si.isCached()) {
                             removed = sp.deleteLongLivedWithId(id, /*ignoreInvisible=*/ true);
                         }
diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java
index 3e3aa67..ec784d0 100644
--- a/services/core/java/com/android/server/pm/ShortcutUser.java
+++ b/services/core/java/com/android/server/pm/ShortcutUser.java
@@ -18,9 +18,14 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
+import android.app.appsearch.AppSearchManager;
+import android.app.appsearch.AppSearchResult;
+import android.app.appsearch.AppSearchSession;
 import android.content.pm.ShortcutManager;
 import android.metrics.LogMaker;
+import android.os.Binder;
 import android.os.FileUtils;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.text.format.Formatter;
 import android.util.ArrayMap;
@@ -32,6 +37,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.server.FgThread;
 import com.android.server.pm.ShortcutService.DumpFilter;
 import com.android.server.pm.ShortcutService.InvalidFileFormatException;
 
@@ -45,6 +51,7 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.Objects;
+import java.util.concurrent.Executor;
 import java.util.function.Consumer;
 
 /**
@@ -111,6 +118,8 @@
     }
 
     final ShortcutService mService;
+    final AppSearchManager mAppSearchManager;
+    final Executor mExecutor;
 
     @UserIdInt
     private final int mUserId;
@@ -132,6 +141,9 @@
     public ShortcutUser(ShortcutService service, int userId) {
         mService = service;
         mUserId = userId;
+        mAppSearchManager = service.mContext.createContextAsUser(UserHandle.of(userId), 0)
+                .getSystemService(AppSearchManager.class);
+        mExecutor = FgThread.getExecutor();
     }
 
     public int getUserId() {
@@ -173,6 +185,9 @@
     public ShortcutPackage removePackage(@NonNull String packageName) {
         final ShortcutPackage removed = mPackages.remove(packageName);
 
+        if (removed != null) {
+            removed.removeShortcuts();
+        }
         mService.cleanupBitmapsForPackage(mUserId, packageName);
 
         return removed;
@@ -318,7 +333,10 @@
 
         if (!shortcutPackage.rescanPackageIfNeeded(isNewApp, forceRescan)) {
             if (isNewApp) {
-                mPackages.remove(packageName);
+                final ShortcutPackage sp = mPackages.remove(packageName);
+                if (sp != null) {
+                    sp.removeShortcuts();
+                }
             }
         }
     }
@@ -442,6 +460,7 @@
                         case ShortcutPackage.TAG_ROOT: {
                             final ShortcutPackage shortcuts = ShortcutPackage.loadFromXml(
                                     s, ret, parser, fromBackup);
+                            shortcuts.restoreParsedShortcuts(false);
 
                             // Don't use addShortcut(), we don't need to save the icon.
                             ret.mPackages.put(shortcuts.getPackageName(), shortcuts);
@@ -476,6 +495,7 @@
                 final ShortcutPackage sp = ShortcutPackage.loadFromFile(s, ret, f, fromBackup);
                 if (sp != null) {
                     ret.mPackages.put(sp.getPackageName(), sp);
+                    sp.restoreParsedShortcuts(false);
                 }
             });
 
@@ -558,6 +578,7 @@
                 Log.w(TAG, "Shortcuts for package " + sp.getPackageName() + " are being restored."
                         + " Existing non-manifeset shortcuts will be overwritten.");
             }
+            sp.restoreParsedShortcuts(true);
             addPackage(sp);
             restoredPackages[0]++;
             restoredShortcuts[0] += sp.getShortcutCount();
@@ -693,4 +714,18 @@
         logger.write(logMaker.setType(MetricsEvent.SHORTCUTS_CHANGED_SHORTCUT_COUNT)
                 .setSubtype(totalSharingShortcutCount));
     }
+
+    void runInAppSearch(@NonNull final AppSearchManager.SearchContext searchContext,
+            @NonNull final Consumer<AppSearchResult<AppSearchSession>> callback) {
+        if (mAppSearchManager == null) {
+            Slog.e(TAG, "app search manager is null");
+            return;
+        }
+        final long callingIdentity = Binder.clearCallingIdentity();
+        try {
+            mAppSearchManager.createSearchSession(searchContext, mExecutor, callback);
+        } finally {
+            Binder.restoreCallingIdentity(callingIdentity);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java
index c17d2e4..eb2de60 100644
--- a/services/core/java/com/android/server/pm/UserManagerInternal.java
+++ b/services/core/java/com/android/server/pm/UserManagerInternal.java
@@ -63,8 +63,13 @@
      */
     public interface UserLifecycleListener {
 
-        /** Called when a new user is created. */
-        default void onUserCreated(UserInfo user) {}
+        /**
+         * Called when a new user is created.
+         *
+         * @param user new user.
+         * @param token token passed to the method that created the user.
+         */
+        default void onUserCreated(UserInfo user, @Nullable Object token) {}
 
         /** Called when an existing user is removed. */
         default void onUserRemoved(UserInfo user) {}
@@ -179,10 +184,12 @@
      * {@link UserManager#DISALLOW_ADD_USER} and {@link UserManager#DISALLOW_ADD_MANAGED_PROFILE}
      *
      * <p>Called by the {@link com.android.server.devicepolicy.DevicePolicyManagerService} when
-     * createAndManageUser is called by the device owner.
+     * createAndManageUser is called by the device owner; it uses {@code token} to block until
+     * the user is created (as it will be passed back to it through
+     * {@link UserLifecycleListener#onUserCreated(UserInfo, Object)});
      */
     public abstract UserInfo createUserEvenWhenDisallowed(String name, String userType,
-            int flags, String[] disallowedPackages)
+            int flags, String[] disallowedPackages, @Nullable Object token)
             throws UserManager.CheckedUserOperationException;
 
     /**
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 24c27be..871576e 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -983,7 +983,11 @@
 
     @Override
     public UserInfo getProfileParent(@UserIdInt int userId) {
-        checkManageUsersPermission("get the profile parent");
+        if (!hasManageUsersOrPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)) {
+            throw new SecurityException(
+                    "You need MANAGE_USERS or INTERACT_ACROSS_USERS permission to get the "
+                            + "profile parent");
+        }
         synchronized (mUsersLock) {
             return getProfileParentLU(userId);
         }
@@ -1522,20 +1526,30 @@
     }
 
     @Override
-    public boolean isUserForeground() {
-        int callingUserId = Binder.getCallingUserHandle().getIdentifier();
+    public boolean isUserForeground(@UserIdInt int userId) {
+        final int callingUserId = UserHandle.getCallingUserId();
+        if (callingUserId != userId
+                && !hasManageUsersOrPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)) {
+            throw new SecurityException("Caller from user " + callingUserId + " needs MANAGE_USERS "
+                    + "or INTERACT_ACROSS_USERS permission to check if another user (" + userId
+                    + ") is running in the foreground");
+        }
+
         int currentUser = Binder.withCleanCallingIdentity(() -> ActivityManager.getCurrentUser());
         // TODO(b/179163496): should return true for profile users of the current user as well
-        return currentUser == callingUserId;
+        return currentUser == userId;
     }
 
     @Override
     public String getUserName() {
-        if (!hasManageUsersOrPermission(android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED)) {
-            throw new SecurityException("You need MANAGE_USERS or GET_ACCOUNTS_PRIVILEGED "
-                    + "permissions to: get user name");
+        final int callingUid = Binder.getCallingUid();
+        if (!hasManageOrCreateUsersPermission()
+                || hasPermissionGranted(
+                        android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED, callingUid)) {
+            throw new SecurityException("You need MANAGE_USERS or CREATE_USERS or "
+                    + "GET_ACCOUNTS_PRIVILEGED permissions to: get user name");
         }
-        final int userId = UserHandle.getUserId(Binder.getCallingUid());
+        final int userId = UserHandle.getUserId(callingUid);
         synchronized (mUsersLock) {
             UserInfo userInfo = userWithName(getUserInfoLU(userId));
             return userInfo == null ? "" : userInfo.name;
@@ -3287,7 +3301,7 @@
      * as well as for {@link UserManager#USER_TYPE_FULL_RESTRICTED}.
      */
     @Override
-    public UserInfo createProfileForUserWithThrow(String name, @NonNull String userType,
+    public UserInfo createProfileForUserWithThrow(@Nullable String name, @NonNull String userType,
             @UserInfoFlag int flags, @UserIdInt int userId, @Nullable String[] disallowedPackages)
             throws ServiceSpecificException {
         checkManageOrCreateUsersPermission(flags);
@@ -3309,7 +3323,7 @@
         checkManageOrCreateUsersPermission(flags);
         try {
             return createUserInternalUnchecked(name, userType, flags, userId,
-                    /* preCreate= */ false, disallowedPackages);
+                    /* preCreate= */ false, disallowedPackages, /* token= */ null);
         } catch (UserManager.CheckedUserOperationException e) {
             throw e.toServiceSpecificException();
         }
@@ -3342,7 +3356,7 @@
         try {
             return createUserInternalUnchecked(/* name= */ null, userType, flags,
                     /* parentId= */ UserHandle.USER_NULL, /* preCreate= */ true,
-                    /* disallowedPackages= */ null);
+                    /* disallowedPackages= */ null, /* token= */ null);
         } catch (UserManager.CheckedUserOperationException e) {
             throw e.toServiceSpecificException();
         }
@@ -3358,12 +3372,13 @@
         enforceUserRestriction(restriction, UserHandle.getCallingUserId(),
                 "Cannot add user");
         return createUserInternalUnchecked(name, userType, flags, parentId,
-                /* preCreate= */ false, disallowedPackages);
+                /* preCreate= */ false, disallowedPackages, /* token= */ null);
     }
 
     private UserInfo createUserInternalUnchecked(@Nullable String name,
             @NonNull String userType, @UserInfoFlag int flags, @UserIdInt int parentId,
-            boolean preCreate, @Nullable String[] disallowedPackages)
+            boolean preCreate, @Nullable String[] disallowedPackages,
+            @Nullable Object token)
             throws UserManager.CheckedUserOperationException {
         final int nextProbableUserId = getNextAvailableId();
         final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
@@ -3372,7 +3387,7 @@
         UserInfo newUser = null;
         try {
             newUser = createUserInternalUncheckedNoTracing(name, userType, flags, parentId,
-                        preCreate, disallowedPackages, t);
+                        preCreate, disallowedPackages, t, token);
             return newUser;
         } finally {
             logUserCreateJourneyFinish(sessionId, nextProbableUserId, newUser != null);
@@ -3383,7 +3398,8 @@
     private UserInfo createUserInternalUncheckedNoTracing(@Nullable String name,
             @NonNull String userType, @UserInfoFlag int flags, @UserIdInt int parentId,
             boolean preCreate, @Nullable String[] disallowedPackages,
-            @NonNull TimingsTraceAndSlog t) throws UserManager.CheckedUserOperationException {
+            @NonNull TimingsTraceAndSlog t, @Nullable Object token)
+                    throws UserManager.CheckedUserOperationException {
         final UserTypeDetails userTypeDetails = mUserTypes.get(userType);
         if (userTypeDetails == null) {
             Slog.e(LOG_TAG, "Cannot create user of invalid user type: " + userType);
@@ -3409,7 +3425,8 @@
 
         // Try to use a pre-created user (if available).
         if (!preCreate && parentId < 0 && isUserTypeEligibleForPreCreation(userTypeDetails)) {
-            final UserInfo preCreatedUser = convertPreCreatedUserIfPossible(userType, flags, name);
+            final UserInfo preCreatedUser = convertPreCreatedUserIfPossible(userType, flags, name,
+                    token);
             if (preCreatedUser != null) {
                 return preCreatedUser;
             }
@@ -3588,7 +3605,7 @@
                     Slog.w(LOG_TAG, "could not start pre-created user " + userId, e);
                 }
             } else {
-                dispatchUserAdded(userInfo);
+                dispatchUserAdded(userInfo, token);
             }
 
         } finally {
@@ -3688,7 +3705,7 @@
      * @return the converted user, or {@code null} if no pre-created user could be converted.
      */
     private @Nullable UserInfo convertPreCreatedUserIfPossible(String userType,
-            @UserInfoFlag int flags, String name) {
+            @UserInfoFlag int flags, String name, @Nullable Object token) {
         final UserData preCreatedUserData;
         synchronized (mUsersLock) {
             preCreatedUserData = getPreCreatedUserLU(userType);
@@ -3726,7 +3743,7 @@
         }
         updateUserIds();
         mPm.onNewUserCreated(preCreatedUser.id, /* convertedFromPreCreated= */ true);
-        dispatchUserAdded(preCreatedUser);
+        dispatchUserAdded(preCreatedUser, token);
         return preCreatedUser;
     }
 
@@ -3758,11 +3775,11 @@
         return (now > EPOCH_PLUS_30_YEARS) ? now : 0;
     }
 
-    private void dispatchUserAdded(@NonNull UserInfo userInfo) {
+    private void dispatchUserAdded(@NonNull UserInfo userInfo, @Nullable Object token) {
         // Notify internal listeners first...
         synchronized (mUserLifecycleListeners) {
             for (int i = 0; i < mUserLifecycleListeners.size(); i++) {
-                mUserLifecycleListeners.get(i).onUserCreated(userInfo);
+                mUserLifecycleListeners.get(i).onUserCreated(userInfo, token);
             }
         }
 
@@ -3868,7 +3885,7 @@
      * @hide
      */
     @Override
-    public UserInfo createRestrictedProfileWithThrow(String name, int parentUserId) {
+    public UserInfo createRestrictedProfileWithThrow(@Nullable String name, int parentUserId) {
         checkManageOrCreateUsersPermission("setupRestrictedProfile");
         final UserInfo user = createProfileForUserWithThrow(
                 name, UserManager.USER_TYPE_FULL_RESTRICTED, 0, parentUserId, null);
@@ -5367,10 +5384,10 @@
 
         @Override
         public UserInfo createUserEvenWhenDisallowed(String name, @NonNull String userType,
-                @UserInfoFlag int flags, String[] disallowedPackages)
+                @UserInfoFlag int flags, String[] disallowedPackages, @Nullable Object token)
                 throws UserManager.CheckedUserOperationException {
             return createUserInternalUnchecked(name, userType, flags,
-                    UserHandle.USER_NULL, /* preCreated= */ false, disallowedPackages);
+                    UserHandle.USER_NULL, /* preCreated= */ false, disallowedPackages, token);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/pm/dex/ArtPackageInfo.java b/services/core/java/com/android/server/pm/dex/ArtPackageInfo.java
new file mode 100644
index 0000000..50bf916
--- /dev/null
+++ b/services/core/java/com/android/server/pm/dex/ArtPackageInfo.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.dex;
+
+import java.util.List;
+
+/**
+ * Holds package information relevant to ART use cases.
+ */
+public class ArtPackageInfo {
+    private final String mPackageName;
+    private final List<String> mInstructionSets;
+    private final List<String> mCodePaths;
+    // TODO: This should be computed on the fly in PackageDexOptimizer / DexManager, but the
+    // logic is too complicated to do it in a single re-factoring.
+    private final String mOatDir;
+
+    public ArtPackageInfo(
+            String packageName,
+            List<String> instructionSets,
+            List<String> codePaths,
+            String oatDir) {
+        mPackageName = packageName;
+        mInstructionSets = instructionSets;
+        mCodePaths = codePaths;
+        mOatDir = oatDir;
+    }
+
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    public List<String> getInstructionSets() {
+        return mInstructionSets;
+    }
+
+    public List<String> getCodePaths() {
+        return mCodePaths;
+    }
+
+    public String getOatDir() {
+        return mOatDir;
+    }
+}
diff --git a/services/core/java/com/android/server/pm/dex/ArtUtils.java b/services/core/java/com/android/server/pm/dex/ArtUtils.java
new file mode 100644
index 0000000..16d7a9a
--- /dev/null
+++ b/services/core/java/com/android/server/pm/dex/ArtUtils.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.dex;
+
+import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
+
+import android.annotation.NonNull;
+
+import com.android.server.pm.PackageDexOptimizer;
+import com.android.server.pm.PackageSetting;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
+
+import java.io.File;
+import java.util.Arrays;
+
+/**
+ * Utility class to interface between PM and ART tooling (e.g. DexManager).
+ */
+public final class ArtUtils {
+    private ArtUtils() {
+    }
+
+    /**
+     * Create the ART-representation of package info.
+     */
+    public static ArtPackageInfo createArtPackageInfo(
+            AndroidPackage pkg, PackageSetting pkgSetting) {
+        return new ArtPackageInfo(
+                pkg.getPackageName(),
+                Arrays.asList(getAppDexInstructionSets(
+                        AndroidPackageUtils.getPrimaryCpuAbi(pkg, pkgSetting),
+                        AndroidPackageUtils.getSecondaryCpuAbi(pkg, pkgSetting))),
+                AndroidPackageUtils.getAllCodePaths(pkg),
+                getOatDir(pkg, pkgSetting));
+    }
+
+    private static String getOatDir(AndroidPackage pkg, @NonNull PackageSetting pkgSetting) {
+        if (!AndroidPackageUtils.canHaveOatDir(pkg,
+                pkgSetting.getPkgState().isUpdatedSystemApp())) {
+            return null;
+        }
+        File codePath = new File(pkg.getPath());
+        if (codePath.isDirectory()) {
+            return PackageDexOptimizer.getOatDir(codePath).getAbsolutePath();
+        }
+        return null;
+    }
+
+}
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index cc6d80a..349561d 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -215,7 +215,7 @@
                         searchResult.mOutcome == DEX_SEARCH_FOUND_SPLIT;
 
                 if (primaryOrSplit && !isUsedByOtherApps
-                        && !PLATFORM_PACKAGE_NAME.equals(searchResult.mOwningPackageName)) {
+                        && !isPlatformPackage(searchResult.mOwningPackageName)) {
                     // If the dex file is the primary apk (or a split) and not isUsedByOtherApps
                     // do not record it. This case does not bring any new usable information
                     // and can be safely skipped.
@@ -232,15 +232,24 @@
                 }
 
                 String classLoaderContext = mapping.getValue();
+
+                // Overwrite the class loader context for system server (instead of merging it).
+                // We expect system server jars to only change contexts in between OTAs and to
+                // otherwise be stable.
+                // Instead of implementing a complex clear-context logic post OTA, it is much
+                // simpler to always override the context for system server. This way, the context
+                // will always be up to date and we will avoid merging which could lead to the
+                // the context being marked as variable and thus making dexopt non-optimal.
+                boolean overwriteCLC = isPlatformPackage(searchResult.mOwningPackageName);
+
                 if (classLoaderContext != null
                         && VMRuntime.isValidClassLoaderContext(classLoaderContext)) {
                     // Record dex file usage. If the current usage is a new pattern (e.g. new
                     // secondary, or UsedByOtherApps), record will return true and we trigger an
                     // async write to disk to make sure we don't loose the data in case of a reboot.
-
                     if (mPackageDexUsage.record(searchResult.mOwningPackageName,
                             dexPath, loaderUserId, loaderIsa, primaryOrSplit,
-                            loadingAppInfo.packageName, classLoaderContext)) {
+                            loadingAppInfo.packageName, classLoaderContext, overwriteCLC)) {
                         mPackageDexUsage.maybeWriteAsync();
                     }
                 }
@@ -474,7 +483,7 @@
      *         because they don't need to be compiled)..
      */
     public boolean dexoptSecondaryDex(DexoptOptions options) {
-        if (PLATFORM_PACKAGE_NAME.equals(options.getPackageName())) {
+        if (isPlatformPackage(options.getPackageName())) {
             // We could easily redirect to #dexoptSystemServer in this case. But there should be
             // no-one calling this method directly for system server.
             // As such we prefer to abort in this case.
@@ -534,7 +543,7 @@
      * <p>PackageDexOptimizer.DEX_OPT_PERFORMED if all dexopt operations succeeded.
      */
     public int dexoptSystemServer(DexoptOptions options) {
-        if (!PLATFORM_PACKAGE_NAME.equals(options.getPackageName())) {
+        if (!isPlatformPackage(options.getPackageName())) {
             Slog.wtf(TAG, "Non system server package used when trying to dexopt system server:"
                     + options.getPackageName());
             return PackageDexOptimizer.DEX_OPT_FAILED;
@@ -662,7 +671,7 @@
             // Special handle system server files.
             // We don't need an installd call because we have permissions to check if the file
             // exists.
-            if (PLATFORM_PACKAGE_NAME.equals(packageName)) {
+            if (isPlatformPackage(packageName)) {
                 if (!Files.exists(Paths.get(dexPath))) {
                     if (DEBUG) {
                         Slog.w(TAG, "A dex file previously loaded by System Server does not exist "
@@ -739,7 +748,8 @@
             boolean newUpdate = mPackageDexUsage.record(searchResult.mOwningPackageName,
                     dexPath, userId, isa, /*primaryOrSplit*/ false,
                     loadingPackage,
-                    PackageDexUsage.VARIABLE_CLASS_LOADER_CONTEXT);
+                    PackageDexUsage.VARIABLE_CLASS_LOADER_CONTEXT,
+                    /*overwriteCLC*/ false);
             update |= newUpdate;
         }
         if (update) {
@@ -809,7 +819,7 @@
         // Note: We don't have any way to detect which code paths are actually
         // owned by system server. We can only assume that such paths are on
         // system partitions.
-        if (PLATFORM_PACKAGE_NAME.equals(loadingAppInfo.packageName)) {
+        if (isPlatformPackage(loadingAppInfo.packageName)) {
             if (isSystemServerDexPathSupportedForOdex(dexPath)) {
                 // We record system server dex files as secondary dex files.
                 // The reason is that we only record the class loader context for secondary dex
@@ -842,6 +852,11 @@
         return new DexSearchResult(null, DEX_SEARCH_NOT_FOUND);
     }
 
+    /** Returns true if this is the platform package .*/
+    private static boolean isPlatformPackage(String packageName) {
+        return PLATFORM_PACKAGE_NAME.equals(packageName);
+    }
+
     private static <K,V> V putIfAbsent(Map<K,V> map, K key, V newValue) {
         V existingValue = map.putIfAbsent(key, newValue);
         return existingValue == null ? newValue : existingValue;
@@ -1000,6 +1015,22 @@
         return isBtmCritical;
     }
 
+    /**
+     * Deletes all the optimizations files generated by ART.
+     * @param packageInfo the package information.
+     */
+    public void deleteOptimizedFiles(ArtPackageInfo packageInfo) {
+        for (String codePath : packageInfo.getCodePaths()) {
+            for (String isa : packageInfo.getInstructionSets()) {
+                try {
+                    mInstaller.deleteOdex(codePath, isa, packageInfo.getOatDir());
+                } catch (InstallerException e) {
+                    Log.e(TAG, "Failed deleting oat files for " + codePath, e);
+                }
+            }
+        }
+    }
+
     public static class RegisterDexModuleResult {
         public RegisterDexModuleResult() {
             this(false, null);
diff --git a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
index 10760f5..3d63b75 100644
--- a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
+++ b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
@@ -111,17 +111,18 @@
      * @param dexPath the path of the dex files being loaded
      * @param ownerUserId the user id which runs the code loading the dex files
      * @param loaderIsa the ISA of the app loading the dex files
-     * @param isUsedByOtherApps whether or not this dex file was not loaded by its owning package
      * @param primaryOrSplit whether or not the dex file is a primary/split dex. True indicates
      *        the file is either primary or a split. False indicates the file is secondary dex.
      * @param loadingPackageName the package performing the load. Recorded only if it is different
      *        than {@param owningPackageName}.
+     * @param overwriteCLC if true, the class loader context will be overwritten instead of being
+     *        merged
      * @return true if the dex load constitutes new information, or false if this information
      *         has been seen before.
      */
     /* package */ boolean record(String owningPackageName, String dexPath, int ownerUserId,
             String loaderIsa, boolean primaryOrSplit,
-            String loadingPackageName, String classLoaderContext) {
+            String loadingPackageName, String classLoaderContext, boolean overwriteCLC) {
         if (!PackageManagerServiceUtils.checkISA(loaderIsa)) {
             throw new IllegalArgumentException("loaderIsa " + loaderIsa + " is unsupported");
         }
@@ -193,7 +194,7 @@
                         }
                         // Merge the information into the existing data.
                         // Returns true if there was an update.
-                        return existingData.merge(newData) || updateLoadingPackages;
+                        return existingData.merge(newData, overwriteCLC) || updateLoadingPackages;
                     }
                 }
             }
@@ -809,14 +810,16 @@
             mLoadingPackages = new HashSet<>(other.mLoadingPackages);
         }
 
-        private boolean merge(DexUseInfo dexUseInfo) {
+        private boolean merge(DexUseInfo dexUseInfo, boolean overwriteCLC) {
             boolean oldIsUsedByOtherApps = mIsUsedByOtherApps;
             mIsUsedByOtherApps = mIsUsedByOtherApps || dexUseInfo.mIsUsedByOtherApps;
             boolean updateIsas = mLoaderIsas.addAll(dexUseInfo.mLoaderIsas);
             boolean updateLoadingPackages = mLoadingPackages.addAll(dexUseInfo.mLoadingPackages);
 
             String oldClassLoaderContext = mClassLoaderContext;
-            if (isUnsupportedContext(mClassLoaderContext)) {
+            if (overwriteCLC) {
+                mClassLoaderContext = dexUseInfo.mClassLoaderContext;
+            } else if (isUnsupportedContext(mClassLoaderContext)) {
                 mClassLoaderContext = dexUseInfo.mClassLoaderContext;
             } else if (!Objects.equals(mClassLoaderContext, dexUseInfo.mClassLoaderContext)) {
                 // We detected a context change.
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 44a2187..e3ccb75 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -1277,12 +1277,7 @@
                     newFlags |= (flags & PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT);
 
                     // If we are allowlisting the permission, update the exempt flag before grant.
-                    // If the permission can't be allowlisted by an installer, skip it here because
-                    // this is where the platform takes the role of the installer for exempting
-                    // preinstalled apps.
-                    if (whitelistRestrictedPermissions && pm.isPermissionRestricted(permission)
-                            && !pm.getPermissionInfo(permission).isInstallerExemptIgnored()) {
-
+                    if (whitelistRestrictedPermissions && pm.isPermissionRestricted(permission)) {
                         pm.updatePermissionFlags(permission, pkg,
                                 PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT,
                                 PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT, user);
diff --git a/services/core/java/com/android/server/pm/permission/Permission.java b/services/core/java/com/android/server/pm/permission/Permission.java
index 32bee58..ac50f29 100644
--- a/services/core/java/com/android/server/pm/permission/Permission.java
+++ b/services/core/java/com/android/server/pm/permission/Permission.java
@@ -239,10 +239,6 @@
         return (mPermissionInfo.flags & PermissionInfo.FLAG_IMMUTABLY_RESTRICTED) != 0;
     }
 
-    public boolean isInstallerExemptIgnored() {
-        return (mPermissionInfo.flags & PermissionInfo.FLAG_INSTALLER_EXEMPT_IGNORED) != 0;
-    }
-
     public boolean isSignature() {
         return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
                 == PermissionInfo.PROTECTION_SIGNATURE;
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 71e53d9..2dfb6ff 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -24,14 +24,12 @@
 import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISALLOWED;
 import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISCOURAGED;
 import static android.content.pm.PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT;
-import static android.content.pm.PackageManager.FLAG_PERMISSION_ALLOWLIST_ROLE;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
-import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_ROLE_EXEMPT;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
@@ -68,15 +66,10 @@
 import android.app.AppOpsManager;
 import android.app.IActivityManager;
 import android.app.admin.DevicePolicyManagerInternal;
-import android.app.role.RoleManager;
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledAfter;
-import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.PermissionGroupInfoFlags;
 import android.content.pm.PackageManager.PermissionInfoFlags;
@@ -86,7 +79,6 @@
 import android.content.pm.ParceledListSlice;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
-import android.content.pm.UserInfo;
 import android.content.pm.parsing.component.ParsedPermission;
 import android.content.pm.parsing.component.ParsedPermissionGroup;
 import android.content.pm.permission.SplitPermissionInfoParcelable;
@@ -401,105 +393,6 @@
                 new PermissionManagerServiceInternalImpl();
         LocalServices.addService(PermissionManagerServiceInternal.class, localService);
         LocalServices.addService(PermissionManagerInternal.class, localService);
-
-        context.getMainThreadHandler().post(() -> context.registerReceiver(new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                if (!Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
-                    return;
-                }
-
-                try {
-                    fixBgMicCamera(context);
-                } catch (Throwable t) {
-                    // Don't crash the system if this fails for any reason. Any intermediate state
-                    // this can leave the permissions in is okay and in the worst case the state is
-                    // the same as before the user rebooted.
-                    Log.e(LOG_TAG, "Unable to fix background permissions", t);
-                }
-            }
-
-
-            private void fixBgMicCamera(Context context) {
-                PackageManager pm = context.getPackageManager();
-                for (UserInfo userInfo : context.getSystemService(UserManager.class).getUsers()) {
-                    UserHandle user = userInfo.getUserHandle();
-                    List<String> assistants = context.getSystemService(RoleManager.class)
-                            .getRoleHoldersAsUser(RoleManager.ROLE_ASSISTANT, user);
-                    List<PackageInfo> packages =
-                            pm.getInstalledPackagesAsUser(PackageManager.MATCH_SYSTEM_ONLY
-                                    | PackageManager.GET_PERMISSIONS, user.getIdentifier());
-                    for (PackageInfo packageInfo : packages) {
-                        String[] requestedPermissions = packageInfo.requestedPermissions;
-                        if (requestedPermissions == null) {
-                            continue;
-                        }
-                        for (String permName : requestedPermissions) {
-                            String pkg = packageInfo.packageName;
-                            switch (permName) {
-                                case Manifest.permission.BACKGROUND_CAMERA:
-                                    removeFromAllowlistsAndRevoke(pm, pkg, permName, user);
-                                    break;
-                                case Manifest.permission.RECORD_BACKGROUND_AUDIO:
-                                    if (assistants.contains(pkg)) {
-                                        removeFromAllowlistsAndRevokeForAssistant(pm, pkg, permName,
-                                                user);
-                                    } else {
-                                        removeFromAllowlistsAndRevoke(pm, pkg, permName, user);
-                                    }
-                                    break;
-                            }
-                        }
-                    }
-                }
-            }
-
-            private void removeFromAllowlistsAndRevoke(PackageManager pm, String pkg,
-                    String permName, UserHandle user) {
-                if ((pm.getPermissionFlags(permName, pkg, user)
-                        & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0) {
-                    Slog.i(LOG_TAG, "removing " + pkg + " " + permName + " from all allowlists");
-                    pm.removeWhitelistedRestrictedPermission(pkg, permName,
-                            FLAG_PERMISSION_WHITELIST_UPGRADE);
-                    pm.removeWhitelistedRestrictedPermission(pkg, permName,
-                            FLAG_PERMISSION_WHITELIST_SYSTEM);
-                    pm.removeWhitelistedRestrictedPermission(pkg, permName,
-                            FLAG_PERMISSION_WHITELIST_INSTALLER);
-                    pm.removeWhitelistedRestrictedPermission(pkg, permName,
-                            FLAG_PERMISSION_ALLOWLIST_ROLE);
-                }
-                if (pm.checkPermission(permName, pkg) == PackageManager.PERMISSION_GRANTED) {
-                    Slog.i(LOG_TAG, "revoking " + pkg + " " + permName);
-                    pm.revokeRuntimePermission(pkg, permName, user);
-                }
-            }
-
-            private void removeFromAllowlistsAndRevokeForAssistant(PackageManager pm, String pkg,
-                    String permName, UserHandle user) {
-                int anyNonRoleExempt =
-                        FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT
-                                | FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT
-                                | FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
-
-                if ((pm.getPermissionFlags(permName, pkg, user) & anyNonRoleExempt) != 0) {
-                    Slog.i(LOG_TAG, "removing " + pkg + " " + permName
-                            + " from all allowlists except role");
-                    pm.removeWhitelistedRestrictedPermission(pkg, permName,
-                            FLAG_PERMISSION_WHITELIST_UPGRADE);
-                    pm.removeWhitelistedRestrictedPermission(pkg, permName,
-                            FLAG_PERMISSION_WHITELIST_SYSTEM);
-                    pm.removeWhitelistedRestrictedPermission(pkg, permName,
-                            FLAG_PERMISSION_WHITELIST_INSTALLER);
-                }
-                if ((pm.getPermissionFlags(permName, pkg, user)
-                        & FLAG_PERMISSION_RESTRICTION_ROLE_EXEMPT) == 0) {
-                    Slog.i(LOG_TAG, "adding " + pkg + " " + permName
-                            + " to role allowlist");
-                    pm.addWhitelistedRestrictedPermission(pkg, permName,
-                            FLAG_PERMISSION_ALLOWLIST_ROLE);
-                }
-            }
-        }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED)));
     }
 
     @Override
@@ -876,10 +769,6 @@
 
             isRuntimePermission = bp.isRuntime();
 
-            if (bp.isInstallerExemptIgnored()) {
-                flagValues &= ~FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
-            }
-
             final UidPermissionState uidState = getUidStateLocked(pkg, userId);
             if (uidState == null) {
                 Slog.e(TAG, "Missing permissions state for " + packageName + " and user " + userId);
@@ -1123,8 +1012,7 @@
         Preconditions.checkFlagsArgument(flags,
                 PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
                         | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
-                        | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER
-                        | PackageManager.FLAG_PERMISSION_ALLOWLIST_ROLE);
+                        | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
         Preconditions.checkArgumentNonNegative(userId, null);
 
         if (UserHandle.getCallingUserId() != userId) {
@@ -1148,9 +1036,9 @@
         final boolean isCallerInstallerOnRecord =
                 mPackageManagerInt.isCallerInstallerOfRecord(pkg, callingUid);
 
-        if ((flags & (PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
-                | PackageManager.FLAG_PERMISSION_ALLOWLIST_ROLE)) != 0 && !isCallerPrivileged) {
-            throw new SecurityException("Querying system or role allowlist requires "
+        if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0
+                && !isCallerPrivileged) {
+            throw new SecurityException("Querying system allowlist requires "
                     + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
         }
 
@@ -1192,9 +1080,6 @@
             if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER) != 0) {
                 queryFlags |= FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
             }
-            if ((flags & PackageManager.FLAG_PERMISSION_ALLOWLIST_ROLE) != 0) {
-                queryFlags |=  FLAG_PERMISSION_RESTRICTION_ROLE_EXEMPT;
-            }
 
             ArrayList<String> allowlistedPermissions = null;
 
@@ -1287,8 +1172,7 @@
         Preconditions.checkFlagsArgument(flags,
                 PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
                         | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
-                        | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER
-                        | PackageManager.FLAG_PERMISSION_ALLOWLIST_ROLE);
+                        | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
         Preconditions.checkArgument(Integer.bitCount(flags) == 1);
         Preconditions.checkArgumentNonNegative(userId, null);
 
@@ -1314,10 +1198,8 @@
         final boolean isCallerInstallerOnRecord =
                 mPackageManagerInt.isCallerInstallerOfRecord(pkg, callingUid);
 
-        if ((flags & (PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
-                | PackageManager.FLAG_PERMISSION_ALLOWLIST_ROLE)) != 0
-                && !isCallerPrivileged) {
-            throw new SecurityException("Modifying system or role allowlist requires "
+        if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0 && !isCallerPrivileged) {
+            throw new SecurityException("Modifying system allowlist requires "
                     + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
         }
 
@@ -3823,15 +3705,6 @@
                         }
                     }
                     break;
-                    case FLAG_PERMISSION_ALLOWLIST_ROLE: {
-                        mask |= FLAG_PERMISSION_RESTRICTION_ROLE_EXEMPT;
-                        if (permissions != null && permissions.contains(permissionName)) {
-                            newFlags |= FLAG_PERMISSION_RESTRICTION_ROLE_EXEMPT;
-                        } else {
-                            newFlags &= ~FLAG_PERMISSION_RESTRICTION_ROLE_EXEMPT;
-                        }
-                    }
-                    break;
                 }
             }
 
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationCollector.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationCollector.java
index 080de73..bf2b3c7 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationCollector.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationCollector.java
@@ -42,6 +42,8 @@
     private static final Pattern DOMAIN_NAME_WITH_WILDCARD =
             Pattern.compile("(\\*\\.)?" + Patterns.DOMAIN_NAME.pattern());
 
+    private static final int MAX_DOMAINS_BYTE_SIZE = 1024 * 1024;
+
     @NonNull
     private final PlatformCompat mPlatformCompat;
 
@@ -71,7 +73,7 @@
      *     <li>- Only IntentFilter.SCHEME_HTTP and/or IntentFilter.SCHEME_HTTPS,
      *           with no other schemes</li>
      * </ul>
-     *
+     * <p>
      * On prior versions of Android, Intent.CATEGORY_BROWSABLE was not a requirement, other
      * schemes were allowed, and setting autoVerify to true in any intent filter would implicitly
      * pretend that all intent filters were set to autoVerify="true".
@@ -82,42 +84,48 @@
 
     @NonNull
     public ArraySet<String> collectAllWebDomains(@NonNull AndroidPackage pkg) {
-        return collectDomains(pkg, false);
+        return collectDomains(pkg, false /* checkAutoVerify */, true /* valid */);
     }
 
     /**
-     * Effectively {@link #collectAllWebDomains(AndroidPackage)}, but requires
-     * {@link IntentFilter#getAutoVerify()} == true.
+     * Effectively {@link #collectAllWebDomains(AndroidPackage)}, but requires {@link
+     * IntentFilter#getAutoVerify()} == true.
      */
     @NonNull
-    public ArraySet<String> collectAutoVerifyDomains(@NonNull AndroidPackage pkg) {
-        return collectDomains(pkg, true);
+    public ArraySet<String> collectValidAutoVerifyDomains(@NonNull AndroidPackage pkg) {
+        return collectDomains(pkg, true /* checkAutoVerify */, true /* valid */);
+    }
+
+    /**
+     * Returns all the domains that are configured to be auto verified, but aren't actually valid
+     * HTTP domains, per {@link #DOMAIN_NAME_WITH_WILDCARD}.
+     */
+    @NonNull
+    public ArraySet<String> collectInvalidAutoVerifyDomains(@NonNull AndroidPackage pkg) {
+        return collectDomains(pkg, true /* checkAutoVerify */, false /* valid */);
     }
 
     @NonNull
     private ArraySet<String> collectDomains(@NonNull AndroidPackage pkg,
-            boolean checkAutoVerify) {
+            boolean checkAutoVerify, boolean valid) {
         boolean restrictDomains =
                 DomainVerificationUtils.isChangeEnabled(mPlatformCompat, pkg, RESTRICT_DOMAINS);
 
-        ArraySet<String> domains = new ArraySet<>();
-
         if (restrictDomains) {
-            collectDomains(domains, pkg, checkAutoVerify);
+            return collectDomainsInternal(pkg, checkAutoVerify, valid);
         } else {
-            collectDomainsLegacy(domains, pkg, checkAutoVerify);
+            return collectDomainsLegacy(pkg, checkAutoVerify, valid);
         }
-
-        return domains;
     }
 
-    /** @see #RESTRICT_DOMAINS */
-    private void collectDomainsLegacy(@NonNull Set<String> domains,
-            @NonNull AndroidPackage pkg, boolean checkAutoVerify) {
+    /**
+     * @see #RESTRICT_DOMAINS
+     */
+    private ArraySet<String> collectDomainsLegacy(@NonNull AndroidPackage pkg,
+            boolean checkAutoVerify, boolean valid) {
         if (!checkAutoVerify) {
             // Per-domain user selection state doesn't have a V1 equivalent on S, so just use V2
-            collectDomains(domains, pkg, false);
-            return;
+            return collectDomainsInternal(pkg, false /* checkAutoVerify */, true /* valid */);
         }
 
         List<ParsedActivity> activities = pkg.getActivities();
@@ -140,39 +148,54 @@
             }
 
             if (!needsAutoVerify) {
-                return;
+                return new ArraySet<>();
             }
         }
 
-        for (int activityIndex = 0; activityIndex < activitiesSize; activityIndex++) {
+        ArraySet<String> domains = new ArraySet<>();
+        int totalSize = 0;
+        boolean underMaxSize = true;
+        for (int activityIndex = 0; activityIndex < activitiesSize && underMaxSize;
+                activityIndex++) {
             ParsedActivity activity = activities.get(activityIndex);
             List<ParsedIntentInfo> intents = activity.getIntents();
             int intentsSize = intents.size();
-            for (int intentIndex = 0; intentIndex < intentsSize; intentIndex++) {
+            for (int intentIndex = 0; intentIndex < intentsSize && underMaxSize; intentIndex++) {
                 ParsedIntentInfo intent = intents.get(intentIndex);
                 if (intent.handlesWebUris(false)) {
                     int authorityCount = intent.countDataAuthorities();
                     for (int index = 0; index < authorityCount; index++) {
                         String host = intent.getDataAuthority(index).getHost();
-                        if (isValidHost(host)) {
+                        if (isValidHost(host) == valid) {
+                            totalSize += byteSizeOf(host);
+                            underMaxSize = totalSize < MAX_DOMAINS_BYTE_SIZE;
                             domains.add(host);
                         }
                     }
                 }
             }
         }
+
+        return domains;
     }
 
-    /** @see #RESTRICT_DOMAINS */
-    private void collectDomains(@NonNull Set<String> domains,
-            @NonNull AndroidPackage pkg, boolean checkAutoVerify) {
+    /**
+     * @see #RESTRICT_DOMAINS
+     */
+    private ArraySet<String> collectDomainsInternal(@NonNull AndroidPackage pkg,
+            boolean checkAutoVerify, boolean valid) {
+        ArraySet<String> domains = new ArraySet<>();
+        int totalSize = 0;
+        boolean underMaxSize = true;
+
         List<ParsedActivity> activities = pkg.getActivities();
         int activitiesSize = activities.size();
-        for (int activityIndex = 0; activityIndex < activitiesSize; activityIndex++) {
+        for (int activityIndex = 0; activityIndex < activitiesSize && underMaxSize;
+                activityIndex++) {
             ParsedActivity activity = activities.get(activityIndex);
             List<ParsedIntentInfo> intents = activity.getIntents();
             int intentsSize = intents.size();
-            for (int intentIndex = 0; intentIndex < intentsSize; intentIndex++) {
+            for (int intentIndex = 0; intentIndex < intentsSize && underMaxSize; intentIndex++) {
                 ParsedIntentInfo intent = intents.get(intentIndex);
                 if (checkAutoVerify && !intent.getAutoVerify()) {
                     continue;
@@ -198,14 +221,27 @@
                 //  app developer by declaring a separate intent-filter. This may not be worth
                 //  fixing.
                 int authorityCount = intent.countDataAuthorities();
-                for (int index = 0; index < authorityCount; index++) {
+                for (int index = 0; index < authorityCount && underMaxSize; index++) {
                     String host = intent.getDataAuthority(index).getHost();
-                    if (isValidHost(host)) {
+                    if (isValidHost(host) == valid) {
+                        totalSize += byteSizeOf(host);
+                        underMaxSize = totalSize < MAX_DOMAINS_BYTE_SIZE;
                         domains.add(host);
                     }
                 }
             }
         }
+
+        return domains;
+    }
+
+    /**
+     * Ballpark the size of domains to avoid a ridiculous amount of domains that could slow
+     * down client-server communication.
+     */
+    private int byteSizeOf(String string) {
+        // Use the same method from core for the data objects so that restrictions are consistent
+        return android.content.pm.verify.domain.DomainVerificationUtils.estimatedByteSizeOf(string);
     }
 
     /**
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationDebug.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationDebug.java
index b3108c5..c9067a3 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationDebug.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationDebug.java
@@ -107,7 +107,7 @@
         reusedMap.clear();
         reusedMap.putAll(pkgState.getStateMap());
 
-        ArraySet<String> declaredDomains = mCollector.collectAutoVerifyDomains(pkg);
+        ArraySet<String> declaredDomains = mCollector.collectValidAutoVerifyDomains(pkg);
         int declaredSize = declaredDomains.size();
         for (int declaredIndex = 0; declaredIndex < declaredSize; declaredIndex++) {
             String domain = declaredDomains.valueAt(declaredIndex);
@@ -132,6 +132,17 @@
             }
 
             writer.increaseIndent();
+            final ArraySet<String> invalidDomains = mCollector.collectInvalidAutoVerifyDomains(pkg);
+            if (!invalidDomains.isEmpty()) {
+                writer.println("Invalid autoVerify domains:");
+                writer.increaseIndent();
+                int size = invalidDomains.size();
+                for (int index = 0; index < size; index++) {
+                    writer.println(invalidDomains.valueAt(index));
+                }
+                writer.decreaseIndent();
+            }
+
             writer.println("Domain verification state:");
             writer.increaseIndent();
             int stateSize = reusedMap.size();
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationEnforcer.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationEnforcer.java
index 275dd053..ed37fa0 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationEnforcer.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationEnforcer.java
@@ -185,6 +185,29 @@
         return !mCallback.filterAppAccess(packageName, callingUid, targetUserId);
     }
 
+    /**
+     * Querying for the owners of a domain. Because this API cannot filter the returned list of
+     * packages, enforces {@link android.Manifest.permission.QUERY_ALL_PACKAGES}, but also enforces
+     * {@link android.Manifest.permission.INTERACT_ACROSS_USERS} because each user has a different
+     * state.
+     */
+    public void assertOwnerQuerent(int callingUid, @UserIdInt int callingUserId,
+            @UserIdInt int targetUserId) {
+        final int callingPid = Binder.getCallingPid();
+        if (callingUserId != targetUserId) {
+            mContext.enforcePermission(android.Manifest.permission.INTERACT_ACROSS_USERS,
+                    callingPid, callingUid, "Caller is not allowed to query other users");
+        }
+
+        mContext.enforcePermission(android.Manifest.permission.QUERY_ALL_PACKAGES,
+                callingPid, callingUid, "Caller " + callingUid + " does not hold "
+                        + android.Manifest.permission.QUERY_ALL_PACKAGES);
+
+        mContext.enforcePermission(
+                android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION,
+                callingPid, callingUid, "Caller is not allowed to query user selections");
+    }
+
     public interface Callback {
         /**
          * @return true if access to the given package should be filtered and the method failed as
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java
index 5d4370a..a68b3da 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java
@@ -310,7 +310,8 @@
      */
     @ApprovalLevel
     int approvalLevelForDomain(@NonNull PackageSetting pkgSetting, @NonNull Intent intent,
-            @UserIdInt int userId);
+            @NonNull List<ResolveInfo> candidates,
+            @PackageManager.ResolveInfoFlags int resolveInfoFlags, @UserIdInt int userId);
 
     /**
      * @return the domain verification set ID for the given package, or null if the ID is
@@ -358,5 +359,8 @@
 
         @Nullable
         AndroidPackage getPackageLocked(@NonNull String pkgName);
+
+        @UserIdInt
+        int[] getAllUserIds();
     }
 }
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerStub.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerStub.java
index 8aa6337..6f28107 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerStub.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerStub.java
@@ -20,13 +20,14 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.verify.domain.DomainOwner;
+import android.content.pm.verify.domain.DomainSet;
+import android.content.pm.verify.domain.DomainVerificationInfo;
 import android.content.pm.verify.domain.DomainVerificationManager.InvalidDomainSetException;
 import android.content.pm.verify.domain.DomainVerificationManagerImpl;
-import android.content.pm.verify.domain.DomainVerificationInfo;
 import android.content.pm.verify.domain.DomainVerificationUserSelection;
 import android.content.pm.verify.domain.IDomainVerificationManager;
 import android.os.ServiceSpecificException;
-import android.util.ArraySet;
 
 import java.util.List;
 import java.util.UUID;
@@ -61,11 +62,11 @@
     }
 
     @Override
-    public void setDomainVerificationStatus(String domainSetId, List<String> domains,
+    public void setDomainVerificationStatus(String domainSetId, @NonNull DomainSet domainSet,
             int state) {
         try {
             mService.setDomainVerificationStatus(UUID.fromString(domainSetId),
-                            new ArraySet<>(domains), state);
+                    domainSet.getDomains(), state);
         } catch (Exception e) {
             throw rethrow(e);
         }
@@ -82,11 +83,11 @@
     }
 
     @Override
-    public void setDomainVerificationUserSelection(String domainSetId, List<String> domains,
+    public void setDomainVerificationUserSelection(String domainSetId, @NonNull DomainSet domainSet,
             boolean enabled, @UserIdInt int userId) {
         try {
             mService.setDomainVerificationUserSelection(UUID.fromString(domainSetId),
-                            new ArraySet<>(domains), enabled, userId);
+                    domainSet.getDomains(), enabled, userId);
         } catch (Exception e) {
             throw rethrow(e);
         }
@@ -103,6 +104,17 @@
         }
     }
 
+    @Nullable
+    @Override
+    public List<DomainOwner> getOwnersForDomain(@NonNull String domain,
+            @UserIdInt int userId) {
+        try {
+            return mService.getOwnersForDomain(domain, userId);
+        } catch (Exception e) {
+            throw rethrow(e);
+        }
+    }
+
     private RuntimeException rethrow(Exception exception) throws RuntimeException {
         if (exception instanceof InvalidDomainSetException) {
             int packedErrorCode = DomainVerificationManagerImpl.ERROR_INVALID_DOMAIN_SET;
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
index e5ed774..dbd7f96 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
@@ -17,6 +17,7 @@
 package com.android.server.pm.verify.domain;
 
 import static java.util.Collections.emptyList;
+import static java.util.Collections.emptySet;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -30,6 +31,7 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.content.pm.parsing.component.ParsedActivity;
+import android.content.pm.verify.domain.DomainOwner;
 import android.content.pm.verify.domain.DomainVerificationInfo;
 import android.content.pm.verify.domain.DomainVerificationManager;
 import android.content.pm.verify.domain.DomainVerificationState;
@@ -254,7 +256,7 @@
             Map<String, Integer> hostToStateMap = new ArrayMap<>(pkgState.getStateMap());
 
             // TODO(b/159952358): Should the domain list be cached?
-            ArraySet<String> domains = mCollector.collectAutoVerifyDomains(pkg);
+            ArraySet<String> domains = mCollector.collectValidAutoVerifyDomains(pkg);
             if (domains.isEmpty()) {
                 return null;
             }
@@ -291,6 +293,8 @@
             throws InvalidDomainSetException, NameNotFoundException {
         mEnforcer.assertApprovedVerifier(callingUid, mProxy);
         synchronized (mLock) {
+            List<String> verifiedDomains = new ArrayList<>();
+
             DomainVerificationPkgState pkgState = getAndValidateAttachedLocked(domainSetId, domains,
                     true /* forAutoVerify */, callingUid, null /* userId */);
             ArrayMap<String, Integer> stateMap = pkgState.getStateMap();
@@ -301,8 +305,17 @@
                     continue;
                 }
 
+                if (DomainVerificationManager.isStateVerified(state)) {
+                    verifiedDomains.add(domain);
+                }
+
                 stateMap.put(domain, state);
             }
+
+            int size = verifiedDomains.size();
+            for (int index = 0; index < size; index++) {
+                removeUserSelectionsForDomain(verifiedDomains.get(index));
+            }
         }
 
         mConnection.scheduleWriteSettings();
@@ -341,7 +354,8 @@
 
                     validDomains.clear();
 
-                    ArraySet<String> autoVerifyDomains = mCollector.collectAutoVerifyDomains(pkg);
+                    ArraySet<String> autoVerifyDomains =
+                            mCollector.collectValidAutoVerifyDomains(pkg);
                     if (domains == null) {
                         validDomains.addAll(autoVerifyDomains);
                     } else {
@@ -366,9 +380,9 @@
 
                 AndroidPackage pkg = pkgSetting.getPkg();
                 if (domains == null) {
-                    domains = mCollector.collectAutoVerifyDomains(pkg);
+                    domains = mCollector.collectValidAutoVerifyDomains(pkg);
                 } else {
-                    domains.retainAll(mCollector.collectAutoVerifyDomains(pkg));
+                    domains.retainAll(mCollector.collectValidAutoVerifyDomains(pkg));
                 }
 
                 setDomainVerificationStatusInternal(pkgState, state, domains);
@@ -387,6 +401,20 @@
         }
     }
 
+    private void removeUserSelectionsForDomain(@NonNull String domain) {
+        synchronized (mLock) {
+            final int size = mAttachedPkgStates.size();
+            for (int index = 0; index < size; index++) {
+                DomainVerificationPkgState pkgState = mAttachedPkgStates.valueAt(index);
+                SparseArray<DomainVerificationUserState> array = pkgState.getUserSelectionStates();
+                int arraySize = array.size();
+                for (int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) {
+                    array.valueAt(arrayIndex).removeHost(domain);
+                }
+            }
+        }
+    }
+
     @Override
     public void setDomainVerificationLinkHandlingAllowed(@NonNull String packageName,
             boolean allowed) throws NameNotFoundException {
@@ -423,12 +451,8 @@
                 for (int pkgStateIndex = 0; pkgStateIndex < pkgStateSize; pkgStateIndex++) {
                     DomainVerificationPkgState pkgState = mAttachedPkgStates.valueAt(pkgStateIndex);
                     if (userId == UserHandle.USER_ALL) {
-                        SparseArray<DomainVerificationUserState> userStates =
-                                pkgState.getUserSelectionStates();
-                        int userStatesSize = userStates.size();
-                        for (int userStateIndex = 0; userStateIndex < userStatesSize;
-                                userStateIndex++) {
-                            userStates.valueAt(userStateIndex)
+                        for (int aUserId : mConnection.getAllUserIds()) {
+                            pkgState.getOrCreateUserSelectionState(aUserId)
                                     .setLinkHandlingAllowed(allowed);
                         }
                     } else {
@@ -436,7 +460,6 @@
                                 .setLinkHandlingAllowed(allowed);
                     }
                 }
-
             }
         } else {
             synchronized (mLock) {
@@ -475,19 +498,59 @@
                         InvalidDomainSetException.REASON_ID_INVALID);
             }
 
+            DomainVerificationPkgState pkgState = getAndValidateAttachedLocked(domainSetId, domains,
+                    false /* forAutoVerify */, callingUid, userId);
+            DomainVerificationUserState userState = pkgState.getOrCreateUserSelectionState(userId);
+
+            // Disable other packages if approving this one. Note that this check is only done for
+            // enabling. This allows an escape hatch in case multiple packages somehow get selected.
+            // They can be disabled without blocking in a circular dependency.
             if (enabled) {
+                // Cache the approved packages from the 1st pass because the search is expensive
+                ArrayMap<String, List<String>> domainToApprovedPackages = new ArrayMap<>();
+
                 for (String domain : domains) {
-                    if (!getApprovedPackages(domain, userId, APPROVAL_LEVEL_LEGACY_ALWAYS + 1,
-                            mConnection::getPackageSettingLocked).first.isEmpty()) {
+                    if (userState.getEnabledHosts().contains(domain)) {
+                        continue;
+                    }
+
+                    Pair<List<String>, Integer> packagesToLevel = getApprovedPackages(domain,
+                            userId, APPROVAL_LEVEL_NONE + 1, mConnection::getPackageSettingLocked);
+                    int highestApproval = packagesToLevel.second;
+                    if (highestApproval > APPROVAL_LEVEL_SELECTION) {
                         throw new InvalidDomainSetException(domainSetId, null,
                                 InvalidDomainSetException.REASON_UNABLE_TO_APPROVE);
                     }
+
+                    domainToApprovedPackages.put(domain, packagesToLevel.first);
+                }
+
+                // The removal for other packages must be done in a 2nd pass after it's determined
+                // that no higher priority owners exist for all of the domains in the set.
+                int mapSize = domainToApprovedPackages.size();
+                for (int mapIndex = 0; mapIndex < mapSize; mapIndex++) {
+                    String domain = domainToApprovedPackages.keyAt(mapIndex);
+                    List<String> approvedPackages = domainToApprovedPackages.valueAt(mapIndex);
+                    int approvedSize = approvedPackages.size();
+                    for (int approvedIndex = 0; approvedIndex < approvedSize; approvedIndex++) {
+                        String approvedPackage = approvedPackages.get(approvedIndex);
+                        DomainVerificationPkgState approvedPkgState =
+                                mAttachedPkgStates.get(approvedPackage);
+                        if (approvedPkgState == null) {
+                            continue;
+                        }
+
+                        DomainVerificationUserState approvedUserState =
+                                approvedPkgState.getUserSelectionState(userId);
+                        if (approvedUserState == null) {
+                            continue;
+                        }
+
+                        approvedUserState.removeHost(domain);
+                    }
                 }
             }
 
-            DomainVerificationPkgState pkgState = getAndValidateAttachedLocked(domainSetId, domains,
-                    false /* forAutoVerify */, callingUid, userId);
-            DomainVerificationUserState userState = pkgState.getOrCreateUserSelectionState(userId);
             if (enabled) {
                 userState.addHosts(domains);
             } else {
@@ -500,28 +563,33 @@
 
     @Override
     public void setDomainVerificationUserSelectionInternal(@UserIdInt int userId,
-            @Nullable String packageName, boolean enabled, @NonNull ArraySet<String> domains)
+            @Nullable String packageName, boolean enabled, @Nullable ArraySet<String> domains)
             throws NameNotFoundException {
         mEnforcer.assertInternal(mConnection.getCallingUid());
 
+
         if (packageName == null) {
             synchronized (mLock) {
                 Set<String> validDomains = new ArraySet<>();
-
                 int size = mAttachedPkgStates.size();
                 for (int index = 0; index < size; index++) {
                     DomainVerificationPkgState pkgState = mAttachedPkgStates.valueAt(index);
                     String pkgName = pkgState.getPackageName();
                     PackageSetting pkgSetting = mConnection.getPackageSettingLocked(pkgName);
-                    if (pkgSetting == null || pkgSetting.getPkg() == null) {
+                    AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg();
+                    if (pkg == null) {
                         continue;
                     }
 
-                    validDomains.clear();
-                    validDomains.addAll(domains);
+                    if (domains == null) {
+                        validDomains = mCollector.collectAllWebDomains(pkg);
+                    } else {
+                        validDomains.clear();
+                        validDomains.addAll(domains);
+                    }
 
                     setDomainVerificationUserSelectionInternal(userId, pkgState,
-                            pkgSetting.getPkg(), enabled, validDomains);
+                            pkg, enabled, validDomains);
                 }
             }
         } else {
@@ -532,12 +600,16 @@
                 }
 
                 PackageSetting pkgSetting = mConnection.getPackageSettingLocked(packageName);
-                if (pkgSetting == null || pkgSetting.getPkg() == null) {
+                AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg();
+                if (pkg == null) {
                     throw DomainVerificationUtils.throwPackageUnavailable(packageName);
                 }
 
+                Set<String> validDomains =
+                        domains == null ? mCollector.collectAllWebDomains(pkg) : domains;
+
                 setDomainVerificationUserSelectionInternal(userId, pkgState, pkgSetting.getPkg(),
-                        enabled, domains);
+                        enabled, validDomains);
             }
         }
 
@@ -549,12 +621,10 @@
             boolean enabled, Set<String> domains) {
         domains.retainAll(mCollector.collectAllWebDomains(pkg));
 
-        SparseArray<DomainVerificationUserState> userStates =
-                pkgState.getUserSelectionStates();
         if (userId == UserHandle.USER_ALL) {
-            int size = userStates.size();
-            for (int index = 0; index < size; index++) {
-                DomainVerificationUserState userState = userStates.valueAt(index);
+            for (int aUserId : mConnection.getAllUserIds()) {
+                DomainVerificationUserState userState =
+                        pkgState.getOrCreateUserSelectionState(aUserId);
                 if (enabled) {
                     userState.addHosts(domains);
                 } else {
@@ -598,32 +668,113 @@
                 throw DomainVerificationUtils.throwPackageUnavailable(packageName);
             }
 
-            ArrayMap<String, Boolean> hostToUserSelectionMap = new ArrayMap<>();
+            ArraySet<String> webDomains = mCollector.collectAllWebDomains(pkg);
+            int webDomainsSize = webDomains.size();
 
-            ArraySet<String> domains = mCollector.collectAllWebDomains(pkg);
-            int domainsSize = domains.size();
-            for (int index = 0; index < domainsSize; index++) {
-                hostToUserSelectionMap.put(domains.valueAt(index), false);
-            }
-
+            Map<String, Integer> domains = new ArrayMap<>(webDomainsSize);
+            ArrayMap<String, Integer> stateMap = pkgState.getStateMap();
             DomainVerificationUserState userState = pkgState.getUserSelectionState(userId);
-            boolean linkHandlingAllowed = true;
-            if (userState != null) {
-                linkHandlingAllowed = userState.isLinkHandlingAllowed();
-                ArraySet<String> enabledHosts = userState.getEnabledHosts();
-                int hostsSize = enabledHosts.size();
-                for (int index = 0; index < hostsSize; index++) {
-                    hostToUserSelectionMap.put(enabledHosts.valueAt(index), true);
+            Set<String> enabledHosts = userState == null ? emptySet() : userState.getEnabledHosts();
+
+            for (int index = 0; index < webDomainsSize; index++) {
+                String host = webDomains.valueAt(index);
+                Integer state = stateMap.get(host);
+
+                int domainState;
+                if (state != null && DomainVerificationManager.isStateVerified(state)) {
+                    domainState = DomainVerificationUserSelection.DOMAIN_STATE_VERIFIED;
+                } else if (enabledHosts.contains(host)) {
+                    domainState = DomainVerificationUserSelection.DOMAIN_STATE_SELECTED;
+                } else {
+                    domainState = DomainVerificationUserSelection.DOMAIN_STATE_NONE;
                 }
+
+                domains.put(host, domainState);
             }
 
+            boolean linkHandlingAllowed = userState == null || userState.isLinkHandlingAllowed();
+
             return new DomainVerificationUserSelection(pkgState.getId(), packageName,
-                    UserHandle.of(userId), linkHandlingAllowed, hostToUserSelectionMap);
+                    UserHandle.of(userId), linkHandlingAllowed, domains);
         }
     }
 
     @NonNull
     @Override
+    public List<DomainOwner> getOwnersForDomain(@NonNull String domain) {
+        return getOwnersForDomain(domain, mConnection.getCallingUserId());
+    }
+
+    public List<DomainOwner> getOwnersForDomain(@NonNull String domain, @UserIdInt int userId) {
+        mEnforcer.assertOwnerQuerent(mConnection.getCallingUid(), mConnection.getCallingUserId(),
+                userId);
+
+        SparseArray<List<String>> levelToPackages = new SparseArray<>();
+
+        // First, collect the raw approval level values
+        synchronized (mLock) {
+            final int size = mAttachedPkgStates.size();
+            for (int index = 0; index < size; index++) {
+                DomainVerificationPkgState pkgState = mAttachedPkgStates.valueAt(index);
+                String packageName = pkgState.getPackageName();
+                PackageSetting pkgSetting = mConnection.getPackageSettingLocked(packageName);
+                if (pkgSetting == null) {
+                    continue;
+                }
+
+                int level = approvalLevelForDomain(pkgSetting, domain, userId, domain);
+                if (level <= APPROVAL_LEVEL_NONE) {
+                    continue;
+                }
+                List<String> list = levelToPackages.get(level);
+                if (list == null) {
+                    list = new ArrayList<>();
+                    levelToPackages.put(level, list);
+                }
+                list.add(packageName);
+            }
+        }
+
+        final int size = levelToPackages.size();
+        if (size == 0) {
+            return emptyList();
+        }
+
+        // Then sort them ascending by first installed time, with package name as the tie breaker
+        for (int index = 0; index < size; index++) {
+            levelToPackages.valueAt(index).sort((first, second) -> {
+                PackageSetting firstPkgSetting = mConnection.getPackageSettingLocked(first);
+                PackageSetting secondPkgSetting = mConnection.getPackageSettingLocked(second);
+
+                long firstInstallTime =
+                        firstPkgSetting == null ? -1L : firstPkgSetting.getFirstInstallTime();
+                long secondInstallTime =
+                        secondPkgSetting == null ? -1L : secondPkgSetting.getFirstInstallTime();
+
+                if (firstInstallTime != secondInstallTime) {
+                    return (int) (firstInstallTime - secondInstallTime);
+                }
+
+                return first.compareToIgnoreCase(second);
+            });
+        }
+
+        List<DomainOwner> owners = new ArrayList<>();
+        for (int index = 0; index < size; index++) {
+            int level = levelToPackages.keyAt(index);
+            boolean overrideable = level <= APPROVAL_LEVEL_SELECTION;
+            List<String> packages = levelToPackages.valueAt(index);
+            int packagesSize = packages.size();
+            for (int packageIndex = 0; packageIndex < packagesSize; packageIndex++) {
+                owners.add(new DomainOwner(packages.get(packageIndex), overrideable));
+            }
+        }
+
+        return owners;
+    }
+
+    @NonNull
+    @Override
     public UUID generateNewId() {
         // TODO(b/159952358): Domain set ID collisions
         return UUID.randomUUID();
@@ -632,7 +783,7 @@
     @Override
     public void migrateState(@NonNull PackageSetting oldPkgSetting,
             @NonNull PackageSetting newPkgSetting) {
-        String pkgName = newPkgSetting.name;
+        String pkgName = newPkgSetting.getName();
         boolean sendBroadcast;
 
         synchronized (mLock) {
@@ -661,7 +812,8 @@
             }
 
             ArrayMap<String, Integer> oldStateMap = oldPkgState.getStateMap();
-            ArraySet<String> newAutoVerifyDomains = mCollector.collectAutoVerifyDomains(newPkg);
+            ArraySet<String> newAutoVerifyDomains =
+                    mCollector.collectValidAutoVerifyDomains(newPkg);
             int newDomainsSize = newAutoVerifyDomains.size();
 
             for (int newDomainsIndex = 0; newDomainsIndex < newDomainsSize; newDomainsIndex++) {
@@ -690,7 +842,7 @@
                     oldPkgState.getUserSelectionStates();
             int oldUserStatesSize = oldUserStates.size();
             if (oldUserStatesSize > 0) {
-                ArraySet<String> newWebDomains = mCollector.collectAutoVerifyDomains(newPkg);
+                ArraySet<String> newWebDomains = mCollector.collectValidAutoVerifyDomains(newPkg);
                 for (int oldUserStatesIndex = 0; oldUserStatesIndex < oldUserStatesSize;
                         oldUserStatesIndex++) {
                     int userId = oldUserStates.keyAt(oldUserStatesIndex);
@@ -728,7 +880,7 @@
         //  gains or loses all domains.
 
         UUID domainSetId = newPkgSetting.getDomainSetId();
-        String pkgName = newPkgSetting.name;
+        String pkgName = newPkgSetting.getName();
 
         boolean sendBroadcast = true;
 
@@ -743,7 +895,7 @@
         }
 
         AndroidPackage pkg = newPkgSetting.getPkg();
-        ArraySet<String> domains = mCollector.collectAutoVerifyDomains(pkg);
+        ArraySet<String> domains = mCollector.collectValidAutoVerifyDomains(pkg);
         boolean hasAutoVerifyDomains = !domains.isEmpty();
         boolean isPendingOrRestored = pkgState != null;
         if (isPendingOrRestored) {
@@ -1007,7 +1159,7 @@
         }
         AndroidPackage pkg = pkgSetting.getPkg();
         ArraySet<String> declaredDomains = forAutoVerify
-                ? mCollector.collectAutoVerifyDomains(pkg)
+                ? mCollector.collectValidAutoVerifyDomains(pkg)
                 : mCollector.collectAllWebDomains(pkg);
 
         if (domains.retainAll(declaredDomains)) {
@@ -1139,7 +1291,7 @@
             }
         }
 
-        applyImmutableState(pkgState, mCollector.collectAutoVerifyDomains(pkg));
+        applyImmutableState(pkgState, mCollector.collectValidAutoVerifyDomains(pkg));
     }
 
     @Override
@@ -1344,9 +1496,11 @@
 
     @Override
     public int approvalLevelForDomain(@NonNull PackageSetting pkgSetting, @NonNull Intent intent,
-            @UserIdInt int userId) {
-        String packageName = pkgSetting.name;
-        if (!DomainVerificationUtils.isDomainVerificationIntent(intent)) {
+            @NonNull List<ResolveInfo> candidates,
+            @PackageManager.ResolveInfoFlags int resolveInfoFlags, @UserIdInt int userId) {
+        String packageName = pkgSetting.getName();
+        if (!DomainVerificationUtils.isDomainVerificationIntent(intent, candidates,
+                resolveInfoFlags)) {
             if (DEBUG_APPROVAL) {
                 debugApproval(packageName, intent, userId, false, "not valid intent");
             }
@@ -1362,7 +1516,7 @@
      */
     private int approvalLevelForDomain(@NonNull PackageSetting pkgSetting, @NonNull String host,
             @UserIdInt int userId, @NonNull Object debugObject) {
-        String packageName = pkgSetting.name;
+        String packageName = pkgSetting.getName();
         final AndroidPackage pkg = pkgSetting.getPkg();
 
         // Should never be null, but if it is, skip this and assume that v2 is enabled
@@ -1407,7 +1561,7 @@
                 // To allow an instant app to immediately open domains after being installed by the
                 // user, auto approve them for any declared autoVerify domains.
                 if (pkgSetting.getInstantApp(userId)
-                        && mCollector.collectAutoVerifyDomains(pkg).contains(host)) {
+                        && mCollector.collectValidAutoVerifyDomains(pkg).contains(host)) {
                     return APPROVAL_LEVEL_INSTANT_APP;
                 }
             }
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationShell.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationShell.java
index 7f9e75a..d083d11 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationShell.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationShell.java
@@ -250,6 +250,10 @@
             return false;
         }
 
+        if (domains.size() == 1 && domains.contains("all")) {
+            domains = null;
+        }
+
         try {
             mCallback.setDomainVerificationUserSelectionInternal(userId,
                     packageName, enabled, domains);
@@ -446,10 +450,10 @@
          * @param packageName the package whose state to change, or all packages if non is
          *                    specified
          * @param enabled     whether the domain is now approved by the user
-         * @param domains     the set of domains to change
+         * @param domains     the set of domains to change, or null to affect all domains
          */
         void setDomainVerificationUserSelectionInternal(@UserIdInt int userId,
-                @Nullable String packageName, boolean enabled, @NonNull ArraySet<String> domains)
+                @Nullable String packageName, boolean enabled, @Nullable ArraySet<String> domains)
                 throws PackageManager.NameNotFoundException;
 
         /**
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationUtils.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationUtils.java
index 474f822..883bbad 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationUtils.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationUtils.java
@@ -22,13 +22,18 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
 import android.os.Binder;
 
+import com.android.internal.util.CollectionUtils;
 import com.android.server.compat.PlatformCompat;
 import com.android.server.pm.PackageManagerService;
 import com.android.server.pm.parsing.pkg.AndroidPackage;
 
-final class DomainVerificationUtils {
+import java.util.List;
+import java.util.Set;
+
+public final class DomainVerificationUtils {
 
     /**
      * Consolidates package exception messages. A generic unavailable message is included since the
@@ -40,10 +45,61 @@
         throw new NameNotFoundException("Package " + packageName + " unavailable");
     }
 
-    static boolean isDomainVerificationIntent(Intent intent) {
-        return intent.isWebIntent()
-                && intent.hasCategory(Intent.CATEGORY_BROWSABLE)
-                && intent.hasCategory(Intent.CATEGORY_DEFAULT);
+    public static boolean isDomainVerificationIntent(Intent intent,
+            @NonNull List<ResolveInfo> candidates,
+            @PackageManager.ResolveInfoFlags int resolveInfoFlags) {
+        if (!intent.isWebIntent()) {
+            return false;
+        }
+
+        Set<String> categories = intent.getCategories();
+        int categoriesSize = CollectionUtils.size(categories);
+        if (categoriesSize > 2) {
+            // Specifying at least one non-app-link category
+            return false;
+        } else if (categoriesSize == 2) {
+            // Check for explicit app link intent with exactly BROWSABLE && DEFAULT
+            return intent.hasCategory(Intent.CATEGORY_DEFAULT)
+                    && intent.hasCategory(Intent.CATEGORY_BROWSABLE);
+        }
+
+            // In cases where at least one browser is resolved and only one non-browser is resolved,
+        // the Intent is coerced into an app links intent, under the assumption the browser can
+        // be skipped if the app is approved at any level for the domain.
+        boolean foundBrowser = false;
+        boolean foundOneApp = false;
+
+        final int candidatesSize = candidates.size();
+        for (int index = 0; index < candidatesSize; index++) {
+            final ResolveInfo info = candidates.get(index);
+            if (info.handleAllWebDataURI) {
+                foundBrowser = true;
+            } else if (foundOneApp) {
+                // Already true, so duplicate app
+                foundOneApp = false;
+                break;
+            } else {
+                foundOneApp = true;
+            }
+        }
+
+        boolean matchDefaultByFlags = (resolveInfoFlags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
+        boolean onlyOneNonBrowser = foundBrowser && foundOneApp;
+
+        // Check if matches (BROWSABLE || none) && DEFAULT
+        if (categoriesSize == 0) {
+            // No categories, run coerce case, matching DEFAULT by flags
+            return onlyOneNonBrowser && matchDefaultByFlags;
+        } else if (intent.hasCategory(Intent.CATEGORY_DEFAULT)) {
+            // Run coerce case, matching by explicit DEFAULT
+            return onlyOneNonBrowser;
+        } else if (intent.hasCategory(Intent.CATEGORY_BROWSABLE)) {
+            // Intent matches BROWSABLE, must match DEFAULT by flags
+            return matchDefaultByFlags;
+        } else {
+            // Otherwise not matching any app link categories
+            return false;
+        }
     }
 
     static boolean isChangeEnabled(PlatformCompat platformCompat, AndroidPackage pkg,
diff --git a/services/core/java/com/android/server/pm/verify/domain/OWNERS b/services/core/java/com/android/server/pm/verify/domain/OWNERS
new file mode 100644
index 0000000..c669112
--- /dev/null
+++ b/services/core/java/com/android/server/pm/verify/domain/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 36137
+
+chiuwinson@google.com
+patb@google.com
+toddke@google.com
\ No newline at end of file
diff --git a/services/core/java/com/android/server/pm/verify/domain/models/DomainVerificationUserState.java b/services/core/java/com/android/server/pm/verify/domain/models/DomainVerificationUserState.java
index 2246864..8fbb33a 100644
--- a/services/core/java/com/android/server/pm/verify/domain/models/DomainVerificationUserState.java
+++ b/services/core/java/com/android/server/pm/verify/domain/models/DomainVerificationUserState.java
@@ -58,6 +58,11 @@
         return this;
     }
 
+    public DomainVerificationUserState removeHost(String host) {
+        mEnabledHosts.remove(host);
+        return this;
+    }
+
     public DomainVerificationUserState removeHosts(@NonNull ArraySet<String> newHosts) {
         mEnabledHosts.removeAll(newHosts);
         return this;
diff --git a/services/core/java/com/android/server/pm/verify/domain/proxy/DomainVerificationProxyV1.java b/services/core/java/com/android/server/pm/verify/domain/proxy/DomainVerificationProxyV1.java
index a804065..18042af 100644
--- a/services/core/java/com/android/server/pm/verify/domain/proxy/DomainVerificationProxyV1.java
+++ b/services/core/java/com/android/server/pm/verify/domain/proxy/DomainVerificationProxyV1.java
@@ -16,6 +16,9 @@
 
 package com.android.server.pm.verify.domain.proxy;
 
+import static android.os.PowerWhitelistManager.REASON_DOMAIN_VERIFICATION_V1;
+import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -238,7 +241,8 @@
         final long allowListTimeout = mConnection.getPowerSaveTempWhitelistAppDuration();
         mConnection.getDeviceIdleInternal().addPowerSaveTempWhitelistApp(Process.myUid(),
                 mVerifierComponent.getPackageName(), allowListTimeout,
-                UserHandle.USER_SYSTEM, true, "domain verification agent");
+                UserHandle.USER_SYSTEM, true, REASON_DOMAIN_VERIFICATION_V1,
+                "domain verification agent");
 
         int size = verifications.size();
         for (int index = 0; index < size; index++) {
@@ -261,7 +265,9 @@
                     .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
 
             final BroadcastOptions options = BroadcastOptions.makeBasic();
-            options.setTemporaryAppWhitelistDuration(allowListTimeout);
+            options.setTemporaryAppAllowlist(allowListTimeout,
+                    TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+                    REASON_DOMAIN_VERIFICATION_V1, "");
             mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM, null, options.toBundle());
         }
     }
@@ -270,7 +276,7 @@
     private String buildHostsString(@NonNull AndroidPackage pkg) {
         // The collector itself handles the v1 vs v2 behavior, which is based on targetSdkVersion,
         // not the version of the verification agent on device.
-        ArraySet<String> domains = mCollector.collectAutoVerifyDomains(pkg);
+        ArraySet<String> domains = mCollector.collectValidAutoVerifyDomains(pkg);
 
         // v1 doesn't handle wildcard domains, so transform them here to the root
         StringBuilder builder = new StringBuilder();
diff --git a/services/core/java/com/android/server/pm/verify/domain/proxy/DomainVerificationProxyV2.java b/services/core/java/com/android/server/pm/verify/domain/proxy/DomainVerificationProxyV2.java
index 1ef06036..2ba17d3 100644
--- a/services/core/java/com/android/server/pm/verify/domain/proxy/DomainVerificationProxyV2.java
+++ b/services/core/java/com/android/server/pm/verify/domain/proxy/DomainVerificationProxyV2.java
@@ -16,6 +16,9 @@
 
 package com.android.server.pm.verify.domain.proxy;
 
+import static android.os.PowerWhitelistManager.REASON_DOMAIN_VERIFICATION_V2;
+import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.BroadcastOptions;
@@ -69,11 +72,14 @@
 
                 final long allowListTimeout = mConnection.getPowerSaveTempWhitelistAppDuration();
                 final BroadcastOptions options = BroadcastOptions.makeBasic();
-                options.setTemporaryAppWhitelistDuration(allowListTimeout);
+                options.setTemporaryAppAllowlist(allowListTimeout,
+                        TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+                        REASON_DOMAIN_VERIFICATION_V2, "");
 
                 mConnection.getDeviceIdleInternal().addPowerSaveTempWhitelistApp(Process.myUid(),
                         mVerifierComponent.getPackageName(), allowListTimeout,
-                        UserHandle.USER_SYSTEM, true, "domain verification agent");
+                        UserHandle.USER_SYSTEM, true, REASON_DOMAIN_VERIFICATION_V2,
+                        "domain verification agent");
 
                 Intent intent = new Intent(Intent.ACTION_DOMAINS_NEED_VERIFICATION)
                         .setComponent(mVerifierComponent)
diff --git a/services/core/java/com/android/server/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java
new file mode 100644
index 0000000..c965390
--- /dev/null
+++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.policy;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.AppOpsManager;
+import android.app.AppOpsManagerInternal;
+import android.location.LocationManagerInternal;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.function.HeptFunction;
+import com.android.internal.util.function.QuadFunction;
+import com.android.server.LocalServices;
+
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * This class defines policy for special behaviors around app ops.
+ */
+public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegate {
+    @NonNull
+    private final Object mLock = new Object();
+
+    /**
+     * The locking policy around the location tags is a bit special. Since we want to
+     * avoid grabbing the lock on every op note we are taking the approach where the
+     * read and write are being done via a thread-safe data structure such that the
+     * lookup/insert are single thread-safe calls. When we update the cached state we
+     * use a lock to ensure the update's lookup and store calls are done atomically,
+     * so multiple writers would not interleave. The tradeoff is we make is that the
+     * concurrent data structure would use boxing/unboxing of integers but this is
+     * preferred to locking.
+     */
+    @GuardedBy("mLock - writes only - see above")
+    @NonNull
+    private final ConcurrentHashMap<Integer, ArrayMap<String, ArraySet<String>>> mLocationTags =
+            new ConcurrentHashMap();
+
+    public AppOpsPolicy() {
+        final LocationManagerInternal locationManagerInternal = LocalServices.getService(
+                LocationManagerInternal.class);
+        locationManagerInternal.setOnProviderLocationTagsChangeListener((providerTagInfo) -> {
+            synchronized (mLock) {
+                final int uid = providerTagInfo.getUid();
+                // We make a copy of the per UID state to limit our mutation to one
+                // operation in the underlying concurrent data structure.
+                ArrayMap<String, ArraySet<String>> uidTags = mLocationTags.get(uid);
+                if (uidTags != null) {
+                    uidTags = new ArrayMap<>(uidTags);
+                }
+
+                final String packageName = providerTagInfo.getPackageName();
+                ArraySet<String> packageTags = (uidTags != null) ? uidTags.get(packageName) : null;
+                if (packageTags != null) {
+                    packageTags = new ArraySet<>(packageTags);
+                }
+
+                final Set<String> providerTags = providerTagInfo.getTags();
+                if (providerTags != null && !providerTags.isEmpty()) {
+                    if (packageTags != null) {
+                        packageTags.clear();
+                        packageTags.addAll(providerTags);
+                    } else {
+                        packageTags = new ArraySet<>(providerTags);
+                    }
+                    if (uidTags == null) {
+                        uidTags = new ArrayMap<>();
+                    }
+                    uidTags.put(packageName, packageTags);
+                    mLocationTags.put(uid, uidTags);
+                } else if (uidTags != null) {
+                    uidTags.remove(packageName);
+                    if (!uidTags.isEmpty()) {
+                        mLocationTags.put(uid, uidTags);
+                    } else {
+                        mLocationTags.remove(uid);
+                    }
+                }
+            }
+        });
+    }
+
+    @Override
+    public int checkOperation(int code, int uid, String packageName, boolean raw,
+            QuadFunction<Integer, Integer, String, Boolean, Integer> superImpl) {
+        return superImpl.apply(code, uid, packageName, raw);
+    }
+
+    @Override
+    public int checkAudioOperation(int code, int usage, int uid, String packageName,
+            QuadFunction<Integer, Integer, Integer, String, Integer> superImpl) {
+        return superImpl.apply(code, usage, uid, packageName);
+    }
+
+    @Override
+    public int noteOperation(int code, int uid, @Nullable String packageName,
+            @Nullable String featureId, boolean shouldCollectAsyncNotedOp, @Nullable String message,
+            boolean shouldCollectMessage, @NonNull HeptFunction<Integer, Integer, String, String,
+                    Boolean, String, Boolean, Integer> superImpl) {
+        if (isHandledOp(code)) {
+            // Only a single lookup from the underlying concurrent data structure
+            final ArrayMap<String, ArraySet<String>> uidTags = mLocationTags.get(uid);
+            if (uidTags != null) {
+                final ArraySet<String> packageTags = uidTags.get(packageName);
+                if (packageTags != null && packageTags.contains(featureId)) {
+                    return superImpl.apply(resolveLocationOp(code), uid, packageName, featureId,
+                            shouldCollectAsyncNotedOp, message, shouldCollectMessage);
+                }
+            }
+        }
+        return superImpl.apply(code, uid, packageName, featureId, shouldCollectAsyncNotedOp,
+                message, shouldCollectMessage);
+    }
+
+    private static boolean isHandledOp(int code) {
+        switch (code) {
+            case AppOpsManager.OP_FINE_LOCATION:
+            case AppOpsManager.OP_COARSE_LOCATION:
+                return true;
+        }
+        return false;
+    }
+
+    private static int resolveLocationOp(int code) {
+        switch (code) {
+            case AppOpsManager.OP_FINE_LOCATION:
+                return AppOpsManager.OP_FINE_LOCATION_SOURCE;
+            case AppOpsManager.OP_COARSE_LOCATION:
+                return AppOpsManager.OP_COARSE_LOCATION_SOURCE;
+        }
+        return code;
+    }
+}
diff --git a/services/core/java/com/android/server/policy/DisplayFoldController.java b/services/core/java/com/android/server/policy/DisplayFoldController.java
index 82fc22c..0e12584 100644
--- a/services/core/java/com/android/server/policy/DisplayFoldController.java
+++ b/services/core/java/com/android/server/policy/DisplayFoldController.java
@@ -74,7 +74,7 @@
         mHandler = handler;
 
         DeviceStateManager deviceStateManager = context.getSystemService(DeviceStateManager.class);
-        deviceStateManager.addDeviceStateListener(new HandlerExecutor(handler),
+        deviceStateManager.registerCallback(new HandlerExecutor(handler),
                 new DeviceStateListener(context));
     }
 
@@ -208,7 +208,7 @@
      * matches the value in the {@link com.android.internal.R.integer.config_foldedDeviceState}
      * resource.
      */
-    private class DeviceStateListener implements DeviceStateManager.DeviceStateListener {
+    private class DeviceStateListener implements DeviceStateManager.DeviceStateCallback {
         private final int[] mFoldedDeviceStates;
 
         DeviceStateListener(Context context) {
@@ -217,7 +217,7 @@
         }
 
         @Override
-        public void onDeviceStateChanged(int deviceState) {
+        public void onStateChanged(int deviceState) {
             boolean folded = false;
             for (int i = 0; i < mFoldedDeviceStates.length; i++) {
                 if (deviceState == mFoldedDeviceStates[i]) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 6a441f1..c50efc7 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -56,13 +56,11 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
 import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
 import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
@@ -522,8 +520,6 @@
     boolean mConsumeSearchKeyUp;
     boolean mPendingMetaAction;
     boolean mPendingCapsLockToggle;
-    int mMetaState;
-    int mInitialMetaState;
 
     // support for activating the lock screen while the screen is on
     private HashSet<Integer> mAllowLockscreenWhenOnDisplays = new HashSet<>();
@@ -2292,25 +2288,6 @@
         return attrs.type == TYPE_NOTIFICATION_SHADE;
     }
 
-    @Override
-    public boolean canBeHiddenByKeyguardLw(WindowState win) {
-
-        // Keyguard visibility of window from activities are determined over activity visibility.
-        if (win.getAppToken() != null) {
-            return false;
-        }
-        switch (win.getAttrs().type) {
-            case TYPE_NOTIFICATION_SHADE:
-            case TYPE_STATUS_BAR:
-            case TYPE_NAVIGATION_BAR:
-            case TYPE_WALLPAPER:
-                return false;
-            default:
-                // Hide only windows below the keyguard host window.
-                return getWindowLayerLw(win) < getWindowLayerFromTypeLw(TYPE_NOTIFICATION_SHADE);
-        }
-    }
-
     /** {@inheritDoc} */
     @Override
     public StartingSurface addSplashScreen(IBinder appToken, String packageName, int theme,
@@ -2568,6 +2545,7 @@
         final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
         final boolean canceled = event.isCanceled();
         final int displayId = event.getDisplayId();
+        final long key_consumed = -1;
 
         if (DEBUG_INPUT) {
             Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
@@ -2575,7 +2553,7 @@
         }
 
         if (mKeyCombinationManager.isKeyConsumed(event)) {
-            return -1;
+            return key_consumed;
         }
 
         if ((flags & KeyEvent.FLAG_FALLBACK) == 0) {
@@ -2596,205 +2574,250 @@
             mPendingCapsLockToggle = false;
         }
 
-        // First we always handle the home key here, so applications
-        // can never break it, although if keyguard is on, we do let
-        // it handle it, because that gives us the correct 5 second
-        // timeout.
-        if (keyCode == KEYCODE_HOME) {
-            DisplayHomeButtonHandler handler = mDisplayHomeButtonHandlers.get(displayId);
-            if (handler == null) {
-                handler = new DisplayHomeButtonHandler(displayId);
-                mDisplayHomeButtonHandlers.put(displayId, handler);
-            }
-            return handler.handleHomeButton(focusedToken, event);
-        } else if (keyCode == KeyEvent.KEYCODE_MENU) {
-            // Hijack modified menu keys for debugging features
-            final int chordBug = KeyEvent.META_SHIFT_ON;
+        switch(keyCode) {
+            case KeyEvent.KEYCODE_HOME:
+                // First we always handle the home key here, so applications
+                // can never break it, although if keyguard is on, we do let
+                // it handle it, because that gives us the correct 5 second
+                // timeout.
+                DisplayHomeButtonHandler handler = mDisplayHomeButtonHandlers.get(displayId);
+                if (handler == null) {
+                    handler = new DisplayHomeButtonHandler(displayId);
+                    mDisplayHomeButtonHandlers.put(displayId, handler);
+                }
+                return handler.handleHomeButton(focusedToken, event);
+            case KeyEvent.KEYCODE_MENU:
+                // Hijack modified menu keys for debugging features
+                final int chordBug = KeyEvent.META_SHIFT_ON;
 
-            if (down && repeatCount == 0) {
-                if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
-                    Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
-                    mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
-                            null, null, null, 0, null, null);
-                    return -1;
-                }
-            }
-        } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
-            if (down) {
-                if (repeatCount == 0) {
-                    mSearchKeyShortcutPending = true;
-                    mConsumeSearchKeyUp = false;
-                }
-            } else {
-                mSearchKeyShortcutPending = false;
-                if (mConsumeSearchKeyUp) {
-                    mConsumeSearchKeyUp = false;
-                    return -1;
-                }
-            }
-            return 0;
-        } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
-            if (!keyguardOn) {
                 if (down && repeatCount == 0) {
-                    preloadRecentApps();
-                } else if (!down) {
-                    toggleRecentApps();
-                }
-            }
-            return -1;
-        } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) {
-            if (down) {
-                IStatusBarService service = getStatusBarService();
-                if (service != null) {
-                    try {
-                        service.expandNotificationsPanel();
-                    } catch (RemoteException e) {
-                        // do nothing.
+                    if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
+                        Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
+                        mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
+                                null, null, null, 0, null, null);
+                        return key_consumed;
                     }
                 }
-            }
-        } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed()
-                && event.isCtrlPressed()) {
-            if (down && repeatCount == 0) {
-                int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION
-                        : TAKE_SCREENSHOT_FULLSCREEN;
-                mScreenshotRunnable.setScreenshotType(type);
-                mScreenshotRunnable.setScreenshotSource(SCREENSHOT_KEY_OTHER);
-                mHandler.post(mScreenshotRunnable);
-                return -1;
-            }
-        } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) {
-            if (down && repeatCount == 0 && !isKeyguardLocked()) {
-                toggleKeyboardShortcutsMenu(event.getDeviceId());
-            }
-        } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
-            Slog.wtf(TAG, "KEYCODE_ASSIST should be handled in interceptKeyBeforeQueueing");
-            return -1;
-        } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
-            Slog.wtf(TAG, "KEYCODE_VOICE_ASSIST should be handled in interceptKeyBeforeQueueing");
-            return -1;
-        } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
-            if (down && repeatCount == 0) {
-                mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
-                mScreenshotRunnable.setScreenshotSource(SCREENSHOT_KEY_OTHER);
-                mHandler.post(mScreenshotRunnable);
-            }
-            return -1;
-        } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP
-                || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) {
-            if (down) {
-                int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
+                break;
+            case  KeyEvent.KEYCODE_SEARCH:
+                if (down) {
+                    if (repeatCount == 0) {
+                        mSearchKeyShortcutPending = true;
+                        mConsumeSearchKeyUp = false;
+                    }
+                } else {
+                    mSearchKeyShortcutPending = false;
+                    if (mConsumeSearchKeyUp) {
+                        mConsumeSearchKeyUp = false;
+                        return key_consumed;
+                    }
+                }
+                return 0;
+            case KeyEvent.KEYCODE_APP_SWITCH:
+                if (!keyguardOn) {
+                    if (down && repeatCount == 0) {
+                        preloadRecentApps();
+                    } else if (!down) {
+                        toggleRecentApps();
+                    }
+                }
+                return key_consumed;
+            case KeyEvent.KEYCODE_N:
+                if (down && event.isMetaPressed()) {
+                    IStatusBarService service = getStatusBarService();
+                    if (service != null) {
+                        try {
+                            service.expandNotificationsPanel();
+                        } catch (RemoteException e) {
+                            // do nothing.
+                        }
+                        return key_consumed;
+                    }
+                }
+                break;
+            case KeyEvent.KEYCODE_S:
+                if (down && event.isMetaPressed() && event.isCtrlPressed() && repeatCount == 0) {
+                    int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION
+                            : TAKE_SCREENSHOT_FULLSCREEN;
+                    mScreenshotRunnable.setScreenshotType(type);
+                    mScreenshotRunnable.setScreenshotSource(SCREENSHOT_KEY_OTHER);
+                    mHandler.post(mScreenshotRunnable);
+                    return key_consumed;
+                }
+                break;
+            case KeyEvent.KEYCODE_SLASH:
+                if (down && repeatCount == 0 && event.isMetaPressed() && !keyguardOn) {
+                    toggleKeyboardShortcutsMenu(event.getDeviceId());
+                    return key_consumed;
+                }
+                break;
+            case KeyEvent.KEYCODE_ASSIST:
+                Slog.wtf(TAG, "KEYCODE_ASSIST should be handled in interceptKeyBeforeQueueing");
+                return key_consumed;
+            case KeyEvent.KEYCODE_VOICE_ASSIST:
+                Slog.wtf(TAG, "KEYCODE_VOICE_ASSIST should be handled in"
+                        + " interceptKeyBeforeQueueing");
+                return key_consumed;
+            case KeyEvent.KEYCODE_SYSRQ:
+                if (down && repeatCount == 0) {
+                    mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
+                    mScreenshotRunnable.setScreenshotSource(SCREENSHOT_KEY_OTHER);
+                    mHandler.post(mScreenshotRunnable);
+                }
+                return key_consumed;
+            case KeyEvent.KEYCODE_BRIGHTNESS_UP:
+            case KeyEvent.KEYCODE_BRIGHTNESS_DOWN:
+                if (down) {
+                    int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
 
-                // Disable autobrightness if it's on
-                int auto = Settings.System.getIntForUser(
-                        mContext.getContentResolver(),
-                        Settings.System.SCREEN_BRIGHTNESS_MODE,
-                        Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
-                        UserHandle.USER_CURRENT_OR_SELF);
-                if (auto != 0) {
-                    Settings.System.putIntForUser(mContext.getContentResolver(),
+                    // Disable autobrightness if it's on
+                    int auto = Settings.System.getIntForUser(
+                            mContext.getContentResolver(),
                             Settings.System.SCREEN_BRIGHTNESS_MODE,
                             Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
                             UserHandle.USER_CURRENT_OR_SELF);
+                    if (auto != 0) {
+                        Settings.System.putIntForUser(mContext.getContentResolver(),
+                                Settings.System.SCREEN_BRIGHTNESS_MODE,
+                                Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
+                                UserHandle.USER_CURRENT_OR_SELF);
+                    }
+                    float minFloat = mPowerManager.getBrightnessConstraint(
+                            PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);
+                    float maxFloat = mPowerManager.getBrightnessConstraint(
+                            PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);
+                    float stepFloat = (maxFloat - minFloat) / BRIGHTNESS_STEPS * direction;
+                    float brightnessFloat = Settings.System.getFloatForUser(
+                            mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_FLOAT,
+                            mContext.getDisplay().getBrightnessDefault(),
+                            UserHandle.USER_CURRENT_OR_SELF);
+                    brightnessFloat += stepFloat;
+                    // Make sure we don't go beyond the limits.
+                    brightnessFloat = Math.min(maxFloat, brightnessFloat);
+                    brightnessFloat = Math.max(minFloat, brightnessFloat);
+
+                    Settings.System.putFloatForUser(mContext.getContentResolver(),
+                            Settings.System.SCREEN_BRIGHTNESS_FLOAT, brightnessFloat,
+                            UserHandle.USER_CURRENT_OR_SELF);
+                    startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
+                            UserHandle.CURRENT_OR_SELF);
                 }
-                float minFloat = mPowerManager.getBrightnessConstraint(
-                        PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);
-                float maxFloat = mPowerManager.getBrightnessConstraint(
-                        PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);
-                float stepFloat = (maxFloat - minFloat) / BRIGHTNESS_STEPS * direction;
-                float brightnessFloat = Settings.System.getFloatForUser(
-                        mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_FLOAT,
-                        mContext.getDisplay().getBrightnessDefault(),
-                        UserHandle.USER_CURRENT_OR_SELF);
-                brightnessFloat += stepFloat;
-                // Make sure we don't go beyond the limits.
-                brightnessFloat = Math.min(maxFloat, brightnessFloat);
-                brightnessFloat = Math.max(minFloat, brightnessFloat);
-
-                Settings.System.putFloatForUser(mContext.getContentResolver(),
-                        Settings.System.SCREEN_BRIGHTNESS_FLOAT, brightnessFloat,
-                        UserHandle.USER_CURRENT_OR_SELF);
-                startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
-                        UserHandle.CURRENT_OR_SELF);
-            }
-            return -1;
-        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
-                || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
-                || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
-            if (mUseTvRouting || mHandleVolumeKeysInWM) {
-                // On TVs or when the configuration is enabled, volume keys never
-                // go to the foreground app.
-                dispatchDirectAudioEvent(event);
-                return -1;
-            }
-
-            // If the device is in VR mode and keys are "internal" (e.g. on the side of the
-            // device), then drop the volume keys and don't forward it to the application/dispatch
-            // the audio event.
-            if (mDefaultDisplayPolicy.isPersistentVrModeEnabled()) {
-                final InputDevice d = event.getDevice();
-                if (d != null && !d.isExternal()) {
-                    return -1;
+                return key_consumed;
+            case KeyEvent.KEYCODE_VOLUME_UP:
+            case KeyEvent.KEYCODE_VOLUME_DOWN:
+            case KeyEvent.KEYCODE_VOLUME_MUTE:
+                if (mUseTvRouting || mHandleVolumeKeysInWM) {
+                    // On TVs or when the configuration is enabled, volume keys never
+                    // go to the foreground app.
+                    dispatchDirectAudioEvent(event);
+                    return key_consumed;
                 }
-            }
-        } else if (keyCode == KeyEvent.KEYCODE_TAB && event.isMetaPressed()) {
-            // Pass through keyboard navigation keys.
-            return 0;
-        } else if (keyCode == KeyEvent.KEYCODE_ALL_APPS) {
-            if (!down) {
-                mHandler.removeMessages(MSG_HANDLE_ALL_APPS);
-                Message msg = mHandler.obtainMessage(MSG_HANDLE_ALL_APPS);
-                msg.setAsynchronous(true);
-                msg.sendToTarget();
-            }
-            return -1;
-        } else if (keyCode == KeyEvent.KEYCODE_NOTIFICATION) {
-            if (!down) {
-                toggleNotificationPanel();
-            }
-            return -1;
-        }
 
-        // Toggle Caps Lock on META-ALT.
-        boolean actionTriggered = false;
-        if (KeyEvent.isModifierKey(keyCode)) {
-            if (!mPendingCapsLockToggle) {
-                // Start tracking meta state for combo.
-                mInitialMetaState = mMetaState;
-                mPendingCapsLockToggle = true;
-            } else if (event.getAction() == KeyEvent.ACTION_UP) {
-                int altOnMask = mMetaState & KeyEvent.META_ALT_MASK;
-                int metaOnMask = mMetaState & KeyEvent.META_META_MASK;
-
-                // Check for Caps Lock toggle
-                if ((metaOnMask != 0) && (altOnMask != 0)) {
-                    // Check if nothing else is pressed
-                    if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) {
-                        // Handle Caps Lock Toggle
-                        mInputManagerInternal.toggleCapsLock(event.getDeviceId());
-                        actionTriggered = true;
+                // If the device is in VR mode and keys are "internal" (e.g. on the side of the
+                // device), then drop the volume keys and don't forward it to the
+                // application/dispatch the audio event.
+                if (mDefaultDisplayPolicy.isPersistentVrModeEnabled()) {
+                    final InputDevice d = event.getDevice();
+                    if (d != null && !d.isExternal()) {
+                        return key_consumed;
                     }
                 }
+                break;
+            case KeyEvent.KEYCODE_TAB:
+                if (event.isMetaPressed()) {
+                    // Pass through keyboard navigation keys.
+                    return 0;
+                }
+                // Display task switcher for ALT-TAB.
+                if (down && repeatCount == 0) {
+                    if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) {
+                        final int shiftlessModifiers =
+                                event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
+                        if (KeyEvent.metaStateHasModifiers(
+                                shiftlessModifiers, KeyEvent.META_ALT_ON)) {
+                            mRecentAppsHeldModifiers = shiftlessModifiers;
+                            showRecentApps(true);
+                            return key_consumed;
+                        }
+                    }
+                }
+                break;
+            case KeyEvent.KEYCODE_ALL_APPS:
+                if (!down) {
+                    mHandler.removeMessages(MSG_HANDLE_ALL_APPS);
+                    Message msg = mHandler.obtainMessage(MSG_HANDLE_ALL_APPS);
+                    msg.setAsynchronous(true);
+                    msg.sendToTarget();
+                }
+                return key_consumed;
+            case KeyEvent.KEYCODE_NOTIFICATION:
+                if (!down) {
+                    toggleNotificationPanel();
+                }
+                return key_consumed;
 
-                // Always stop tracking when key goes up.
-                mPendingCapsLockToggle = false;
-            }
-        }
-        // Store current meta state to be able to evaluate it later.
-        mMetaState = metaState;
+            case KeyEvent.KEYCODE_SPACE:
+                // Handle keyboard layout switching.
+                if ((metaState & (KeyEvent.META_CTRL_MASK | KeyEvent.META_META_MASK)) == 0) {
+                    return 0;
+                }
+                // Share the same behavior with KEYCODE_LANGUAGE_SWITCH.
+            case KeyEvent.KEYCODE_LANGUAGE_SWITCH:
+                if (down && repeatCount == 0) {
+                    int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
+                    mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
+                    return key_consumed;
+                }
+                break;
+            case KeyEvent.KEYCODE_META_LEFT:
+            case KeyEvent.KEYCODE_META_RIGHT:
+                if (down) {
+                    if (event.isAltPressed()) {
+                        mPendingCapsLockToggle = true;
+                        mPendingMetaAction = false;
+                    } else {
+                        mPendingCapsLockToggle = false;
+                        mPendingMetaAction = true;
+                    }
+                } else {
+                    // Toggle Caps Lock on META-ALT.
+                    if (mPendingCapsLockToggle) {
+                        mInputManagerInternal.toggleCapsLock(event.getDeviceId());
+                        mPendingCapsLockToggle = false;
+                    } else if (mPendingMetaAction) {
+                        launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD,
+                                event.getDeviceId(),
+                                event.getEventTime());
+                        mPendingMetaAction = false;
+                    }
+                }
+                return key_consumed;
+            case KeyEvent.KEYCODE_ALT_LEFT:
+            case KeyEvent.KEYCODE_ALT_RIGHT:
+                if (down) {
+                    if (event.isMetaPressed()) {
+                        mPendingCapsLockToggle = true;
+                        mPendingMetaAction = false;
+                    } else {
+                        mPendingCapsLockToggle = false;
+                    }
+                } else {
+                    // hide recent if triggered by ALT-TAB.
+                    if (mRecentAppsHeldModifiers != 0
+                            && (metaState & mRecentAppsHeldModifiers) == 0) {
+                        mRecentAppsHeldModifiers = 0;
+                        hideRecentApps(true, false);
+                        return key_consumed;
+                    }
 
-        if (actionTriggered) {
-            return -1;
-        }
-
-        if (KeyEvent.isMetaKey(keyCode)) {
-            if (down) {
-                mPendingMetaAction = true;
-            } else if (mPendingMetaAction) {
-                launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId(),
-                        event.getEventTime());
-            }
-            return -1;
+                    // Toggle Caps Lock on META-ALT.
+                    if (mPendingCapsLockToggle) {
+                        mInputManagerInternal.toggleCapsLock(event.getDeviceId());
+                        mPendingCapsLockToggle = false;
+                        return key_consumed;
+                    }
+                }
+                break;
         }
 
         // Shortcuts are invoked through Search+key, so intercept those here
@@ -2824,7 +2847,7 @@
                                 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode));
                     }
                 }
-                return -1;
+                return key_consumed;
             }
         }
 
@@ -2846,7 +2869,7 @@
                                 + "the activity to which it is registered was not found: "
                                 + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
                     }
-                    return -1;
+                    return key_consumed;
                 }
             }
         }
@@ -2865,39 +2888,13 @@
                             + "the activity to which it is registered was not found: "
                             + "keyCode=" + keyCode + ", category=" + category, ex);
                 }
-                return -1;
+                return key_consumed;
             }
         }
 
-        // Display task switcher for ALT-TAB.
-        if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
-            if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) {
-                final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
-                if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
-                    mRecentAppsHeldModifiers = shiftlessModifiers;
-                    showRecentApps(true);
-                    return -1;
-                }
-            }
-        } else if (!down && mRecentAppsHeldModifiers != 0
-                && (metaState & mRecentAppsHeldModifiers) == 0) {
-            mRecentAppsHeldModifiers = 0;
-            hideRecentApps(true, false);
-        }
-
-        // Handle keyboard language switching.
-        final boolean isCtrlOrMetaSpace = keyCode == KeyEvent.KEYCODE_SPACE
-                && (metaState & (KeyEvent.META_CTRL_MASK | KeyEvent.META_META_MASK)) != 0;
-        if (down && repeatCount == 0
-                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH || isCtrlOrMetaSpace)) {
-            int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
-            mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
-            return -1;
-        }
-
         if (isValidGlobalKey(keyCode)
                 && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
-            return -1;
+            return key_consumed;
         }
 
         if (down) {
@@ -2927,13 +2924,13 @@
                 } catch (RemoteException e) {
                     mShortcutKeyServices.delete(shortcutCode);
                 }
-                return -1;
+                return key_consumed;
             }
         }
 
         // Reserve all the META modifier combos for system behavior
         if ((metaState & KeyEvent.META_META_ON) != 0) {
-            return -1;
+            return key_consumed;
         }
 
         // Let the application handle the key.
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index db33e75..b5a9aca 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -672,7 +672,22 @@
     /**
      * @return whether {@param win} can be hidden by Keyguard
      */
-    public boolean canBeHiddenByKeyguardLw(WindowState win);
+    default boolean canBeHiddenByKeyguardLw(WindowState win) {
+        // Keyguard visibility of window from activities are determined over activity visibility.
+        if (win.getAppToken() != null) {
+            return false;
+        }
+        switch (win.getAttrs().type) {
+            case TYPE_NOTIFICATION_SHADE:
+            case TYPE_STATUS_BAR:
+            case TYPE_NAVIGATION_BAR:
+            case TYPE_WALLPAPER:
+                return false;
+            default:
+                // Hide only windows below the keyguard host window.
+                return getWindowLayerLw(win) < getWindowLayerFromTypeLw(TYPE_NOTIFICATION_SHADE);
+        }
+    }
 
     /**
      * Called when the system would like to show a UI to indicate that an
diff --git a/services/core/java/com/android/server/power/DisplayGroupPowerStateMapper.java b/services/core/java/com/android/server/power/DisplayGroupPowerStateMapper.java
new file mode 100644
index 0000000..2fcd178
--- /dev/null
+++ b/services/core/java/com/android/server/power/DisplayGroupPowerStateMapper.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power;
+
+import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
+import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
+import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING;
+import static android.os.PowerManagerInternal.WAKEFULNESS_DREAMING;
+
+import static com.android.server.power.DisplayGroupPowerStateMapper.DisplayGroupPowerChangeListener.DISPLAY_GROUP_ADDED;
+import static com.android.server.power.DisplayGroupPowerStateMapper.DisplayGroupPowerChangeListener.DISPLAY_GROUP_CHANGED;
+import static com.android.server.power.DisplayGroupPowerStateMapper.DisplayGroupPowerChangeListener.DISPLAY_GROUP_REMOVED;
+
+import android.hardware.display.DisplayManagerInternal;
+import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
+import android.os.PowerManagerInternal;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.view.Display;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.ArrayUtils;
+import com.android.server.display.DisplayGroup;
+
+/**
+ * Responsible for creating {@link DisplayPowerRequest}s and associating them with
+ * {@link com.android.server.display.DisplayGroup}s.
+ *
+ * Each {@link com.android.server.display.DisplayGroup} has a single {@link DisplayPowerRequest}
+ * which is used to request power state changes to every display in the group.
+ */
+public class DisplayGroupPowerStateMapper {
+
+    private static final String TAG = "DisplayPowerRequestMapper";
+
+    /** Lock obtained from {@link PowerManagerService}. */
+    private final Object mLock;
+
+    /** Listener to inform of changes to display groups. */
+    private final DisplayGroupPowerChangeListener mListener;
+
+    /** A mapping from DisplayGroup Id to DisplayGroup information. */
+    @GuardedBy("mLock")
+    private final SparseArray<DisplayGroupInfo> mDisplayGroupInfos = new SparseArray<>();
+
+    /** A cached array of DisplayGroup Ids. */
+    @GuardedBy("mLock")
+    private int[] mDisplayGroupIds;
+
+    private final DisplayManagerInternal.DisplayGroupListener mDisplayGroupListener =
+            new DisplayManagerInternal.DisplayGroupListener() {
+                @Override
+                public void onDisplayGroupAdded(int groupId) {
+                    synchronized (mLock) {
+                        if (mDisplayGroupInfos.contains(groupId)) {
+                            Slog.e(TAG, "Tried to add already existing group:" + groupId);
+                            return;
+                        }
+                        // For now, only the default group supports sandman (dream/AOD).
+                        final boolean supportsSandman = groupId == Display.DEFAULT_DISPLAY_GROUP;
+                        final DisplayGroupInfo displayGroupInfo = new DisplayGroupInfo(
+                                new DisplayPowerRequest(),
+                                getGlobalWakefulnessLocked(),
+                                /* ready= */ false,
+                                supportsSandman);
+                        mDisplayGroupInfos.append(groupId, displayGroupInfo);
+                        mDisplayGroupIds = ArrayUtils.appendInt(mDisplayGroupIds, groupId);
+                        mListener.onDisplayGroupEventLocked(DISPLAY_GROUP_ADDED, groupId);
+                    }
+                }
+
+                @Override
+                public void onDisplayGroupRemoved(int groupId) {
+                    synchronized (mLock) {
+                        if (!mDisplayGroupInfos.contains(groupId)) {
+                            Slog.e(TAG, "Tried to remove non-existent group:" + groupId);
+                            return;
+                        }
+                        mDisplayGroupInfos.delete(groupId);
+                        mDisplayGroupIds = ArrayUtils.removeInt(mDisplayGroupIds, groupId);
+                        mListener.onDisplayGroupEventLocked(DISPLAY_GROUP_REMOVED, groupId);
+                    }
+                }
+
+                @Override
+                public void onDisplayGroupChanged(int groupId) {
+                    synchronized (mLock) {
+                        mListener.onDisplayGroupEventLocked(DISPLAY_GROUP_CHANGED, groupId);
+                    }
+                }
+            };
+
+    DisplayGroupPowerStateMapper(Object lock, DisplayManagerInternal displayManagerInternal,
+            DisplayGroupPowerChangeListener listener) {
+        mLock = lock;
+        mListener = listener;
+        displayManagerInternal.registerDisplayGroupListener(mDisplayGroupListener);
+
+        final DisplayGroupInfo displayGroupInfo = new DisplayGroupInfo(
+                new DisplayPowerRequest(), WAKEFULNESS_AWAKE, /* ready= */
+                false, /* supportsSandman= */ true);
+        mDisplayGroupInfos.append(Display.DEFAULT_DISPLAY_GROUP, displayGroupInfo);
+        mDisplayGroupIds = new int[]{Display.DEFAULT_DISPLAY_GROUP};
+    }
+
+    DisplayPowerRequest getPowerRequestLocked(int groupId) {
+        return mDisplayGroupInfos.get(groupId).displayPowerRequest;
+    }
+
+    int[] getDisplayGroupIdsLocked() {
+        return mDisplayGroupIds;
+    }
+
+    int getWakefulnessLocked(int groupId) {
+        return mDisplayGroupInfos.get(groupId).wakefulness;
+    }
+
+    void setLastPowerOnTimeLocked(int groupId, long eventTime) {
+        mDisplayGroupInfos.get(groupId).lastPowerOnTime = eventTime;
+    }
+
+    long getLastPowerOnTimeLocked(int groupId) {
+        return mDisplayGroupInfos.get(groupId).lastPowerOnTime;
+    }
+
+    /**
+     * Returns the amalgamated wakefulness of all {@link DisplayGroup DisplayGroups}.
+     *
+     * <p>This will be the highest wakeful state of all {@link DisplayGroup DisplayGroups}; ordered
+     * from highest to lowest:
+     * <ol>
+     *     <li>{@link PowerManagerInternal#WAKEFULNESS_AWAKE}
+     *     <li>{@link PowerManagerInternal#WAKEFULNESS_DREAMING}
+     *     <li>{@link PowerManagerInternal#WAKEFULNESS_DOZING}
+     *     <li>{@link PowerManagerInternal#WAKEFULNESS_ASLEEP}
+     * </ol>
+     */
+    int getGlobalWakefulnessLocked() {
+        final int size = mDisplayGroupInfos.size();
+        int deviceWakefulness = WAKEFULNESS_ASLEEP;
+        for (int i = 0; i < size; i++) {
+            final int wakefulness = mDisplayGroupInfos.valueAt(i).wakefulness;
+            if (wakefulness == WAKEFULNESS_AWAKE) {
+                return WAKEFULNESS_AWAKE;
+            } else if (wakefulness == WAKEFULNESS_DREAMING
+                    && (deviceWakefulness == WAKEFULNESS_ASLEEP
+                    || deviceWakefulness == WAKEFULNESS_DOZING)) {
+                deviceWakefulness = WAKEFULNESS_DREAMING;
+            } else if (wakefulness == WAKEFULNESS_DOZING
+                    && deviceWakefulness == WAKEFULNESS_ASLEEP) {
+                deviceWakefulness = WAKEFULNESS_DOZING;
+            }
+        }
+
+        return deviceWakefulness;
+    }
+
+    /**
+     * Sets the {@code wakefulness} value for the {@link DisplayGroup} specified by the provided
+     * {@code groupId}.
+     *
+     * @return {@code true} if the wakefulness value was changed; {@code false} otherwise.
+     */
+    boolean setWakefulnessLocked(int groupId, int wakefulness) {
+        final DisplayGroupInfo displayGroupInfo = mDisplayGroupInfos.get(groupId);
+        if (displayGroupInfo.wakefulness != wakefulness) {
+            displayGroupInfo.wakefulness = wakefulness;
+            return true;
+        }
+
+        return false;
+    }
+
+    boolean isSandmanSummoned(int groupId) {
+        return mDisplayGroupInfos.get(groupId).sandmanSummoned;
+    }
+
+    boolean isSandmanSupported(int groupId) {
+        return mDisplayGroupInfos.get(groupId).supportsSandman;
+    }
+
+    /**
+     * Sets whether or not the sandman is summoned for the given {@code groupId}.
+     *
+     * @param groupId         Signifies the DisplayGroup for which to summon or unsummon the
+     *                        sandman.
+     * @param sandmanSummoned {@code true} to summon the sandman; {@code false} to unsummon.
+     */
+    void setSandmanSummoned(int groupId, boolean sandmanSummoned) {
+        final DisplayGroupInfo displayGroupInfo = mDisplayGroupInfos.get(groupId);
+        displayGroupInfo.sandmanSummoned = displayGroupInfo.supportsSandman && sandmanSummoned;
+    }
+
+    /**
+     * Returns {@code true} if every display in the specified group has its requested state matching
+     * its actual state.
+     *
+     * @param groupId The identifier for the display group to check for readiness.
+     */
+    boolean isReady(int groupId) {
+        return mDisplayGroupInfos.get(groupId).ready;
+    }
+
+    /** Returns {@code true} if every display has its requested state matching its actual state. */
+    boolean areAllDisplaysReadyLocked() {
+        final int size = mDisplayGroupInfos.size();
+        for (int i = 0; i < size; i++) {
+            if (!mDisplayGroupInfos.valueAt(i).ready) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Sets whether the displays specified by the provided {@code groupId} are all ready.
+     *
+     * <p>A display is ready if its reported
+     * {@link DisplayManagerInternal.DisplayPowerCallbacks#onStateChanged() actual state} matches
+     * its {@link DisplayManagerInternal#requestPowerState requested state}.
+     *
+     * @param groupId The identifier for the display group.
+     * @param ready   {@code true} if every display in the group is ready; otherwise {@code false}.
+     * @return {@code true} if the ready state changed; otherwise {@code false}.
+     */
+    boolean setDisplayGroupReadyLocked(int groupId, boolean ready) {
+        final DisplayGroupInfo displayGroupInfo = mDisplayGroupInfos.get(groupId);
+        if (displayGroupInfo.ready != ready) {
+            displayGroupInfo.ready = ready;
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Interface through which an interested party may be informed of {@link DisplayGroup} events.
+     */
+    interface DisplayGroupPowerChangeListener {
+        int DISPLAY_GROUP_ADDED = 0;
+        int DISPLAY_GROUP_REMOVED = 1;
+        int DISPLAY_GROUP_CHANGED = 2;
+
+        void onDisplayGroupEventLocked(int event, int groupId);
+    }
+
+    private static final class DisplayGroupInfo {
+        public final DisplayPowerRequest displayPowerRequest;
+        public int wakefulness;
+        public boolean ready;
+        public long lastPowerOnTime;
+        public boolean sandmanSummoned;
+
+        /** {@code true} if this DisplayGroup supports dreaming; otherwise {@code false}. */
+        public boolean supportsSandman;
+
+        DisplayGroupInfo(DisplayPowerRequest displayPowerRequest, int wakefulness, boolean ready,
+                boolean supportsSandman) {
+            this.displayPowerRequest = displayPowerRequest;
+            this.wakefulness = wakefulness;
+            this.ready = ready;
+            this.supportsSandman = supportsSandman;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/power/DisplayPowerRequestMapper.java b/services/core/java/com/android/server/power/DisplayPowerRequestMapper.java
deleted file mode 100644
index 2fc3e40..0000000
--- a/services/core/java/com/android/server/power/DisplayPowerRequestMapper.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.power;
-
-import android.hardware.display.DisplayManager;
-import android.hardware.display.DisplayManagerInternal;
-import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
-import android.os.Handler;
-import android.util.SparseArray;
-import android.util.SparseIntArray;
-import android.view.Display;
-
-import com.android.internal.annotations.GuardedBy;
-
-/**
- * Responsible for creating {@link DisplayPowerRequest}s and associating them with
- * {@link com.android.server.display.DisplayGroup}s.
- *
- * Each {@link com.android.server.display.DisplayGroup} has a single {@link DisplayPowerRequest}
- * which is used to request power state changes to every display in the group.
- */
-class DisplayPowerRequestMapper {
-
-    private final Object mLock = new Object();
-
-    /** A mapping from LogicalDisplay Id to DisplayGroup Id. */
-    @GuardedBy("mLock")
-    private final SparseIntArray mDisplayGroupIds = new SparseIntArray();
-
-    /** A mapping from DisplayGroup Id to DisplayPowerRequest. */
-    @GuardedBy("mLock")
-    private final SparseArray<DisplayPowerRequest> mDisplayPowerRequests = new SparseArray<>();
-
-    private final DisplayManagerInternal mDisplayManagerInternal;
-
-    private final DisplayManager.DisplayListener mDisplayListener =
-            new DisplayManager.DisplayListener() {
-
-                @Override
-                public void onDisplayAdded(int displayId) {
-                    synchronized (mLock) {
-                        if (mDisplayGroupIds.indexOfKey(displayId) >= 0) {
-                            return;
-                        }
-                        final int displayGroupId = mDisplayManagerInternal.getDisplayGroupId(
-                                displayId);
-                        if (!mDisplayPowerRequests.contains(displayGroupId)) {
-                            // A new DisplayGroup was created; create a new DisplayPowerRequest.
-                            mDisplayPowerRequests.append(displayGroupId, new DisplayPowerRequest());
-                        }
-                        mDisplayGroupIds.append(displayId, displayGroupId);
-                    }
-                }
-
-                @Override
-                public void onDisplayRemoved(int displayId) {
-                    synchronized (mLock) {
-                        final int index = mDisplayGroupIds.indexOfKey(displayId);
-                        if (index < 0) {
-                            return;
-                        }
-                        final int displayGroupId = mDisplayGroupIds.valueAt(index);
-                        mDisplayGroupIds.removeAt(index);
-
-                        if (mDisplayGroupIds.indexOfValue(displayGroupId) < 0) {
-                            // The DisplayGroup no longer exists; delete the DisplayPowerRequest.
-                            mDisplayPowerRequests.delete(displayGroupId);
-                        }
-                    }
-                }
-
-                @Override
-                public void onDisplayChanged(int displayId) {
-                    synchronized (mLock) {
-                        final int newDisplayGroupId = mDisplayManagerInternal.getDisplayGroupId(
-                                displayId);
-                        final int oldDisplayGroupId = mDisplayGroupIds.get(displayId);
-
-                        if (!mDisplayPowerRequests.contains(newDisplayGroupId)) {
-                            // A new DisplayGroup was created; create a new DisplayPowerRequest.
-                            mDisplayPowerRequests.append(newDisplayGroupId,
-                                    new DisplayPowerRequest());
-                        }
-                        mDisplayGroupIds.put(displayId, newDisplayGroupId);
-
-                        if (mDisplayGroupIds.indexOfValue(oldDisplayGroupId) < 0) {
-                            // The DisplayGroup no longer exists; delete the DisplayPowerRequest.
-                            mDisplayPowerRequests.delete(oldDisplayGroupId);
-                        }
-                    }
-                }
-            };
-
-    DisplayPowerRequestMapper(DisplayManager displayManager,
-            DisplayManagerInternal displayManagerInternal, Handler handler) {
-        mDisplayManagerInternal = displayManagerInternal;
-        displayManager.registerDisplayListener(mDisplayListener, handler);
-        mDisplayPowerRequests.append(Display.DEFAULT_DISPLAY_GROUP, new DisplayPowerRequest());
-        mDisplayGroupIds.append(Display.DEFAULT_DISPLAY, Display.DEFAULT_DISPLAY_GROUP);
-    }
-
-    DisplayPowerRequest get(int displayId) {
-        synchronized (mLock) {
-            return mDisplayPowerRequests.get(mDisplayGroupIds.get(displayId));
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/power/FaceDownDetector.java b/services/core/java/com/android/server/power/FaceDownDetector.java
new file mode 100644
index 0000000..2442079
--- /dev/null
+++ b/services/core/java/com/android/server/power/FaceDownDetector.java
@@ -0,0 +1,456 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power;
+
+import static android.provider.DeviceConfig.NAMESPACE_ATTENTION_MANAGER_SERVICE;
+
+import android.annotation.NonNull;
+import android.app.ActivityThread;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.SystemClock;
+import android.provider.DeviceConfig;
+import android.util.Slog;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+import java.io.PrintWriter;
+import java.time.Duration;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Consumer;
+
+/**
+ * Class used to detect when the phone is placed face down. This is used for Flip to Screen Off. A
+ * client can use this detector to trigger state changes like screen off when the phone is face
+ * down.
+ */
+public class FaceDownDetector implements SensorEventListener {
+
+    private static final String TAG = "FaceDownDetector";
+    private static final boolean DEBUG = false;
+
+    private static final int SCREEN_OFF_RESULT =
+            FrameworkStatsLog.FACE_DOWN_REPORTED__FACE_DOWN_RESPONSE__SCREEN_OFF;
+    private static final int USER_INTERACTION =
+            FrameworkStatsLog.FACE_DOWN_REPORTED__FACE_DOWN_RESPONSE__USER_INTERACTION;
+    private static final int UNFLIP =
+            FrameworkStatsLog.FACE_DOWN_REPORTED__FACE_DOWN_RESPONSE__UNFLIP;
+
+    /**
+     * Used by the ExponentialMovingAverage accelerations, this determines how quickly the
+     * average can change. A number closer to 1 will mean it will take longer to change.
+     */
+    private static final float MOVING_AVERAGE_WEIGHT = 0.5f;
+
+    /** DeviceConfig flag name, if {@code true}, enables Face Down features. */
+    private static final String KEY_FEATURE_ENABLED = "enable_flip_to_screen_off";
+
+    /** Default value in absence of {@link DeviceConfig} override. */
+    private static final boolean DEFAULT_FEATURE_ENABLED = true;
+
+    private boolean mIsEnabled;
+
+    /**
+     * DeviceConfig flag name, determines how long to disable sensor when user interacts while
+     * device is flipped.
+     */
+    private static final String KEY_INTERACTION_BACKOFF = "face_down_interaction_backoff_millis";
+
+    /** Default value in absence of {@link DeviceConfig} override. */
+    private static final long DEFAULT_INTERACTION_BACKOFF = 60_000;
+
+    private long mUserInteractionBackoffMillis;
+
+    /**
+     * DeviceConfig flag name, defines the max change in acceleration which will prevent face down
+     * due to movement.
+     */
+    static final String KEY_ACCELERATION_THRESHOLD = "acceleration_threshold";
+
+    /** Default value in absence of {@link DeviceConfig} override. */
+    static final float DEFAULT_ACCELERATION_THRESHOLD = 0.2f;
+
+    private float mAccelerationThreshold;
+
+    /**
+     * DeviceConfig flag name, defines the maximum z-axis acceleration that will indicate the phone
+     * is face down.
+     */
+    static final String KEY_Z_ACCELERATION_THRESHOLD = "z_acceleration_threshold";
+
+    /** Default value in absence of {@link DeviceConfig} override. */
+    static final float DEFAULT_Z_ACCELERATION_THRESHOLD = -9.5f;
+
+    private float mZAccelerationThreshold;
+
+    /**
+     * After going face down, we relax the threshold to make it more difficult to exit face down
+     * than to enter it.
+     */
+    private float mZAccelerationThresholdLenient;
+
+    /**
+     * DeviceConfig flag name, defines the minimum amount of time that has to pass while the phone
+     * is face down and not moving in order to trigger face down behavior, in milliseconds.
+     */
+    static final String KEY_TIME_THRESHOLD_MILLIS = "time_threshold_millis";
+
+    /** Default value in absence of {@link DeviceConfig} override. */
+    static final long DEFAULT_TIME_THRESHOLD_MILLIS = 1_000L;
+
+    private Duration mTimeThreshold;
+
+    private Sensor mAccelerometer;
+    private SensorManager mSensorManager;
+    private final Consumer<Boolean> mOnFlip;
+
+    /** Values we store for logging purposes. */
+    private long mLastFlipTime = 0L;
+    public int mPreviousResultType = 0;
+    public long mPreviousResultTime = 0L;
+    private long mMillisSaved = 0L;
+
+    private final ExponentialMovingAverage mCurrentXYAcceleration =
+            new ExponentialMovingAverage(MOVING_AVERAGE_WEIGHT);
+    private final ExponentialMovingAverage mCurrentZAcceleration =
+            new ExponentialMovingAverage(MOVING_AVERAGE_WEIGHT);
+
+    private boolean mFaceDown = false;
+    private boolean mActive = false;
+
+    private float mPrevAcceleration = 0;
+    private long mPrevAccelerationTime = 0;
+
+    private boolean mZAccelerationIsFaceDown = false;
+    private long mZAccelerationFaceDownTime = 0L;
+
+    private final Handler mHandler;
+    private final Runnable mUserActivityRunnable;
+
+    public FaceDownDetector(@NonNull Consumer<Boolean> onFlip) {
+        mOnFlip = Objects.requireNonNull(onFlip);
+        mHandler = new Handler(Looper.getMainLooper());
+        mUserActivityRunnable = () -> {
+            if (mFaceDown) {
+                exitFaceDown(USER_INTERACTION, SystemClock.uptimeMillis() - mLastFlipTime);
+                checkAndUpdateActiveState(false);
+            }
+        };
+    }
+
+    /** Initializes the FaceDownDetector and all necessary listeners. */
+    public void systemReady(Context context) {
+        mSensorManager = context.getSystemService(SensorManager.class);
+        mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+        readValuesFromDeviceConfig();
+        checkAndUpdateActiveState(true);
+        DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+                ActivityThread.currentApplication().getMainExecutor(),
+                (properties) -> onDeviceConfigChange(properties.getKeyset()));
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
+        intentFilter.addAction(Intent.ACTION_SCREEN_ON);
+        intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+        context.registerReceiver(new ScreenStateReceiver(), intentFilter);
+    }
+
+    /**
+     * Sets the active state of the detector. If false, we will not process accelerometer changes.
+     */
+    private void checkAndUpdateActiveState(boolean active) {
+        if (mIsEnabled && mActive != active) {
+            final long currentTime = SystemClock.uptimeMillis();
+            // Don't make active if there was recently a user interaction while face down.
+            if (active && mPreviousResultType == USER_INTERACTION
+                    && currentTime - mPreviousResultTime  < mUserInteractionBackoffMillis) {
+                return;
+            }
+            if (DEBUG) Slog.d(TAG, "Update active - " + active);
+            mActive = active;
+            if (!active) {
+                if (mFaceDown && mPreviousResultTime != USER_INTERACTION) {
+                    mPreviousResultType = SCREEN_OFF_RESULT;
+                    mPreviousResultTime = currentTime;
+                }
+                mSensorManager.unregisterListener(this);
+                mFaceDown = false;
+                mOnFlip.accept(false);
+            } else {
+                if (mPreviousResultType == SCREEN_OFF_RESULT) {
+                    logScreenOff();
+                }
+                mSensorManager.registerListener(
+                        this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
+            }
+        }
+    }
+
+    /** Prints state information about FaceDownDetector */
+    public void dump(PrintWriter pw) {
+        pw.println("FaceDownDetector:");
+        pw.println("  mFaceDown=" + mFaceDown);
+        pw.println("  mActive=" + mActive);
+        pw.println("  mLastFlipTime=" + mLastFlipTime);
+        pw.println("  mUserInteractionBackoffMillis=" + mUserInteractionBackoffMillis);
+        pw.println("  mPreviousResultTime=" + mPreviousResultTime);
+        pw.println("  mPreviousResultType=" + mPreviousResultType);
+        pw.println("  mMillisSaved=" + mMillisSaved);
+        pw.println("  mZAccelerationThreshold=" + mZAccelerationThreshold);
+        pw.println("  mAccelerationThreshold=" + mAccelerationThreshold);
+        pw.println("  mTimeThreshold=" + mTimeThreshold);
+    }
+
+    @Override
+    public void onSensorChanged(SensorEvent event) {
+        if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) return;
+        if (!mActive || !mIsEnabled) return;
+
+        final float x = event.values[0];
+        final float y = event.values[1];
+        mCurrentXYAcceleration.updateMovingAverage(x * x + y * y);
+        mCurrentZAcceleration.updateMovingAverage(event.values[2]);
+
+        // Detect movement
+        // If the x, y acceleration is within the acc threshold for at least a length of time longer
+        // than the time threshold, we set moving to true.
+        final long curTime = event.timestamp;
+        if (Math.abs(mCurrentXYAcceleration.mMovingAverage - mPrevAcceleration)
+                > mAccelerationThreshold) {
+            mPrevAcceleration = mCurrentXYAcceleration.mMovingAverage;
+            mPrevAccelerationTime = curTime;
+        }
+        final boolean moving = curTime - mPrevAccelerationTime <= mTimeThreshold.toNanos();
+
+        // If the z acceleration is beyond the gravity/z-acceleration threshold for at least a
+        // length of time longer than the time threshold, we set isFaceDownForPeriod to true.
+        final float zAccelerationThreshold =
+                mFaceDown ? mZAccelerationThresholdLenient : mZAccelerationThreshold;
+        final boolean isCurrentlyFaceDown =
+                mCurrentZAcceleration.mMovingAverage < zAccelerationThreshold;
+        final boolean isFaceDownForPeriod = isCurrentlyFaceDown
+                && mZAccelerationIsFaceDown
+                && curTime - mZAccelerationFaceDownTime > mTimeThreshold.toNanos();
+        if (isCurrentlyFaceDown && !mZAccelerationIsFaceDown) {
+            mZAccelerationFaceDownTime = curTime;
+            mZAccelerationIsFaceDown = true;
+        } else if (!isCurrentlyFaceDown) {
+            mZAccelerationIsFaceDown = false;
+        }
+
+
+        if (!moving && isFaceDownForPeriod && !mFaceDown) {
+            faceDownDetected();
+        } else if (!isFaceDownForPeriod && mFaceDown) {
+            unFlipDetected();
+        }
+    }
+
+    @Override
+    public void onAccuracyChanged(Sensor sensor, int accuracy) {}
+
+    private void faceDownDetected() {
+        if (DEBUG) Slog.d(TAG, "Triggered faceDownDetected.");
+        mLastFlipTime = SystemClock.uptimeMillis();
+        mFaceDown = true;
+        mOnFlip.accept(true);
+    }
+
+    private void unFlipDetected() {
+        if (DEBUG) Slog.d(TAG, "Triggered exitFaceDown");
+        exitFaceDown(UNFLIP, SystemClock.uptimeMillis() - mLastFlipTime);
+    }
+
+    /**
+     * The user interacted with the screen while face down, indicated the phone is in use.
+     * We log this event and temporarily make this detector inactive.
+     */
+    public void userActivity() {
+        mHandler.post(mUserActivityRunnable);
+    }
+
+    private void exitFaceDown(int resultType, long millisSinceFlip) {
+        FrameworkStatsLog.write(FrameworkStatsLog.FACE_DOWN_REPORTED,
+                resultType,
+                millisSinceFlip,
+                /* millis_until_normal_timeout= */ 0L,
+                /* millis_until_next_screen_on= */ 0L);
+        mFaceDown = false;
+        mLastFlipTime = 0L;
+        mPreviousResultType = resultType;
+        mPreviousResultTime = SystemClock.uptimeMillis();
+        mOnFlip.accept(false);
+    }
+
+    private void logScreenOff() {
+        if (mPreviousResultType == SCREEN_OFF_RESULT) {
+            final long currentTime = SystemClock.uptimeMillis();
+            FrameworkStatsLog.write(FrameworkStatsLog.FACE_DOWN_REPORTED,
+                    mPreviousResultType,
+                    /* millis_since_flip= */ mPreviousResultTime  - mLastFlipTime,
+                    mMillisSaved,
+                    /* millis_until_next_screen_on= */ currentTime - mPreviousResultTime);
+            mPreviousResultType = -1;
+        }
+    }
+
+    private boolean isEnabled() {
+        return DeviceConfig.getBoolean(NAMESPACE_ATTENTION_MANAGER_SERVICE, KEY_FEATURE_ENABLED,
+                DEFAULT_FEATURE_ENABLED);
+    }
+
+    private float getAccelerationThreshold() {
+        return getFloatFlagValue(KEY_ACCELERATION_THRESHOLD,
+                DEFAULT_ACCELERATION_THRESHOLD,
+                -2.0f,
+                2.0f);
+    }
+
+    private float getZAccelerationThreshold() {
+        return getFloatFlagValue(KEY_Z_ACCELERATION_THRESHOLD,
+                DEFAULT_Z_ACCELERATION_THRESHOLD,
+                -15.0f,
+                0.0f);
+    }
+
+    private long getUserInteractionBackoffMillis() {
+        return getLongFlagValue(KEY_INTERACTION_BACKOFF,
+                DEFAULT_INTERACTION_BACKOFF,
+                0,
+                3600_000);
+    }
+
+    private float getFloatFlagValue(String key, float defaultValue, float min, float max) {
+        final float value = DeviceConfig.getFloat(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+                key,
+                defaultValue);
+
+        if (value < min || value > max) {
+            Slog.w(TAG, "Bad flag value supplied for: " + key);
+            return defaultValue;
+        }
+
+        return value;
+    }
+
+    private long getLongFlagValue(String key, long defaultValue, long min, long max) {
+        final long value = DeviceConfig.getLong(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+                key,
+                defaultValue);
+
+        if (value < min || value > max) {
+            Slog.w(TAG, "Bad flag value supplied for: " + key);
+            return defaultValue;
+        }
+
+        return value;
+    }
+
+    private Duration getTimeThreshold() {
+        final long millis = DeviceConfig.getLong(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+                KEY_TIME_THRESHOLD_MILLIS,
+                DEFAULT_TIME_THRESHOLD_MILLIS);
+
+        if (millis < 0 || millis > 15_000) {
+            Slog.w(TAG, "Bad flag value supplied for: " + KEY_TIME_THRESHOLD_MILLIS);
+            return Duration.ofMillis(DEFAULT_TIME_THRESHOLD_MILLIS);
+        }
+
+        return Duration.ofMillis(millis);
+    }
+
+    private void onDeviceConfigChange(@NonNull Set<String> keys) {
+        for (String key : keys) {
+            switch (key) {
+                case KEY_ACCELERATION_THRESHOLD:
+                case KEY_Z_ACCELERATION_THRESHOLD:
+                case KEY_TIME_THRESHOLD_MILLIS:
+                case KEY_FEATURE_ENABLED:
+                    readValuesFromDeviceConfig();
+                    return;
+                default:
+                    Slog.i(TAG, "Ignoring change on " + key);
+            }
+        }
+    }
+
+    private void readValuesFromDeviceConfig() {
+        mAccelerationThreshold = getAccelerationThreshold();
+        mZAccelerationThreshold = getZAccelerationThreshold();
+        mZAccelerationThresholdLenient = mZAccelerationThreshold + 1.0f;
+        mTimeThreshold = getTimeThreshold();
+        mIsEnabled = isEnabled();
+        mUserInteractionBackoffMillis = getUserInteractionBackoffMillis();
+
+        Slog.i(TAG, "readValuesFromDeviceConfig():"
+                + "\nmAccelerationThreshold=" + mAccelerationThreshold
+                + "\nmZAccelerationThreshold=" + mZAccelerationThreshold
+                + "\nmTimeThreshold=" + mTimeThreshold
+                + "\nmIsEnabled=" + mIsEnabled);
+    }
+
+    /**
+     * Sets how much screen on time might be saved as a result of this detector. Currently used for
+     * logging purposes.
+     */
+    public void setMillisSaved(long millisSaved) {
+        mMillisSaved = millisSaved;
+    }
+
+    private final class ScreenStateReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
+                checkAndUpdateActiveState(false);
+            } else if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {
+                checkAndUpdateActiveState(true);
+            }
+        }
+    }
+
+    private final class ExponentialMovingAverage {
+        private final float mAlpha;
+        private final float mInitialAverage;
+        private float mMovingAverage;
+
+        ExponentialMovingAverage(float alpha) {
+            this(alpha, 0.0f);
+        }
+
+        ExponentialMovingAverage(float alpha, float initialAverage) {
+            this.mAlpha = alpha;
+            this.mInitialAverage = initialAverage;
+            this.mMovingAverage = initialAverage;
+        }
+
+        void updateMovingAverage(float newValue) {
+            mMovingAverage = newValue + mAlpha * (mMovingAverage - newValue);
+        }
+
+        void reset() {
+            mMovingAverage = this.mInitialAverage;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index b8e0156..f49e2f1 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -119,6 +119,7 @@
     private final AppOpsManager mAppOps;
     private final SuspendBlocker mSuspendBlocker;
     private final WindowManagerPolicy mPolicy;
+    private final FaceDownDetector mFaceDownDetector;
     private final ActivityManagerInternal mActivityManagerInternal;
     private final InputManagerInternal mInputManagerInternal;
     private final InputMethodManagerInternal mInputMethodManagerInternal;
@@ -165,12 +166,14 @@
     private boolean mUserActivityPending;
 
     public Notifier(Looper looper, Context context, IBatteryStats batteryStats,
-            SuspendBlocker suspendBlocker, WindowManagerPolicy policy) {
+            SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
+            FaceDownDetector faceDownDetector) {
         mContext = context;
         mBatteryStats = batteryStats;
         mAppOps = mContext.getSystemService(AppOpsManager.class);
         mSuspendBlocker = suspendBlocker;
         mPolicy = policy;
+        mFaceDownDetector = faceDownDetector;
         mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
         mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
         mInputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class);
@@ -654,6 +657,7 @@
         TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
         tm.notifyUserActivity();
         mPolicy.userActivity();
+        mFaceDownDetector.userActivity();
     }
 
     void postEnhancedDischargePredictionBroadcast(long delayMs) {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index c0b8202..bc11709 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -16,8 +16,13 @@
 
 package com.android.server.power;
 
+import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.policyToString;
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT;
+import static android.os.PowerManager.GO_TO_SLEEP_REASON_DISPLAY_GROUPS_TURNED_OFF;
+import static android.os.PowerManager.GO_TO_SLEEP_REASON_DISPLAY_GROUP_REMOVED;
+import static android.os.PowerManager.WAKE_REASON_DISPLAY_GROUP_ADDED;
+import static android.os.PowerManager.WAKE_REASON_DISPLAY_GROUP_TURNED_ON;
 import static android.os.PowerManagerInternal.MODE_DEVICE_IDLE;
 import static android.os.PowerManagerInternal.MODE_DISPLAY_INACTIVE;
 import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
@@ -42,7 +47,6 @@
 import android.hardware.SensorManager;
 import android.hardware.SystemSensorManager;
 import android.hardware.display.AmbientDisplayConfiguration;
-import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
 import android.hardware.power.Boost;
@@ -176,6 +180,10 @@
     private static final int DIRTY_VR_MODE_CHANGED = 1 << 13;
     // Dirty bit: attentive timer may have timed out
     private static final int DIRTY_ATTENTIVE = 1 << 14;
+    // Dirty bit: phone flipped to face down
+    private static final int DIRTY_FACE_DOWN = 1 << 15;
+    // Dirty bit: display group power state has changed
+    private static final int DIRTY_DISPLAY_GROUP_POWER_UPDATED = 1 << 16;
 
     // Summarizes the state of all active wakelocks.
     private static final int WAKE_LOCK_CPU = 1 << 0;
@@ -263,6 +271,7 @@
     private final BatterySaverStateMachine mBatterySaverStateMachine;
     private final BatterySavingStats mBatterySavingStats;
     private final AttentionDetector mAttentionDetector;
+    private final FaceDownDetector mFaceDownDetector;
     private final BinderService mBinderService;
     private final LocalService mLocalService;
     private final NativeWrapper mNativeWrapper;
@@ -297,10 +306,6 @@
     private int mWakefulnessRaw;
     private boolean mWakefulnessChanging;
 
-    // True if the sandman has just been summoned for the first time since entering the
-    // dreaming or dozing state.  Indicates whether a new dream should begin.
-    private boolean mSandmanSummoned;
-
     // True if MSG_SANDMAN has been scheduled.
     private boolean mSandmanScheduled;
 
@@ -351,11 +356,7 @@
 
     // Manages the desired power state of displays. The actual state may lag behind the
     // requested because it is updated asynchronously by the display power controller.
-    private DisplayPowerRequestMapper mDisplayPowerRequestMapper;
-
-    // True if the display power state has been fully applied, which means the display
-    // is actually on or actually off or whatever was requested.
-    private boolean mDisplayReady;
+    private DisplayGroupPowerStateMapper mDisplayGroupPowerStateMapper;
 
     // The suspend blocker used to keep the CPU alive when an application has acquired
     // a wake lock.
@@ -547,6 +548,10 @@
     public final float mScreenBrightnessMaximumVr;
     public final float mScreenBrightnessDefaultVr;
 
+    // Value we store for tracking face down behavior.
+    private boolean mIsFaceDown = false;
+    private long mLastFlipTime = 0L;
+
     // The screen brightness mode.
     // One of the Settings.System.SCREEN_BRIGHTNESS_MODE_* constants.
     private int mScreenBrightnessModeSetting;
@@ -625,6 +630,39 @@
     // but the DreamService has not yet been told to start (it's an async process).
     private boolean mDozeStartInProgress;
 
+    private final class DisplayGroupPowerChangeListener implements
+            DisplayGroupPowerStateMapper.DisplayGroupPowerChangeListener {
+        @Override
+        public void onDisplayGroupEventLocked(int event, int groupId) {
+            final int oldWakefulness = getWakefulnessLocked();
+            final int newWakefulness = mDisplayGroupPowerStateMapper.getGlobalWakefulnessLocked();
+            if (oldWakefulness != newWakefulness) {
+                final int reason;
+                switch (newWakefulness) {
+                    case WAKEFULNESS_AWAKE:
+                        reason = event == DISPLAY_GROUP_ADDED ? WAKE_REASON_DISPLAY_GROUP_ADDED
+                                : WAKE_REASON_DISPLAY_GROUP_TURNED_ON;
+                        break;
+                    case WAKEFULNESS_DOZING:
+                        reason = event == DISPLAY_GROUP_REMOVED
+                                ? GO_TO_SLEEP_REASON_DISPLAY_GROUP_REMOVED
+                                : GO_TO_SLEEP_REASON_DISPLAY_GROUPS_TURNED_OFF;
+                        break;
+                    default:
+                        reason = 0;
+                }
+
+                setGlobalWakefulnessLocked(
+                        mDisplayGroupPowerStateMapper.getGlobalWakefulnessLocked(),
+                        mClock.uptimeMillis(), reason, Process.SYSTEM_UID, Process.SYSTEM_UID,
+                        mContext.getOpPackageName(), "groupId: " + groupId);
+            }
+
+            mDirty |= DIRTY_DISPLAY_GROUP_POWER_UPDATED;
+            updatePowerStateLocked();
+        }
+    }
+
     private final class ForegroundProfileObserver extends SynchronousUserSwitchObserver {
         @Override
         public void onUserSwitching(@UserIdInt int newUserId) throws RemoteException {
@@ -791,8 +829,10 @@
     @VisibleForTesting
     static class Injector {
         Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
-                SuspendBlocker suspendBlocker, WindowManagerPolicy policy) {
-            return new Notifier(looper, context, batteryStats, suspendBlocker, policy);
+                SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
+                FaceDownDetector faceDownDetector) {
+            return new Notifier(
+                    looper, context, batteryStats, suspendBlocker, policy, faceDownDetector);
         }
 
         SuspendBlocker createSuspendBlocker(PowerManagerService service, String name) {
@@ -868,6 +908,12 @@
         void invalidateIsInteractiveCaches() {
             PowerManager.invalidateIsInteractiveCaches();
         }
+
+        DisplayGroupPowerStateMapper createDisplayPowerRequestMapper(Object lock,
+                DisplayManagerInternal displayManagerInternal,
+                DisplayGroupPowerStateMapper.DisplayGroupPowerChangeListener listener) {
+            return new DisplayGroupPowerStateMapper(lock, displayManagerInternal, listener);
+        }
     }
 
     final Constants mConstants;
@@ -906,6 +952,7 @@
         mAmbientDisplaySuppressionController =
                 mInjector.createAmbientDisplaySuppressionController(context);
         mAttentionDetector = new AttentionDetector(this::onUserAttention, mLock);
+        mFaceDownDetector = new FaceDownDetector(this::onFlip);
 
         mBatterySavingStats = new BatterySavingStats(mLock);
         mBatterySaverPolicy =
@@ -1011,6 +1058,26 @@
         }
     }
 
+    private void onFlip(boolean isFaceDown) {
+        long millisUntilNormalTimeout = 0;
+        synchronized (mLock) {
+            mIsFaceDown = isFaceDown;
+            if (isFaceDown) {
+                final long currentTime = mClock.uptimeMillis();
+                mLastFlipTime = currentTime;
+                final long sleepTimeout = getSleepTimeoutLocked(-1L);
+                final long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout, -1L);
+                millisUntilNormalTimeout =
+                        mLastUserActivityTime + screenOffTimeout - mClock.uptimeMillis();
+                mDirty |= DIRTY_FACE_DOWN;
+                updatePowerStateLocked();
+            }
+        }
+        if (isFaceDown) {
+            mFaceDownDetector.setMillisSaved(millisUntilNormalTimeout);
+        }
+    }
+
     @Override
     public void onStart() {
         publishBinderService(Context.POWER_SERVICE, mBinderService, /* allowIsolated= */ false,
@@ -1038,7 +1105,8 @@
 
                 updatePowerStateLocked();
                 if (sQuiescent) {
-                    goToSleepNoUpdateLocked(mClock.uptimeMillis(),
+                    sleepDisplayGroupNoUpdateLocked(Display.DEFAULT_DISPLAY_GROUP,
+                            mClock.uptimeMillis(),
                             PowerManager.GO_TO_SLEEP_REASON_QUIESCENT,
                             PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, Process.SYSTEM_UID);
                 }
@@ -1055,8 +1123,8 @@
             mPolicy = getLocalService(WindowManagerPolicy.class);
             mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);
             mAttentionDetector.systemReady(mContext);
-            mDisplayPowerRequestMapper = new DisplayPowerRequestMapper(mContext.getSystemService(
-                    DisplayManager.class), mDisplayManagerInternal, mHandler);
+            mDisplayGroupPowerStateMapper = mInjector.createDisplayPowerRequestMapper(mLock,
+                    mDisplayManagerInternal, new DisplayGroupPowerChangeListener());
 
             SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
 
@@ -1065,7 +1133,7 @@
             mBatteryStats = BatteryStatsService.getService();
             mNotifier = mInjector.createNotifier(Looper.getMainLooper(), mContext, mBatteryStats,
                     mInjector.createSuspendBlocker(this, "PowerManagerService.Broadcasts"),
-                    mPolicy);
+                    mPolicy, mFaceDownDetector);
 
             mWirelessChargerDetector = mInjector.createWirelessChargerDetector(sensorManager,
                     mInjector.createSuspendBlocker(
@@ -1099,6 +1167,7 @@
 
         mBatterySaverController.systemReady();
         mBatterySaverPolicy.systemReady();
+        mFaceDownDetector.systemReady(mContext);
 
         // Register for settings changes.
         resolver.registerContentObserver(Settings.Secure.getUriFor(
@@ -1373,9 +1442,11 @@
                 opPackageName = wakeLock.mPackageName;
                 opUid = wakeLock.mOwnerUid;
             }
-            wakeUpNoUpdateLocked(mClock.uptimeMillis(),
-                    PowerManager.WAKE_REASON_APPLICATION, wakeLock.mTag,
-                    opUid, opPackageName, opUid);
+            for (int id : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
+                wakeDisplayGroupNoUpdateLocked(id, mClock.uptimeMillis(),
+                        PowerManager.WAKE_REASON_APPLICATION, wakeLock.mTag,
+                        opUid, opPackageName, opUid);
+            }
         }
     }
 
@@ -1574,7 +1645,7 @@
     }
 
     // Called from native code.
-    private void userActivityFromNative(long eventTime, int event, int flags) {
+    private void userActivityFromNative(long eventTime, int event, int displayId, int flags) {
         userActivityInternal(eventTime, event, flags, Process.SYSTEM_UID);
     }
 
@@ -1664,26 +1735,29 @@
         }
     }
 
-    private void wakeUpInternal(long eventTime, @WakeReason int reason, String details, int uid,
-            String opPackageName, int opUid) {
+    private void wakeDisplayGroup(int groupId, long eventTime, @WakeReason int reason,
+            String details, int uid, String opPackageName, int opUid) {
         synchronized (mLock) {
-            if (wakeUpNoUpdateLocked(eventTime, reason, details, uid, opPackageName, opUid)) {
+            if (wakeDisplayGroupNoUpdateLocked(groupId, eventTime, reason, details, uid,
+                    opPackageName, opUid)) {
                 updatePowerStateLocked();
             }
         }
     }
 
-    private boolean wakeUpNoUpdateLocked(long eventTime, @WakeReason int reason, String details,
-            int reasonUid, String opPackageName, int opUid) {
+    private boolean wakeDisplayGroupNoUpdateLocked(int groupId, long eventTime,
+            @WakeReason int reason, String details, int uid, String opPackageName, int opUid) {
         if (DEBUG_SPEW) {
-            Slog.d(TAG, "wakeUpNoUpdateLocked: eventTime=" + eventTime + ", uid=" + reasonUid);
+            Slog.d(TAG, "wakeDisplayGroupNoUpdateLocked: eventTime=" + eventTime
+                    + ", groupId=" + groupId + ", uid=" + uid);
         }
 
         if (eventTime < mLastSleepTime || mForceSuspendActive || !mSystemReady) {
             return false;
         }
 
-        if (getWakefulnessLocked() == WAKEFULNESS_AWAKE) {
+        final int currentState = mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId);
+        if (currentState == WAKEFULNESS_AWAKE) {
             if (!mBootCompleted && sQuiescent) {
                 mDirty |= DIRTY_QUIESCENT;
                 return true;
@@ -1691,113 +1765,90 @@
             return false;
         }
 
-        Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, 0);
-
-        Trace.traceBegin(Trace.TRACE_TAG_POWER, "wakeUp");
+        Trace.traceBegin(Trace.TRACE_TAG_POWER, "powerOnDisplay");
         try {
-            Slog.i(TAG, "Waking up from "
-                    + PowerManagerInternal.wakefulnessToString(getWakefulnessLocked())
-                    + " (uid=" + reasonUid
+            Slog.i(TAG, "Powering on display group from"
+                    + PowerManagerInternal.wakefulnessToString(currentState)
+                    + " (groupId=" + groupId
+                    + ", uid=" + uid
                     + ", reason=" + PowerManager.wakeReasonToString(reason)
                     + ", details=" + details
                     + ")...");
+            Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, groupId);
 
-            mLastWakeTime = eventTime;
-            mLastWakeReason = reason;
-            setWakefulnessLocked(WAKEFULNESS_AWAKE, reason, eventTime);
-
-            mNotifier.onWakeUp(reason, details, reasonUid, opPackageName, opUid);
-            userActivityNoUpdateLocked(
-                    eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, reasonUid);
-
-            if (sQuiescent) {
-                mDirty |= DIRTY_QUIESCENT;
-            }
+            setWakefulnessLocked(groupId, WAKEFULNESS_AWAKE, eventTime, uid, reason, opUid,
+                    opPackageName, details);
+            mDisplayGroupPowerStateMapper.setLastPowerOnTimeLocked(groupId, eventTime);
+            mDirty |= DIRTY_DISPLAY_GROUP_POWER_UPDATED;
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_POWER);
         }
+
         return true;
     }
 
-    private void goToSleepInternal(long eventTime, int reason, int flags, int uid) {
+    private void sleepDisplayGroup(int groupId, long eventTime, int reason, int flags,
+            int uid) {
         synchronized (mLock) {
-            if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) {
+            if (sleepDisplayGroupNoUpdateLocked(groupId, eventTime, reason, flags, uid)) {
                 updatePowerStateLocked();
             }
         }
     }
 
-    /**
-     * Puts the system in doze.
-     *
-     * This method is called goToSleep for historical reasons but actually attempts to DOZE,
-     * and only tucks itself in to SLEEP if requested with the flag
-     * {@link PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE}.
-     */
-    @SuppressWarnings("deprecation")
-    private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {
+    private boolean sleepDisplayGroupNoUpdateLocked(int groupId, long eventTime, int reason,
+            int flags, int uid) {
         if (DEBUG_SPEW) {
-            Slog.d(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime
-                    + ", reason=" + reason + ", flags=" + flags + ", uid=" + uid);
+            Slog.d(TAG, "sleepDisplayGroupNoUpdateLocked: eventTime=" + eventTime
+                    + ", groupId=" + groupId + ", reason=" + reason + ", flags=" + flags
+                    + ", uid=" + uid);
         }
 
         if (eventTime < mLastWakeTime
-                || getWakefulnessLocked() == WAKEFULNESS_ASLEEP
-                || getWakefulnessLocked() == WAKEFULNESS_DOZING
+                || !PowerManagerInternal.isInteractive(getWakefulnessLocked())
                 || !mSystemReady
                 || !mBootCompleted) {
             return false;
         }
 
-        Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep");
+        final int wakefulness = mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId);
+        if (!PowerManagerInternal.isInteractive(wakefulness)) {
+            return false;
+        }
+
+        Trace.traceBegin(Trace.TRACE_TAG_POWER, "powerOffDisplay");
         try {
             reason = Math.min(PowerManager.GO_TO_SLEEP_REASON_MAX,
                     Math.max(reason, PowerManager.GO_TO_SLEEP_REASON_MIN));
-            Slog.i(TAG, "Going to sleep due to " + PowerManager.sleepReasonToString(reason)
-                    + " (uid " + uid + ")...");
+            Slog.i(TAG, "Powering off display group due to "
+                    + PowerManager.sleepReasonToString(reason) + " (groupId= " + groupId
+                    + ", uid= " + uid + ")...");
 
-            mLastSleepTime = eventTime;
-            mLastSleepReason = reason;
-            mSandmanSummoned = true;
-            mDozeStartInProgress = true;
-            setWakefulnessLocked(WAKEFULNESS_DOZING, reason, eventTime);
-
-            // Report the number of wake locks that will be cleared by going to sleep.
-            int numWakeLocksCleared = 0;
-            final int numWakeLocks = mWakeLocks.size();
-            for (int i = 0; i < numWakeLocks; i++) {
-                final WakeLock wakeLock = mWakeLocks.get(i);
-                switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
-                    case PowerManager.FULL_WAKE_LOCK:
-                    case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
-                    case PowerManager.SCREEN_DIM_WAKE_LOCK:
-                        numWakeLocksCleared += 1;
-                        break;
-                }
-            }
-            EventLogTags.writePowerSleepRequested(numWakeLocksCleared);
-
-            // Skip dozing if requested.
+            mDisplayGroupPowerStateMapper.setSandmanSummoned(groupId, true);
+            setWakefulnessLocked(groupId, WAKEFULNESS_DOZING, eventTime, uid, reason,
+                    /* opUid= */ 0, /* opPackageName= */ null, /* details= */ null);
             if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {
-                reallyGoToSleepNoUpdateLocked(eventTime, uid);
+                reallySleepDisplayGroupNoUpdateLocked(groupId, eventTime, uid);
             }
+            mDirty |= DIRTY_DISPLAY_GROUP_POWER_UPDATED;
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_POWER);
         }
         return true;
     }
 
-    private void napInternal(long eventTime, int uid) {
+    private void dreamDisplayGroup(int groupId, long eventTime, int uid) {
         synchronized (mLock) {
-            if (napNoUpdateLocked(eventTime, uid)) {
+            if (dreamDisplayGroupNoUpdateLocked(groupId, eventTime, uid)) {
                 updatePowerStateLocked();
             }
         }
     }
 
-    private boolean napNoUpdateLocked(long eventTime, int uid) {
+    private boolean dreamDisplayGroupNoUpdateLocked(int groupId, long eventTime, int uid) {
         if (DEBUG_SPEW) {
-            Slog.d(TAG, "napNoUpdateLocked: eventTime=" + eventTime + ", uid=" + uid);
+            Slog.d(TAG, "dreamDisplayGroupNoUpdateLocked: eventTime=" + eventTime
+                    + ", uid=" + uid);
         }
 
         if (eventTime < mLastWakeTime || getWakefulnessLocked() != WAKEFULNESS_AWAKE
@@ -1805,36 +1856,42 @@
             return false;
         }
 
-        Trace.traceBegin(Trace.TRACE_TAG_POWER, "nap");
+        Trace.traceBegin(Trace.TRACE_TAG_POWER, "napDisplayGroup");
         try {
-            Slog.i(TAG, "Nap time (uid " + uid +")...");
+            Slog.i(TAG, "Napping display group (groupId=" + groupId + ", uid=" + uid + ")...");
 
-            mSandmanSummoned = true;
-            setWakefulnessLocked(WAKEFULNESS_DREAMING, 0, eventTime);
+            mDisplayGroupPowerStateMapper.setSandmanSummoned(groupId, true);
+            setWakefulnessLocked(groupId, WAKEFULNESS_DREAMING, eventTime, uid, /* reason= */
+                    0, /* opUid= */ 0, /* opPackageName= */ null, /* details= */ null);
+            mDirty |= DIRTY_DISPLAY_GROUP_POWER_UPDATED;
+
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_POWER);
         }
         return true;
     }
 
-    // Done dozing, drop everything and go to sleep.
-    private boolean reallyGoToSleepNoUpdateLocked(long eventTime, int uid) {
+    private boolean reallySleepDisplayGroupNoUpdateLocked(int groupId, long eventTime, int uid) {
         if (DEBUG_SPEW) {
-            Slog.d(TAG, "reallyGoToSleepNoUpdateLocked: eventTime=" + eventTime
+            Slog.d(TAG, "reallySleepDisplayGroupNoUpdateLocked: eventTime=" + eventTime
                     + ", uid=" + uid);
         }
 
         if (eventTime < mLastWakeTime || getWakefulnessLocked() == WAKEFULNESS_ASLEEP
-                || !mBootCompleted || !mSystemReady) {
+                || !mBootCompleted || !mSystemReady
+                || mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId)
+                == WAKEFULNESS_ASLEEP) {
             return false;
         }
 
-        Trace.traceBegin(Trace.TRACE_TAG_POWER, "reallyGoToSleep");
+        Trace.traceBegin(Trace.TRACE_TAG_POWER, "reallySleepDisplayGroup");
         try {
-            Slog.i(TAG, "Sleeping (uid " + uid +")...");
+            Slog.i(TAG, "Sleeping display group (groupId=" + groupId + ", uid=" + uid + ")...");
 
-            setWakefulnessLocked(WAKEFULNESS_ASLEEP, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,
-                    eventTime);
+            setWakefulnessLocked(groupId, WAKEFULNESS_ASLEEP, eventTime, uid,
+                    PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,  /* opUid= */ 0,
+                    /* opPackageName= */ null, /* details= */ null);
+            mDirty |= DIRTY_DISPLAY_GROUP_POWER_UPDATED;
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_POWER);
         }
@@ -1842,8 +1899,62 @@
     }
 
     @VisibleForTesting
-    void setWakefulnessLocked(int wakefulness, int reason, long eventTime) {
-        if (getWakefulnessLocked() != wakefulness) {
+    void setWakefulnessLocked(int groupId, int wakefulness, long eventTime, int uid, int reason,
+            int opUid, String opPackageName, String details) {
+        if (mDisplayGroupPowerStateMapper.setWakefulnessLocked(groupId, wakefulness)) {
+            setGlobalWakefulnessLocked(mDisplayGroupPowerStateMapper.getGlobalWakefulnessLocked(),
+                    eventTime, reason, uid, opUid, opPackageName, details);
+        }
+    }
+
+    private void setGlobalWakefulnessLocked(int wakefulness, long eventTime, int reason, int uid,
+            int opUid, String opPackageName, String details) {
+        if (getWakefulnessLocked() == wakefulness) {
+            return;
+        }
+
+        // Phase 1: Handle pre-wakefulness change bookkeeping.
+        final String traceMethodName;
+        switch (wakefulness) {
+            case WAKEFULNESS_ASLEEP:
+                traceMethodName = "reallyGoToSleep";
+                Slog.i(TAG, "Sleeping (uid " + uid + ")...");
+                break;
+
+            case WAKEFULNESS_AWAKE:
+                traceMethodName = "wakeUp";
+                Slog.i(TAG, "Waking up from "
+                        + PowerManagerInternal.wakefulnessToString(getWakefulnessLocked())
+                        + " (uid=" + uid
+                        + ", reason=" + PowerManager.wakeReasonToString(reason)
+                        + ", details=" + details
+                        + ")...");
+                mLastWakeTime = eventTime;
+                mLastWakeReason = reason;
+                break;
+
+            case WAKEFULNESS_DREAMING:
+                traceMethodName = "nap";
+                Slog.i(TAG, "Nap time (uid " + uid + ")...");
+                break;
+
+            case WAKEFULNESS_DOZING:
+                traceMethodName = "goToSleep";
+                Slog.i(TAG, "Going to sleep due to " + PowerManager.sleepReasonToString(reason)
+                        + " (uid " + uid + ")...");
+
+                mLastSleepTime = eventTime;
+                mLastSleepReason = reason;
+                mDozeStartInProgress = true;
+                break;
+
+            default:
+                throw new IllegalArgumentException("Unexpected wakefulness: " + wakefulness);
+        }
+
+        Trace.traceBegin(Trace.TRACE_TAG_POWER, traceMethodName);
+        try {
+            // Phase 2: Handle wakefulness change and bookkeeping.
             // Under lock, invalidate before set ensures caches won't return stale values.
             mInjector.invalidateIsInteractiveCaches();
             mWakefulnessRaw = wakefulness;
@@ -1857,6 +1968,37 @@
                 mNotifier.onWakefulnessChangeStarted(wakefulness, reason, eventTime);
             }
             mAttentionDetector.onWakefulnessChangeStarted(wakefulness);
+
+            // Phase 3: Handle post-wakefulness change bookkeeping.
+            switch (wakefulness) {
+                case WAKEFULNESS_AWAKE:
+                    mNotifier.onWakeUp(reason, details, uid, opPackageName, opUid);
+                    userActivityNoUpdateLocked(
+                            eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, uid);
+                    if (sQuiescent) {
+                        mDirty |= DIRTY_QUIESCENT;
+                    }
+                    break;
+
+                case WAKEFULNESS_DOZING:
+                    // Report the number of wake locks that will be cleared by going to sleep.
+                    int numWakeLocksCleared = 0;
+                    final int numWakeLocks = mWakeLocks.size();
+                    for (int i = 0; i < numWakeLocks; i++) {
+                        final WakeLock wakeLock = mWakeLocks.get(i);
+                        switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
+                            case PowerManager.FULL_WAKE_LOCK:
+                            case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
+                            case PowerManager.SCREEN_DIM_WAKE_LOCK:
+                                numWakeLocksCleared += 1;
+                                break;
+                        }
+                    }
+                    EventLogTags.writePowerSleepRequested(numWakeLocksCleared);
+                    break;
+            }
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_POWER);
         }
     }
 
@@ -1879,7 +2021,7 @@
     }
 
     private void finishWakefulnessChangeIfNeededLocked() {
-        if (mWakefulnessChanging && mDisplayReady) {
+        if (mWakefulnessChanging && mDisplayGroupPowerStateMapper.areAllDisplaysReadyLocked()) {
             if (getWakefulnessLocked() == WAKEFULNESS_DOZING
                     && (mWakeLockSummary & WAKE_LOCK_DOZE) == 0) {
                 return; // wait until dream has enabled dozing
@@ -1891,13 +2033,6 @@
                     || getWakefulnessLocked() == WAKEFULNESS_ASLEEP) {
                 logSleepTimeoutRecapturedLocked();
             }
-            if (getWakefulnessLocked() == WAKEFULNESS_AWAKE) {
-                Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, 0);
-                final int latencyMs = (int) (mClock.uptimeMillis() - mLastWakeTime);
-                if (latencyMs >= SCREEN_ON_LATENCY_WARNING_MS) {
-                    Slog.w(TAG, "Screen on took " + latencyMs + " ms");
-                }
-            }
             mWakefulnessChanging = false;
             mNotifier.onWakefulnessChangeFinished();
         }
@@ -1996,7 +2131,6 @@
         if ((dirty & DIRTY_BATTERY_STATE) != 0) {
             final boolean wasPowered = mIsPowered;
             final int oldPlugType = mPlugType;
-            final boolean oldLevelLow = mBatteryLevelLow;
             mIsPowered = mBatteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
             mPlugType = mBatteryManagerInternal.getPlugType();
             mBatteryLevel = mBatteryManagerInternal.getBatteryLevel();
@@ -2025,7 +2159,8 @@
                 final long now = mClock.uptimeMillis();
                 if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,
                         dockedOnWirelessCharger)) {
-                    wakeUpNoUpdateLocked(now, PowerManager.WAKE_REASON_PLUGGED_IN,
+                    wakeDisplayGroupNoUpdateLocked(Display.DEFAULT_DISPLAY_GROUP, now,
+                            PowerManager.WAKE_REASON_PLUGGED_IN,
                             "android.server.power:PLUGGED:" + mIsPowered, Process.SYSTEM_UID,
                             mContext.getOpPackageName(), Process.SYSTEM_UID);
                 }
@@ -2283,9 +2418,11 @@
                     || getWakefulnessLocked() == WAKEFULNESS_DOZING) {
                 final long attentiveTimeout = getAttentiveTimeoutLocked();
                 final long sleepTimeout = getSleepTimeoutLocked(attentiveTimeout);
-                final long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout,
+                long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout,
                         attentiveTimeout);
                 final long screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
+                screenOffTimeout =
+                        getScreenOffTimeoutWithFaceDownLocked(screenOffTimeout, screenDimDuration);
                 final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager;
                 final long nextProfileTimeout = getNextProfileTimeoutLocked(now);
 
@@ -2307,7 +2444,8 @@
                     nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;
                     if (now < nextTimeout) {
                         final DisplayPowerRequest displayPowerRequest =
-                                mDisplayPowerRequestMapper.get(Display.DEFAULT_DISPLAY);
+                                mDisplayGroupPowerStateMapper.getPowerRequestLocked(
+                                        Display.DEFAULT_DISPLAY_GROUP);
                         if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT
                                 || displayPowerRequest.policy == DisplayPowerRequest.POLICY_VR) {
                             mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
@@ -2541,6 +2679,16 @@
                 (long)(screenOffTimeout * mMaximumScreenDimRatioConfig));
     }
 
+    private long getScreenOffTimeoutWithFaceDownLocked(
+            long screenOffTimeout, long screenDimDuration) {
+        // If face down, we decrease the timeout to equal the dim duration so that the
+        // device will go into a dim state.
+        if (mIsFaceDown) {
+            return Math.min(screenDimDuration, screenOffTimeout);
+        }
+        return screenOffTimeout;
+    }
+
     /**
      * Updates the wakefulness of the device.
      *
@@ -2562,13 +2710,23 @@
                 }
                 final long time = mClock.uptimeMillis();
                 if (isAttentiveTimeoutExpired(time)) {
-                    changed = goToSleepNoUpdateLocked(time, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,
-                            PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, Process.SYSTEM_UID);
+                    // TODO (b/175764389): Support per-display timeouts.
+                    for (int id : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
+                        changed = sleepDisplayGroupNoUpdateLocked(id, time,
+                                PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,
+                                PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, Process.SYSTEM_UID);
+                    }
                 } else if (shouldNapAtBedTimeLocked()) {
-                    changed = napNoUpdateLocked(time, Process.SYSTEM_UID);
+                    // TODO (b/175764389): Support per-display timeouts.
+                    for (int id : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
+                        changed = dreamDisplayGroupNoUpdateLocked(id, time, Process.SYSTEM_UID);
+                    }
                 } else {
-                    changed = goToSleepNoUpdateLocked(time,
-                            PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);
+                    // TODO (b/175764389): Support per-display timeouts.
+                    for (int id : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
+                        changed = sleepDisplayGroupNoUpdateLocked(id, time,
+                                PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);
+                    }
                 }
             }
         }
@@ -2643,6 +2801,7 @@
     private void updateDreamLocked(int dirty, boolean displayBecameReady) {
         if ((dirty & (DIRTY_WAKEFULNESS
                 | DIRTY_USER_ACTIVITY
+                | DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED
                 | DIRTY_ATTENTIVE
                 | DIRTY_WAKE_LOCKS
                 | DIRTY_BOOT_COMPLETED
@@ -2651,7 +2810,7 @@
                 | DIRTY_STAY_ON
                 | DIRTY_PROXIMITY_POSITIVE
                 | DIRTY_BATTERY_STATE)) != 0 || displayBecameReady) {
-            if (mDisplayReady) {
+            if (mDisplayGroupPowerStateMapper.areAllDisplaysReadyLocked()) {
                 scheduleSandmanLocked();
             }
         }
@@ -2666,6 +2825,14 @@
         }
     }
 
+    private void handleSandman() {
+        for (int id : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
+            if (mDisplayGroupPowerStateMapper.isSandmanSupported(id)) {
+                handleSandman(id);
+            }
+        }
+    }
+
     /**
      * Called when the device enters or exits a dreaming or dozing state.
      *
@@ -2673,16 +2840,19 @@
      * the dream and we don't want to hold our lock while doing so.  There is a risk that
      * the device will wake or go to sleep in the meantime so we have to handle that case.
      */
-    private void handleSandman() { // runs on handler thread
+    private void handleSandman(int groupId) { // runs on handler thread
         // Handle preconditions.
         final boolean startDreaming;
         final int wakefulness;
         synchronized (mLock) {
             mSandmanScheduled = false;
+            // TODO (b/175764708): Support per-display doze.
             wakefulness = getWakefulnessLocked();
-            if (mSandmanSummoned && mDisplayReady) {
-                startDreaming = canDreamLocked() || canDozeLocked();
-                mSandmanSummoned = false;
+            if ((wakefulness == WAKEFULNESS_DREAMING || wakefulness == WAKEFULNESS_DOZING) &&
+                    mDisplayGroupPowerStateMapper.isSandmanSummoned(groupId)
+                    && mDisplayGroupPowerStateMapper.isReady(groupId)) {
+                startDreaming = canDreamLocked(groupId) || canDozeLocked();
+                mDisplayGroupPowerStateMapper.setSandmanSummoned(groupId, false);
             } else {
                 startDreaming = false;
             }
@@ -2721,14 +2891,15 @@
 
             // If preconditions changed, wait for the next iteration to determine
             // whether the dream should continue (or be restarted).
-            if (mSandmanSummoned || getWakefulnessLocked() != wakefulness) {
+            if (mDisplayGroupPowerStateMapper.isSandmanSummoned(groupId)
+                    || mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId) != wakefulness) {
                 return; // wait for next cycle
             }
 
             // Determine whether the dream should continue.
             long now = mClock.uptimeMillis();
             if (wakefulness == WAKEFULNESS_DREAMING) {
-                if (isDreaming && canDreamLocked()) {
+                if (isDreaming && canDreamLocked(groupId)) {
                     if (mDreamsBatteryLevelDrainCutoffConfig >= 0
                             && mBatteryLevel < mBatteryLevelWhenDreamStarted
                                     - mDreamsBatteryLevelDrainCutoffConfig
@@ -2748,16 +2919,13 @@
 
                 // Dream has ended or will be stopped.  Update the power state.
                 if (isItBedTimeYetLocked()) {
-                    int flags = 0;
-                    if (isAttentiveTimeoutExpired(now)) {
-                        flags |= PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE;
-                    }
-                    goToSleepNoUpdateLocked(now, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, flags,
-                            Process.SYSTEM_UID);
+                    final int flags = isAttentiveTimeoutExpired(now)
+                            ? PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE : 0;
+                    sleepDisplayGroupNoUpdateLocked(groupId, now,
+                            PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, flags, Process.SYSTEM_UID);
                     updatePowerStateLocked();
                 } else {
-                    wakeUpNoUpdateLocked(now,
-                            PowerManager.WAKE_REASON_UNKNOWN,
+                    wakeDisplayGroupNoUpdateLocked(groupId, now, PowerManager.WAKE_REASON_UNKNOWN,
                             "android.server.power:DREAM_FINISHED", Process.SYSTEM_UID,
                             mContext.getOpPackageName(), Process.SYSTEM_UID);
                     updatePowerStateLocked();
@@ -2768,7 +2936,7 @@
                 }
 
                 // Doze has ended or will be stopped.  Update the power state.
-                reallyGoToSleepNoUpdateLocked(now, Process.SYSTEM_UID);
+                reallySleepDisplayGroupNoUpdateLocked(groupId, now, Process.SYSTEM_UID);
                 updatePowerStateLocked();
             }
         }
@@ -2780,11 +2948,11 @@
     }
 
     /**
-     * Returns true if the device is allowed to dream in its current state.
+     * Returns true if the {@code groupId} is allowed to dream in its current state.
      */
-    private boolean canDreamLocked() {
+    private boolean canDreamLocked(int groupId) {
         final DisplayPowerRequest displayPowerRequest =
-                mDisplayPowerRequestMapper.get(Display.DEFAULT_DISPLAY);
+                mDisplayGroupPowerStateMapper.getPowerRequestLocked(groupId);
         if (getWakefulnessLocked() != WAKEFULNESS_DREAMING
                 || !mDreamsSupportedConfig
                 || !mDreamsEnabledSetting
@@ -2822,95 +2990,117 @@
 
     /**
      * Updates the display power state asynchronously.
-     * When the update is finished, mDisplayReady will be set to true.  The display
-     * controller posts a message to tell us when the actual display power state
+     * When the update is finished, the ready state of the displays will be updated.  The display
+     * controllers post a message to tell us when the actual display power state
      * has been updated so we come back here to double-check and finish up.
      *
      * This function recalculates the display power state each time.
      *
-     * @return true if the display became ready.
+     * @return {@code true} if all displays became ready; {@code false} otherwise
      */
     private boolean updateDisplayPowerStateLocked(int dirty) {
-        final boolean oldDisplayReady = mDisplayReady;
+        final boolean oldDisplayReady = mDisplayGroupPowerStateMapper.areAllDisplaysReadyLocked();
         if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
                 | DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
                 | DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST | DIRTY_VR_MODE_CHANGED |
-                DIRTY_QUIESCENT)) != 0) {
+                DIRTY_QUIESCENT | DIRTY_DISPLAY_GROUP_POWER_UPDATED)) != 0) {
             if ((dirty & DIRTY_QUIESCENT) != 0) {
-                if (mDisplayReady) {
+                if (mDisplayGroupPowerStateMapper.areAllDisplaysReadyLocked()) {
                     sQuiescent = false;
                 } else {
                     mDirty |= DIRTY_QUIESCENT;
                 }
             }
 
-            final DisplayPowerRequest displayPowerRequest = mDisplayPowerRequestMapper.get(
-                    Display.DEFAULT_DISPLAY);
-            displayPowerRequest.policy = getDesiredScreenPolicyLocked();
+            for (final int groupId : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
+                final DisplayPowerRequest displayPowerRequest =
+                        mDisplayGroupPowerStateMapper.getPowerRequestLocked(groupId);
+                displayPowerRequest.policy = getDesiredScreenPolicyLocked(groupId);
 
-            // Determine appropriate screen brightness and auto-brightness adjustments.
-            final boolean autoBrightness;
-            final float screenBrightnessOverride;
-            if (!mBootCompleted) {
-                // Keep the brightness steady during boot. This requires the
-                // bootloader brightness and the default brightness to be identical.
-                autoBrightness = false;
-                screenBrightnessOverride = mScreenBrightnessDefault;
-            } else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
-                autoBrightness = false;
-                screenBrightnessOverride = mScreenBrightnessOverrideFromWindowManager;
-            } else {
-                autoBrightness = (mScreenBrightnessModeSetting ==
-                        Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
-                screenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;
-            }
+                // Determine appropriate screen brightness and auto-brightness adjustments.
+                final boolean autoBrightness;
+                final float screenBrightnessOverride;
+                if (!mBootCompleted) {
+                    // Keep the brightness steady during boot. This requires the
+                    // bootloader brightness and the default brightness to be identical.
+                    autoBrightness = false;
+                    screenBrightnessOverride = mScreenBrightnessDefault;
+                } else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
+                    autoBrightness = false;
+                    screenBrightnessOverride = mScreenBrightnessOverrideFromWindowManager;
+                } else {
+                    autoBrightness = (mScreenBrightnessModeSetting
+                            == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
+                    screenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+                }
 
-            // Update display power request.
-            displayPowerRequest.screenBrightnessOverride = screenBrightnessOverride;
-            displayPowerRequest.useAutoBrightness = autoBrightness;
-            displayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
-            displayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();
+                // Update display power request.
+                displayPowerRequest.screenBrightnessOverride = screenBrightnessOverride;
+                displayPowerRequest.useAutoBrightness = autoBrightness;
+                displayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
+                displayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();
 
-            updatePowerRequestFromBatterySaverPolicy(displayPowerRequest);
+                updatePowerRequestFromBatterySaverPolicy(displayPowerRequest);
 
-            if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
-                displayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
-                if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0
-                        && !mDrawWakeLockOverrideFromSidekick) {
-                    if (displayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND) {
-                        displayPowerRequest.dozeScreenState = Display.STATE_DOZE;
+                if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
+                    displayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
+                    if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0
+                            && !mDrawWakeLockOverrideFromSidekick) {
+                        if (displayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND) {
+                            displayPowerRequest.dozeScreenState = Display.STATE_DOZE;
+                        }
+                        if (displayPowerRequest.dozeScreenState == Display.STATE_ON_SUSPEND) {
+                            displayPowerRequest.dozeScreenState = Display.STATE_ON;
+                        }
                     }
-                    if (displayPowerRequest.dozeScreenState == Display.STATE_ON_SUSPEND) {
-                        displayPowerRequest.dozeScreenState = Display.STATE_ON;
+                    displayPowerRequest.dozeScreenBrightness =
+                            mDozeScreenBrightnessOverrideFromDreamManagerFloat;
+                } else {
+                    displayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN;
+                    displayPowerRequest.dozeScreenBrightness =
+                            PowerManager.BRIGHTNESS_INVALID_FLOAT;
+                }
+
+                final boolean ready = mDisplayManagerInternal.requestPowerState(groupId,
+                        displayPowerRequest, mRequestWaitForNegativeProximity);
+
+                if (DEBUG_SPEW) {
+                    Slog.d(TAG, "updateDisplayPowerStateLocked: displayReady=" + ready
+                            + ", groupId=" + groupId
+                            + ", policy=" + policyToString(displayPowerRequest.policy)
+                            + ", mWakefulness="
+                            + PowerManagerInternal.wakefulnessToString(
+                            mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId))
+                            + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)
+                            + ", mUserActivitySummary=0x" + Integer.toHexString(
+                            mUserActivitySummary)
+                            + ", mBootCompleted=" + mBootCompleted
+                            + ", screenBrightnessOverride="
+                            + displayPowerRequest.screenBrightnessOverride
+                            + ", useAutoBrightness=" + displayPowerRequest.useAutoBrightness
+                            + ", mScreenBrightnessBoostInProgress="
+                            + mScreenBrightnessBoostInProgress
+                            + ", mIsVrModeEnabled= " + mIsVrModeEnabled
+                            + ", sQuiescent=" + sQuiescent);
+                }
+
+                final boolean displayReadyStateChanged =
+                        mDisplayGroupPowerStateMapper.setDisplayGroupReadyLocked(groupId, ready);
+                if (ready && displayReadyStateChanged
+                        && mDisplayGroupPowerStateMapper.getWakefulnessLocked(
+                        groupId) == WAKEFULNESS_AWAKE) {
+                    Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, groupId);
+                    final int latencyMs = (int) (mClock.uptimeMillis()
+                            - mDisplayGroupPowerStateMapper.getLastPowerOnTimeLocked(groupId));
+                    if (latencyMs >= SCREEN_ON_LATENCY_WARNING_MS) {
+                        Slog.w(TAG, "Screen on took " + latencyMs + " ms");
                     }
                 }
-                displayPowerRequest.dozeScreenBrightness =
-                        mDozeScreenBrightnessOverrideFromDreamManagerFloat;
-            } else {
-                displayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN;
-                displayPowerRequest.dozeScreenBrightness =
-                        PowerManager.BRIGHTNESS_INVALID_FLOAT;
             }
-
-            mDisplayReady = mDisplayManagerInternal.requestPowerState(Display.DEFAULT_DISPLAY_GROUP,
-                    displayPowerRequest, mRequestWaitForNegativeProximity);
             mRequestWaitForNegativeProximity = false;
-
-            if (DEBUG_SPEW) {
-                Slog.d(TAG, "updateDisplayPowerStateLocked: mDisplayReady=" + mDisplayReady
-                        + ", policy=" + displayPowerRequest.policy
-                        + ", mWakefulness=" + getWakefulnessLocked()
-                        + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)
-                        + ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
-                        + ", mBootCompleted=" + mBootCompleted
-                        + ", screenBrightnessOverride=" + screenBrightnessOverride
-                        + ", useAutoBrightness=" + autoBrightness
-                        + ", mScreenBrightnessBoostInProgress=" + mScreenBrightnessBoostInProgress
-                        + ", mIsVrModeEnabled= " + mIsVrModeEnabled
-                        + ", sQuiescent=" + sQuiescent);
-            }
         }
-        return mDisplayReady && !oldDisplayReady;
+
+        return mDisplayGroupPowerStateMapper.areAllDisplaysReadyLocked() && !oldDisplayReady;
     }
 
     private void updateScreenBrightnessBoostLocked(int dirty) {
@@ -2944,12 +3134,11 @@
     }
 
     @VisibleForTesting
-    int getDesiredScreenPolicyLocked() {
-        if (getWakefulnessLocked() == WAKEFULNESS_ASLEEP || sQuiescent) {
+    int getDesiredScreenPolicyLocked(int groupId) {
+        final int wakefulness = mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId);
+        if (wakefulness == WAKEFULNESS_ASLEEP || sQuiescent) {
             return DisplayPowerRequest.POLICY_OFF;
-        }
-
-        if (getWakefulnessLocked() == WAKEFULNESS_DOZING) {
+        } else if (wakefulness == WAKEFULNESS_DOZING) {
             if ((mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {
                 return DisplayPowerRequest.POLICY_DOZE;
             }
@@ -2979,7 +3168,6 @@
 
     private final DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks =
             new DisplayManagerInternal.DisplayPowerCallbacks() {
-        private int mDisplayState = Display.STATE_UNKNOWN;
 
         @Override
         public void onStateChanged() {
@@ -3010,29 +3198,25 @@
         }
 
         @Override
-        public void onDisplayStateChange(int state) {
+        public void onDisplayStateChange(boolean allInactive, boolean allOff) {
             // This method is only needed to support legacy display blanking behavior
             // where the display's power state is coupled to suspend or to the power HAL.
             // The order of operations matters here.
             synchronized (mLock) {
-                if (mDisplayState != state) {
-                    mDisplayState = state;
-                    setPowerModeInternal(MODE_DISPLAY_INACTIVE,
-                            !Display.isActiveState(state));
-                    if (state == Display.STATE_OFF) {
-                        if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
-                            setHalInteractiveModeLocked(false);
-                        }
-                        if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
-                            setHalAutoSuspendModeLocked(true);
-                        }
-                    } else {
-                        if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
-                            setHalAutoSuspendModeLocked(false);
-                        }
-                        if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
-                            setHalInteractiveModeLocked(true);
-                        }
+                setPowerModeInternal(MODE_DISPLAY_INACTIVE, allInactive);
+                if (allOff) {
+                    if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
+                        setHalInteractiveModeLocked(false);
+                    }
+                    if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
+                        setHalAutoSuspendModeLocked(true);
+                    }
+                } else {
+                    if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
+                        setHalAutoSuspendModeLocked(false);
+                    }
+                    if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
+                        setHalInteractiveModeLocked(true);
                     }
                 }
             }
@@ -3047,13 +3231,6 @@
         public void releaseSuspendBlocker() {
             mDisplaySuspendBlocker.release();
         }
-
-        @Override
-        public String toString() {
-            synchronized (this) {
-                return "state=" + Display.stateToString(mDisplayState);
-            }
-        }
     };
 
     private boolean shouldUseProximitySensorLocked() {
@@ -3069,9 +3246,11 @@
         final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);
         final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked();
         final boolean autoSuspend = !needDisplaySuspendBlocker;
-        final DisplayPowerRequest displayPowerRequest = mDisplayPowerRequestMapper.get(
-                Display.DEFAULT_DISPLAY);
-        final boolean interactive = displayPowerRequest.isBrightOrDim();
+        final int[] groupIds = mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked();
+        boolean interactive = false;
+        for (int id : groupIds) {
+            interactive |= mDisplayGroupPowerStateMapper.getPowerRequestLocked(id).isBrightOrDim();
+        }
 
         // Disable auto-suspend if needed.
         // FIXME We should consider just leaving auto-suspend enabled forever since
@@ -3101,7 +3280,7 @@
             // until the display is actually ready so that all transitions have
             // completed.  This is probably a good sign that things have gotten
             // too tangled over here...
-            if (interactive || mDisplayReady) {
+            if (interactive || mDisplayGroupPowerStateMapper.areAllDisplaysReadyLocked()) {
                 setHalInteractiveModeLocked(interactive);
             }
         }
@@ -3127,29 +3306,10 @@
      * We do so if the screen is on or is in transition between states.
      */
     private boolean needDisplaySuspendBlockerLocked() {
-        if (!mDisplayReady) {
+        if (!mDisplayGroupPowerStateMapper.areAllDisplaysReadyLocked()) {
             return true;
         }
-        final DisplayPowerRequest displayPowerRequest = mDisplayPowerRequestMapper.get(
-                Display.DEFAULT_DISPLAY);
-        if (displayPowerRequest.isBrightOrDim()) {
-            // If we asked for the screen to be on but it is off due to the proximity
-            // sensor then we may suspend but only if the configuration allows it.
-            // On some hardware it may not be safe to suspend because the proximity
-            // sensor may not be correctly configured as a wake-up source.
-            if (!displayPowerRequest.useProximitySensor || !mProximityPositive
-                    || !mSuspendWhenScreenOffDueToProximityConfig) {
-                return true;
-            }
-        }
 
-        if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE
-                && displayPowerRequest.dozeScreenState == Display.STATE_ON) {
-            // Although we are in DOZE and would normally allow the device to suspend,
-            // the doze service has explicitly requested the display to remain in the ON
-            // state which means we should hold the display suspend blocker.
-            return true;
-        }
         if (mScreenBrightnessBoostInProgress) {
             return true;
         }
@@ -3163,6 +3323,30 @@
             return true;
         }
 
+        final int[] groupIds = mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked();
+        for (int id : groupIds) {
+            final DisplayPowerRequest displayPowerRequest =
+                    mDisplayGroupPowerStateMapper.getPowerRequestLocked(id);
+            if (displayPowerRequest.isBrightOrDim()) {
+                // If we asked for the screen to be on but it is off due to the proximity
+                // sensor then we may suspend but only if the configuration allows it.
+                // On some hardware it may not be safe to suspend because the proximity
+                // sensor may not be correctly configured as a wake-up source.
+                if (!displayPowerRequest.useProximitySensor || !mProximityPositive
+                        || !mSuspendWhenScreenOffDueToProximityConfig) {
+                    return true;
+                }
+            }
+
+            if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE
+                    && displayPowerRequest.dozeScreenState == Display.STATE_ON) {
+                // Although we are in DOZE and would normally allow the device to suspend,
+                // the doze service has explicitly requested the display to remain in the ON
+                // state which means we should hold the display suspend blocker.
+                return true;
+            }
+        }
+
         // Let the system suspend if the screen is off or dozing.
         return false;
     }
@@ -3696,9 +3880,15 @@
             synchronized (mLock) {
                 mForceSuspendActive = true;
                 // Place the system in an non-interactive state
-                goToSleepInternal(mClock.uptimeMillis(),
-                        PowerManager.GO_TO_SLEEP_REASON_FORCE_SUSPEND,
-                        PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, uid);
+                boolean updatePowerState = false;
+                for (int id : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
+                    updatePowerState |= sleepDisplayGroupNoUpdateLocked(id, mClock.uptimeMillis(),
+                            PowerManager.GO_TO_SLEEP_REASON_FORCE_SUSPEND,
+                            PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, uid);
+                }
+                if (updatePowerState) {
+                    updatePowerStateLocked();
+                }
 
                 // Disable all the partial wake locks as well
                 updateWakeLockDisabledStatesLocked();
@@ -3838,7 +4028,6 @@
             pw.println("  mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary));
             pw.println("  mRequestWaitForNegativeProximity=" + mRequestWaitForNegativeProximity);
             pw.println("  mSandmanScheduled=" + mSandmanScheduled);
-            pw.println("  mSandmanSummoned=" + mSandmanSummoned);
             pw.println("  mBatteryLevelLow=" + mBatteryLevelLow);
             pw.println("  mLightDeviceIdleMode=" + mLightDeviceIdleMode);
             pw.println("  mDeviceIdleMode=" + mDeviceIdleMode);
@@ -3856,9 +4045,10 @@
                     + TimeUtils.formatUptime(mLastScreenBrightnessBoostTime));
             pw.println("  mScreenBrightnessBoostInProgress="
                     + mScreenBrightnessBoostInProgress);
-            pw.println("  mDisplayReady=" + mDisplayReady);
             pw.println("  mHoldingWakeLockSuspendBlocker=" + mHoldingWakeLockSuspendBlocker);
             pw.println("  mHoldingDisplaySuspendBlocker=" + mHoldingDisplaySuspendBlocker);
+            pw.println("  mLastFlipTime=" + mLastFlipTime);
+            pw.println("  mIsFaceDown=" + mIsFaceDown);
 
             pw.println();
             pw.println("Settings and Configuration:");
@@ -4003,6 +4193,8 @@
             mNotifier.dump(pw);
         }
 
+        mFaceDownDetector.dump(pw);
+
         mAmbientDisplaySuppressionController.dump(pw);
     }
 
@@ -4091,7 +4283,6 @@
                     PowerManagerServiceDumpProto.IS_REQUEST_WAIT_FOR_NEGATIVE_PROXIMITY,
                     mRequestWaitForNegativeProximity);
             proto.write(PowerManagerServiceDumpProto.IS_SANDMAN_SCHEDULED, mSandmanScheduled);
-            proto.write(PowerManagerServiceDumpProto.IS_SANDMAN_SUMMONED, mSandmanSummoned);
             proto.write(PowerManagerServiceDumpProto.IS_BATTERY_LEVEL_LOW, mBatteryLevelLow);
             proto.write(PowerManagerServiceDumpProto.IS_LIGHT_DEVICE_IDLE_MODE, mLightDeviceIdleMode);
             proto.write(PowerManagerServiceDumpProto.IS_DEVICE_IDLE_MODE, mDeviceIdleMode);
@@ -4118,7 +4309,6 @@
             proto.write(
                     PowerManagerServiceDumpProto.IS_SCREEN_BRIGHTNESS_BOOST_IN_PROGRESS,
                     mScreenBrightnessBoostInProgress);
-            proto.write(PowerManagerServiceDumpProto.IS_DISPLAY_READY, mDisplayReady);
             proto.write(
                     PowerManagerServiceDumpProto.IS_HOLDING_WAKE_LOCK_SUSPEND_BLOCKER,
                     mHoldingWakeLockSuspendBlocker);
@@ -4932,7 +5122,8 @@
             final int uid = Binder.getCallingUid();
             final long ident = Binder.clearCallingIdentity();
             try {
-                wakeUpInternal(eventTime, reason, details, uid, opPackageName, uid);
+                wakeDisplayGroup(Display.DEFAULT_DISPLAY_GROUP, eventTime, reason, details, uid,
+                        opPackageName, uid);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -4950,7 +5141,7 @@
             final int uid = Binder.getCallingUid();
             final long ident = Binder.clearCallingIdentity();
             try {
-                goToSleepInternal(eventTime, reason, flags, uid);
+                sleepDisplayGroup(Display.DEFAULT_DISPLAY_GROUP, eventTime, reason, flags, uid);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -4968,7 +5159,7 @@
             final int uid = Binder.getCallingUid();
             final long ident = Binder.clearCallingIdentity();
             try {
-                napInternal(eventTime, uid);
+                dreamDisplayGroup(Display.DEFAULT_DISPLAY_GROUP, eventTime, uid);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -5121,7 +5312,6 @@
 
         @Override // Binder call
         public int getPowerSaveModeTrigger() {
-            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.POWER_SAVER, null);
             final long ident = Binder.clearCallingIdentity();
             try {
                 return Settings.Global.getInt(mContext.getContentResolver(),
@@ -5631,7 +5821,8 @@
             // also tells us that we're not already ignoring the proximity sensor.
 
             final DisplayPowerRequest displayPowerRequest =
-                    mDisplayPowerRequestMapper.get(Display.DEFAULT_DISPLAY);
+                    mDisplayGroupPowerStateMapper.getPowerRequestLocked(
+                            Display.DEFAULT_DISPLAY_GROUP);
             if (displayPowerRequest.useProximitySensor && mProximityPositive) {
                 mDisplayManagerInternal.ignoreProximitySensorUntilChanged();
                 return true;
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsHALWrapper.java b/services/core/java/com/android/server/powerstats/PowerStatsHALWrapper.java
index 9a91848..f382d10 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsHALWrapper.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsHALWrapper.java
@@ -16,6 +16,7 @@
 
 package com.android.server.powerstats;
 
+import android.annotation.Nullable;
 import android.hardware.power.stats.Channel;
 import android.hardware.power.stats.EnergyMeasurement;
 import android.hardware.power.stats.IPowerStats;
@@ -51,6 +52,7 @@
          *
          * @return List of information on each PowerEntity.
          */
+        @Nullable
         android.hardware.power.stats.PowerEntity[] getPowerEntityInfo();
 
         /**
@@ -70,6 +72,7 @@
          *
          * @return StateResidency since boot for each requested PowerEntity
          */
+        @Nullable
         android.hardware.power.stats.StateResidencyResult[] getStateResidency(int[] powerEntityIds);
 
         /**
@@ -81,6 +84,7 @@
          *
          * @return List of EnergyConsumers all available energy consumers.
          */
+        @Nullable
         android.hardware.power.stats.EnergyConsumer[] getEnergyConsumerInfo();
 
         /**
@@ -96,6 +100,7 @@
          * @return List of EnergyConsumerResult objects containing energy consumer results for all
          *         available energy consumers (power models).
          */
+        @Nullable
         android.hardware.power.stats.EnergyConsumerResult[] getEnergyConsumed(
                 int[] energyConsumerIds);
 
@@ -105,6 +110,7 @@
          * @return List of Channel objects containing channel info for all available energy
          *         meters.
          */
+        @Nullable
         android.hardware.power.stats.Channel[] getEnergyMeterInfo();
 
         /**
@@ -120,6 +126,7 @@
          * @return List of EnergyMeasurement objects containing energy measurements for all
          *         available energy meters.
          */
+        @Nullable
         android.hardware.power.stats.EnergyMeasurement[] readEnergyMeter(int[] channelIds);
 
         /**
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsLogger.java b/services/core/java/com/android/server/powerstats/PowerStatsLogger.java
index c4f29ea..ef0079e 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsLogger.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsLogger.java
@@ -16,6 +16,8 @@
 
 package com.android.server.powerstats;
 
+import static java.lang.System.currentTimeMillis;
+
 import android.content.Context;
 import android.hardware.power.stats.Channel;
 import android.hardware.power.stats.EnergyConsumer;
@@ -26,11 +28,14 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.SystemClock;
 import android.util.AtomicFile;
 import android.util.Slog;
 import android.util.proto.ProtoInputStream;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import com.android.server.powerstats.PowerStatsHALWrapper.IPowerStatsHALWrapper;
 import com.android.server.powerstats.ProtoStreamUtils.ChannelUtils;
 import com.android.server.powerstats.ProtoStreamUtils.EnergyConsumerResultUtils;
@@ -61,6 +66,8 @@
     protected static final int MSG_LOG_TO_DATA_STORAGE_LOW_FREQUENCY = 1;
     protected static final int MSG_LOG_TO_DATA_STORAGE_HIGH_FREQUENCY = 2;
 
+    // TODO(b/181240441): Add a listener to update the Wall clock baseline when changed
+    private final long mStartWallTime;
     private final PowerStatsDataStorage mPowerStatsMeterStorage;
     private final PowerStatsDataStorage mPowerStatsModelStorage;
     private final PowerStatsDataStorage mPowerStatsResidencyStorage;
@@ -79,6 +86,8 @@
                 // Log power meter data.
                 EnergyMeasurement[] energyMeasurements =
                     mPowerStatsHALWrapper.readEnergyMeter(new int[0]);
+                EnergyMeasurementUtils.adjustTimeSinceBootToEpoch(energyMeasurements,
+                        mStartWallTime);
                 mPowerStatsMeterStorage.write(
                         EnergyMeasurementUtils.getProtoBytes(energyMeasurements));
                 if (DEBUG) EnergyMeasurementUtils.print(energyMeasurements);
@@ -86,6 +95,8 @@
                 // Log power model data without attribution data.
                 EnergyConsumerResult[] ecrNoAttribution =
                     mPowerStatsHALWrapper.getEnergyConsumed(new int[0]);
+                EnergyConsumerResultUtils.adjustTimeSinceBootToEpoch(ecrNoAttribution,
+                        mStartWallTime);
                 mPowerStatsModelStorage.write(
                         EnergyConsumerResultUtils.getProtoBytes(ecrNoAttribution, false));
                 if (DEBUG) EnergyConsumerResultUtils.print(ecrNoAttribution);
@@ -97,6 +108,8 @@
                 // Log power model data with attribution data.
                 EnergyConsumerResult[] ecrAttribution =
                     mPowerStatsHALWrapper.getEnergyConsumed(new int[0]);
+                EnergyConsumerResultUtils.adjustTimeSinceBootToEpoch(ecrAttribution,
+                        mStartWallTime);
                 mPowerStatsModelStorage.write(
                         EnergyConsumerResultUtils.getProtoBytes(ecrAttribution, true));
                 if (DEBUG) EnergyConsumerResultUtils.print(ecrAttribution);
@@ -108,6 +121,8 @@
                 // Log state residency data.
                 StateResidencyResult[] stateResidencyResults =
                     mPowerStatsHALWrapper.getStateResidency(new int[0]);
+                StateResidencyResultUtils.adjustTimeSinceBootToEpoch(stateResidencyResults,
+                        mStartWallTime);
                 mPowerStatsResidencyStorage.write(
                         StateResidencyResultUtils.getProtoBytes(stateResidencyResults));
                 if (DEBUG) StateResidencyResultUtils.print(stateResidencyResults);
@@ -293,12 +308,19 @@
         return mDeleteResidencyDataOnBoot;
     }
 
+    @VisibleForTesting
+    public long getStartWallTime() {
+        return mStartWallTime;
+    }
+
     public PowerStatsLogger(Context context, File dataStoragePath,
             String meterFilename, String meterCacheFilename,
             String modelFilename, String modelCacheFilename,
             String residencyFilename, String residencyCacheFilename,
             IPowerStatsHALWrapper powerStatsHALWrapper) {
         super(Looper.getMainLooper());
+        mStartWallTime = currentTimeMillis() - SystemClock.elapsedRealtime();
+        if (DEBUG) Slog.d(TAG, "mStartWallTime: " + mStartWallTime);
         mPowerStatsHALWrapper = powerStatsHALWrapper;
         mDataStoragePath = dataStoragePath;
 
diff --git a/services/core/java/com/android/server/powerstats/ProtoStreamUtils.java b/services/core/java/com/android/server/powerstats/ProtoStreamUtils.java
index 11b22a5..746a098 100644
--- a/services/core/java/com/android/server/powerstats/ProtoStreamUtils.java
+++ b/services/core/java/com/android/server/powerstats/ProtoStreamUtils.java
@@ -109,6 +109,18 @@
     }
 
     static class StateResidencyResultUtils {
+        public static void adjustTimeSinceBootToEpoch(StateResidencyResult[] stateResidencyResult,
+                long startWallTime) {
+            for (int i = 0; i < stateResidencyResult.length; i++) {
+                final int stateLength = stateResidencyResult[i].stateResidencyData.length;
+                for (int j = 0; j < stateLength; j++) {
+                    final StateResidency stateResidencyData =
+                            stateResidencyResult[i].stateResidencyData[j];
+                    stateResidencyData.lastEntryTimestampMs += startWallTime;
+                }
+            }
+        }
+
         public static byte[] getProtoBytes(StateResidencyResult[] stateResidencyResult) {
             ProtoOutputStream pos = new ProtoOutputStream();
             packProtoMessage(stateResidencyResult, pos);
@@ -306,6 +318,13 @@
     }
 
     static class EnergyMeasurementUtils {
+        public static void adjustTimeSinceBootToEpoch(EnergyMeasurement[] energyMeasurement,
+                long startWallTime) {
+            for (int i = 0; i < energyMeasurement.length; i++) {
+                energyMeasurement[i].timestampMs += startWallTime;
+            }
+        }
+
         public static byte[] getProtoBytes(EnergyMeasurement[] energyMeasurement) {
             ProtoOutputStream pos = new ProtoOutputStream();
             packProtoMessage(energyMeasurement, pos);
@@ -518,6 +537,13 @@
     }
 
     static class EnergyConsumerResultUtils {
+        public static void adjustTimeSinceBootToEpoch(EnergyConsumerResult[] energyConsumerResult,
+                long startWallTime) {
+            for (int i = 0; i < energyConsumerResult.length; i++) {
+                energyConsumerResult[i].timestampMs += startWallTime;
+            }
+        }
+
         public static byte[] getProtoBytes(EnergyConsumerResult[] energyConsumerResult,
                 boolean includeAttribution) {
             ProtoOutputStream pos = new ProtoOutputStream();
diff --git a/services/core/java/com/android/server/powerstats/StatsPullAtomCallbackImpl.java b/services/core/java/com/android/server/powerstats/StatsPullAtomCallbackImpl.java
index bdabefb..ba778b3 100644
--- a/services/core/java/com/android/server/powerstats/StatsPullAtomCallbackImpl.java
+++ b/services/core/java/com/android/server/powerstats/StatsPullAtomCallbackImpl.java
@@ -87,6 +87,8 @@
             return StatsManager.PULL_SKIP;
         }
 
+        if (energyMeasurements == null) return StatsManager.PULL_SKIP;
+
         for (int i = 0; i < energyMeasurements.length; i++) {
             // Only report energy measurements that have been accumulated since boot
             final EnergyMeasurement energyMeasurement = energyMeasurements[i];
@@ -135,6 +137,8 @@
             return StatsManager.PULL_SKIP;
         }
 
+        if (results == null) return StatsManager.PULL_SKIP;
+
         for (int i = 0; i < results.length; i++) {
             final StateResidencyResult result = results[i];
             for (int j = 0; j < result.stateResidencyData.length; j++) {
diff --git a/services/core/java/com/android/server/rotationresolver/RotationResolverManagerPerUserService.java b/services/core/java/com/android/server/rotationresolver/RotationResolverManagerPerUserService.java
index 6f7c016..0cd0458 100644
--- a/services/core/java/com/android/server/rotationresolver/RotationResolverManagerPerUserService.java
+++ b/services/core/java/com/android/server/rotationresolver/RotationResolverManagerPerUserService.java
@@ -65,6 +65,7 @@
     @GuardedBy("mLock")
     RemoteRotationResolverService mRemoteService;
 
+    private static String sTestingPackage;
     private ComponentName mComponentName;
 
     RotationResolverManagerPerUserService(@NonNull RotationResolverManagerService main,
@@ -136,19 +137,43 @@
     }
 
     /**
+     * Set the testing package name.
+     *
+     * @param packageName the name of the package that implements {@link RotationResolverService}
+     *                    and is used for testing only.
+     */
+    @VisibleForTesting
+    void setTestingPackage(String packageName) {
+        sTestingPackage = packageName;
+        mComponentName = resolveRotationResolverService(getContext());
+    }
+
+    /**
+     * get the currently bound component name.
+     */
+    @VisibleForTesting
+    ComponentName getComponentName() {
+        return mComponentName;
+    }
+
+    /**
      * Provides rotation resolver service component name at runtime, making sure it's provided
      * by the system.
      */
-    private static ComponentName resolveRotationResolverService(Context context) {
-        final String serviceConfigPackage = getServiceConfigPackage(context);
-
+    static ComponentName resolveRotationResolverService(Context context) {
         String resolvedPackage;
         int flags = PackageManager.MATCH_SYSTEM_ONLY;
-
-        if (!TextUtils.isEmpty(serviceConfigPackage)) {
-            resolvedPackage = serviceConfigPackage;
+        if (!TextUtils.isEmpty(sTestingPackage)) {
+            // Testing Package is set.
+            resolvedPackage = sTestingPackage;
+            flags = PackageManager.GET_META_DATA;
         } else {
-            return null;
+            final String serviceConfigPackage = getServiceConfigPackage(context);
+            if (!TextUtils.isEmpty(serviceConfigPackage)) {
+                resolvedPackage = serviceConfigPackage;
+            } else {
+                return null;
+            }
         }
 
         final Intent intent = new Intent(
@@ -158,14 +183,15 @@
                 flags, context.getUserId());
         if (resolveInfo == null || resolveInfo.serviceInfo == null) {
             Slog.wtf(TAG, String.format("Service %s not found in package %s",
-                    RotationResolverService.SERVICE_INTERFACE, serviceConfigPackage
-            ));
+                    RotationResolverService.SERVICE_INTERFACE, resolvedPackage));
             return null;
         }
 
         final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
         final String permission = serviceInfo.permission;
         if (Manifest.permission.BIND_ROTATION_RESOLVER_SERVICE.equals(permission)) {
+            Slog.i(TAG, String.format("Successfully bound the service from package: %s",
+                    resolvedPackage));
             return serviceInfo.getComponentName();
         }
         Slog.e(TAG, String.format(
diff --git a/services/core/java/com/android/server/rotationresolver/RotationResolverShellCommand.java b/services/core/java/com/android/server/rotationresolver/RotationResolverShellCommand.java
index 54a9edb..e5088c0 100644
--- a/services/core/java/com/android/server/rotationresolver/RotationResolverShellCommand.java
+++ b/services/core/java/com/android/server/rotationresolver/RotationResolverShellCommand.java
@@ -16,12 +16,13 @@
 
 package com.android.server.rotationresolver;
 
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.ComponentName;
 import android.os.CancellationSignal;
 import android.os.ShellCommand;
 import android.rotationresolver.RotationResolverInternal.RotationResolverCallbackInternal;
+import android.text.TextUtils;
 import android.view.Surface;
 
 import java.io.PrintWriter;
@@ -59,7 +60,7 @@
         }
     }
 
-    final TestableRotationCallbackInternal mTestableRotationCallbackInternal =
+    static final TestableRotationCallbackInternal sTestableRotationCallbackInternal =
             new TestableRotationCallbackInternal();
 
     @Override
@@ -73,20 +74,47 @@
                 return runResolveRotation();
             case "get-last-resolution":
                 return getLastResolution();
+            case "set-testing-package":
+                return setTestRotationResolverPackage(getNextArgRequired());
+            case "get-bound-package":
+                return getBoundPackageName();
+            case "clear-testing-package":
+                return resetTestRotationResolverPackage();
             default:
                 return handleDefaultCommands(cmd);
         }
     }
 
+    private int getBoundPackageName() {
+        final PrintWriter out = getOutPrintWriter();
+        final ComponentName componentName = mService.getComponentName();
+        out.println(componentName == null ? "" : componentName.getPackageName());
+        return 0;
+    }
+
+    private int setTestRotationResolverPackage(String testingPackage) {
+        if (!TextUtils.isEmpty((testingPackage))) {
+            mService.setTestingPackage(testingPackage);
+            sTestableRotationCallbackInternal.reset();
+        }
+        return 0;
+    }
+
+    private int resetTestRotationResolverPackage() {
+        mService.setTestingPackage("");
+        sTestableRotationCallbackInternal.reset();
+        return 0;
+    }
+
     private int runResolveRotation() {
-        mService.resolveRotationLocked(mTestableRotationCallbackInternal, Surface.ROTATION_0,
+        mService.resolveRotationLocked(sTestableRotationCallbackInternal, Surface.ROTATION_0,
                 Surface.ROTATION_0, "", 2000L, new CancellationSignal());
         return 0;
     }
 
     private int getLastResolution() {
         final PrintWriter out = getOutPrintWriter();
-        out.println(mTestableRotationCallbackInternal.getLastCallbackCode());
+        out.println(sTestableRotationCallbackInternal.getLastCallbackCode());
         return 0;
     }
 
@@ -99,5 +127,8 @@
         pw.println();
         pw.println("  resolve-rotation: request a rotation resolution.");
         pw.println("  get-last-resolution: show the last rotation resolution result.");
+        pw.println("  set-testing-package: Set the testing package that implements the service.");
+        pw.println("  get-bound-package: print the bound package that implements the service.");
+        pw.println("  clear-testing-package: reset the testing package.");
     }
 }
diff --git a/services/core/java/com/android/server/security/FileIntegrityService.java b/services/core/java/com/android/server/security/FileIntegrityService.java
index 6ec71b7..74bb993 100644
--- a/services/core/java/com/android/server/security/FileIntegrityService.java
+++ b/services/core/java/com/android/server/security/FileIntegrityService.java
@@ -23,10 +23,8 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.os.Binder;
-import android.os.Build;
 import android.os.Environment;
 import android.os.IBinder;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.security.IFileIntegrityService;
 import android.util.Slog;
@@ -60,7 +58,7 @@
     private final IBinder mService = new IFileIntegrityService.Stub() {
         @Override
         public boolean isApkVeritySupported() {
-            return FileIntegrityService.isApkVeritySupported();
+            return VerityUtils.isFsVeritySupported();
         }
 
         @Override
@@ -69,7 +67,7 @@
             checkCallerPermission(packageName);
 
             try {
-                if (!isApkVeritySupported()) {
+                if (!VerityUtils.isFsVeritySupported()) {
                     return false;
                 }
                 if (certificateBytes == null) {
@@ -110,11 +108,6 @@
         }
     };
 
-    public static boolean isApkVeritySupported() {
-        return Build.VERSION.FIRST_SDK_INT >= Build.VERSION_CODES.R
-                || SystemProperties.getInt("ro.apk_verity.mode", 0) == 2;
-    }
-
     public FileIntegrityService(final Context context) {
         super(context);
         try {
diff --git a/services/core/java/com/android/server/security/KeyChainSystemService.java b/services/core/java/com/android/server/security/KeyChainSystemService.java
index 3c06d0e..edd4a3d 100644
--- a/services/core/java/com/android/server/security/KeyChainSystemService.java
+++ b/services/core/java/com/android/server/security/KeyChainSystemService.java
@@ -16,6 +16,8 @@
 
 package com.android.server.security;
 
+import static android.os.PowerWhitelistManager.REASON_KEY_CHAIN;
+
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -102,7 +104,8 @@
         final DeviceIdleInternal idleController =
                 LocalServices.getService(DeviceIdleInternal.class);
         idleController.addPowerSaveTempWhitelistApp(Process.myUid(), packageName,
-                KEYCHAIN_IDLE_WHITELIST_DURATION_MS, user.getIdentifier(), false, "keychain");
+                KEYCHAIN_IDLE_WHITELIST_DURATION_MS, user.getIdentifier(), false,
+                REASON_KEY_CHAIN, "keychain");
 
         getContext().startServiceAsUser(intent, user);
     }
diff --git a/services/core/java/com/android/server/security/VerityUtils.java b/services/core/java/com/android/server/security/VerityUtils.java
index 09ee001..48a60387 100644
--- a/services/core/java/com/android/server/security/VerityUtils.java
+++ b/services/core/java/com/android/server/security/VerityUtils.java
@@ -17,7 +17,9 @@
 package com.android.server.security;
 
 import android.annotation.NonNull;
+import android.os.Build;
 import android.os.SharedMemory;
+import android.os.SystemProperties;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
@@ -57,6 +59,11 @@
 
     private static final boolean DEBUG = false;
 
+    public static boolean isFsVeritySupported() {
+        return Build.VERSION.FIRST_SDK_INT >= Build.VERSION_CODES.R
+                || SystemProperties.getInt("ro.apk_verity.mode", 0) == 2;
+    }
+
     /** Returns true if the given file looks like containing an fs-verity signature. */
     public static boolean isFsveritySignatureFile(File file) {
         return file.getName().endsWith(FSVERITY_SIGNATURE_FILE_EXTENSION);
diff --git a/services/core/java/com/android/server/speech/Android.bp b/services/core/java/com/android/server/speech/Android.bp
index 379b075..5605349 100644
--- a/services/core/java/com/android/server/speech/Android.bp
+++ b/services/core/java/com/android/server/speech/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.speech-sources",
     srcs: ["java/**/*.java"],
diff --git a/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java b/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java
index 96248c3..3f20302 100644
--- a/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java
+++ b/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java
@@ -18,22 +18,65 @@
 
 import static com.android.internal.infra.AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS;
 
+import android.annotation.Nullable;
+import android.app.AppOpsManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.os.Binder;
+import android.os.Bundle;
 import android.os.RemoteException;
 import android.speech.IRecognitionListener;
 import android.speech.IRecognitionService;
 import android.speech.RecognitionService;
+import android.speech.SpeechRecognizer;
+import android.util.Log;
 import android.util.Slog;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.infra.ServiceConnector;
 
 final class RemoteSpeechRecognitionService extends ServiceConnector.Impl<IRecognitionService> {
     private static final String TAG = RemoteSpeechRecognitionService.class.getSimpleName();
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
 
-    RemoteSpeechRecognitionService(Context context, ComponentName serviceName, int userId) {
+    private static final String APP_OP_MESSAGE = "Recording audio for speech recognition";
+    private static final String RECORD_AUDIO_APP_OP =
+            AppOpsManager.permissionToOp(android.Manifest.permission.RECORD_AUDIO);
+
+    private final Object mLock = new Object();
+
+    private boolean mConnected = false;
+
+    @Nullable
+    private IRecognitionListener mListener;
+
+    @Nullable
+    @GuardedBy("mLock")
+    private String mPackageName;
+
+    @Nullable
+    @GuardedBy("mLock")
+    private String mFeatureId;
+
+    @Nullable
+    @GuardedBy("mLock")
+    private DelegatingListener mDelegatingListener;
+
+    // Makes sure we can block startListening() if session is still in progress.
+    @GuardedBy("mLock")
+    private boolean mSessionInProgress = false;
+
+    // Makes sure we call startProxyOp / finishProxyOp at right times and only once per session.
+    @GuardedBy("mLock")
+    private boolean mRecordingInProgress = false;
+
+    private final int mCallingUid;
+    private final AppOpsManager mAppOpsManager;
+    private final ComponentName mComponentName;
+
+    RemoteSpeechRecognitionService(
+            Context context, ComponentName serviceName, int userId, int callingUid) {
         super(context,
                 new Intent(RecognitionService.SERVICE_INTERFACE).setComponent(serviceName),
                 Context.BIND_AUTO_CREATE
@@ -43,46 +86,197 @@
                 userId,
                 IRecognitionService.Stub::asInterface);
 
+        mCallingUid = callingUid;
+        mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
+        mComponentName = serviceName;
+
         if (DEBUG) {
             Slog.i(TAG, "Bound to recognition service at: " + serviceName.flattenToString());
         }
     }
 
-    void startListening(Intent recognizerIntent, IRecognitionListener listener, String packageName,
-            String featureId) throws RemoteException {
-        if (DEBUG) {
-            Slog.i(TAG, "#startListening for package: " + packageName + ", feature=" + featureId);
-        }
-        run(service -> service.startListening(recognizerIntent, listener, packageName, featureId));
+    ComponentName getServiceComponentName() {
+        return mComponentName;
     }
 
-    void stopListening(IRecognitionListener listener, String packageName, String featureId)
-            throws RemoteException {
+    void startListening(Intent recognizerIntent, IRecognitionListener listener, String packageName,
+            String featureId) {
+        if (DEBUG) {
+            Slog.i(TAG, String.format("#startListening for package: %s, feature=%s, callingUid=%d",
+                    packageName, featureId, mCallingUid));
+        }
+
+        if (listener == null) {
+            Log.w(TAG, "#startListening called with no preceding #setListening - ignoring");
+            return;
+        }
+
+        if (!mConnected) {
+            tryRespondWithError(listener, SpeechRecognizer.ERROR_SERVER_DISCONNECTED);
+            return;
+        }
+
+        synchronized (mLock) {
+            if (mSessionInProgress) {
+                Slog.i(TAG, "#startListening called while listening is in progress.");
+                tryRespondWithError(listener, SpeechRecognizer.ERROR_RECOGNIZER_BUSY);
+                return;
+            }
+
+            if (startProxyOp(packageName, featureId) != AppOpsManager.MODE_ALLOWED) {
+                tryRespondWithError(listener, SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS);
+                return;
+            }
+            mSessionInProgress = true;
+            mRecordingInProgress = true;
+
+            mListener = listener;
+            mDelegatingListener = new DelegatingListener(listener, () -> {
+                // To be invoked in terminal calls of the callback: results() or error()
+                if (DEBUG) {
+                    Slog.i(TAG, "Recognition session complete");
+                }
+
+                synchronized (mLock) {
+                    resetStateLocked();
+                }
+            });
+            mPackageName = packageName;
+            mFeatureId = featureId;
+
+            run(service ->
+                    service.startListening(
+                            recognizerIntent,
+                            mDelegatingListener,
+                            packageName,
+                            featureId,
+                            mCallingUid));
+        }
+    }
+
+    void stopListening(
+            IRecognitionListener listener, String packageName, String featureId) {
         if (DEBUG) {
             Slog.i(TAG, "#stopListening for package: " + packageName + ", feature=" + featureId);
         }
-        run(service -> service.stopListening(listener, packageName, featureId));
+
+        if (!mConnected) {
+            tryRespondWithError(listener, SpeechRecognizer.ERROR_SERVER_DISCONNECTED);
+            return;
+        }
+
+        synchronized (mLock) {
+            if (mListener == null) {
+                Log.w(TAG, "#stopListening called with no preceding #startListening - ignoring");
+                tryRespondWithError(listener, SpeechRecognizer.ERROR_CLIENT);
+                return;
+            }
+
+            if (mListener.asBinder() != listener.asBinder()) {
+                Log.w(TAG, "#stopListening called with an unexpected listener");
+                tryRespondWithError(listener, SpeechRecognizer.ERROR_CLIENT);
+                return;
+            }
+
+            if (!mRecordingInProgress) {
+                Slog.i(TAG, "#stopListening called while listening isn't in progress, ignoring.");
+                return;
+            }
+            mRecordingInProgress = false;
+
+            finishProxyOp(packageName, featureId);
+
+            run(service -> service.stopListening(mDelegatingListener, packageName, featureId));
+        }
     }
 
-    void cancel(IRecognitionListener listener, String packageName, String featureId)
-            throws RemoteException {
+    void cancel(
+            IRecognitionListener listener,
+            String packageName,
+            String featureId,
+            boolean isShutdown) {
         if (DEBUG) {
             Slog.i(TAG, "#cancel for package: " + packageName + ", feature=" + featureId);
         }
-        run(service -> service.cancel(listener, packageName, featureId));
+
+        if (!mConnected) {
+            tryRespondWithError(listener, SpeechRecognizer.ERROR_SERVER_DISCONNECTED);
+        }
+
+        synchronized (mLock) {
+            if (mListener == null) {
+                if (DEBUG) {
+                    Log.w(TAG, "#cancel called with no preceding #startListening - ignoring");
+                }
+                return;
+            }
+
+            if (mListener.asBinder() != listener.asBinder()) {
+                Log.w(TAG, "#cancel called with an unexpected listener");
+                tryRespondWithError(listener, SpeechRecognizer.ERROR_CLIENT);
+                return;
+            }
+
+            // Temporary reference to allow for resetting the hard link mDelegatingListener to null.
+            IRecognitionListener delegatingListener = mDelegatingListener;
+
+            run(service -> service.cancel(delegatingListener, packageName, featureId, isShutdown));
+
+            if (mRecordingInProgress) {
+                finishProxyOp(packageName, featureId);
+            }
+            mRecordingInProgress = false;
+            mSessionInProgress = false;
+
+            mDelegatingListener = null;
+            mListener = null;
+
+            // Schedule to unbind after cancel is delivered.
+            if (isShutdown) {
+                run(service -> unbind());
+            }
+        }
+    }
+
+    void shutdown() {
+        synchronized (mLock) {
+            if (this.mListener == null) {
+                if (DEBUG) {
+                    Slog.i(TAG, "Package died, but session wasn't initialized. "
+                            + "Not invoking #cancel");
+                }
+                return;
+            }
+        }
+
+        cancel(mListener, mPackageName, mFeatureId, true /* isShutdown */);
     }
 
     @Override // from ServiceConnector.Impl
     protected void onServiceConnectionStatusChanged(
             IRecognitionService service, boolean connected) {
-        if (!DEBUG) {
-            return;
+        mConnected = connected;
+
+        if (DEBUG) {
+            if (connected) {
+                Slog.i(TAG, "Connected to speech recognition service");
+            } else {
+                Slog.w(TAG, "Disconnected from speech recognition service");
+            }
         }
 
-        if (connected) {
-            Slog.i(TAG, "Connected to ASR service");
-        } else {
-            Slog.w(TAG, "Disconnected from ASR service");
+        synchronized (mLock) {
+            if (!connected) {
+                if (mListener == null) {
+                    Slog.i(TAG, "Connection to speech recognition service lost, but no "
+                            + "#startListening has been invoked yet.");
+                    return;
+                }
+
+                tryRespondWithError(mListener, SpeechRecognizer.ERROR_SERVER_DISCONNECTED);
+
+                resetStateLocked();
+            }
         }
     }
 
@@ -90,4 +284,119 @@
     protected long getAutoDisconnectTimeoutMs() {
         return PERMANENT_BOUND_TIMEOUT_MS;
     }
+
+    private void resetStateLocked() {
+        if (mRecordingInProgress && mPackageName != null) {
+            finishProxyOp(mPackageName, mFeatureId);
+        }
+
+        mListener = null;
+        mDelegatingListener = null;
+        mSessionInProgress = false;
+        mRecordingInProgress = false;
+    }
+
+    private int startProxyOp(String packageName, String featureId) {
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return mAppOpsManager.startProxyOp(
+                    RECORD_AUDIO_APP_OP,
+                    mCallingUid,
+                    packageName,
+                    featureId,
+                    APP_OP_MESSAGE);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    private void finishProxyOp(String packageName, String featureId) {
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            mAppOpsManager.finishProxyOp(
+                    RECORD_AUDIO_APP_OP, mCallingUid, packageName, featureId);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    private static void tryRespondWithError(IRecognitionListener listener, int errorCode) {
+        if (DEBUG) {
+            Slog.i(TAG, "Responding with error " + errorCode);
+        }
+
+        try {
+            if (listener != null) {
+                listener.onError(errorCode);
+            }
+        } catch (RemoteException e) {
+            Slog.w(TAG,
+                    String.format("Failed to respond with an error %d to the client", errorCode),
+                    e);
+        }
+    }
+
+    private static class DelegatingListener extends IRecognitionListener.Stub {
+
+        private final IRecognitionListener mRemoteListener;
+        private final Runnable mOnSessionComplete;
+
+        DelegatingListener(IRecognitionListener listener, Runnable onSessionComplete) {
+            mRemoteListener = listener;
+            mOnSessionComplete = onSessionComplete;
+        }
+
+        @Override
+        public void onReadyForSpeech(Bundle params) throws RemoteException {
+            mRemoteListener.onReadyForSpeech(params);
+        }
+
+        @Override
+        public void onBeginningOfSpeech() throws RemoteException {
+            mRemoteListener.onBeginningOfSpeech();
+        }
+
+        @Override
+        public void onRmsChanged(float rmsdB) throws RemoteException {
+            mRemoteListener.onRmsChanged(rmsdB);
+        }
+
+        @Override
+        public void onBufferReceived(byte[] buffer) throws RemoteException {
+            mRemoteListener.onBufferReceived(buffer);
+        }
+
+        @Override
+        public void onEndOfSpeech() throws RemoteException {
+            mRemoteListener.onEndOfSpeech();
+        }
+
+        @Override
+        public void onError(int error) throws RemoteException {
+            if (DEBUG) {
+                Slog.i(TAG, String.format("Error %d during recognition session", error));
+            }
+            mOnSessionComplete.run();
+            mRemoteListener.onError(error);
+        }
+
+        @Override
+        public void onResults(Bundle results) throws RemoteException {
+            if (DEBUG) {
+                Slog.i(TAG, "#onResults invoked for a recognition session");
+            }
+            mOnSessionComplete.run();
+            mRemoteListener.onResults(results);
+        }
+
+        @Override
+        public void onPartialResults(Bundle results) throws RemoteException {
+            mRemoteListener.onPartialResults(results);
+        }
+
+        @Override
+        public void onEvent(int eventType, Bundle params) throws RemoteException {
+            mRemoteListener.onEvent(eventType, params);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/speech/SpeechRecognitionManagerService.java b/services/core/java/com/android/server/speech/SpeechRecognitionManagerService.java
index 592ba9e..dbe7354 100644
--- a/services/core/java/com/android/server/speech/SpeechRecognitionManagerService.java
+++ b/services/core/java/com/android/server/speech/SpeechRecognitionManagerService.java
@@ -18,7 +18,9 @@
 
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
+import android.content.ComponentName;
 import android.content.Context;
+import android.os.IBinder;
 import android.os.UserHandle;
 import android.speech.IRecognitionServiceManager;
 import android.speech.IRecognitionServiceManagerCallback;
@@ -42,6 +44,7 @@
 
     public SpeechRecognitionManagerService(@NonNull Context context) {
         super(context,
+                // TODO(b/176578753): think if we want to favor the particular service here.
                 new FrameworkResourcesServiceNameResolver(
                         context,
                         R.string.config_defaultOnDeviceSpeechRecognitionService),
@@ -63,11 +66,15 @@
     final class SpeechRecognitionManagerServiceStub extends IRecognitionServiceManager.Stub {
 
         @Override
-        public void createSession(IRecognitionServiceManagerCallback callback) {
+        public void createSession(
+                ComponentName componentName,
+                IBinder clientToken,
+                boolean onDevice,
+                IRecognitionServiceManagerCallback callback) {
             int userId = UserHandle.getCallingUserId();
             synchronized (mLock) {
                 SpeechRecognitionManagerServiceImpl service = getServiceForUserLocked(userId);
-                service.createSessionLocked(callback);
+                service.createSessionLocked(componentName, clientToken, onDevice, callback);
             }
         }
     }
diff --git a/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java b/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java
index bcaf174..2656a3d 100644
--- a/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java
@@ -24,30 +24,44 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
+import android.os.Binder;
+import android.os.IBinder;
 import android.os.RemoteException;
 import android.speech.IRecognitionListener;
 import android.speech.IRecognitionService;
 import android.speech.IRecognitionServiceManagerCallback;
+import android.speech.SpeechRecognizer;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.server.infra.AbstractPerUserSystemService;
 
+import com.google.android.collect.Sets;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
 final class SpeechRecognitionManagerServiceImpl extends
         AbstractPerUserSystemService<SpeechRecognitionManagerServiceImpl,
             SpeechRecognitionManagerService> {
-
     private static final String TAG = SpeechRecognitionManagerServiceImpl.class.getSimpleName();
 
+    private static final int MAX_CONCURRENT_CONNECTIONS_BY_CLIENT = 10;
+
+    private final Object mLock = new Object();
+
+    @NonNull
     @GuardedBy("mLock")
-    @Nullable
-    private RemoteSpeechRecognitionService mRemoteService;
+    private final Map<Integer, Set<RemoteSpeechRecognitionService>> mRemoteServicesByUid =
+            new HashMap<>();
 
     SpeechRecognitionManagerServiceImpl(
             @NonNull SpeechRecognitionManagerService master,
             @NonNull Object lock, @UserIdInt int userId, boolean disabled) {
         super(master, lock, userId);
-        updateRemoteServiceLocked();
     }
 
     @GuardedBy("mLock")
@@ -67,92 +81,196 @@
     @Override // from PerUserSystemService
     protected boolean updateLocked(boolean disabled) {
         final boolean enabledChanged = super.updateLocked(disabled);
-        updateRemoteServiceLocked();
         return enabledChanged;
     }
 
-    /**
-     * Updates the reference to the remote service.
-     */
-    @GuardedBy("mLock")
-    private void updateRemoteServiceLocked() {
-        if (mRemoteService != null) {
-            if (mMaster.debug) {
-                Slog.d(TAG, "updateRemoteService(): destroying old remote service");
-            }
-            mRemoteService.unbind();
-            mRemoteService = null;
+    void createSessionLocked(
+            ComponentName componentName,
+            IBinder clientToken,
+            boolean onDevice,
+            IRecognitionServiceManagerCallback callback) {
+        if (mMaster.debug) {
+            Slog.i(TAG, String.format("#createSessionLocked, component=%s, onDevice=%s",
+                    componentName, onDevice));
         }
-    }
 
-    void createSessionLocked(IRecognitionServiceManagerCallback callback) {
-        // TODO(b/176578753): check clients have record audio permission.
-        // TODO(b/176578753): verify caller package is the one supplied
+        ComponentName serviceComponent = componentName;
+        if (onDevice) {
+            serviceComponent = getOnDeviceComponentNameLocked();
+        }
 
-        RemoteSpeechRecognitionService service = ensureRemoteServiceLocked();
+        if (serviceComponent == null) {
+            tryRespondWithError(callback, SpeechRecognizer.ERROR_CLIENT);
+            return;
+        }
+
+        final int creatorCallingUid = Binder.getCallingUid();
+        Set<String> creatorPackageNames =
+                Sets.newArraySet(
+                        getContext().getPackageManager().getPackagesForUid(creatorCallingUid));
+
+        RemoteSpeechRecognitionService service = createService(creatorCallingUid, serviceComponent);
 
         if (service == null) {
-            tryRespondWithError(callback);
+            tryRespondWithError(callback, SpeechRecognizer.ERROR_TOO_MANY_REQUESTS);
             return;
         }
 
+        IBinder.DeathRecipient deathRecipient =
+                () -> handleClientDeath(creatorCallingUid, service, true /* invoke #cancel */);
+
+        try {
+            clientToken.linkToDeath(deathRecipient, 0);
+        } catch (RemoteException e) {
+            // RemoteException == binder already died, schedule disconnect anyway.
+            handleClientDeath(creatorCallingUid, service, true /* invoke #cancel */);
+        }
+
         service.connect().thenAccept(binderService -> {
             if (binderService != null) {
                 try {
                     callback.onSuccess(new IRecognitionService.Stub() {
                         @Override
-                        public void startListening(Intent recognizerIntent,
+                        public void startListening(
+                                Intent recognizerIntent,
                                 IRecognitionListener listener,
-                                String packageName, String featureId) throws RemoteException {
+                                String packageName,
+                                String featureId,
+                                int callingUid) throws RemoteException {
+                            verifyCallerIdentity(
+                                    creatorCallingUid, packageName, creatorPackageNames, listener);
+                            if (callingUid != creatorCallingUid) {
+                                listener.onError(SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS);
+                                return;
+                            }
+
                             service.startListening(
                                     recognizerIntent, listener, packageName, featureId);
                         }
 
                         @Override
-                        public void stopListening(IRecognitionListener listener,
+                        public void stopListening(
+                                IRecognitionListener listener,
                                 String packageName,
                                 String featureId) throws RemoteException {
+                            verifyCallerIdentity(
+                                    creatorCallingUid, packageName, creatorPackageNames, listener);
+
                             service.stopListening(listener, packageName, featureId);
                         }
 
                         @Override
-                        public void cancel(IRecognitionListener listener,
+                        public void cancel(
+                                IRecognitionListener listener,
                                 String packageName,
-                                String featureId) throws RemoteException {
-                            service.cancel(listener, packageName, featureId);
+                                String featureId,
+                                boolean isShutdown) throws RemoteException {
+                            verifyCallerIdentity(
+                                    creatorCallingUid, packageName, creatorPackageNames, listener);
+
+                            service.cancel(listener, packageName, featureId, isShutdown);
+
+                            if (isShutdown) {
+                                handleClientDeath(
+                                        creatorCallingUid,
+                                        service,
+                                        false /* invoke #cancel */);
+                                clientToken.unlinkToDeath(deathRecipient, 0);
+                            }
                         }
                     });
                 } catch (RemoteException e) {
                     Slog.e(TAG, "Error creating a speech recognition session", e);
-                    tryRespondWithError(callback);
+                    tryRespondWithError(callback, SpeechRecognizer.ERROR_CLIENT);
                 }
             } else {
-                tryRespondWithError(callback);
+                tryRespondWithError(callback, SpeechRecognizer.ERROR_CLIENT);
             }
         });
     }
 
-    @GuardedBy("mLock")
-    @Nullable
-    private RemoteSpeechRecognitionService ensureRemoteServiceLocked() {
-        if (mRemoteService == null) {
-            final String serviceName = getComponentNameLocked();
-            if (serviceName == null) {
-                if (mMaster.verbose) {
-                    Slog.v(TAG, "ensureRemoteServiceLocked(): no service component name.");
-                }
-                return null;
-            }
-            final ComponentName serviceComponent = ComponentName.unflattenFromString(serviceName);
-            mRemoteService =
-                    new RemoteSpeechRecognitionService(getContext(), serviceComponent, mUserId);
+    private void verifyCallerIdentity(
+            int creatorCallingUid,
+            String packageName,
+            Set<String> creatorPackageNames,
+            IRecognitionListener listener) throws RemoteException {
+        if (creatorCallingUid != Binder.getCallingUid()
+                || !creatorPackageNames.contains(packageName)) {
+            listener.onError(SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS);
         }
-        return mRemoteService;
     }
 
-    private static void tryRespondWithError(IRecognitionServiceManagerCallback callback) {
+    private void handleClientDeath(
+            int callingUid,
+            RemoteSpeechRecognitionService service, boolean invokeCancel) {
+        if (invokeCancel) {
+            service.shutdown();
+        }
+        removeService(callingUid, service);
+    }
+
+    @GuardedBy("mLock")
+    @Nullable
+    private ComponentName getOnDeviceComponentNameLocked() {
+        final String serviceName = getComponentNameLocked();
+        if (serviceName == null) {
+            if (mMaster.verbose) {
+                Slog.v(TAG, "ensureRemoteServiceLocked(): no service component name.");
+            }
+            return null;
+        }
+        return ComponentName.unflattenFromString(serviceName);
+    }
+
+    private RemoteSpeechRecognitionService createService(
+            int callingUid, ComponentName serviceComponent) {
+        synchronized (mLock) {
+            Set<RemoteSpeechRecognitionService> servicesForClient =
+                    mRemoteServicesByUid.get(callingUid);
+
+            if (servicesForClient != null
+                    && servicesForClient.size() >= MAX_CONCURRENT_CONNECTIONS_BY_CLIENT) {
+                return null;
+            }
+
+            if (servicesForClient != null) {
+                Optional<RemoteSpeechRecognitionService> existingService =
+                        servicesForClient
+                                .stream()
+                                .filter(service ->
+                                        service.getServiceComponentName().equals(serviceComponent))
+                                .findFirst();
+                if (existingService.isPresent()) {
+                    return existingService.get();
+                }
+            }
+
+            RemoteSpeechRecognitionService service =
+                    new RemoteSpeechRecognitionService(
+                            getContext(), serviceComponent, getUserId(), callingUid);
+
+            Set<RemoteSpeechRecognitionService> valuesByCaller =
+                    mRemoteServicesByUid.computeIfAbsent(callingUid, key -> new HashSet<>());
+            valuesByCaller.add(service);
+
+            return service;
+        }
+    }
+
+    private void removeService(int callingUid, RemoteSpeechRecognitionService service) {
+        synchronized (mLock) {
+            Set<RemoteSpeechRecognitionService> valuesByCaller =
+                    mRemoteServicesByUid.get(callingUid);
+            if (valuesByCaller != null) {
+                valuesByCaller.remove(service);
+            }
+        }
+    }
+
+    private static void tryRespondWithError(IRecognitionServiceManagerCallback callback,
+            int errorCode) {
         try {
-            callback.onError();
+            callback.onError(errorCode);
         } catch (RemoteException e) {
             Slog.w(TAG, "Failed to respond with error");
         }
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 15c72b3..6aa7c8a 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -1471,12 +1471,18 @@
     }
 
     int pullCpuTimePerClusterFreqLocked(int atomTag, List<StatsEvent> pulledData) {
-        boolean success = KernelCpuTotalBpfMapReader.read((cluster, freq, timeMs) -> {
-            pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, cluster, freq, timeMs));
-        });
-        if (!success) {
+        int[] freqsClusters = KernelCpuBpfTracking.getFreqsClusters();
+        long[] freqs = KernelCpuBpfTracking.getFreqs();
+        long[] timesMs = KernelCpuTotalBpfMapReader.read();
+        if (timesMs == null) {
             return StatsManager.PULL_SKIP;
         }
+        for (int freqIndex = 0; freqIndex < timesMs.length; ++freqIndex) {
+            int cluster = freqsClusters[freqIndex];
+            long freq = freqs[freqIndex];
+            long timeMs = timesMs[freqIndex];
+            pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, cluster, freq, timeMs));
+        }
         return StatsManager.PULL_SUCCESS;
     }
 
@@ -1503,48 +1509,42 @@
     }
 
     private void registerCpuCyclesPerUidCluster() {
-        int tagId = FrameworkStatsLog.CPU_CYCLES_PER_UID_CLUSTER;
-        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
-                .setAdditiveFields(new int[] {3, 4, 5})
-                .build();
-        mStatsManager.setPullAtomCallback(
-                tagId,
-                metadata,
-                DIRECT_EXECUTOR,
-                mStatsCallbackImpl
-        );
+        // If eBPF tracking is not support, the procfs fallback is used if the kernel knows about
+        // CPU frequencies.
+        if (KernelCpuBpfTracking.isSupported() || KernelCpuBpfTracking.getClusters() > 0) {
+            int tagId = FrameworkStatsLog.CPU_CYCLES_PER_UID_CLUSTER;
+            PullAtomMetadata metadata = new PullAtomMetadata.Builder()
+                    .setAdditiveFields(new int[] {3, 4, 5})
+                    .build();
+            mStatsManager.setPullAtomCallback(
+                    tagId,
+                    metadata,
+                    DIRECT_EXECUTOR,
+                    mStatsCallbackImpl
+            );
+        }
     }
 
     int pullCpuCyclesPerUidClusterLocked(int atomTag, List<StatsEvent> pulledData) {
-        // TODO(b/179485697): Remove power profile dependency.
         PowerProfile powerProfile = new PowerProfile(mContext);
-        // Frequency index to frequency mapping.
-        long[] freqs = mCpuUidFreqTimeReader.readFreqs(powerProfile);
-        // Frequency index to cluster mapping.
-        int[] freqClusters = new int[freqs.length];
-        // Frequency index to power mapping.
-        double[] freqPowers = new double[freqs.length];
-        // Number of clusters.
-        int clusters;
-
-        // Initialize frequency mappings.
+        int[] freqsClusters = KernelCpuBpfTracking.getFreqsClusters();
+        int clusters = KernelCpuBpfTracking.getClusters();
+        long[] freqs = KernelCpuBpfTracking.getFreqs();
+        double[] freqsPowers = new double[freqs.length];
+        // Initialize frequency power mapping.
         {
-            int cluster = 0;
             int freqClusterIndex = 0;
-            long lastFreq = -1;
+            int lastCluster = -1;
             for (int freqIndex = 0; freqIndex < freqs.length; ++freqIndex, ++freqClusterIndex) {
-                long currFreq = freqs[freqIndex];
-                if (currFreq <= lastFreq) {
-                    cluster++;
+                int cluster = freqsClusters[freqIndex];
+                if (cluster != lastCluster) {
                     freqClusterIndex = 0;
                 }
-                freqClusters[freqIndex] = cluster;
-                freqPowers[freqIndex] =
-                        powerProfile.getAveragePowerForCpuCore(cluster, freqClusterIndex);
-                lastFreq = currFreq;
-            }
+                lastCluster = cluster;
 
-            clusters = cluster + 1;
+                freqsPowers[freqIndex] =
+                        powerProfile.getAveragePowerForCpuCore(cluster, freqClusterIndex);
+            }
         }
 
         // Aggregate 0: mcycles, 1: runtime ms, 2: power profile estimate for the same uids for
@@ -1570,12 +1570,12 @@
             }
 
             for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) {
-                int cluster = freqClusters[freqIndex];
+                int cluster = freqsClusters[freqIndex];
                 long timeMs = cpuFreqTimeMs[freqIndex];
                 values[cluster * CPU_CYCLES_PER_UID_CLUSTER_VALUES] += freqs[freqIndex] * timeMs;
                 values[cluster * CPU_CYCLES_PER_UID_CLUSTER_VALUES + 1] += timeMs;
                 values[cluster * CPU_CYCLES_PER_UID_CLUSTER_VALUES + 2] +=
-                        freqPowers[freqIndex] * timeMs;
+                        freqsPowers[freqIndex] * timeMs;
             }
         });
 
@@ -1665,34 +1665,6 @@
     }
 
     int pullCpuCyclesPerThreadGroupCluster(int atomTag, List<StatsEvent> pulledData) {
-        // TODO(b/179485697): Remove power profile dependency.
-        PowerProfile powerProfile = new PowerProfile(mContext);
-        // Frequency index to frequency mapping.
-        long[] freqs = mCpuUidFreqTimeReader.readFreqs(powerProfile);
-        if (freqs == null) {
-            return StatsManager.PULL_SKIP;
-        }
-        // Frequency index to cluster mapping.
-        int[] freqClusters = new int[freqs.length];
-        // Number of clusters.
-        int clusters;
-
-        // Initialize frequency mappings.
-        {
-            int cluster = 0;
-            long lastFreq = -1;
-            for (int freqIndex = 0; freqIndex < freqs.length; ++freqIndex) {
-                long currFreq = freqs[freqIndex];
-                if (currFreq <= lastFreq) {
-                    cluster++;
-                }
-                freqClusters[freqIndex] = cluster;
-                lastFreq = currFreq;
-            }
-
-            clusters = cluster + 1;
-        }
-
         SystemServiceCpuThreadTimes times = LocalServices.getService(BatteryStatsInternal.class)
                 .getSystemServiceCpuThreadTimes();
         if (times == null) {
@@ -1701,22 +1673,24 @@
 
         addCpuCyclesPerThreadGroupClusterAtoms(atomTag, pulledData,
                 FrameworkStatsLog.CPU_CYCLES_PER_THREAD_GROUP_CLUSTER__THREAD_GROUP__SYSTEM_SERVER,
-                times.threadCpuTimesUs, clusters, freqs, freqClusters);
+                times.threadCpuTimesUs);
         addCpuCyclesPerThreadGroupClusterAtoms(atomTag, pulledData,
                 FrameworkStatsLog.CPU_CYCLES_PER_THREAD_GROUP_CLUSTER__THREAD_GROUP__SYSTEM_SERVER_BINDER,
-                times.binderThreadCpuTimesUs, clusters, freqs, freqClusters);
+                times.binderThreadCpuTimesUs);
 
         return StatsManager.PULL_SUCCESS;
     }
 
     private static void addCpuCyclesPerThreadGroupClusterAtoms(
-            int atomTag, List<StatsEvent> pulledData, int threadGroup, long[] cpuTimesUs,
-            int clusters, long[] freqs, int[] freqClusters) {
+            int atomTag, List<StatsEvent> pulledData, int threadGroup, long[] cpuTimesUs) {
+        int[] freqsClusters = KernelCpuBpfTracking.getFreqsClusters();
+        int clusters = KernelCpuBpfTracking.getClusters();
+        long[] freqs = KernelCpuBpfTracking.getFreqs();
         long[] aggregatedCycles = new long[clusters];
         long[] aggregatedTimesUs = new long[clusters];
         for (int i = 0; i < cpuTimesUs.length; ++i) {
-            aggregatedCycles[freqClusters[i]] += freqs[i] * cpuTimesUs[i] / 1_000;
-            aggregatedTimesUs[freqClusters[i]] += cpuTimesUs[i];
+            aggregatedCycles[freqsClusters[i]] += freqs[i] * cpuTimesUs[i] / 1_000;
+            aggregatedTimesUs[freqsClusters[i]] += cpuTimesUs[i];
         }
         for (int cluster = 0; cluster < clusters; ++cluster) {
             pulledData.add(FrameworkStatsLog.buildStatsEvent(
@@ -2134,7 +2108,9 @@
                         metrics.kernelStackKb,
                         metrics.totalIonKb,
                         metrics.unaccountedKb,
-                        metrics.gpuTotalUsageKb));
+                        metrics.gpuTotalUsageKb,
+                        metrics.gpuPrivateAllocationsKb,
+                        metrics.dmaBufTotalExportedKb));
         return StatsManager.PULL_SUCCESS;
     }
 
diff --git a/services/core/java/com/android/server/stats/pull/SystemMemoryUtil.java b/services/core/java/com/android/server/stats/pull/SystemMemoryUtil.java
index 1e80c4f..628c1d6 100644
--- a/services/core/java/com/android/server/stats/pull/SystemMemoryUtil.java
+++ b/services/core/java/com/android/server/stats/pull/SystemMemoryUtil.java
@@ -28,6 +28,8 @@
     static Metrics getMetrics() {
         int totalIonKb = (int) Debug.getIonHeapsSizeKb();
         int gpuTotalUsageKb = (int) Debug.getGpuTotalUsageKb();
+        int gpuDmaBufUsageKb = (int) Debug.getGpuDmaBufUsageKb();
+        int dmaBufTotalExportedKb = (int) Debug.getDmabufTotalExportedKb();
 
         long[] mInfos = new long[Debug.MEMINFO_COUNT];
         Debug.getMemInfo(mInfos);
@@ -49,14 +51,36 @@
                 + mInfos[Debug.MEMINFO_SLAB_UNRECLAIMABLE]
                 + kReclaimableKb
                 + mInfos[Debug.MEMINFO_VM_ALLOC_USED]
-                + mInfos[Debug.MEMINFO_PAGE_TABLES]
-                + Math.max(totalIonKb, 0);
+                + mInfos[Debug.MEMINFO_PAGE_TABLES];
 
         if (!Debug.isVmapStack()) {
             // See b/146088882
             accountedKb += mInfos[Debug.MEMINFO_KERNEL_STACK];
         }
 
+        int gpuPrivateAllocationsKb = -1;
+        if (gpuTotalUsageKb >= 0 && gpuDmaBufUsageKb >= 0) {
+            gpuPrivateAllocationsKb = gpuTotalUsageKb - gpuDmaBufUsageKb;
+        }
+        // If we can distinguish gpu private allocs it means the dmabuf metrics
+        // are supported already.
+        if (dmaBufTotalExportedKb >= 0 && gpuPrivateAllocationsKb >= 0) {
+            // If we can calculate the overlap between dma memory and gpu
+            // drivers we can do more accurate tracking. But this is only
+            // available on 5.4+ kernels.
+            accountedKb += dmaBufTotalExportedKb + gpuPrivateAllocationsKb;
+        } else {
+            // If we cannot distinguish, accept that we will double count the
+            // dma buffers also used by the gpu driver.
+            accountedKb += Math.max(0, gpuTotalUsageKb);
+            if (dmaBufTotalExportedKb >= 0) {
+                accountedKb += dmaBufTotalExportedKb;
+            } else if (totalIonKb >= 0) {
+                // ION is a subset of total exported dmabuf memory.
+                accountedKb += totalIonKb;
+            }
+        }
+
         Metrics result = new Metrics();
         result.unreclaimableSlabKb = (int) mInfos[Debug.MEMINFO_SLAB_UNRECLAIMABLE];
         result.vmallocUsedKb = (int) mInfos[Debug.MEMINFO_VM_ALLOC_USED];
@@ -64,6 +88,8 @@
         result.kernelStackKb = (int) mInfos[Debug.MEMINFO_KERNEL_STACK];
         result.totalIonKb = totalIonKb;
         result.gpuTotalUsageKb = gpuTotalUsageKb;
+        result.gpuPrivateAllocationsKb = gpuPrivateAllocationsKb;
+        result.dmaBufTotalExportedKb = dmaBufTotalExportedKb;
         result.unaccountedKb = (int) (mInfos[Debug.MEMINFO_TOTAL] - accountedKb);
         return result;
     }
@@ -75,6 +101,8 @@
         public int kernelStackKb;
         public int totalIonKb;
         public int gpuTotalUsageKb;
+        public int gpuPrivateAllocationsKb;
+        public int dmaBufTotalExportedKb;
         public int unaccountedKb;
     }
 }
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index d664651a..8ffbb0a 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -1336,7 +1336,7 @@
     }
 
     @Override
-    public void onNotificationClear(String pkg, String tag, int id, int userId, String key,
+    public void onNotificationClear(String pkg, int userId, String key,
             @NotificationStats.DismissalSurface int dismissalSurface,
             @NotificationStats.DismissalSentiment int dismissalSentiment,
             NotificationVisibility nv) {
@@ -1345,7 +1345,7 @@
         final int callingPid = Binder.getCallingPid();
         final long identity = Binder.clearCallingIdentity();
         try {
-            mNotificationDelegate.onNotificationClear(callingUid, callingPid, pkg, tag, id, userId,
+            mNotificationDelegate.onNotificationClear(callingUid, callingPid, pkg, userId,
                     key, dismissalSurface, dismissalSentiment, nv);
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -1501,6 +1501,18 @@
     }
 
     @Override
+    public void onNotificationFeedbackReceived(String key, Bundle feedback) {
+        enforceStatusBarService();
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            mNotificationDelegate.onNotificationFeedbackReceived(key, feedback);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+
+    @Override
     public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
             String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
         (new StatusBarShellCommand(this, mContext)).exec(
diff --git a/services/core/java/com/android/server/storage/StorageSessionController.java b/services/core/java/com/android/server/storage/StorageSessionController.java
index 0087c0c..dedb3ac 100644
--- a/services/core/java/com/android/server/storage/StorageSessionController.java
+++ b/services/core/java/com/android/server/storage/StorageSessionController.java
@@ -32,6 +32,7 @@
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
 import android.os.UserHandle;
+import android.os.storage.StorageManager;
 import android.os.storage.StorageVolume;
 import android.os.storage.VolumeInfo;
 import android.provider.MediaStore;
@@ -162,22 +163,17 @@
      *
      * @return ANR dialog delay in milliseconds
      */
-    public long getAnrDelayMillis(String packageName, int uid)
+    public void notifyAnrDelayStarted(String packageName, int uid, int tid, int reason)
             throws ExternalStorageServiceException {
+        final int userId = UserHandle.getUserId(uid);
+        final StorageUserConnection connection;
         synchronized (mLock) {
-            int size = mConnections.size();
-            for (int i = 0; i < size; i++) {
-                int key = mConnections.keyAt(i);
-                StorageUserConnection connection = mConnections.get(key);
-                if (connection != null) {
-                    long delay = connection.getAnrDelayMillis(packageName, uid);
-                    if (delay > 0) {
-                        return delay;
-                    }
-                }
-            }
+            connection = mConnections.get(userId);
         }
-        return 0;
+
+        if (connection != null) {
+            connection.notifyAnrDelayStarted(packageName, uid, tid, reason);
+        }
     }
 
     /**
@@ -371,6 +367,60 @@
         return mExternalStorageServiceComponent;
     }
 
+    /**
+     * Notify the controller that an app with {@code uid} and {@code tid} is blocked on an IO
+     * request on {@code volumeUuid} for {@code reason}.
+     *
+     * This blocked state can be queried with {@link #isAppIoBlocked}
+     *
+     * @hide
+     */
+    public void notifyAppIoBlocked(String volumeUuid, int uid, int tid,
+            @StorageManager.AppIoBlockedReason int reason) {
+        final int userId = UserHandle.getUserId(uid);
+        final StorageUserConnection connection;
+        synchronized (mLock) {
+            connection = mConnections.get(userId);
+        }
+
+        if (connection != null) {
+            connection.notifyAppIoBlocked(volumeUuid, uid, tid, reason);
+        }
+    }
+
+    /**
+     * Notify the controller that an app with {@code uid} and {@code tid} has resmed a previously
+     * blocked IO request on {@code volumeUuid} for {@code reason}.
+     *
+     * All app IO will be automatically marked as unblocked if {@code volumeUuid} is unmounted.
+     */
+    public void notifyAppIoResumed(String volumeUuid, int uid, int tid,
+            @StorageManager.AppIoBlockedReason int reason) {
+        final int userId = UserHandle.getUserId(uid);
+        final StorageUserConnection connection;
+        synchronized (mLock) {
+            connection = mConnections.get(userId);
+        }
+
+        if (connection != null) {
+            connection.notifyAppIoResumed(volumeUuid, uid, tid, reason);
+        }
+    }
+
+    /** Returns {@code true} if {@code uid} is blocked on IO, {@code false} otherwise */
+    public boolean isAppIoBlocked(int uid) {
+        final int userId = UserHandle.getUserId(uid);
+        final StorageUserConnection connection;
+        synchronized (mLock) {
+            connection = mConnections.get(userId);
+        }
+
+        if (connection != null) {
+            return connection.isAppIoBlocked(uid);
+        }
+        return false;
+    }
+
     private void killExternalStorageService(int userId) {
         IActivityManager am = ActivityManager.getService();
         try {
diff --git a/services/core/java/com/android/server/storage/StorageUserConnection.java b/services/core/java/com/android/server/storage/StorageUserConnection.java
index 709d558..d2b05c0 100644
--- a/services/core/java/com/android/server/storage/StorageUserConnection.java
+++ b/services/core/java/com/android/server/storage/StorageUserConnection.java
@@ -16,7 +16,6 @@
 
 package com.android.server.storage;
 
-import static android.service.storage.ExternalStorageService.EXTRA_ANR_TIMEOUT_MS;
 import static android.service.storage.ExternalStorageService.EXTRA_ERROR;
 import static android.service.storage.ExternalStorageService.FLAG_SESSION_ATTRIBUTE_INDEXABLE;
 import static android.service.storage.ExternalStorageService.FLAG_SESSION_TYPE_FUSE;
@@ -38,10 +37,12 @@
 import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.os.storage.StorageManager;
 import android.os.storage.StorageManagerInternal;
 import android.os.storage.StorageVolume;
 import android.service.storage.ExternalStorageService;
 import android.service.storage.IExternalStorageService;
+import android.util.ArraySet;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
@@ -73,6 +74,7 @@
     private final StorageSessionController mSessionController;
     private final ActiveConnection mActiveConnection = new ActiveConnection();
     @GuardedBy("mLock") private final Map<String, Session> mSessions = new HashMap<>();
+    @GuardedBy("mLock") private final Set<Integer> mUidsBlockedOnIo = new ArraySet<>();
     private final HandlerThread mHandlerThread;
 
     public StorageUserConnection(Context context, int userId, StorageSessionController controller) {
@@ -148,17 +150,13 @@
      *
      * @return ANR dialog delay in milliseconds
      */
-    public long getAnrDelayMillis(String packageName, int uid)
+    public void notifyAnrDelayStarted(String packageName, int uid, int tid, int reason)
             throws ExternalStorageServiceException {
         synchronized (mSessionsLock) {
             for (String sessionId : mSessions.keySet()) {
-                long delay = mActiveConnection.getAnrDelayMillis(packageName, uid);
-                if (delay > 0) {
-                    return delay;
-                }
+                mActiveConnection.notifyAnrDelayStarted(packageName, uid, tid, reason);
             }
         }
-        return 0;
     }
 
     /**
@@ -170,6 +168,7 @@
      **/
     public Session removeSession(String sessionId) {
         synchronized (mSessionsLock) {
+            mUidsBlockedOnIo.clear();
             return mSessions.remove(sessionId);
         }
     }
@@ -232,6 +231,41 @@
         }
     }
 
+    /**
+     * Notify the controller that an app with {@code uid} and {@code tid} is blocked on an IO
+     * request on {@code volumeUuid} for {@code reason}.
+     *
+     * This blocked state can be queried with {@link #isAppIoBlocked}
+     *
+     * @hide
+     */
+    public void notifyAppIoBlocked(String volumeUuid, int uid, int tid,
+            @StorageManager.AppIoBlockedReason int reason) {
+        synchronized (mSessionsLock) {
+            mUidsBlockedOnIo.add(uid);
+        }
+    }
+
+    /**
+     * Notify the connection that an app with {@code uid} and {@code tid} has resmed a previously
+     * blocked IO request on {@code volumeUuid} for {@code reason}.
+     *
+     * All app IO will be automatically marked as unblocked if {@code volumeUuid} is unmounted.
+     */
+    public void notifyAppIoResumed(String volumeUuid, int uid, int tid,
+            @StorageManager.AppIoBlockedReason int reason) {
+        synchronized (mSessionsLock) {
+            mUidsBlockedOnIo.remove(uid);
+        }
+    }
+
+    /** Returns {@code true} if {@code uid} is blocked on IO, {@code false} otherwise */
+    public boolean isAppIoBlocked(int uid) {
+        synchronized (mSessionsLock) {
+            return mUidsBlockedOnIo.contains(uid);
+        }
+    }
+
     @FunctionalInterface
     interface AsyncStorageServiceCall {
         void run(@NonNull IExternalStorageService service, RemoteCallback callback) throws
@@ -253,9 +287,6 @@
         @GuardedBy("mLock")
         private final ArrayList<CompletableFuture<Void>> mOutstandingOps = new ArrayList<>();
 
-        @GuardedBy("mLock")
-        private final ArrayList<CompletableFuture<Long>> mOutstandingTimeoutOps = new ArrayList<>();
-
         @Override
         public void close() {
             ServiceConnection oldConnection = null;
@@ -272,9 +303,6 @@
                 for (CompletableFuture<Void> op : mOutstandingOps) {
                     op.cancel(true);
                 }
-                for (CompletableFuture<Long> op : mOutstandingTimeoutOps) {
-                    op.cancel(true);
-                }
                 mOutstandingOps.clear();
             }
 
@@ -297,15 +325,6 @@
                     DEFAULT_REMOTE_TIMEOUT_SECONDS);
         }
 
-        private long waitForAsyncLong(AsyncStorageServiceCall asyncCall) throws Exception {
-            CompletableFuture<Long> opFuture = new CompletableFuture<>();
-            RemoteCallback callback =
-                    new RemoteCallback(result -> setTimeoutResult(result, opFuture));
-
-            return waitForAsync(asyncCall, callback, opFuture, mOutstandingTimeoutOps,
-                    1 /* timeoutSeconds */);
-        }
-
         private <T> T waitForAsync(AsyncStorageServiceCall asyncCall, RemoteCallback callback,
                 CompletableFuture<T> opFuture, ArrayList<CompletableFuture<T>> outstandingOps,
                 long timeoutSeconds) throws Exception {
@@ -380,27 +399,17 @@
             }
         }
 
-        public long getAnrDelayMillis(String packgeName, int uid)
+        public void notifyAnrDelayStarted(String packgeName, int uid, int tid, int reason)
                 throws ExternalStorageServiceException {
             try {
-                return waitForAsyncLong((service, callback) ->
-                        service.getAnrDelayMillis(packgeName, uid, callback));
+                waitForAsyncVoid((service, callback) ->
+                        service.notifyAnrDelayStarted(packgeName, uid, tid, reason, callback));
             } catch (Exception e) {
-                throw new ExternalStorageServiceException("Failed to notify app not responding: "
+                throw new ExternalStorageServiceException("Failed to notify ANR delay started: "
                         + packgeName, e);
             }
         }
 
-        private void setTimeoutResult(Bundle result, CompletableFuture<Long> future) {
-            ParcelableException ex = result.getParcelable(EXTRA_ERROR);
-            if (ex != null) {
-                future.completeExceptionally(ex);
-            } else {
-                long timeoutMs = result.getLong(EXTRA_ANR_TIMEOUT_MS);
-                future.complete(timeoutMs);
-            }
-        }
-
         private void setResult(Bundle result, CompletableFuture<Void> future) {
             ParcelableException ex = result.getParcelable(EXTRA_ERROR);
             if (ex != null) {
diff --git a/services/core/java/com/android/server/telecom/InternalServiceRepository.java b/services/core/java/com/android/server/telecom/InternalServiceRepository.java
index 76ea5c7..bd1746d 100644
--- a/services/core/java/com/android/server/telecom/InternalServiceRepository.java
+++ b/services/core/java/com/android/server/telecom/InternalServiceRepository.java
@@ -16,6 +16,8 @@
 
 package com.android.server.telecom;
 
+import static android.os.PowerWhitelistManager.REASON_UNKNOWN;
+
 import android.content.Context;
 import android.os.Binder;
 import android.os.Process;
@@ -38,7 +40,7 @@
         public void exemptAppTemporarilyForEvent(String packageName, long duration, int userHandle,
                 String reason) {
             mDeviceIdleController.addPowerSaveTempWhitelistApp(Process.myUid(), packageName,
-                    duration, userHandle, true /*sync*/, reason);
+                    duration, userHandle, true /*sync*/, REASON_UNKNOWN, reason);
         }
     };
 
diff --git a/services/core/java/com/android/server/timedetector/DeviceConfig.java b/services/core/java/com/android/server/timedetector/DeviceConfig.java
deleted file mode 100644
index 7b9ad0f..0000000
--- a/services/core/java/com/android/server/timedetector/DeviceConfig.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.timedetector;
-
-import static android.provider.DeviceConfig.NAMESPACE_SYSTEM_TIME;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.StringDef;
-
-import java.time.Duration;
-import java.util.concurrent.Executor;
-
-/**
- * A helper class for reading / monitoring the {@link
- * android.provider.DeviceConfig#NAMESPACE_SYSTEM_TIME} namespace for server-configured flags.
- */
-public final class DeviceConfig {
-
-    /**
-     * An annotation used to indicate when a {@link
-     * android.provider.DeviceConfig#NAMESPACE_SYSTEM_TIME} key is required.
-     *
-     * <p>Note that the com.android.geotz module deployment of the Offline LocationTimeZoneProvider
-     * also shares the {@link android.provider.DeviceConfig#NAMESPACE_SYSTEM_TIME}, and uses the
-     * prefix "geotz_" on all of its key strings.
-     */
-    @StringDef(prefix = "KEY_", value = {
-            KEY_FORCE_LOCATION_TIME_ZONE_DETECTION_ENABLED,
-            KEY_LOCATION_TIME_ZONE_DETECTION_ENABLED_DEFAULT,
-            KEY_LOCATION_TIME_ZONE_DETECTION_UNCERTAINTY_DELAY_MILLIS,
-            KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ_MILLIS,
-            KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_MILLIS,
-    })
-    @interface DeviceConfigKey {}
-
-    /**
-     * The key to force location time zone detection on for a device. Only intended for use during
-     * release testing with droidfooders. The user can still disable the feature by turning off the
-     * master location switch, or disabling automatic time zone detection.
-     */
-    @DeviceConfigKey
-    public static final String KEY_FORCE_LOCATION_TIME_ZONE_DETECTION_ENABLED =
-            "force_location_time_zone_detection_enabled";
-
-    /**
-     * The key for the default value used to determine whether location time zone detection is
-     * enabled when the user hasn't explicitly set it yet.
-     */
-    @DeviceConfigKey
-    public static final String KEY_LOCATION_TIME_ZONE_DETECTION_ENABLED_DEFAULT =
-            "location_time_zone_detection_enabled_default";
-
-    /**
-     * The key for the minimum delay after location time zone detection has been enabled before the
-     * location time zone manager can report it is uncertain about the time zone.
-     */
-    @DeviceConfigKey
-    public static final String KEY_LOCATION_TIME_ZONE_DETECTION_UNCERTAINTY_DELAY_MILLIS =
-            "location_time_zone_detection_uncertainty_delay_millis";
-
-    /**
-     * The key for the timeout passed to a location time zone provider that tells it how long it has
-     * to provide an explicit first suggestion without being declared uncertain.
-     */
-    @DeviceConfigKey
-    public static final String KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_MILLIS =
-            "ltpz_init_timeout_millis";
-
-    /**
-     * The key for the extra time added to {@link
-     * #KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_MILLIS} by the location time zone
-     * manager before the location time zone provider will actually be declared uncertain.
-     */
-    @DeviceConfigKey
-    public static final String KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ_MILLIS =
-            "ltpz_init_timeout_fuzz_millis";
-
-    /** Creates an instance. */
-    public DeviceConfig() {}
-
-    /** Adds a listener for the system_time namespace. */
-    public void addListener(
-            @NonNull Executor handlerExecutor, @NonNull Runnable listener) {
-        android.provider.DeviceConfig.addOnPropertiesChangedListener(
-                NAMESPACE_SYSTEM_TIME,
-                handlerExecutor,
-                properties -> listener.run());
-    }
-
-    /**
-     * Returns a boolean value from {@link android.provider.DeviceConfig} from the system_time
-     * namespace, or {@code defaultValue} if there is no explicit value set.
-     */
-    public boolean getBoolean(@DeviceConfigKey String key, boolean defaultValue) {
-        return android.provider.DeviceConfig.getBoolean(NAMESPACE_SYSTEM_TIME, key, defaultValue);
-    }
-
-    /**
-     * Returns a positive duration from {@link android.provider.DeviceConfig} from the system_time
-     * namespace, or {@code defaultValue} if there is no explicit value set.
-     */
-    @Nullable
-    public Duration getDurationFromMillis(
-            @DeviceConfigKey String key, @Nullable Duration defaultValue) {
-        long deviceConfigValue =
-                android.provider.DeviceConfig.getLong(NAMESPACE_SYSTEM_TIME, key, -1);
-        if (deviceConfigValue < 0) {
-            return defaultValue;
-        }
-        return Duration.ofMillis(deviceConfigValue);
-    }
-}
diff --git a/services/core/java/com/android/server/timedetector/ServerFlags.java b/services/core/java/com/android/server/timedetector/ServerFlags.java
new file mode 100644
index 0000000..8819b37
--- /dev/null
+++ b/services/core/java/com/android/server/timedetector/ServerFlags.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.timedetector;
+
+import static android.provider.DeviceConfig.NAMESPACE_SYSTEM_TIME;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.StringDef;
+import android.content.Context;
+import android.provider.DeviceConfig;
+import android.util.ArrayMap;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.timezonedetector.ConfigurationChangeListener;
+import com.android.server.timezonedetector.ServiceConfigAccessor;
+
+import java.time.Duration;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * A helper class for reading / monitoring the {@link DeviceConfig#NAMESPACE_SYSTEM_TIME} namespace
+ * for server-configured flags.
+ */
+public final class ServerFlags {
+
+    private static final Optional<Boolean> OPTIONAL_TRUE = Optional.of(true);
+    private static final Optional<Boolean> OPTIONAL_FALSE = Optional.of(false);
+
+    /**
+     * An annotation used to indicate when a {@link DeviceConfig#NAMESPACE_SYSTEM_TIME} key is
+     * required.
+     *
+     * <p>Note that the com.android.geotz module deployment of the Offline LocationTimeZoneProvider
+     * also shares the {@link DeviceConfig#NAMESPACE_SYSTEM_TIME}, and uses the
+     * prefix "geotz_" on all of its key strings.
+     */
+    @StringDef(prefix = "KEY_", value = {
+            KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED,
+            KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_ENABLED_OVERRIDE,
+            KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_ENABLED_OVERRIDE,
+            KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ_MILLIS,
+            KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_MILLIS,
+            KEY_LOCATION_TIME_ZONE_DETECTION_UNCERTAINTY_DELAY_MILLIS,
+            KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE,
+            KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT,
+    })
+    @interface DeviceConfigKey {}
+
+    /**
+     * Controls whether the location time zone manager service will started. Only observed if
+     * the device build is configured to support location-based time zone detection. See
+     * {@link ServiceConfigAccessor#isGeoTimeZoneDetectionFeatureSupportedInConfig()} and {@link
+     * ServiceConfigAccessor#isGeoTimeZoneDetectionFeatureSupported()}.
+     */
+    @DeviceConfigKey
+    public static final String KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED =
+            "location_time_zone_detection_feature_supported";
+
+    /**
+     * The key for the server flag that can override the device config for whether the primary
+     * location time zone provider is enabled or disabled.
+     */
+    @DeviceConfigKey
+    public static final String KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_ENABLED_OVERRIDE =
+            "primary_location_time_zone_provider_enabled_override";
+
+    /**
+     * The key for the server flag that can override the device config for whether the secondary
+     * location time zone provider is enabled or disabled.
+     */
+    @DeviceConfigKey
+    public static final String KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_ENABLED_OVERRIDE =
+            "secondary_location_time_zone_provider_enabled_override";
+
+    /**
+     * The key for the minimum delay after location time zone detection has been enabled before the
+     * location time zone manager can report it is uncertain about the time zone.
+     */
+    @DeviceConfigKey
+    public static final String KEY_LOCATION_TIME_ZONE_DETECTION_UNCERTAINTY_DELAY_MILLIS =
+            "location_time_zone_detection_uncertainty_delay_millis";
+
+    /**
+     * The key for the timeout passed to a location time zone provider that tells it how long it has
+     * to provide an explicit first suggestion without being declared uncertain.
+     */
+    @DeviceConfigKey
+    public static final String KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_MILLIS =
+            "ltpz_init_timeout_millis";
+
+    /**
+     * The key for the extra time added to {@link
+     * #KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_MILLIS} by the location time zone
+     * manager before the location time zone provider will actually be declared uncertain.
+     */
+    @DeviceConfigKey
+    public static final String KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ_MILLIS =
+            "ltpz_init_timeout_fuzz_millis";
+
+    /**
+     * The key for the server flag that can override location time zone detection being enabled for
+     * a user. Only intended for use during release testing with droidfooders. The user can still
+     * disable the feature by turning off the master location switch, or by disabling automatic time
+     * zone detection.
+     */
+    @DeviceConfigKey
+    public static final String KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE =
+            "location_time_zone_detection_setting_enabled_override";
+
+    /**
+     * The key for the default value used to determine whether location time zone detection is
+     * enabled when the user hasn't explicitly set it yet.
+     */
+    @DeviceConfigKey
+    public static final String KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT =
+            "location_time_zone_detection_setting_enabled_default";
+
+    @GuardedBy("mListeners")
+    private final ArrayMap<ConfigurationChangeListener, Set<String>> mListeners = new ArrayMap<>();
+
+    private static final Object SLOCK = new Object();
+
+    @GuardedBy("SLOCK")
+    @Nullable
+    private static ServerFlags sInstance;
+
+    private ServerFlags(Context context) {
+        DeviceConfig.addOnPropertiesChangedListener(
+                NAMESPACE_SYSTEM_TIME,
+                context.getMainExecutor(),
+                this::handlePropertiesChanged);
+    }
+
+    /** Returns the singleton instance. */
+    public static ServerFlags getInstance(Context context) {
+        synchronized (SLOCK) {
+            if (sInstance == null) {
+                sInstance = new ServerFlags(context);
+            }
+            return sInstance;
+        }
+    }
+
+    private void handlePropertiesChanged(@NonNull DeviceConfig.Properties properties) {
+        synchronized (mListeners) {
+            for (Map.Entry<ConfigurationChangeListener, Set<String>> listenerEntry
+                    : mListeners.entrySet()) {
+                if (intersects(listenerEntry.getValue(), properties.getKeyset())) {
+                    listenerEntry.getKey().onChange();
+                }
+            }
+        }
+    }
+
+    private static boolean intersects(@NonNull Set<String> one, @NonNull Set<String> two) {
+        for (String toFind : one) {
+            if (two.contains(toFind)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Adds a listener for the system_time namespace that will trigger if any of the specified keys
+     * change. Listener callbacks are delivered on the main looper thread.
+     *
+     * <p>Note: Only for use by long-lived objects like other singletons. There is deliberately no
+     * associated remove method.
+     */
+    public void addListener(@NonNull ConfigurationChangeListener listener,
+            @NonNull Set<String> keys) {
+        Objects.requireNonNull(listener);
+        Objects.requireNonNull(keys);
+
+        synchronized (mListeners) {
+            mListeners.put(listener, keys);
+        }
+    }
+
+    /**
+     * Returns an optional boolean value from {@link DeviceConfig} from the system_time
+     * namespace, returns {@link Optional#empty()} if there is no explicit value set.
+     */
+    @NonNull
+    public Optional<Boolean> getOptionalBoolean(@DeviceConfigKey String key) {
+        String value = DeviceConfig.getProperty(NAMESPACE_SYSTEM_TIME, key);
+        return parseOptionalBoolean(value);
+    }
+
+    @NonNull
+    private static Optional<Boolean> parseOptionalBoolean(@Nullable String value) {
+        if (value == null) {
+            return Optional.empty();
+        } else {
+            return Boolean.parseBoolean(value) ? OPTIONAL_TRUE : OPTIONAL_FALSE;
+        }
+    }
+
+    /**
+     * Returns a boolean value from {@link DeviceConfig} from the system_time
+     * namespace, or {@code defaultValue} if there is no explicit value set.
+     */
+    public boolean getBoolean(@DeviceConfigKey String key, boolean defaultValue) {
+        return DeviceConfig.getBoolean(NAMESPACE_SYSTEM_TIME, key, defaultValue);
+    }
+
+    /**
+     * Returns a positive duration from {@link DeviceConfig} from the system_time
+     * namespace, or {@code defaultValue} if there is no explicit value set.
+     */
+    @Nullable
+    public Duration getDurationFromMillis(
+            @DeviceConfigKey String key, @Nullable Duration defaultValue) {
+        long deviceConfigValue = DeviceConfig.getLong(NAMESPACE_SYSTEM_TIME, key, -1);
+        if (deviceConfigValue < 0) {
+            return defaultValue;
+        }
+        return Duration.ofMillis(deviceConfigValue);
+    }
+}
diff --git a/services/core/java/com/android/server/timezonedetector/ConfigurationChangeListener.java b/services/core/java/com/android/server/timezonedetector/ConfigurationChangeListener.java
index 4c7b1f3..aa8ad37 100644
--- a/services/core/java/com/android/server/timezonedetector/ConfigurationChangeListener.java
+++ b/services/core/java/com/android/server/timezonedetector/ConfigurationChangeListener.java
@@ -17,10 +17,11 @@
 package com.android.server.timezonedetector;
 
 /**
- * A listener used to receive notification that time zone configuration has changed.
+ * A listener used to receive notification that configuration has / may have changed (depending on
+ * the usecase).
  */
 @FunctionalInterface
 public interface ConfigurationChangeListener {
-    /** Called when the current user or a configuration value has changed. */
+    /** Called when the configuration may have changed. */
     void onChange();
 }
diff --git a/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java b/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
index 1f73977..3ae9d64 100644
--- a/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
+++ b/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
@@ -33,26 +33,27 @@
 import java.util.Objects;
 
 /**
- * Holds all configuration values that affect time zone behavior and some associated logic, e.g.
- * {@link #getAutoDetectionEnabledBehavior()}, {@link #getGeoDetectionEnabledBehavior()} and {@link
- * #createCapabilitiesAndConfig()}.
+ * Holds configuration values that affect user-facing time zone behavior and some associated logic.
+ * Some configuration is global, some is user scoped, but this class deliberately doesn't make a
+ * distinction for simplicity.
  */
 public final class ConfigurationInternal {
 
-    private final @UserIdInt int mUserId;
-    private final boolean mUserConfigAllowed;
     private final boolean mAutoDetectionSupported;
     private final boolean mGeoDetectionSupported;
     private final boolean mAutoDetectionEnabled;
+    private final @UserIdInt int mUserId;
+    private final boolean mUserConfigAllowed;
     private final boolean mLocationEnabled;
     private final boolean mGeoDetectionEnabled;
 
     private ConfigurationInternal(Builder builder) {
-        mUserId = builder.mUserId;
-        mUserConfigAllowed = builder.mUserConfigAllowed;
         mAutoDetectionSupported = builder.mAutoDetectionSupported;
         mGeoDetectionSupported = builder.mGeoDetectionSupported;
         mAutoDetectionEnabled = builder.mAutoDetectionEnabled;
+
+        mUserId = builder.mUserId;
+        mUserConfigAllowed = builder.mUserConfigAllowed;
         mLocationEnabled = builder.mLocationEnabled;
         mGeoDetectionEnabled = builder.mGeoDetectionEnabled;
         // if mGeoDetectionSupported then mAutoDetectionSupported, i.e. mGeoDetectionSupported
@@ -60,22 +61,6 @@
         Preconditions.checkState(mAutoDetectionSupported || !mGeoDetectionSupported);
     }
 
-    /** Returns the ID of the user this configuration is associated with. */
-    public @UserIdInt int getUserId() {
-        return mUserId;
-    }
-
-    /** Returns the handle of the user this configuration is associated with. */
-    @NonNull
-    public UserHandle getUserHandle() {
-        return UserHandle.of(mUserId);
-    }
-
-    /** Returns true if the user allowed to modify time zone configuration. */
-    public boolean isUserConfigAllowed() {
-        return mUserConfigAllowed;
-    }
-
     /** Returns true if the device supports any form of auto time zone detection. */
     public boolean isAutoDetectionSupported() {
         return mAutoDetectionSupported;
@@ -98,6 +83,22 @@
         return mAutoDetectionSupported && mAutoDetectionEnabled;
     }
 
+    /** Returns the ID of the user this configuration is associated with. */
+    public @UserIdInt int getUserId() {
+        return mUserId;
+    }
+
+    /** Returns the handle of the user this configuration is associated with. */
+    @NonNull
+    public UserHandle getUserHandle() {
+        return UserHandle.of(mUserId);
+    }
+
+    /** Returns true if the user allowed to modify time zone configuration. */
+    public boolean isUserConfigAllowed() {
+        return mUserConfigAllowed;
+    }
+
     /** Returns true if user's location can be used generally. */
     public boolean isLocationEnabled() {
         return mLocationEnabled;
@@ -283,7 +284,7 @@
         /**
          * Sets whether any form of automatic time zone detection is supported on this device.
          */
-        public Builder setAutoDetectionSupported(boolean supported) {
+        public Builder setAutoDetectionFeatureSupported(boolean supported) {
             mAutoDetectionSupported = supported;
             return this;
         }
@@ -291,7 +292,7 @@
         /**
          * Sets whether geolocation time zone detection is supported on this device.
          */
-        public Builder setGeoDetectionSupported(boolean supported) {
+        public Builder setGeoDetectionFeatureSupported(boolean supported) {
             mGeoDetectionSupported = supported;
             return this;
         }
diff --git a/services/core/java/com/android/server/timezonedetector/EnvironmentImpl.java b/services/core/java/com/android/server/timezonedetector/EnvironmentImpl.java
index f52b9b1..e3caae94 100644
--- a/services/core/java/com/android/server/timezonedetector/EnvironmentImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/EnvironmentImpl.java
@@ -31,9 +31,7 @@
 import android.content.IntentFilter;
 import android.database.ContentObserver;
 import android.location.LocationManager;
-import android.net.ConnectivityManager;
 import android.os.Handler;
-import android.os.HandlerExecutor;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -42,10 +40,9 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.server.LocalServices;
-import com.android.server.timedetector.DeviceConfig;
 
 import java.util.Objects;
-import java.util.concurrent.Executor;
+import java.util.Optional;
 
 /**
  * The real implementation of {@link TimeZoneDetectorStrategyImpl.Environment}.
@@ -59,8 +56,7 @@
     @NonNull private final Handler mHandler;
     @NonNull private final ContentResolver mCr;
     @NonNull private final UserManager mUserManager;
-    @NonNull private final DeviceConfig mDeviceConfig;
-    @NonNull private final boolean mGeoDetectionSupported;
+    @NonNull private final ServiceConfigAccessor mServiceConfigAccessor;
     @NonNull private final LocationManager mLocationManager;
 
     // @NonNull after setConfigChangeListener() is called.
@@ -68,17 +64,16 @@
     private ConfigurationChangeListener mConfigChangeListener;
 
     EnvironmentImpl(@NonNull Context context, @NonNull Handler handler,
-            @NonNull DeviceConfig deviceConfig, boolean geoDetectionSupported) {
+            @NonNull ServiceConfigAccessor serviceConfigAccessor) {
         mContext = Objects.requireNonNull(context);
         mHandler = Objects.requireNonNull(handler);
-        Executor handlerExecutor = new HandlerExecutor(mHandler);
         mCr = context.getContentResolver();
         mUserManager = context.getSystemService(UserManager.class);
         mLocationManager = context.getSystemService(LocationManager.class);
-        mDeviceConfig = deviceConfig;
-        mGeoDetectionSupported = geoDetectionSupported;
+        mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor);
 
-        // Wire up the change listeners. All invocations are performed on the mHandler thread.
+        // Wire up the config change listeners. All invocations are performed on the mHandler
+        // thread.
 
         // Listen for the user changing / the user's location mode changing.
         IntentFilter filter = new IntentFilter();
@@ -112,13 +107,6 @@
                         handleConfigChangeOnHandlerThread();
                     }
                 }, UserHandle.USER_ALL);
-
-        // Add async callbacks for changes to server-side flags: some of the flags affect device /
-        // user config. All changes can be treated like a config change. If flags that affect config
-        // haven't changed then call will be a no-op.
-        mDeviceConfig.addListener(
-                handlerExecutor,
-                this::handleConfigChangeOnHandlerThread);
     }
 
     private void handleConfigChangeOnHandlerThread() {
@@ -140,10 +128,12 @@
     @Override
     public ConfigurationInternal getConfigurationInternal(@UserIdInt int userId) {
         return new ConfigurationInternal.Builder(userId)
-                .setUserConfigAllowed(isUserConfigAllowed(userId))
-                .setAutoDetectionSupported(isAutoDetectionSupported())
-                .setGeoDetectionSupported(isGeoDetectionSupported())
+                .setAutoDetectionFeatureSupported(
+                        mServiceConfigAccessor.isAutoDetectionFeatureSupported())
+                .setGeoDetectionFeatureSupported(
+                        mServiceConfigAccessor.isGeoTimeZoneDetectionFeatureSupported())
                 .setAutoDetectionEnabled(isAutoDetectionEnabled())
+                .setUserConfigAllowed(isUserConfigAllowed(userId))
                 .setLocationEnabled(isLocationEnabled(userId))
                 .setGeoDetectionEnabled(isGeoDetectionEnabled(userId))
                 .build();
@@ -186,18 +176,19 @@
         // time zone detection: if we wrote it down then we'd set the value explicitly, which would
         // prevent detecting "default" later. That might influence what happens on later releases
         // that support new types of auto detection on the same hardware.
-        if (isAutoDetectionSupported()) {
+        if (mServiceConfigAccessor.isAutoDetectionFeatureSupported()) {
             final boolean autoDetectionEnabled = configuration.isAutoDetectionEnabled();
             setAutoDetectionEnabledIfRequired(autoDetectionEnabled);
 
-            // Avoid writing the geo detection enabled setting for devices that do not support geo
-            // time zone detection: if we wrote it down then we'd set the value explicitly, which
-            // would prevent detecting "default" later. That might influence what happens on later
-            // releases that support geo detection on the same hardware.
-            // Also avoid writing the geo detection enabled setting for devices that are currently
-            // force-enabled: otherwise we might overwrite a droidfood user's real setting
-            // permanently.
-            if (isGeoDetectionSupported() && !isGeoDetectionForceEnabled()) {
+            // Avoid writing the geo detection enabled setting for devices with settings that
+            // are currently overridden by server flags: otherwise we might overwrite a droidfood
+            // user's real setting permanently.
+            // Also avoid writing the geo detection enabled setting for devices that do not support
+            // geo time zone detection: if we wrote it down then we'd set the value explicitly,
+            // which would prevent detecting "default" later. That might influence what happens on
+            // later releases that start to support geo detection on the same hardware.
+            if (!mServiceConfigAccessor.getGeoDetectionSettingEnabledOverride().isPresent()
+                    && mServiceConfigAccessor.isGeoTimeZoneDetectionFeatureSupported()) {
                 final boolean geoTzDetectionEnabled = configuration.isGeoDetectionEnabled();
                 setGeoDetectionEnabledIfRequired(userId, geoTzDetectionEnabled);
             }
@@ -209,14 +200,6 @@
         return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_DATE_TIME, userHandle);
     }
 
-    private boolean isAutoDetectionSupported() {
-        return deviceHasTelephonyNetwork() || isGeoDetectionSupported();
-    }
-
-    private boolean isGeoDetectionSupported() {
-        return mGeoDetectionSupported;
-    }
-
     private boolean isAutoDetectionEnabled() {
         return Settings.Global.getInt(mCr, Settings.Global.AUTO_TIME_ZONE, 1 /* default */) > 0;
     }
@@ -237,24 +220,20 @@
 
     private boolean isGeoDetectionEnabled(@UserIdInt int userId) {
         // We may never use this, but it gives us a way to force location-based time zone detection
-        // on for testers (where their other settings allow).
-        boolean forceEnabled = isGeoDetectionForceEnabled();
-        if (forceEnabled) {
-            return true;
+        // on/off for testers (but only where their other settings would allow them to turn it on
+        // for themselves).
+        Optional<Boolean> override = mServiceConfigAccessor.getGeoDetectionSettingEnabledOverride();
+        if (override.isPresent()) {
+            return override.get();
         }
 
-        final boolean geoDetectionEnabledByDefault = mDeviceConfig.getBoolean(
-                DeviceConfig.KEY_LOCATION_TIME_ZONE_DETECTION_ENABLED_DEFAULT, false);
+        final boolean geoDetectionEnabledByDefault =
+                mServiceConfigAccessor.isGeoDetectionEnabledForUsersByDefault();
         return Settings.Secure.getIntForUser(mCr,
                 Settings.Secure.LOCATION_TIME_ZONE_DETECTION_ENABLED,
                 (geoDetectionEnabledByDefault ? 1 : 0) /* defaultValue */, userId) != 0;
     }
 
-    private boolean isGeoDetectionForceEnabled() {
-        return mDeviceConfig.getBoolean(
-                DeviceConfig.KEY_FORCE_LOCATION_TIME_ZONE_DETECTION_ENABLED, false);
-    }
-
     private void setGeoDetectionEnabledIfRequired(@UserIdInt int userId, boolean enabled) {
         // See comment in setAutoDetectionEnabledIfRequired. http://b/171953500
         if (isGeoDetectionEnabled(userId) != enabled) {
@@ -262,10 +241,4 @@
                     enabled ? 1 : 0, userId);
         }
     }
-
-    private boolean deviceHasTelephonyNetwork() {
-        // TODO b/150583524 Avoid the use of a deprecated API.
-        return mContext.getSystemService(ConnectivityManager.class)
-                .isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
-    }
 }
diff --git a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java
new file mode 100644
index 0000000..86c32f8
--- /dev/null
+++ b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.timezonedetector;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Resources;
+import android.net.ConnectivityManager;
+import android.os.SystemProperties;
+import android.util.ArraySet;
+
+import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.timedetector.ServerFlags;
+
+import java.time.Duration;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * A singleton that provides access to service configuration for time zone detection. This hides how
+ * configuration is split between static, compile-time config and dynamic, server-pushed flags. It
+ * provides a rudimentary mechanism to signal when values have changed.
+ */
+public final class ServiceConfigAccessor {
+
+    private static final Set<String> SERVER_FLAGS_KEYS_TO_WATCH = Collections.unmodifiableSet(
+            new ArraySet<>(new String[] {
+                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED,
+                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT,
+                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE,
+                    ServerFlags.KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_ENABLED_OVERRIDE,
+                    ServerFlags.KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_ENABLED_OVERRIDE,
+                    ServerFlags.KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_MILLIS,
+                    ServerFlags.KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ_MILLIS,
+                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_UNCERTAINTY_DELAY_MILLIS
+            }));
+
+    // TODO(b/179488561): Put this back to 5 minutes when primary provider is fully implemented
+    private static final Duration DEFAULT_PROVIDER_INITIALIZATION_TIMEOUT = Duration.ofMinutes(1);
+    // TODO(b/179488561): Put this back to 1 minute when primary provider is fully implemented
+    private static final Duration DEFAULT_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ =
+            Duration.ofSeconds(20);
+    private static final Duration DEFAULT_PROVIDER_UNCERTAINTY_DELAY = Duration.ofMinutes(5);
+
+    private static final Object SLOCK = new Object();
+
+    /** The singleton instance. Initialized once in {@link #getInstance(Context)}. */
+    @GuardedBy("SLOCK")
+    @Nullable
+    private static ServiceConfigAccessor sInstance;
+
+    @NonNull private final Context mContext;
+
+    /**
+     * An ultimate "feature switch" for location-based time zone detection. If this is
+     * {@code false}, the device cannot support the feature without a config change or a reboot:
+     * This affects what services are started on boot to minimize expense when the feature is not
+     * wanted.
+     */
+    private final boolean mGeoDetectionFeatureSupportedInConfig;
+
+    @NonNull private final ServerFlags mServerFlags;
+
+    private ServiceConfigAccessor(@NonNull Context context) {
+        mContext = Objects.requireNonNull(context);
+
+        // The config value is expected to be the main feature flag. Platform developers can also
+        // force enable the feature using a persistent system property. Because system properties
+        // can change, this value is cached and only changes on reboot.
+        mGeoDetectionFeatureSupportedInConfig = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_enableGeolocationTimeZoneDetection)
+                || SystemProperties.getBoolean(
+                "persist.sys.location_time_zone_detection_feature_supported", false);
+
+        mServerFlags = ServerFlags.getInstance(mContext);
+    }
+
+    /** Returns the singleton instance. */
+    public static ServiceConfigAccessor getInstance(Context context) {
+        synchronized (SLOCK) {
+            if (sInstance == null) {
+                sInstance = new ServiceConfigAccessor(context);
+            }
+            return sInstance;
+        }
+    }
+
+    /**
+     * Adds a listener that will be called server flags related to this class change. The callbacks
+     * are delivered on the main looper thread.
+     *
+     * <p>Note: Only for use by long-lived objects. There is deliberately no associated remove
+     * method.
+     */
+    public void addListener(@NonNull ConfigurationChangeListener listener) {
+        mServerFlags.addListener(listener, SERVER_FLAGS_KEYS_TO_WATCH);
+    }
+
+    /** Returns {@code true} if any form of automatic time zone detection is supported. */
+    public boolean isAutoDetectionFeatureSupported() {
+        return deviceHasTelephonyNetwork() || isGeoTimeZoneDetectionFeatureSupported();
+    }
+
+    private boolean deviceHasTelephonyNetwork() {
+        // TODO b/150583524 Avoid the use of a deprecated API.
+        return mContext.getSystemService(ConnectivityManager.class)
+                .isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
+    }
+
+    /**
+     * Returns {@code true} if the location-based time zone detection feature can be supported on
+     * this device at all according to config. When {@code false}, implies that various other
+     * location-based settings will be turned off or rendered meaningless. Typically {@link
+     * #isGeoTimeZoneDetectionFeatureSupported()} should be used instead.
+     */
+    public boolean isGeoTimeZoneDetectionFeatureSupportedInConfig() {
+        return mGeoDetectionFeatureSupportedInConfig;
+    }
+
+    /**
+     * Returns {@code true} if the location-based time zone detection feature is supported on the
+     * device. This can be used during feature testing on builds that are capable of location time
+     * zone detection to enable / disable the feature for some users.
+     */
+    public boolean isGeoTimeZoneDetectionFeatureSupported() {
+        return mGeoDetectionFeatureSupportedInConfig
+                && isGeoTimeZoneDetectionFeatureSupportedInternal();
+    }
+
+    private boolean isGeoTimeZoneDetectionFeatureSupportedInternal() {
+        final boolean defaultEnabled = true;
+        return mServerFlags.getBoolean(
+                ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED,
+                defaultEnabled);
+    }
+
+    /**
+     * Returns {@code true} if the primary location time zone provider can be used.
+     */
+    public boolean isPrimaryLocationTimeZoneProviderEnabled() {
+        return getPrimaryLocationTimeZoneProviderEnabledOverride()
+                .orElse(isPrimaryLocationTimeZoneProviderEnabledInConfig());
+    }
+
+    private boolean isPrimaryLocationTimeZoneProviderEnabledInConfig() {
+        int providerEnabledConfigId = R.bool.config_enablePrimaryLocationTimeZoneProvider;
+        return getConfigBoolean(providerEnabledConfigId);
+    }
+
+    @NonNull
+    private Optional<Boolean> getPrimaryLocationTimeZoneProviderEnabledOverride() {
+        return mServerFlags.getOptionalBoolean(
+                ServerFlags.KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_ENABLED_OVERRIDE);
+    }
+
+    /**
+     * Returns {@code true} if the secondary location time zone provider can be used.
+     */
+    public boolean isSecondaryLocationTimeZoneProviderEnabled() {
+        return getSecondaryLocationTimeZoneProviderEnabledOverride()
+                .orElse(isSecondaryLocationTimeZoneProviderEnabledInConfig());
+    }
+
+    private boolean isSecondaryLocationTimeZoneProviderEnabledInConfig() {
+        int providerEnabledConfigId = R.bool.config_enableSecondaryLocationTimeZoneProvider;
+        return getConfigBoolean(providerEnabledConfigId);
+    }
+
+    @NonNull
+    private Optional<Boolean> getSecondaryLocationTimeZoneProviderEnabledOverride() {
+        return mServerFlags.getOptionalBoolean(
+                ServerFlags.KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_ENABLED_OVERRIDE);
+    }
+
+    /**
+     * Returns whether location time zone detection is enabled for users when there's no setting
+     * value. Intended for use during feature release testing to "opt-in" users that haven't shown
+     * an explicit preference.
+     */
+    public boolean isGeoDetectionEnabledForUsersByDefault() {
+        return mServerFlags.getBoolean(
+                ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT, false);
+    }
+
+    /**
+     * Returns whether location time zone detection is force enabled/disabled for users. Intended
+     * for use during feature release testing to force a given state.
+     */
+    @NonNull
+    public Optional<Boolean> getGeoDetectionSettingEnabledOverride() {
+        return mServerFlags.getOptionalBoolean(
+                ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE);
+    }
+
+    /**
+     * Returns the time to send to a location time zone provider that informs it how long it has
+     * to return its first time zone suggestion.
+     */
+    @NonNull
+    public Duration getLocationTimeZoneProviderInitializationTimeout() {
+        return mServerFlags.getDurationFromMillis(
+                ServerFlags.KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_MILLIS,
+                DEFAULT_PROVIDER_INITIALIZATION_TIMEOUT);
+    }
+
+    /**
+     * Returns the time added to {@link #getLocationTimeZoneProviderInitializationTimeout()} by the
+     * server before unilaterally declaring the provider is uncertain.
+     */
+    @NonNull
+    public Duration getLocationTimeZoneProviderInitializationTimeoutFuzz() {
+        return mServerFlags.getDurationFromMillis(
+                ServerFlags.KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ_MILLIS,
+                DEFAULT_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ);
+    }
+
+    /**
+     * Returns the time after uncertainty is detected by providers before the location time zone
+     * manager makes a suggestion to the time zone detector.
+     */
+    @NonNull
+    public Duration getLocationTimeZoneUncertaintyDelay() {
+        return mServerFlags.getDurationFromMillis(
+                ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_UNCERTAINTY_DELAY_MILLIS,
+                DEFAULT_PROVIDER_UNCERTAINTY_DELAY);
+    }
+
+    private boolean getConfigBoolean(int providerEnabledConfigId) {
+        Resources resources = mContext.getResources();
+        return resources.getBoolean(providerEnabledConfigId);
+    }
+}
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java
index 203a8a4..cd220b1 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java
@@ -27,16 +27,21 @@
  */
 public interface TimeZoneDetectorInternal extends Dumpable.Container {
 
-    /** Adds a listener that will be invoked when time zone detection configuration is changed. */
-    void addConfigurationListener(ConfigurationChangeListener listener);
+    /** Adds a listener that will be invoked when {@link ConfigurationInternal} may have changed. */
+    void addConfigurationListener(@NonNull ConfigurationChangeListener listener);
 
     /**
      * Removes a listener previously added via {@link
      * #addConfigurationListener(ConfigurationChangeListener)}.
      */
-    void removeConfigurationListener(ConfigurationChangeListener listener);
+    void removeConfigurationListener(@NonNull ConfigurationChangeListener listener);
 
-    /** Returns the {@link ConfigurationInternal} for the current user. */
+    /**
+     * Returns a snapshot of the {@link ConfigurationInternal} for the current user. This is only a
+     * snapshot so callers must use {@link #addConfigurationListener(ConfigurationChangeListener)}
+     * to be notified when it changes.
+     */
+    @NonNull
     ConfigurationInternal getCurrentUserConfigurationInternal();
 
     /**
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
index bd71ddf..c20400a 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
@@ -33,7 +33,6 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
-import android.os.SystemProperties;
 import android.util.ArrayMap;
 import android.util.IndentingPrintWriter;
 import android.util.Slog;
@@ -62,27 +61,6 @@
     static final String TAG = "time_zone_detector";
 
     /**
-     * A "feature switch" for location-based time zone detection. If this is {@code false}. It is
-     * initialized and never refreshed; it affects what services are started on boot so consistency
-     * is important.
-     */
-    @Nullable
-    private static Boolean sGeoLocationTimeZoneDetectionSupported;
-
-    /** Returns {@code true} if the location-based time zone detection feature is enabled. */
-    public static boolean isGeoLocationTimeZoneDetectionSupported(Context context) {
-        if (sGeoLocationTimeZoneDetectionSupported == null) {
-            // The config value is expected to be the main switch. Platform developers can also
-            // enable the feature using a persistent system property.
-            sGeoLocationTimeZoneDetectionSupported = context.getResources().getBoolean(
-                    com.android.internal.R.bool.config_enableGeolocationTimeZoneDetection)
-                    || SystemProperties.getBoolean(
-                            "persist.sys.location_time_zone_detection_feature_enabled", false);
-        }
-        return sGeoLocationTimeZoneDetectionSupported;
-    }
-
-    /**
      * Handles the service lifecycle for {@link TimeZoneDetectorService} and
      * {@link TimeZoneDetectorInternalImpl}.
      */
@@ -98,11 +76,10 @@
             Context context = getContext();
             Handler handler = FgThread.getHandler();
 
-            boolean geolocationTimeZoneDetectionSupported =
-                    isGeoLocationTimeZoneDetectionSupported(context);
+            ServiceConfigAccessor serviceConfigAccessor =
+                    ServiceConfigAccessor.getInstance(context);
             TimeZoneDetectorStrategy timeZoneDetectorStrategy =
-                    TimeZoneDetectorStrategyImpl.create(
-                            context, handler, geolocationTimeZoneDetectionSupported);
+                    TimeZoneDetectorStrategyImpl.create(context, handler, serviceConfigAccessor);
 
             // Create and publish the local service for use by internal callers.
             TimeZoneDetectorInternal internal =
@@ -330,7 +307,8 @@
     boolean isGeoTimeZoneDetectionSupported() {
         enforceManageTimeZoneDetectorPermission();
 
-        return isGeoLocationTimeZoneDetectionSupported(mContext);
+        return ServiceConfigAccessor.getInstance(mContext)
+                .isGeoTimeZoneDetectionFeatureSupported();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
index 0b1d6d7..8266f12 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
@@ -75,17 +75,21 @@
 public interface TimeZoneDetectorStrategy extends Dumpable, Dumpable.Container {
 
     /**
-     * Sets a listener that will be triggered whenever time zone detection configuration is
+     * Adds a listener that will be triggered whenever {@link ConfigurationInternal} may have
      * changed.
      */
     void addConfigChangeListener(@NonNull ConfigurationChangeListener listener);
 
-    /** Returns the user's time zone configuration. */
+    /**
+     * Returns a snapshot of the configuration that controls time zone detector behavior for the
+     * specified user.
+     */
     @NonNull
     ConfigurationInternal getConfigurationInternal(@UserIdInt int userId);
 
     /**
-     * Returns the configuration that controls time zone detector behavior for the current user.
+     * Returns a snapshot of the configuration that controls time zone detector behavior for the
+     * current user.
      */
     @NonNull
     ConfigurationInternal getCurrentUserConfigurationInternal();
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
index c464b74..d163a0e 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
@@ -38,7 +38,6 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.timedetector.DeviceConfig;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -204,11 +203,9 @@
      */
     public static TimeZoneDetectorStrategyImpl create(
             @NonNull Context context, @NonNull Handler handler,
-            boolean geoDetectionSupported) {
+            @NonNull ServiceConfigAccessor serviceConfigAccessor) {
 
-        DeviceConfig deviceConfig = new DeviceConfig();
-        EnvironmentImpl environment = new EnvironmentImpl(
-                context, handler, deviceConfig, geoDetectionSupported);
+        Environment environment = new EnvironmentImpl(context, handler, serviceConfigAccessor);
         return new TimeZoneDetectorStrategyImpl(environment);
     }
 
diff --git a/services/core/java/com/android/server/timezonedetector/location/ControllerEnvironmentImpl.java b/services/core/java/com/android/server/timezonedetector/location/ControllerEnvironmentImpl.java
index e463ee2..98e984d 100644
--- a/services/core/java/com/android/server/timezonedetector/location/ControllerEnvironmentImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/location/ControllerEnvironmentImpl.java
@@ -19,9 +19,9 @@
 import android.annotation.NonNull;
 
 import com.android.server.LocalServices;
-import com.android.server.timedetector.DeviceConfig;
 import com.android.server.timezonedetector.ConfigurationChangeListener;
 import com.android.server.timezonedetector.ConfigurationInternal;
+import com.android.server.timezonedetector.ServiceConfigAccessor;
 import com.android.server.timezonedetector.TimeZoneDetectorInternal;
 
 import java.time.Duration;
@@ -33,28 +33,19 @@
  */
 class ControllerEnvironmentImpl extends LocationTimeZoneProviderController.Environment {
 
-    // TODO(b/179488561): Put this back to 5 minutes when primary provider is fully implemented
-    private static final Duration DEFAULT_PROVIDER_INITIALIZATION_TIMEOUT = Duration.ofMinutes(1);
-    // TODO(b/179488561): Put this back to 5 minutes when primary provider is fully implemented
-    private static final Duration DEFAULT_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ =
-            Duration.ofSeconds(20);
-    private static final Duration DEFAULT_PROVIDER_UNCERTAINTY_DELAY = Duration.ofMinutes(5);
-
     @NonNull private final TimeZoneDetectorInternal mTimeZoneDetectorInternal;
-    @NonNull private final LocationTimeZoneProviderController mController;
-    @NonNull private final DeviceConfig mDeviceConfig;
+    @NonNull private final ServiceConfigAccessor mServiceConfigAccessor;
     @NonNull private final ConfigurationChangeListener mConfigurationChangeListener;
 
     ControllerEnvironmentImpl(@NonNull ThreadingDomain threadingDomain,
-            @NonNull DeviceConfig deviceConfig,
+            @NonNull ServiceConfigAccessor serviceConfigAccessor,
             @NonNull LocationTimeZoneProviderController controller) {
         super(threadingDomain);
-        mController = Objects.requireNonNull(controller);
-        mDeviceConfig = Objects.requireNonNull(deviceConfig);
+        mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor);
         mTimeZoneDetectorInternal = LocalServices.getService(TimeZoneDetectorInternal.class);
 
         // Listen for configuration changes.
-        mConfigurationChangeListener = () -> mThreadingDomain.post(mController::onConfigChanged);
+        mConfigurationChangeListener = () -> mThreadingDomain.post(controller::onConfigChanged);
         mTimeZoneDetectorInternal.addConfigurationListener(mConfigurationChangeListener);
     }
 
@@ -73,24 +64,18 @@
     @Override
     @NonNull
     Duration getProviderInitializationTimeout() {
-        return mDeviceConfig.getDurationFromMillis(
-                DeviceConfig.KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_MILLIS,
-                DEFAULT_PROVIDER_INITIALIZATION_TIMEOUT);
+        return mServiceConfigAccessor.getLocationTimeZoneProviderInitializationTimeout();
     }
 
     @Override
     @NonNull
     Duration getProviderInitializationTimeoutFuzz() {
-        return mDeviceConfig.getDurationFromMillis(
-                DeviceConfig.KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ_MILLIS,
-                DEFAULT_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ);
+        return mServiceConfigAccessor.getLocationTimeZoneProviderInitializationTimeoutFuzz();
     }
 
     @Override
     @NonNull
     Duration getUncertaintyDelay() {
-        return mDeviceConfig.getDurationFromMillis(
-                DeviceConfig.KEY_LOCATION_TIME_ZONE_DETECTION_UNCERTAINTY_DELAY_MILLIS,
-                DEFAULT_PROVIDER_UNCERTAINTY_DELAY);
+        return mServiceConfigAccessor.getLocationTimeZoneUncertaintyDelay();
     }
 }
diff --git a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java
index 364eaf8..0d1692a 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java
@@ -21,11 +21,11 @@
 import static android.app.time.LocationTimeZoneManager.PROVIDER_MODE_OVERRIDE_NONE;
 import static android.app.time.LocationTimeZoneManager.PROVIDER_MODE_OVERRIDE_SIMULATED;
 import static android.app.time.LocationTimeZoneManager.SECONDARY_PROVIDER_NAME;
+import static android.app.time.LocationTimeZoneManager.SERVICE_NAME;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
-import android.content.res.Resources;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
@@ -43,9 +43,8 @@
 import com.android.internal.util.Preconditions;
 import com.android.server.FgThread;
 import com.android.server.SystemService;
-import com.android.server.timedetector.DeviceConfig;
+import com.android.server.timezonedetector.ServiceConfigAccessor;
 import com.android.server.timezonedetector.TimeZoneDetectorInternal;
-import com.android.server.timezonedetector.TimeZoneDetectorService;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -96,28 +95,31 @@
 
         private LocationTimeZoneManagerService mService;
 
+        @NonNull
+        private final ServiceConfigAccessor mServerConfigAccessor;
+
         public Lifecycle(@NonNull Context context) {
             super(Objects.requireNonNull(context));
+            mServerConfigAccessor = ServiceConfigAccessor.getInstance(context);
         }
 
         @Override
         public void onStart() {
             Context context = getContext();
-            if (TimeZoneDetectorService.isGeoLocationTimeZoneDetectionSupported(context)) {
+            if (mServerConfigAccessor.isGeoTimeZoneDetectionFeatureSupportedInConfig()) {
                 mService = new LocationTimeZoneManagerService(context);
 
                 // The service currently exposes no LocalService or Binder API, but it extends
                 // Binder and is registered as a binder service so it can receive shell commands.
-                publishBinderService("location_time_zone_manager", mService);
+                publishBinderService(SERVICE_NAME, mService);
             } else {
-                Slog.i(TAG, getClass() + " is disabled");
+                Slog.d(TAG, "Geo time zone detection feature is disabled in config");
             }
         }
 
         @Override
-        public void onBootPhase(int phase) {
-            Context context = getContext();
-            if (TimeZoneDetectorService.isGeoLocationTimeZoneDetectionSupported(context)) {
+        public void onBootPhase(@BootPhase int phase) {
+            if (mServerConfigAccessor.isGeoTimeZoneDetectionFeatureSupportedInConfig()) {
                 if (phase == PHASE_SYSTEM_SERVICES_READY) {
                     // The location service must be functioning after this boot phase.
                     mService.onSystemReady();
@@ -159,6 +161,9 @@
     /** The shared lock from {@link #mThreadingDomain}. */
     @NonNull private final Object mSharedLock;
 
+    @NonNull
+    private final ServiceConfigAccessor mServiceConfigAccessor;
+
     // Lazily initialized. Can be null if the service has been stopped.
     @GuardedBy("mSharedLock")
     private ControllerImpl mLocationTimeZoneDetectorController;
@@ -180,24 +185,38 @@
         mHandler = FgThread.getHandler();
         mThreadingDomain = new HandlerThreadingDomain(mHandler);
         mSharedLock = mThreadingDomain.getLockObject();
+        mServiceConfigAccessor = ServiceConfigAccessor.getInstance(mContext);
     }
 
+    // According to the SystemService docs: All lifecycle methods are called from the system
+    // server's main looper thread.
     void onSystemReady() {
-        // Called on an arbitrary thread during initialization.
-        synchronized (mSharedLock) {
-            // TODO(b/152744911): LocationManagerService watches for packages disappearing. Need to
-            //  do anything here?
+        mServiceConfigAccessor.addListener(this::handleServiceConfigurationChangedOnMainThread);
+    }
 
-            // TODO(b/152744911): LocationManagerService watches for foreground app changes. Need to
-            //  do anything here?
-            // TODO(b/152744911): LocationManagerService watches screen state. Need to do anything
-            //  here?
+    private void handleServiceConfigurationChangedOnMainThread() {
+        // This method is called on the main thread, but service logic takes place on the threading
+        // domain thread, so we post the work there.
+
+        // The way all service-level configuration changes are handled is to just restart this
+        // service - this is simple and effective, and service configuration changes should be rare.
+        mThreadingDomain.post(this::restartIfRequiredOnDomainThread);
+    }
+
+    private void restartIfRequiredOnDomainThread() {
+        mThreadingDomain.assertCurrentThread();
+
+        synchronized (mSharedLock) {
+            // Stop and start the service, waiting until completion.
+            stopOnDomainThread();
+            startOnDomainThread();
         }
     }
 
+    // According to the SystemService docs: All lifecycle methods are called from the system
+    // server's main looper thread.
     void onSystemThirdPartyAppsCanStart() {
-        // Called on an arbitrary thread during initialization. We do not want to wait for
-        // completion as it would delay boot.
+        // Do not wait for completion as it would delay boot.
         final boolean waitForCompletion = false;
         startInternal(waitForCompletion);
     }
@@ -205,6 +224,9 @@
     /**
      * Starts the service during server initialization or during tests after a call to
      * {@link #stop()}.
+     *
+     * <p>Because this method posts work to the {@code mThreadingDomain} thread and waits for
+     * completion, it cannot be called from the {@code mThreadingDomain} thread.
      */
     void start() {
         enforceManageTimeZoneDetectorPermission();
@@ -214,28 +236,17 @@
     }
 
     /**
-     * Starts the service during server initialization or during tests after a call to
-     * {@link #stop()}.
+     * Starts the service during server initialization, if the configuration changes or during tests
+     * after a call to {@link #stop()}.
      *
      * <p>To avoid tests needing to sleep, when {@code waitForCompletion} is {@code true}, this
      * method will not return until all the system server components have started.
+     *
+     * <p>Because this method posts work to the {@code mThreadingDomain} thread, it cannot be
+     * called from the {@code mThreadingDomain} thread when {@code waitForCompletion} is true.
      */
     private void startInternal(boolean waitForCompletion) {
-        Runnable runnable = () -> {
-            synchronized (mSharedLock) {
-                if (mLocationTimeZoneDetectorController == null) {
-                    LocationTimeZoneProvider primary = createPrimaryProvider();
-                    LocationTimeZoneProvider secondary = createSecondaryProvider();
-                    mLocationTimeZoneDetectorController =
-                            new ControllerImpl(mThreadingDomain, primary, secondary);
-                    DeviceConfig deviceConfig = new DeviceConfig();
-                    mEnvironment = new ControllerEnvironmentImpl(
-                            mThreadingDomain, deviceConfig, mLocationTimeZoneDetectorController);
-                    ControllerCallbackImpl callback = new ControllerCallbackImpl(mThreadingDomain);
-                    mLocationTimeZoneDetectorController.initialize(mEnvironment, callback);
-                }
-            }
-        };
+        Runnable runnable = this::startOnDomainThread;
         if (waitForCompletion) {
             mThreadingDomain.postAndWait(runnable, BLOCKING_OP_WAIT_DURATION_MILLIS);
         } else {
@@ -243,11 +254,38 @@
         }
     }
 
+    private void startOnDomainThread() {
+        mThreadingDomain.assertCurrentThread();
+
+        synchronized (mSharedLock) {
+            if (!mServiceConfigAccessor.isGeoTimeZoneDetectionFeatureSupported()) {
+                debugLog("Not starting " + SERVICE_NAME + ": it is disabled in service config");
+                return;
+            }
+
+            if (mLocationTimeZoneDetectorController == null) {
+                LocationTimeZoneProvider primary = createPrimaryProvider();
+                LocationTimeZoneProvider secondary = createSecondaryProvider();
+
+                ControllerImpl controller =
+                        new ControllerImpl(mThreadingDomain, primary, secondary);
+                ControllerEnvironmentImpl environment = new ControllerEnvironmentImpl(
+                        mThreadingDomain, mServiceConfigAccessor, controller);
+                ControllerCallbackImpl callback = new ControllerCallbackImpl(mThreadingDomain);
+                controller.initialize(environment, callback);
+
+                mEnvironment = environment;
+                mLocationTimeZoneDetectorController = controller;
+            }
+        }
+    }
+
+    @NonNull
     private LocationTimeZoneProvider createPrimaryProvider() {
         LocationTimeZoneProviderProxy proxy;
         if (isProviderInSimulationMode(PRIMARY_PROVIDER_NAME)) {
             proxy = new SimulatedLocationTimeZoneProviderProxy(mContext, mThreadingDomain);
-        } else if (isProviderDisabled(PRIMARY_PROVIDER_NAME)) {
+        } else if (!isProviderEnabled(PRIMARY_PROVIDER_NAME)) {
             proxy = new NullLocationTimeZoneProviderProxy(mContext, mThreadingDomain);
         } else {
             proxy = new RealLocationTimeZoneProviderProxy(
@@ -262,11 +300,12 @@
         return new BinderLocationTimeZoneProvider(mThreadingDomain, PRIMARY_PROVIDER_NAME, proxy);
     }
 
+    @NonNull
     private LocationTimeZoneProvider createSecondaryProvider() {
         LocationTimeZoneProviderProxy proxy;
         if (isProviderInSimulationMode(SECONDARY_PROVIDER_NAME)) {
             proxy = new SimulatedLocationTimeZoneProviderProxy(mContext, mThreadingDomain);
-        } else if (isProviderDisabled(SECONDARY_PROVIDER_NAME)) {
+        } else if (!isProviderEnabled(SECONDARY_PROVIDER_NAME)) {
             proxy = new NullLocationTimeZoneProviderProxy(mContext, mThreadingDomain);
         } else {
             proxy = new RealLocationTimeZoneProviderProxy(
@@ -282,33 +321,27 @@
     }
 
     /** Used for bug triage and in tests to simulate provider events. */
-    private boolean isProviderInSimulationMode(String providerName) {
+    private boolean isProviderInSimulationMode(@NonNull String providerName) {
         return isProviderModeOverrideSet(providerName, PROVIDER_MODE_OVERRIDE_SIMULATED);
     }
 
-    /** Used for bug triage, tests and experiments to remove a provider. */
-    private boolean isProviderDisabled(String providerName) {
-        return !isProviderEnabledInConfig(providerName)
-                || isProviderModeOverrideSet(providerName, PROVIDER_MODE_OVERRIDE_DISABLED);
-    }
+    /** Used for bug triage, and by tests and experiments to remove a provider. */
+    private boolean isProviderEnabled(@NonNull String providerName) {
+        if (isProviderModeOverrideSet(providerName, PROVIDER_MODE_OVERRIDE_DISABLED)) {
+            return false;
+        }
 
-    private boolean isProviderEnabledInConfig(String providerName) {
-        int providerEnabledConfigId;
         switch (providerName) {
             case PRIMARY_PROVIDER_NAME: {
-                providerEnabledConfigId = R.bool.config_enablePrimaryLocationTimeZoneProvider;
-                break;
+                return mServiceConfigAccessor.isPrimaryLocationTimeZoneProviderEnabled();
             }
             case SECONDARY_PROVIDER_NAME: {
-                providerEnabledConfigId = R.bool.config_enableSecondaryLocationTimeZoneProvider;
-                break;
+                return mServiceConfigAccessor.isSecondaryLocationTimeZoneProviderEnabled();
             }
             default: {
                 throw new IllegalArgumentException(providerName);
             }
         }
-        Resources resources = mContext.getResources();
-        return resources.getBoolean(providerEnabledConfigId);
     }
 
     private boolean isProviderModeOverrideSet(@NonNull String providerName, @NonNull String mode) {
@@ -326,22 +359,29 @@
     }
 
     /**
-     * Stops the service for tests. To avoid tests needing to sleep, this method will not return
-     * until all the system server components have stopped.
+     * Stops the service for tests and other rare cases. To avoid tests needing to sleep, this
+     * method will not return until all the system server components have stopped.
+     *
+     * <p>Because this method posts work to the {@code mThreadingDomain} thread and waits it cannot
+     * be called from the {@code mThreadingDomain} thread.
      */
     void stop() {
         enforceManageTimeZoneDetectorPermission();
 
-        mThreadingDomain.postAndWait(() -> {
-            synchronized (mSharedLock) {
-                if (mLocationTimeZoneDetectorController != null) {
-                    mLocationTimeZoneDetectorController.destroy();
-                    mLocationTimeZoneDetectorController = null;
-                    mEnvironment.destroy();
-                    mEnvironment = null;
-                }
+        mThreadingDomain.postAndWait(this::stopOnDomainThread, BLOCKING_OP_WAIT_DURATION_MILLIS);
+    }
+
+    private void stopOnDomainThread() {
+        mThreadingDomain.assertCurrentThread();
+
+        synchronized (mSharedLock) {
+            if (mLocationTimeZoneDetectorController != null) {
+                mLocationTimeZoneDetectorController.destroy();
+                mLocationTimeZoneDetectorController = null;
+                mEnvironment.destroy();
+                mEnvironment = null;
             }
-        }, BLOCKING_OP_WAIT_DURATION_MILLIS);
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerShellCommand.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerShellCommand.java
index b53150c..bdf4a70 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerShellCommand.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerShellCommand.java
@@ -21,6 +21,7 @@
 import static android.app.time.LocationTimeZoneManager.PROVIDER_MODE_OVERRIDE_NONE;
 import static android.app.time.LocationTimeZoneManager.PROVIDER_MODE_OVERRIDE_SIMULATED;
 import static android.app.time.LocationTimeZoneManager.SECONDARY_PROVIDER_NAME;
+import static android.app.time.LocationTimeZoneManager.SERVICE_NAME;
 import static android.app.time.LocationTimeZoneManager.SHELL_COMMAND_DUMP_STATE;
 import static android.app.time.LocationTimeZoneManager.SHELL_COMMAND_RECORD_PROVIDER_STATES;
 import static android.app.time.LocationTimeZoneManager.SHELL_COMMAND_SEND_PROVIDER_TEST_COMMAND;
@@ -102,7 +103,7 @@
     @Override
     public void onHelp() {
         final PrintWriter pw = getOutPrintWriter();
-        pw.println("Location Time Zone Manager (location_time_zone_manager) commands for tests:");
+        pw.printf("Location Time Zone Manager (%s) commands for tests:\n", SERVICE_NAME);
         pw.println("  help");
         pw.println("    Print this help text.");
         pw.printf("  %s\n", SHELL_COMMAND_START);
diff --git a/services/core/java/com/android/server/timezonedetector/location/RealLocationTimeZoneProviderProxy.java b/services/core/java/com/android/server/timezonedetector/location/RealLocationTimeZoneProviderProxy.java
index 38211ef..531c62c 100644
--- a/services/core/java/com/android/server/timezonedetector/location/RealLocationTimeZoneProviderProxy.java
+++ b/services/core/java/com/android/server/timezonedetector/location/RealLocationTimeZoneProviderProxy.java
@@ -25,7 +25,6 @@
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
@@ -41,6 +40,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.server.ServiceWatcher;
+import com.android.server.ServiceWatcher.BoundService;
 
 import java.util.Objects;
 import java.util.function.Predicate;
@@ -123,7 +123,7 @@
         return resolves;
     }
 
-    private void onBind(IBinder binder, ComponentName componentName) {
+    private void onBind(IBinder binder, BoundService boundService) {
         mThreadingDomain.assertCurrentThread();
 
         synchronized (mSharedLock) {
diff --git a/services/core/java/com/android/server/timezonedetector/location/TimeZoneProviderRequest.java b/services/core/java/com/android/server/timezonedetector/location/TimeZoneProviderRequest.java
index 1482031..e8386bc 100644
--- a/services/core/java/com/android/server/timezonedetector/location/TimeZoneProviderRequest.java
+++ b/services/core/java/com/android/server/timezonedetector/location/TimeZoneProviderRequest.java
@@ -63,8 +63,6 @@
         return mSendUpdates;
     }
 
-    // TODO(b/152744911) - once there are a couple of implementations, decide whether this needs to
-    //  be passed to the TimeZoneProviderService and remove if it is not useful.
     /**
      * Returns the maximum time that the provider is allowed to initialize before it is expected to
      * send an event of any sort. Only valid when {@link #sendUpdates()} is {@code true}. Failure to
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index da3e48a..4fbc795 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -703,7 +703,7 @@
         if (changed) {
             dispatchDeviceLocked(userId, locked);
 
-            mAuthorizationService.onLockScreenEvent(locked, userId, null);
+            Authorization.onLockScreenEvent(locked, userId, null);
             KeyStore.getInstance().onUserLockedStateChanged(userId, locked);
             // Also update the user's profiles who have unified challenge, since they
             // share the same unlocked state (see {@link #isDeviceLocked(int)})
@@ -1261,7 +1261,7 @@
                         mDeviceLockedForUser.put(userId, locked);
                     }
 
-                    mAuthorizationService.onLockScreenEvent(locked, userId, null);
+                    Authorization.onLockScreenEvent(locked, userId, null);
                     KeyStore.getInstance().onUserLockedStateChanged(userId, locked);
 
                     if (locked) {
diff --git a/services/core/java/com/android/server/utils/WatchedLongSparseArray.java b/services/core/java/com/android/server/utils/WatchedLongSparseArray.java
new file mode 100644
index 0000000..bf23de1
--- /dev/null
+++ b/services/core/java/com/android/server/utils/WatchedLongSparseArray.java
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.utils;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.LongSparseArray;
+
+/**
+ * A watched variant of {@link LongSparseArray}.  If a {@link Watchable} is stored in the
+ * array, the array registers with the {@link Watchable}.  The array registers only once
+ * with each {@link Watchable} no matter how many times the {@link Watchable} is stored in
+ * the array.
+ * @param <E> The element type, stored in the array.
+ */
+public class WatchedLongSparseArray<E> extends WatchableImpl
+        implements Snappable {
+
+    // The storage
+    private final LongSparseArray<E> mStorage;
+
+    // If true, the array is watching its children
+    private volatile boolean mWatching = false;
+
+    // The local observer
+    private final Watcher mObserver = new Watcher() {
+            @Override
+            public void onChange(@Nullable Watchable o) {
+                WatchedLongSparseArray.this.dispatchChange(o);
+            }
+        };
+
+    /**
+     * A private convenience function that notifies registered listeners that an element
+     * has been added to or removed from the array.  The what parameter is the array itself.
+     */
+    private void onChanged() {
+        dispatchChange(this);
+    }
+
+    /**
+     * A convenience function.  Register the object if it is {@link Watchable} and if the
+     * array is currently watching.  Note that the watching flag must be true if this
+     * function is to succeed.
+     */
+    private void registerChild(Object o) {
+        if (mWatching && o instanceof Watchable) {
+            ((Watchable) o).registerObserver(mObserver);
+        }
+    }
+
+    /**
+     * A convenience function.  Unregister the object if it is {@link Watchable} and if
+     * the array is currently watching.  Note that the watching flag must be true if this
+     * function is to succeed.
+     */
+    private void unregisterChild(Object o) {
+        if (mWatching && o instanceof Watchable) {
+            ((Watchable) o).unregisterObserver(mObserver);
+        }
+    }
+
+    /**
+     * A convenience function.  Unregister the object if it is {@link Watchable}, if the array is
+     * currently watching, and if the storage does not contain the object.  Note that the watching
+     * flag must be true if this function is to succeed.  This must be called after an object has
+     * been removed from the storage.
+     */
+    private void unregisterChildIf(Object o) {
+        if (mWatching && o instanceof Watchable) {
+            if (mStorage.indexOfValue((E) o) == -1) {
+                ((Watchable) o).unregisterObserver(mObserver);
+            }
+        }
+    }
+
+    /**
+     * Register a {@link Watcher} with the array.  If this is the first Watcher than any
+     * array values that are {@link Watchable} are registered to the array itself.
+     */
+    @Override
+    public void registerObserver(@NonNull Watcher observer) {
+        super.registerObserver(observer);
+        if (registeredObserverCount() == 1) {
+            // The watching flag must be set true before any children are registered.
+            mWatching = true;
+            final int end = mStorage.size();
+            for (int i = 0; i < end; i++) {
+                registerChild(mStorage.valueAt(i));
+            }
+        }
+    }
+
+    /**
+     * Unregister a {@link Watcher} from the array.  If this is the last Watcher than any
+     * array values that are {@link Watchable} are unregistered to the array itself.
+     */
+    @Override
+    public void unregisterObserver(@NonNull Watcher observer) {
+        super.unregisterObserver(observer);
+        if (registeredObserverCount() == 0) {
+            final int end = mStorage.size();
+            for (int i = 0; i < end; i++) {
+                unregisterChild(mStorage.valueAt(i));
+            }
+            // The watching flag must be true while children are unregistered.
+            mWatching = false;
+        }
+    }
+
+    /**
+     * Creates a new WatchedSparseArray containing no mappings.
+     */
+    public WatchedLongSparseArray() {
+        mStorage = new LongSparseArray();
+    }
+
+    /**
+     * Creates a new WatchedSparseArray containing no mappings that
+     * will not require any additional memory allocation to store the
+     * specified number of mappings.  If you supply an initial capacity of
+     * 0, the sparse array will be initialized with a light-weight
+     * representation not requiring any additional array allocations.
+     */
+    public WatchedLongSparseArray(int initialCapacity) {
+        mStorage = new LongSparseArray(initialCapacity);
+    }
+
+    /**
+     * Create a {@link WatchedLongSparseArray} from a {@link LongSparseArray}.
+     */
+    public WatchedLongSparseArray(@NonNull LongSparseArray<E> c) {
+        mStorage = c.clone();
+    }
+
+    /**
+     * The copy constructor does not copy the watcher data.
+     */
+    public WatchedLongSparseArray(@NonNull WatchedLongSparseArray<E> r) {
+        mStorage = r.mStorage.clone();
+    }
+
+    /**
+     * Make <this> a copy of src.  Any data in <this> is discarded.
+     */
+    public void copyFrom(@NonNull LongSparseArray<E> src) {
+        clear();
+        final int end = src.size();
+        for (int i = 0; i < end; i++) {
+            put(src.keyAt(i), src.valueAt(i));
+        }
+    }
+
+    /**
+     * Make dst a copy of <this>.  Any previous data in dst is discarded.
+     */
+    public void copyTo(@NonNull LongSparseArray<E> dst) {
+        dst.clear();
+        final int end = size();
+        for (int i = 0; i < end; i++) {
+            dst.put(keyAt(i), valueAt(i));
+        }
+    }
+
+    /**
+     * Return the underlying storage.  This breaks the wrapper but is necessary when
+     * passing the array to distant methods.
+     */
+    public LongSparseArray<E> untrackedStorage() {
+        return mStorage;
+    }
+
+    /**
+     * Gets the Object mapped from the specified key, or <code>null</code>
+     * if no such mapping has been made.
+     */
+    public E get(long key) {
+        return mStorage.get(key);
+    }
+
+    /**
+     * Gets the Object mapped from the specified key, or the specified Object
+     * if no such mapping has been made.
+     */
+    public E get(long key, E valueIfKeyNotFound) {
+        return mStorage.get(key, valueIfKeyNotFound);
+    }
+
+    /**
+     * Removes the mapping from the specified key, if there was any.
+     */
+    public void delete(long key) {
+        E old = mStorage.get(key, null);
+        mStorage.delete(key);
+        unregisterChildIf(old);
+        onChanged();
+
+    }
+
+    /**
+     * Alias for {@link #delete(long)}.
+     */
+    public void remove(long key) {
+        delete(key);
+    }
+
+    /**
+     * Removes the mapping at the specified index.
+     *
+     * <p>For indices outside of the range <code>0...size()-1</code>, an
+     * {@link ArrayIndexOutOfBoundsException} is thrown.</p>
+     */
+    public void removeAt(int index) {
+        E old = mStorage.valueAt(index);
+        mStorage.removeAt(index);
+        unregisterChildIf(old);
+        onChanged();
+    }
+
+    /**
+     * Adds a mapping from the specified key to the specified value,
+     * replacing the previous mapping from the specified key if there
+     * was one.
+     */
+    public void put(long key, E value) {
+        E old = mStorage.get(key);
+        mStorage.put(key, value);
+        unregisterChildIf(old);
+        registerChild(value);
+        onChanged();
+    }
+
+    /**
+     * Returns the number of key-value mappings that this LongSparseArray
+     * currently stores.
+     */
+    public int size() {
+        return mStorage.size();
+    }
+
+    /**
+     * Given an index in the range <code>0...size()-1</code>, returns
+     * the key from the <code>index</code>th key-value mapping that this
+     * LongSparseArray stores.
+     *
+     * <p>The keys corresponding to indices in ascending order are guaranteed to
+     * be in ascending order, e.g., <code>keyAt(0)</code> will return the
+     * smallest key and <code>keyAt(size()-1)</code> will return the largest
+     * key.</p>
+     *
+     * <p>For indices outside of the range <code>0...size()-1</code>, an
+     * {@link ArrayIndexOutOfBoundsException} is thrown.</p>
+     */
+    public long keyAt(int index) {
+        return mStorage.keyAt(index);
+    }
+
+    /**
+     * Given an index in the range <code>0...size()-1</code>, returns
+     * the value from the <code>index</code>th key-value mapping that this
+     * LongSparseArray stores.
+     *
+     * <p>The values corresponding to indices in ascending order are guaranteed
+     * to be associated with keys in ascending order, e.g.,
+     * <code>valueAt(0)</code> will return the value associated with the
+     * smallest key and <code>valueAt(size()-1)</code> will return the value
+     * associated with the largest key.</p>
+     *
+     * <p>For indices outside of the range <code>0...size()-1</code>, an
+     * {@link ArrayIndexOutOfBoundsException} is thrown.</p>
+     */
+    public E valueAt(int index) {
+        return mStorage.valueAt(index);
+    }
+
+    /**
+     * Given an index in the range <code>0...size()-1</code>, sets a new
+     * value for the <code>index</code>th key-value mapping that this
+     * LongSparseArray stores.
+     *
+     * <p>For indices outside of the range <code>0...size()-1</code>, an
+     * {@link ArrayIndexOutOfBoundsException} is thrown.</p>
+     */
+    public void setValueAt(int index, E value) {
+        E old = mStorage.valueAt(index);
+        mStorage.setValueAt(index, value);
+        unregisterChildIf(old);
+        registerChild(value);
+        onChanged();
+    }
+
+    /**
+     * Returns the index for which {@link #keyAt} would return the
+     * specified key, or a negative number if the specified
+     * key is not mapped.
+     */
+    public int indexOfKey(long key) {
+        return mStorage.indexOfKey(key);
+    }
+
+    /**
+     * Returns an index for which {@link #valueAt} would return the
+     * specified key, or a negative number if no keys map to the
+     * specified value.
+     * Beware that this is a linear search, unlike lookups by key,
+     * and that multiple keys can map to the same value and this will
+     * find only one of them.
+     */
+    public int indexOfValue(E value) {
+        return mStorage.indexOfValue(value);
+    }
+
+    /**
+     * Returns an index for which {@link #valueAt} would return the
+     * specified key, or a negative number if no keys map to the
+     * specified value.
+     * <p>Beware that this is a linear search, unlike lookups by key,
+     * and that multiple keys can map to the same value and this will
+     * find only one of them.
+     * <p>Note also that this method uses {@code equals} unlike {@code indexOfValue}.
+     * @hide
+     */
+    public int indexOfValueByValue(E value) {
+        return mStorage.indexOfValueByValue(value);
+    }
+
+    /**
+     * Removes all key-value mappings from this LongSparseArray.
+     */
+    public void clear() {
+        final int end = mStorage.size();
+        for (int i = 0; i < end; i++) {
+            unregisterChild(mStorage.valueAt(i));
+        }
+        mStorage.clear();
+        onChanged();
+    }
+
+    /**
+     * Puts a key/value pair into the array, optimizing for the case where
+     * the key is greater than all existing keys in the array.
+     */
+    public void append(long key, E value) {
+        mStorage.append(key, value);
+        registerChild(value);
+        onChanged();
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>This implementation composes a string by iterating over its mappings. If
+     * this map contains itself as a value, the string "(this Map)"
+     * will appear in its place.
+     */
+    @Override
+    public String toString() {
+        return mStorage.toString();
+    }
+
+    /**
+     * Create a copy of the array.  If the element is a subclass of Snapper then the copy
+     * contains snapshots of the elements.  Otherwise the copy contains references to the
+     * elements.  The returned snapshot is immutable.
+     * @return A new array whose elements are the elements of <this>.
+     */
+    public WatchedLongSparseArray<E> snapshot() {
+        WatchedLongSparseArray<E> l = new WatchedLongSparseArray<>(size());
+        snapshot(l, this);
+        return l;
+    }
+
+    /**
+     * Make <this> a snapshot of the argument.  Note that <this> is immutable when the
+     * method returns.  <this> must be empty when the function is called.
+     * @param r The source array, which is copied into <this>
+     */
+    public void snapshot(@NonNull WatchedLongSparseArray<E> r) {
+        snapshot(this, r);
+    }
+
+    /**
+     * Make the destination a copy of the source.  If the element is a subclass of Snapper then the
+     * copy contains snapshots of the elements.  Otherwise the copy contains references to the
+     * elements.  The destination must be initially empty.  Upon return, the destination is
+     * immutable.
+     * @param dst The destination array.  It must be empty.
+     * @param src The source array.  It is not modified.
+     */
+    public static <E> void snapshot(@NonNull WatchedLongSparseArray<E> dst,
+            @NonNull WatchedLongSparseArray<E> src) {
+        if (dst.size() != 0) {
+            throw new IllegalArgumentException("snapshot destination is not empty");
+        }
+        final int end = src.size();
+        for (int i = 0; i < end; i++) {
+            final E val = Snapshots.maybeSnapshot(src.valueAt(i));
+            final long key = src.keyAt(i);
+            dst.put(key, val);
+        }
+        dst.seal();
+    }
+
+}
diff --git a/services/core/java/com/android/server/vcn/Android.bp b/services/core/java/com/android/server/vcn/Android.bp
index 5ed204f..ab5da3e 100644
--- a/services/core/java/com/android/server/vcn/Android.bp
+++ b/services/core/java/com/android/server/vcn/Android.bp
@@ -1,4 +1,13 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "framework-vcn-util-sources",
     srcs: ["util/**/*.java"],
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java
index 02a597e..6ad30b5 100644
--- a/services/core/java/com/android/server/vcn/Vcn.java
+++ b/services/core/java/com/android/server/vcn/Vcn.java
@@ -19,10 +19,12 @@
 import static com.android.server.VcnManagementService.VDBG;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
 import android.net.vcn.VcnConfig;
 import android.net.vcn.VcnGatewayConnectionConfig;
+import android.net.vcn.VcnManager.VcnErrorCode;
 import android.os.Handler;
 import android.os.Message;
 import android.os.ParcelUuid;
@@ -30,7 +32,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.annotations.VisibleForTesting.Visibility;
-import com.android.server.VcnManagementService.VcnSafeModeCallback;
+import com.android.server.VcnManagementService.VcnCallback;
 import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
 
 import java.util.Collections;
@@ -97,7 +99,7 @@
     @NonNull private final ParcelUuid mSubscriptionGroup;
     @NonNull private final Dependencies mDeps;
     @NonNull private final VcnNetworkRequestListener mRequestListener;
-    @NonNull private final VcnSafeModeCallback mVcnSafeModeCallback;
+    @NonNull private final VcnCallback mVcnCallback;
 
     @NonNull
     private final Map<VcnGatewayConnectionConfig, VcnGatewayConnection> mVcnGatewayConnections =
@@ -125,14 +127,8 @@
             @NonNull ParcelUuid subscriptionGroup,
             @NonNull VcnConfig config,
             @NonNull TelephonySubscriptionSnapshot snapshot,
-            @NonNull VcnSafeModeCallback vcnSafeModeCallback) {
-        this(
-                vcnContext,
-                subscriptionGroup,
-                config,
-                snapshot,
-                vcnSafeModeCallback,
-                new Dependencies());
+            @NonNull VcnCallback vcnCallback) {
+        this(vcnContext, subscriptionGroup, config, snapshot, vcnCallback, new Dependencies());
     }
 
     @VisibleForTesting(visibility = Visibility.PRIVATE)
@@ -141,13 +137,12 @@
             @NonNull ParcelUuid subscriptionGroup,
             @NonNull VcnConfig config,
             @NonNull TelephonySubscriptionSnapshot snapshot,
-            @NonNull VcnSafeModeCallback vcnSafeModeCallback,
+            @NonNull VcnCallback vcnCallback,
             @NonNull Dependencies deps) {
         super(Objects.requireNonNull(vcnContext, "Missing vcnContext").getLooper());
         mVcnContext = vcnContext;
         mSubscriptionGroup = Objects.requireNonNull(subscriptionGroup, "Missing subscriptionGroup");
-        mVcnSafeModeCallback =
-                Objects.requireNonNull(vcnSafeModeCallback, "Missing vcnSafeModeCallback");
+        mVcnCallback = Objects.requireNonNull(vcnCallback, "Missing vcnCallback");
         mDeps = Objects.requireNonNull(deps, "Missing deps");
         mRequestListener = new VcnNetworkRequestListener();
 
@@ -246,7 +241,7 @@
     private void handleEnterSafeMode() {
         handleTeardown();
 
-        mVcnSafeModeCallback.onEnteredSafeMode();
+        mVcnCallback.onEnteredSafeMode();
     }
 
     private void handleNetworkRequested(
@@ -337,6 +332,13 @@
     public interface VcnGatewayStatusCallback {
         /** Called by a VcnGatewayConnection to indicate that it has entered safe mode. */
         void onEnteredSafeMode();
+
+        /** Callback by a VcnGatewayConnection to indicate that an error occurred. */
+        void onGatewayConnectionError(
+                @NonNull int[] networkCapabilities,
+                @VcnErrorCode int errorCode,
+                @Nullable String exceptionClass,
+                @Nullable String exceptionMessage);
     }
 
     private class VcnGatewayStatusCallbackImpl implements VcnGatewayStatusCallback {
@@ -344,6 +346,16 @@
         public void onEnteredSafeMode() {
             sendMessage(obtainMessage(MSG_CMD_ENTER_SAFE_MODE));
         }
+
+        @Override
+        public void onGatewayConnectionError(
+                @NonNull int[] networkCapabilities,
+                @VcnErrorCode int errorCode,
+                @Nullable String exceptionClass,
+                @Nullable String exceptionMessage) {
+            mVcnCallback.onGatewayConnectionError(
+                    networkCapabilities, errorCode, exceptionClass, exceptionMessage);
+        }
     }
 
     /** External dependencies used by Vcn, for injection in tests */
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 59cb6ac..06748a3 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -22,6 +22,9 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.vcn.VcnManager.VCN_ERROR_CODE_CONFIG_ERROR;
+import static android.net.vcn.VcnManager.VCN_ERROR_CODE_INTERNAL_ERROR;
+import static android.net.vcn.VcnManager.VCN_ERROR_CODE_NETWORK_ERROR;
 
 import static com.android.server.VcnManagementService.VDBG;
 
@@ -52,7 +55,9 @@
 import android.net.ipsec.ike.IkeSessionCallback;
 import android.net.ipsec.ike.IkeSessionConfiguration;
 import android.net.ipsec.ike.IkeSessionParams;
+import android.net.ipsec.ike.exceptions.AuthenticationFailedException;
 import android.net.ipsec.ike.exceptions.IkeException;
+import android.net.ipsec.ike.exceptions.IkeInternalException;
 import android.net.ipsec.ike.exceptions.IkeProtocolException;
 import android.net.vcn.VcnGatewayConnectionConfig;
 import android.net.vcn.VcnTransportInfo;
@@ -951,15 +956,68 @@
         removeEqualMessages(EVENT_SAFE_MODE_TIMEOUT_EXCEEDED);
     }
 
-    private void sessionLost(int token, @Nullable Exception exception) {
+    private void sessionLostWithoutCallback(int token, @Nullable Exception exception) {
         sendMessageAndAcquireWakeLock(
                 EVENT_SESSION_LOST, token, new EventSessionLostInfo(exception));
     }
 
+    private void sessionLost(int token, @Nullable Exception exception) {
+        // Only notify mGatewayStatusCallback if the session was lost with an error. All
+        // authentication and DNS failures are sent through
+        // IkeSessionCallback.onClosedExceptionally(), which calls sessionClosed()
+        if (exception != null) {
+            mGatewayStatusCallback.onGatewayConnectionError(
+                    mConnectionConfig.getRequiredUnderlyingCapabilities(),
+                    VCN_ERROR_CODE_INTERNAL_ERROR,
+                    RuntimeException.class.getName(),
+                    "Received "
+                            + exception.getClass().getSimpleName()
+                            + " with message: "
+                            + exception.getMessage());
+        }
+
+        sessionLostWithoutCallback(token, exception);
+    }
+
+    private void notifyStatusCallbackForSessionClosed(@NonNull Exception exception) {
+        final int errorCode;
+        final String exceptionClass;
+        final String exceptionMessage;
+
+        if (exception instanceof AuthenticationFailedException) {
+            errorCode = VCN_ERROR_CODE_CONFIG_ERROR;
+            exceptionClass = exception.getClass().getName();
+            exceptionMessage = exception.getMessage();
+        } else if (exception instanceof IkeInternalException
+                && exception.getCause() instanceof IOException) {
+            errorCode = VCN_ERROR_CODE_NETWORK_ERROR;
+            exceptionClass = IOException.class.getName();
+            exceptionMessage = exception.getCause().getMessage();
+        } else {
+            errorCode = VCN_ERROR_CODE_INTERNAL_ERROR;
+            exceptionClass = RuntimeException.class.getName();
+            exceptionMessage =
+                    "Received "
+                            + exception.getClass().getSimpleName()
+                            + " with message: "
+                            + exception.getMessage();
+        }
+
+        mGatewayStatusCallback.onGatewayConnectionError(
+                mConnectionConfig.getRequiredUnderlyingCapabilities(),
+                errorCode,
+                exceptionClass,
+                exceptionMessage);
+    }
+
     private void sessionClosed(int token, @Nullable Exception exception) {
+        if (exception != null) {
+            notifyStatusCallbackForSessionClosed(exception);
+        }
+
         // SESSION_LOST MUST be sent before SESSION_CLOSED to ensure that the SM moves to the
         // Disconnecting state.
-        sessionLost(token, exception);
+        sessionLostWithoutCallback(token, exception);
         sendMessageAndAcquireWakeLock(EVENT_SESSION_CLOSED, token);
     }
 
@@ -1084,6 +1142,8 @@
         }
 
         protected void handleDisconnectRequested(String msg) {
+            // TODO(b/180526152): notify VcnStatusCallback for Network loss
+
             Slog.v(TAG, "Tearing down. Cause: " + msg);
             mIsRunning = false;
 
@@ -1228,6 +1288,8 @@
 
                     String reason = ((EventDisconnectRequestedInfo) msg.obj).reason;
                     if (reason.equals(DISCONNECT_REASON_UNDERLYING_NETWORK_LOST)) {
+                        // TODO(b/180526152): notify VcnStatusCallback for Network loss
+
                         // Will trigger EVENT_SESSION_CLOSED immediately.
                         mIkeSession.kill();
                         break;
@@ -1573,8 +1635,7 @@
 
         @Override
         protected void exitState() {
-            // Attempt to set the safe mode alarm - this requires the Vcn Network being validated
-            // while in ConnectedState (which cancels the previous alarm)
+            // Will only set a new alarm if no safe mode alarm is currently scheduled.
             setSafeModeAlarm();
         }
     }
@@ -1710,8 +1771,6 @@
             }
         }
 
-        // TODO: Make a VcnNetworkSpecifier, and match all underlying subscription IDs.
-
         return builder.build();
     }
 
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 5697564..370d921 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -31,6 +31,7 @@
 import android.app.ActivityManager;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
+import android.app.ILocalWallpaperColorConsumer;
 import android.app.IWallpaperManager;
 import android.app.IWallpaperManagerCallback;
 import android.app.PendingIntent;
@@ -59,6 +60,7 @@
 import android.graphics.BitmapRegionDecoder;
 import android.graphics.Color;
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.hardware.display.DisplayManager;
 import android.os.Binder;
 import android.os.Bundle;
@@ -85,7 +87,10 @@
 import android.service.wallpaper.WallpaperService;
 import android.system.ErrnoException;
 import android.system.Os;
+import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.EventLog;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
@@ -105,7 +110,6 @@
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
-import com.android.server.SystemService.TargetUser;
 import com.android.server.pm.UserManagerInternal;
 import com.android.server.utils.TimingsTraceAndSlog;
 import com.android.server.wm.WindowManagerInternal;
@@ -136,6 +140,8 @@
     private static final String TAG = "WallpaperManagerService";
     private static final boolean DEBUG = false;
     private static final boolean DEBUG_LIVE = true;
+    private static final @NonNull RectF LOCAL_COLOR_BOUNDS =
+            new RectF(0, 0, 1, 1);
 
     public static class Lifecycle extends SystemService {
         private IWallpaperManagerService mService;
@@ -866,6 +872,12 @@
     private final SparseBooleanArray mUserRestorecon = new SparseBooleanArray();
     private int mCurrentUserId = UserHandle.USER_NULL;
     private boolean mInAmbientMode;
+    private ArrayMap<IBinder, ArraySet<RectF>> mLocalColorCallbackAreas =
+            new ArrayMap<>();
+    private ArrayMap<RectF, RemoteCallbackList<ILocalWallpaperColorConsumer>>
+            mLocalColorAreaCallbacks = new ArrayMap<>();
+    private ArrayMap<Integer, ArraySet<RectF>> mLocalColorDisplayIdAreas = new ArrayMap<>();
+    private ArrayMap<IBinder, Integer> mLocalColorCallbackDisplayId = new ArrayMap<>();
 
     static class WallpaperData {
 
@@ -1276,6 +1288,32 @@
         }
 
         @Override
+        public void onLocalWallpaperColorsChanged(RectF area, WallpaperColors colors,
+                int displayId) {
+            forEachDisplayConnector(displayConnector -> {
+                if (displayConnector.mDisplayId == displayId) {
+                    RemoteCallbackList<ILocalWallpaperColorConsumer> callbacks;
+                    ArrayMap<IBinder, Integer> callbackDisplayIds;
+                    synchronized (mLock) {
+                        callbacks = mLocalColorAreaCallbacks.get(area);
+                        callbackDisplayIds = new ArrayMap<>(mLocalColorCallbackDisplayId);
+                    }
+                    if (callbacks == null) return;
+                    callbacks.broadcast(c -> {
+                        try {
+                            int targetDisplayId =
+                                    callbackDisplayIds.get(c.asBinder());
+                            if (targetDisplayId == displayId) c.onColorsChanged(area, colors);
+                        } catch (RemoteException e) {
+                            e.printStackTrace();
+                        }
+                    });
+                }
+            });
+        }
+
+
+        @Override
         public void onServiceDisconnected(ComponentName name) {
             synchronized (mLock) {
                 Slog.w(TAG, "Wallpaper service gone: " + name);
@@ -1437,6 +1475,15 @@
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Failed to request wallpaper colors", e);
                 }
+
+                ArraySet<RectF> areas = mLocalColorDisplayIdAreas.get(displayId);
+                if (areas != null && areas.size() != 0) {
+                    try {
+                        connector.mEngine.addLocalColorsAreas(new ArrayList<>(areas));
+                    } catch (RemoteException e) {
+                        Slog.w(TAG, "Failed to register local colors areas", e);
+                    }
+                }
             }
         }
 
@@ -2340,6 +2387,115 @@
         return true;
     }
 
+    private IWallpaperEngine getEngine(int which, int userId, int displayId) {
+        WallpaperData wallpaperData = findWallpaperAtDisplay(userId, displayId);
+        if (wallpaperData == null) return null;
+        IWallpaperEngine engine = null;
+        synchronized (mLock) {
+            for (int i = 0; i < wallpaperData.connection.mDisplayConnector.size(); i++) {
+                int id = wallpaperData.connection.mDisplayConnector.get(i).mDisplayId;
+                int currentWhich = wallpaperData.connection.mDisplayConnector.get(i).mDisplayId;
+                if (id != displayId && currentWhich != which) continue;
+                engine = wallpaperData.connection.mDisplayConnector.get(i).mEngine;
+                break;
+            }
+        }
+        return engine;
+    }
+
+    @Override
+    public void addOnLocalColorsChangedListener(@NonNull ILocalWallpaperColorConsumer callback,
+            @NonNull List<RectF> regions, int which, int userId, int displayId)
+            throws RemoteException {
+        if (which != FLAG_LOCK && which != FLAG_SYSTEM) {
+            throw new IllegalArgumentException("which should be either FLAG_LOCK or FLAG_SYSTEM");
+        }
+        IWallpaperEngine engine = getEngine(which, userId, displayId);
+        if (engine == null) return;
+        ArrayList<RectF> validAreas = new ArrayList<>(regions.size());
+        synchronized (mLock) {
+            ArraySet<RectF> areas = mLocalColorCallbackAreas.get(callback);
+            if (areas == null) areas = new ArraySet<>(regions.size());
+            areas.addAll(regions);
+            mLocalColorCallbackAreas.put(callback.asBinder(), areas);
+        }
+        for (int i = 0; i < regions.size(); i++) {
+            if (!LOCAL_COLOR_BOUNDS.contains(regions.get(i))) {
+                continue;
+            }
+            RemoteCallbackList callbacks;
+            synchronized (mLock) {
+                callbacks = mLocalColorAreaCallbacks.get(
+                        regions.get(i));
+                if (callbacks == null) {
+                    callbacks = new RemoteCallbackList();
+                    mLocalColorAreaCallbacks.put(regions.get(i), callbacks);
+                }
+                mLocalColorCallbackDisplayId.put(callback.asBinder(), displayId);
+                ArraySet<RectF> displayAreas = mLocalColorDisplayIdAreas.get(displayId);
+                if (displayAreas == null) {
+                    displayAreas = new ArraySet<>(1);
+                    mLocalColorDisplayIdAreas.put(displayId, displayAreas);
+                }
+                displayAreas.add(regions.get(i));
+            }
+            validAreas.add(regions.get(i));
+            callbacks.register(callback);
+        }
+        engine.addLocalColorsAreas(validAreas);
+    }
+
+    @Override
+    public void removeOnLocalColorsChangedListener(
+            @NonNull ILocalWallpaperColorConsumer callback, int which, int userId,
+            int displayId) throws RemoteException {
+        if (which != FLAG_LOCK && which != FLAG_SYSTEM) {
+            throw new IllegalArgumentException("which should be either FLAG_LOCK or FLAG_SYSTEM");
+        }
+        final UserHandle callingUser = Binder.getCallingUserHandle();
+        if (callingUser.getIdentifier() != userId) {
+            throw new SecurityException("calling user id does not match");
+        }
+        final long identity = Binder.clearCallingIdentity();
+        ArrayList<RectF> removeAreas = new ArrayList<>();
+        ArrayList<Pair<RemoteCallbackList, ILocalWallpaperColorConsumer>>
+                callbacksToRemove = new ArrayList<>();
+        try {
+            synchronized (mLock) {
+                ArraySet<RectF> areas = mLocalColorCallbackAreas.remove(callback.asBinder());
+                mLocalColorCallbackDisplayId.remove(callback.asBinder());
+                if (areas == null) areas = new ArraySet<>();
+                for (RectF area : areas) {
+                    RemoteCallbackList callbacks = mLocalColorAreaCallbacks.get(area);
+                    if (callbacks == null) continue;
+                    callbacksToRemove.add(new Pair<>(callbacks, callback));
+                    if (callbacks.getRegisteredCallbackCount() == 0) {
+                        mLocalColorAreaCallbacks.remove(area);
+                        removeAreas.add(area);
+                    }
+                    ArraySet<RectF> displayAreas = mLocalColorDisplayIdAreas.get(displayId);
+                    if (displayAreas != null) {
+                        displayAreas.remove(area);
+                    }
+                }
+            }
+            for (int i = 0; i < callbacksToRemove.size(); i++) {
+                Pair<RemoteCallbackList, ILocalWallpaperColorConsumer>
+                        pair = callbacksToRemove.get(i);
+                pair.first.unregister(pair.second);
+            }
+        } catch (Exception e) {
+            // ignore any exception
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+
+        if (removeAreas.size() == 0) return;
+        IWallpaperEngine engine = getEngine(which, userId, displayId);
+        if (engine == null) return;
+        engine.removeLocalColorsAreas(removeAreas);
+    }
+
     @Override
     public WallpaperColors getWallpaperColors(int which, int userId, int displayId)
             throws RemoteException {
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index c63a0f0..c830ba9 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -43,6 +43,7 @@
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.app.IActivityClientController;
+import android.app.IRequestFinishCallback;
 import android.app.PictureInPictureParams;
 import android.app.servertransaction.ClientTransaction;
 import android.app.servertransaction.EnterPipRequestedItem;
@@ -50,6 +51,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.os.Binder;
 import android.os.Bundle;
@@ -232,7 +235,10 @@
     public void activityRelaunched(IBinder token) {
         final long origId = Binder.clearCallingIdentity();
         synchronized (mGlobalLock) {
-            mTaskSupervisor.activityRelaunchedLocked(token);
+            final ActivityRecord r = ActivityRecord.forTokenLocked(token);
+            if (r != null) {
+                r.finishRelaunching();
+            }
         }
         Binder.restoreCallingIdentity(origId);
     }
@@ -802,7 +808,7 @@
 
                 if (rootTask.inFreeformWindowingMode()) {
                     rootTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
-                } else if (!mService.mSizeCompatFreeform && r.inSizeCompatMode()) {
+                } else if (!mService.mSupportsNonResizableMultiWindow && r.inSizeCompatMode()) {
                     throw new IllegalStateException("Size-compat windows are currently not"
                             + "freeform-enabled");
                 } else if (rootTask.getParent().inFreeformWindowingMode()) {
@@ -1124,24 +1130,78 @@
     }
 
     @Override
-    public void onBackPressedOnTaskRoot(IBinder token) {
+    public void onBackPressedOnTaskRoot(IBinder token, IRequestFinishCallback callback) {
         final long origId = Binder.clearCallingIdentity();
         try {
+            final Intent baseActivityIntent;
+            final boolean launchedFromHome;
+
             synchronized (mGlobalLock) {
                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
-                if (r == null) {
-                    return;
-                }
+                if (r == null) return;
+
                 if (mService.mWindowOrganizerController.mTaskOrganizerController
                         .handleInterceptBackPressedOnTaskRoot(r.getRootTask())) {
                     // This task is handled by a task organizer that has requested the back pressed
                     // callback.
-                } else {
-                    moveActivityTaskToBack(token, false /* nonRoot */);
+                    return;
                 }
+
+                final Intent baseIntent = r.getTask().getBaseIntent();
+                final boolean activityIsBaseActivity = baseIntent != null
+                        && r.mActivityComponent.equals(baseIntent.getComponent());
+                baseActivityIntent = activityIsBaseActivity ? r.intent : null;
+                launchedFromHome = r.launchedFromHomeProcess;
+            }
+
+            // If the activity is one of the main entry points for the application, then we should
+            // refrain from finishing the activity and instead move it to the back to keep it in
+            // memory. The requirements for this are:
+            //   1. The current activity is the base activity for the task.
+            //   2. a. If the activity was launched by the home process, we trust that its intent
+            //         was resolved, so we check if the it is a main intent for the application.
+            //      b. Otherwise, we query Package Manager to verify whether the activity is a
+            //         launcher activity for the application.
+            if (baseActivityIntent != null
+                    && ((launchedFromHome && ActivityRecord.isMainIntent(baseActivityIntent))
+                        || isLauncherActivity(baseActivityIntent.getComponent()))) {
+                moveActivityTaskToBack(token, false /* nonRoot */);
+                return;
+            }
+
+            // The default option for handling the back button is to finish the Activity.
+            try {
+                callback.requestFinish();
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to invoke request finish callback", e);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
         }
     }
+
+    /**
+     * Queries PackageManager to see if the given activity is one of the main entry point for the
+     * application. This should not be called with the WM lock held.
+     */
+    @SuppressWarnings("unchecked")
+    private boolean isLauncherActivity(@NonNull ComponentName activity) {
+        final Intent queryIntent = new Intent(Intent.ACTION_MAIN);
+        queryIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+        queryIntent.setPackage(activity.getPackageName());
+        try {
+            final ParceledListSlice<ResolveInfo> resolved =
+                    mService.getPackageManager().queryIntentActivities(
+                            queryIntent, null, 0, mContext.getUserId());
+            if (resolved == null) return false;
+            for (final ResolveInfo ri : resolved.getList()) {
+                if (ri.getComponentInfo().getComponentName().equals(activity)) {
+                    return true;
+                }
+            }
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to query intent activities", e);
+        }
+        return false;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 9bf6df4..33abcb4 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -40,8 +40,11 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.activityTypeToString;
+import static android.app.WindowConfiguration.isSplitScreenWindowingMode;
 import static android.app.servertransaction.TransferSplashScreenViewStateItem.ATTACH_TO;
 import static android.app.servertransaction.TransferSplashScreenViewStateItem.HANDOVER_TO;
 import static android.content.Intent.ACTION_MAIN;
@@ -209,6 +212,7 @@
 import static com.android.server.wm.WindowManagerService.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND;
 import static com.android.server.wm.WindowManagerService.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING;
 import static com.android.server.wm.WindowManagerService.LETTERBOX_BACKGROUND_SOLID_COLOR;
+import static com.android.server.wm.WindowManagerService.MIN_TASK_LETTERBOX_ASPECT_RATIO;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
 import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
@@ -436,6 +440,7 @@
     final int launchedFromUid; // always the uid who started the activity.
     final String launchedFromPackage; // always the package who started the activity.
     final @Nullable String launchedFromFeatureId; // always the feature in launchedFromPackage
+    final boolean launchedFromHomeProcess; // as per original caller
     final Intent intent;    // the original intent that generated us
     final String shortComponentName; // the short component name of the intent
     final String resolvedType; // as per original caller;
@@ -556,7 +561,7 @@
 
     /**
      * The precomputed display insets for resolving configuration. It will be non-null if
-     * {@link #shouldUseSizeCompatMode} returns {@code true}.
+     * {@link #shouldCreateCompatDisplayInsets} returns {@code true}.
      */
     private CompatDisplayInsets mCompatDisplayInsets;
 
@@ -566,6 +571,7 @@
     boolean mVoiceInteraction;
 
     private int mPendingRelaunchCount;
+    long mRelaunchStartTime;
 
     // True if we are current in the process of removing this app token from the display
     private boolean mRemovingFromDisplay = false;
@@ -646,6 +652,18 @@
      */
     private Rect mSizeCompatBounds;
 
+    // Whether this activity is in size compatibility mode because its bounds don't fit in parent
+    // naturally.
+    private boolean mInSizeCompatModeForBounds = false;
+
+    // Whether this activity is letterboxed for fixed orientation. If letterboxed due to fixed
+    // orientation then aspect ratio restrictions are also already respected.
+    // This happens when an activity has fixed orientation which doesn't match orientation of the
+    // parent because a display is ignoring orientation request or fixed to user rotation.
+    // See WindowManagerService#getIgnoreOrientationRequest and
+    // WindowManagerService#getFixedToUserRotation for more context.
+    private boolean mIsLetterboxedForFixedOrientationAndAspectRatio = false;
+
     // activity is not displayed?
     // TODO: rename to mNoDisplay
     @VisibleForTesting
@@ -745,6 +763,10 @@
     // Token for targeting this activity for assist purposes.
     final Binder assistToken = new Binder();
 
+    // A reusable token for other purposes, e.g. content capture, translation. It shouldn't be used
+    // without security checks
+    final Binder shareableActivityToken = new Binder();
+
     // Tracking cookie for the launch of this activity and it's task.
     IBinder mLaunchCookie;
 
@@ -1294,9 +1316,6 @@
             // TODO(b/36505427): Maybe this call should be moved inside
             // updateOverrideConfiguration()
             newTask.updateOverrideConfigurationFromLaunchBounds();
-            // Make sure override configuration is up-to-date before using to create window
-            // controller.
-            updateSizeCompatMode();
             // When an activity is started directly into a split-screen fullscreen root task, we
             // need to update the initial multi-window modes so that the callbacks are scheduled
             // correctly when the user leaves that mode.
@@ -1667,6 +1686,7 @@
         launchedFromUid = _launchedFromUid;
         launchedFromPackage = _launchedFromPackage;
         launchedFromFeatureId = _launchedFromFeature;
+        launchedFromHomeProcess = _caller != null && _caller.isHomeProcess();
         shortComponentName = _intent.getComponent().flattenToShortString();
         resolvedType = _resolvedType;
         componentSpecified = _componentSpecified;
@@ -2546,9 +2566,7 @@
      *         root task.
      */
     boolean supportsFreeform() {
-        return mAtmService.mSupportsFreeformWindowManagement
-                // Either the activity is resizable, or we allow size compat in freeform.
-                && (supportsMultiWindow() || mAtmService.mSizeCompatFreeform);
+        return mAtmService.mSupportsFreeformWindowManagement && supportsMultiWindow();
     }
 
     /**
@@ -3355,7 +3373,11 @@
         return task.isDragResizing();
     }
 
+    @VisibleForTesting
     void startRelaunching() {
+        if (mPendingRelaunchCount == 0) {
+            mRelaunchStartTime = SystemClock.elapsedRealtime();
+        }
         if (shouldFreezeBounds()) {
             freezeBounds();
         }
@@ -3394,6 +3416,14 @@
             // Update keyguard flags upon finishing relaunch.
             checkKeyguardFlagsChanged();
         }
+
+        final Task rootTask = getRootTask();
+        if (rootTask != null && rootTask.shouldSleepOrShutDownActivities()) {
+            // Activity is always relaunched to either resumed or paused state. If it was
+            // relaunched while hidden (by keyguard or smth else), it should be stopped.
+            rootTask.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
+                    false /* preserveWindows */);
+        }
     }
 
     void clearRelaunching() {
@@ -3402,6 +3432,7 @@
         }
         unfreezeBounds();
         mPendingRelaunchCount = 0;
+        mRelaunchStartTime = 0;
     }
 
     /**
@@ -3608,7 +3639,7 @@
         }
 
         // Reset the last saved PiP snap fraction on removal.
-        mDisplayContent.mPinnedStackControllerLocked.onActivityHidden(mActivityComponent);
+        mDisplayContent.mPinnedTaskControllerLocked.onActivityHidden(mActivityComponent);
         mWmService.mEmbeddedWindowController.onActivityRemoved(this);
         mRemovingFromDisplay = false;
     }
@@ -4960,7 +4991,7 @@
         ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppStopped: %s", this);
         mAppStopped = true;
         // Reset the last saved PiP snap fraction on app stop.
-        mDisplayContent.mPinnedStackControllerLocked.onActivityHidden(mActivityComponent);
+        mDisplayContent.mPinnedTaskControllerLocked.onActivityHidden(mActivityComponent);
         destroySurfaces();
         // Remove any starting window that was added for this app if they are still around.
         removeStartingWindow();
@@ -6702,12 +6733,8 @@
         }
 
         if (onDescendantOrientationChanged(this)) {
-            // The app is just becoming visible, and the parent Task has updated with the
-            // orientation request. Update the size compat mode.
-            updateSizeCompatMode();
-            // WM Shell can override WM Core positioning (e.g. for letterboxing) so ensure
-            // that WM Shell is called when an activity becomes visible. Without this, WM Core
-            // will handle positioning instead of WM Shell when an app is reopened.
+            // WM Shell can show additional UI elements, e.g. a restart button for size compat mode
+            // so ensure that WM Shell is called when an activity becomes visible.
             task.dispatchTaskInfoChangedIfNeeded(/* force= */ true);
         }
     }
@@ -6772,7 +6799,10 @@
      *         density than its parent or its bounds don't fit in parent naturally.
      */
     boolean inSizeCompatMode() {
-        if (mCompatDisplayInsets == null || !shouldUseSizeCompatMode()
+        if (mInSizeCompatModeForBounds) {
+            return true;
+        }
+        if (mCompatDisplayInsets == null || !shouldCreateCompatDisplayInsets()
                 // The orientation is different from parent when transforming.
                 || isFixedRotationTransforming()) {
             return false;
@@ -6782,70 +6812,30 @@
             // The app bounds hasn't been computed yet.
             return false;
         }
-
         final Configuration parentConfig = getParent().getConfiguration();
         // Although colorMode, screenLayout, smallestScreenWidthDp are also fixed, generally these
         // fields should be changed with density and bounds, so here only compares the most
         // significant field.
-        if (parentConfig.densityDpi != getConfiguration().densityDpi) {
-            return true;
-        }
-
-        final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
-        final int appWidth = appBounds.width();
-        final int appHeight = appBounds.height();
-        final int parentAppWidth = parentAppBounds.width();
-        final int parentAppHeight = parentAppBounds.height();
-        if (parentAppWidth == appWidth && parentAppHeight == appHeight) {
-            // Matched the parent bounds.
-            return false;
-        }
-        if (parentAppWidth > appWidth && parentAppHeight > appHeight) {
-            // Both sides are smaller than the parent.
-            return true;
-        }
-        if (parentAppWidth < appWidth || parentAppHeight < appHeight) {
-            // One side is larger than the parent.
-            return true;
-        }
-
-        // The rest of the condition is that only one side is smaller than the parent, but it still
-        // needs to exclude the cases where the size is limited by the fixed aspect ratio.
-        if (info.maxAspectRatio > 0) {
-            final float aspectRatio = (0.5f + Math.max(appWidth, appHeight))
-                    / Math.min(appWidth, appHeight);
-            if (aspectRatio >= info.maxAspectRatio) {
-                // The current size has reached the max aspect ratio.
-                return false;
-            }
-        }
-        if (info.minAspectRatio > 0) {
-            // The activity should have at least the min aspect ratio, so this checks if the parent
-            // still has available space to provide larger aspect ratio.
-            final float parentAspectRatio = (0.5f + Math.max(parentAppWidth, parentAppHeight))
-                    / Math.min(parentAppWidth, parentAppHeight);
-            if (parentAspectRatio <= info.minAspectRatio) {
-                // The long side has reached the parent.
-                return false;
-            }
-        }
-        return true;
+        return parentConfig.densityDpi != getConfiguration().densityDpi;
     }
 
     /**
      * Indicates the activity will keep the bounds and screen configuration when it was first
      * launched, no matter how its parent changes.
      *
+     * <p>If {@true}, then {@link CompatDisplayInsets} will be created in {@link
+     * #resolveOverrideConfiguration} to "freeze" activity bounds and insets.
+     *
      * @return {@code true} if this activity is declared as non-resizable and fixed orientation or
      *         aspect ratio.
      */
-    boolean shouldUseSizeCompatMode() {
+    boolean shouldCreateCompatDisplayInsets() {
         if (info.supportsSizeChanges() != ActivityInfo.SIZE_CHANGES_UNSUPPORTED) {
             return false;
         }
         if (inMultiWindowMode() || getWindowConfiguration().hasWindowDecorCaption()) {
             final ActivityRecord root = task != null ? task.getRootActivity() : null;
-            if (root != null && root != this && !root.shouldUseSizeCompatMode()) {
+            if (root != null && root != this && !root.shouldCreateCompatDisplayInsets()) {
                 // If the root activity doesn't use size compatibility mode, the activities above
                 // are forced to be the same for consistent visual appearance.
                 return false;
@@ -6867,25 +6857,11 @@
     }
 
     // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
-    private void updateSizeCompatMode() {
-        if (mCompatDisplayInsets != null || !shouldUseSizeCompatMode()) {
+    private void updateCompatDisplayInsets(@Nullable Rect fixedOrientationBounds) {
+        if (mCompatDisplayInsets != null || !shouldCreateCompatDisplayInsets()) {
             // The override configuration is set only once in size compatibility mode.
             return;
         }
-        final Configuration parentConfig = getParent().getConfiguration();
-        if (!hasProcess() && !isConfigurationCompatible(parentConfig)) {
-            // Don't compute when launching in fullscreen and the fixed orientation is not the
-            // current orientation. It is more accurately to compute the override bounds from
-            // the updated configuration after the fixed orientation is applied.
-            return;
-        }
-
-        if (task == null || (!handlesOrientationChangeFromDescendant()
-                && task.getLastTaskBoundsComputeActivity() != this)) {
-            // Don't compute when Task hasn't computed its bounds for this app, because the Task can
-            // be letterboxed, and its bounds may not be accurate until then.
-            return;
-        }
 
         Configuration overrideConfig = getRequestedOverrideConfiguration();
         final Configuration fullConfig = getConfiguration();
@@ -6908,17 +6884,18 @@
         }
 
         // The role of CompatDisplayInsets is like the override bounds.
-        mCompatDisplayInsets = new CompatDisplayInsets(mDisplayContent, this);
+        mCompatDisplayInsets =
+                new CompatDisplayInsets(mDisplayContent, this, fixedOrientationBounds);
     }
 
     @VisibleForTesting
     void clearSizeCompatMode() {
+        mInSizeCompatModeForBounds = false;
         mSizeCompatScale = 1f;
         mSizeCompatBounds = null;
         mCompatDisplayInsets = null;
 
-        // Recompute from Task because letterbox can also happen on Task level.
-        task.onRequestedOverrideConfigurationChanged(task.getRequestedOverrideConfiguration());
+        onRequestedOverrideConfigurationChanged(getRequestedOverrideConfiguration());
     }
 
     @Override
@@ -6953,23 +6930,41 @@
             mTmpConfig.updateFrom(resolvedConfig);
             newParentConfiguration = mTmpConfig;
         }
+
+        final int windowingMode = getWindowingMode();
+        // TODO(b/181207944): Consider removing the if condition and always run
+        // resolveFixedOrientationConfiguration() since this should be applied for all cases.
+        if (isSplitScreenWindowingMode(windowingMode)
+                || windowingMode == WINDOWING_MODE_MULTI_WINDOW
+                || windowingMode == WINDOWING_MODE_FULLSCREEN) {
+            resolveFixedOrientationConfiguration(newParentConfiguration);
+        }
+        final Rect fixedOrientationBounds = isLetterboxedForFixedOrientationAndAspectRatio()
+                ? new Rect(resolvedConfig.windowConfiguration.getBounds()) : null;
+
         if (mCompatDisplayInsets != null) {
             resolveSizeCompatModeConfiguration(newParentConfiguration);
-        } else {
-            if (inMultiWindowMode()) {
-                // We ignore activities' requested orientation in multi-window modes. Task level may
-                // take them into consideration when calculating bounds.
-                resolvedConfig.orientation = Configuration.ORIENTATION_UNDEFINED;
-                // If the activity has requested override bounds, the configuration needs to be
-                // computed accordingly.
-                if (!matchParentBounds()) {
-                    task.computeConfigResourceOverrides(resolvedConfig, newParentConfiguration);
-                }
-            } else {
-                resolveFullscreenConfiguration(newParentConfiguration);
+        } else if (inMultiWindowMode()) {
+            // We ignore activities' requested orientation in multi-window modes. They may be
+            // taken into consideration in resolveFixedOrientationConfiguration call above.
+            resolvedConfig.orientation = Configuration.ORIENTATION_UNDEFINED;
+            // If the activity has requested override bounds, the configuration needs to be
+            // computed accordingly.
+            if (!matchParentBounds()) {
+                task.computeConfigResourceOverrides(resolvedConfig, newParentConfiguration);
             }
+        // If activity in fullscreen mode is letterboxed because of fixed orientation then bounds
+        // are already calculated in resolveFixedOrientationConfiguration.
+        } else if (!isLetterboxedForFixedOrientationAndAspectRatio()) {
+            resolveFullscreenConfiguration(newParentConfiguration);
         }
 
+        if (mVisibleRequested) {
+            updateCompatDisplayInsets(fixedOrientationBounds);
+        }
+
+        // TODO(b/175212232): Consolidate position logic from each "resolve" method above here.
+
         // Assign configuration sequence number into hierarchy because there is a different way than
         // ensureActivityConfiguration() in this class that uses configuration in WindowState during
         // layout traversals.
@@ -6978,6 +6973,109 @@
     }
 
     /**
+     * Whether this activity is letterboxed for fixed orientation. If letterboxed due to fixed
+     * orientation then aspect ratio restrictions are also already respected.
+     *
+     * <p>This happens when an activity has fixed orientation which doesn't match orientation of the
+     * parent because a display setting 'ignoreOrientationRequest' is set to true. See {@link
+     * WindowManagerService#getIgnoreOrientationRequest} for more context.
+     */
+    boolean isLetterboxedForFixedOrientationAndAspectRatio() {
+        return mIsLetterboxedForFixedOrientationAndAspectRatio;
+    }
+
+    /**
+     * Computes bounds (letterbox or pillarbox) when the parent doesn't handle the orientation
+     * change and the requested orientation is different from the parent.
+     *
+     * <p>If letterboxed due to fixed orientation then aspect ratio restrictions are also applied
+     * in this methiod.
+     */
+    private void resolveFixedOrientationConfiguration(@NonNull Configuration newParentConfig) {
+        mIsLetterboxedForFixedOrientationAndAspectRatio = false;
+        if (handlesOrientationChangeFromDescendant()) {
+            // No need to letterbox because of fixed orientation. Display will handle
+            // fixed-orientation requests.
+            return;
+        }
+
+        final Rect resolvedBounds =
+                getResolvedOverrideConfiguration().windowConfiguration.getBounds();
+        final int parentOrientation = newParentConfig.orientation;
+
+        // If the activity requires a different orientation (either by override or activityInfo),
+        // make it fit the available bounds by scaling down its bounds.
+        final int forcedOrientation = getRequestedConfigurationOrientation();
+        if (forcedOrientation == ORIENTATION_UNDEFINED || forcedOrientation == parentOrientation) {
+            return;
+        }
+
+        if (mCompatDisplayInsets != null && !mCompatDisplayInsets.mIsInFixedOrientationLetterbox) {
+            // App prefers to keep its original size.
+            // If the size compat is from previous fixed orientation letterboxing, we may want to
+            // have fixed orientation letterbox again, otherwise it will show the size compat
+            // restart button even if the restart bounds will be the same.
+            return;
+        }
+
+        final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
+        final int parentWidth = parentBounds.width();
+        final int parentHeight = parentBounds.height();
+        float aspect = Math.max(parentWidth, parentHeight)
+                / (float) Math.min(parentWidth, parentHeight);
+
+        // Adjust the fixed orientation letterbox bounds to fit the app request aspect ratio in
+        // order to use the extra available space.
+        final float maxAspectRatio = info.maxAspectRatio;
+        final float minAspectRatio = info.minAspectRatio;
+        if (aspect > maxAspectRatio && maxAspectRatio != 0) {
+            aspect = maxAspectRatio;
+        } else if (aspect < minAspectRatio) {
+            aspect = minAspectRatio;
+        }
+
+        // Override from config_letterboxAspectRatio or via ADB with set-letterbox-aspect-ratio.
+        // TODO(b/175212232): Rename getTaskLetterboxAspectRatio and all related methods since fixed
+        // orientation letterbox is on the activity level now.
+        final float letterboxAspectRatioOverride = mWmService.getTaskLetterboxAspectRatio();
+        // Activity min/max aspect ratio restrictions will be respected by the activity-level
+        // letterboxing (size-compat mode). Therefore this override can control the maximum screen
+        // area that can be occupied by the app in the letterbox mode.
+        aspect = letterboxAspectRatioOverride > MIN_TASK_LETTERBOX_ASPECT_RATIO
+                ? letterboxAspectRatioOverride : aspect;
+
+        // Store the current bounds to be able to revert to size compat mode values below if needed.
+        Rect mTmpFullBounds = new Rect(resolvedBounds);
+        if (forcedOrientation == ORIENTATION_LANDSCAPE) {
+            final int height = (int) Math.rint(parentWidth / aspect);
+            final int top = parentBounds.centerY() - height / 2;
+            resolvedBounds.set(parentBounds.left, top, parentBounds.right, top + height);
+        } else {
+            final int width = (int) Math.rint(parentHeight / aspect);
+            final int left = parentBounds.centerX() - width / 2;
+            resolvedBounds.set(left, parentBounds.top, left + width, parentBounds.bottom);
+        }
+
+        if (mCompatDisplayInsets != null) {
+            mCompatDisplayInsets.getBoundsByRotation(
+                    mTmpBounds, newParentConfig.windowConfiguration.getRotation());
+            if (resolvedBounds.width() != mTmpBounds.width()
+                    || resolvedBounds.height() != mTmpBounds.height()) {
+                // The app shouldn't be resized, we only do fixed orientation letterboxing if the
+                // compat bounds are also from the same fixed orientation letterbox. Otherwise,
+                // clear the fixed orientation bounds to show app in size compat mode.
+                resolvedBounds.set(mTmpFullBounds);
+                return;
+            }
+        }
+
+        // Calculate app bounds using fixed orientation bounds because they will be needed later
+        // for comparison with size compat app bounds in {@link resolveSizeCompatModeConfiguration}.
+        task.computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig);
+        mIsLetterboxedForFixedOrientationAndAspectRatio = true;
+    }
+
+    /**
      * Resolves the configuration of activity in fullscreen mode. If the bounds are restricted by
      * aspect ratio, the position will be centered horizontally in parent's app bounds to balance
      * the visual appearance. The policy of aspect ratio has higher priority than the requested
@@ -7021,6 +7119,18 @@
     private void resolveSizeCompatModeConfiguration(Configuration newParentConfiguration) {
         final Configuration resolvedConfig = getResolvedOverrideConfiguration();
         final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds();
+
+        // When an activity needs to be letterboxed because of fixed orientation, use fixed
+        // orientation bounds (stored in resolved bounds) instead of parent bounds since the
+        // activity will be displayed within them even if it is in size compat mode. They should be
+        // saved here before resolved bounds are overridden below.
+        final Rect containerBounds = isLetterboxedForFixedOrientationAndAspectRatio()
+                ? new Rect(resolvedBounds)
+                : newParentConfiguration.windowConfiguration.getBounds();
+        final Rect containerAppBounds = isLetterboxedForFixedOrientationAndAspectRatio()
+                ? new Rect(getResolvedOverrideConfiguration().windowConfiguration.getAppBounds())
+                : newParentConfiguration.windowConfiguration.getAppBounds();
+
         final int requestedOrientation = getRequestedConfigurationOrientation();
         final boolean orientationRequested = requestedOrientation != ORIENTATION_UNDEFINED;
         final int orientation = orientationRequested
@@ -7079,7 +7189,7 @@
         // Below figure is an example that puts an activity which was launched in a larger container
         // into a smaller container.
         //   The outermost rectangle is the real display bounds.
-        //   "@" is the parent app bounds.
+        //   "@" is the container app bounds (parent bounds or fixed orientation bouds)
         //   "#" is the {@code resolvedBounds} that applies to application.
         //   "*" is the {@code mSizeCompatBounds} that used to show on screen if scaled.
         // ------------------------------
@@ -7095,19 +7205,18 @@
         // The application is still layouted in "#" since it was launched, and it will be visually
         // scaled and positioned to "*".
 
+        final Rect resolvedAppBounds = resolvedConfig.windowConfiguration.getAppBounds();
+
         // Calculates the scale and offset to horizontal center the size compatibility bounds into
         // the region which is available to application.
-        final Rect parentBounds = newParentConfiguration.windowConfiguration.getBounds();
-        final Rect parentAppBounds = newParentConfiguration.windowConfiguration.getAppBounds();
-        final Rect resolvedAppBounds = resolvedConfig.windowConfiguration.getAppBounds();
         final int contentW = resolvedAppBounds.width();
         final int contentH = resolvedAppBounds.height();
-        final int viewportW = parentAppBounds.width();
-        final int viewportH = parentAppBounds.height();
+        final int viewportW = containerAppBounds.width();
+        final int viewportH = containerAppBounds.height();
         // Only allow to scale down.
         mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
                 ? 1f : Math.min((float) viewportW / contentW, (float) viewportH / contentH);
-        final int screenTopInset = parentAppBounds.top - parentBounds.top;
+        final int screenTopInset = containerAppBounds.top - containerBounds.top;
         final boolean topNotAligned = screenTopInset != resolvedAppBounds.top - resolvedBounds.top;
         if (mSizeCompatScale != 1f || topNotAligned) {
             if (mSizeCompatBounds == null) {
@@ -7127,8 +7236,9 @@
         final int offsetX = getHorizontalCenterOffset(
                 (int) viewportW, (int) (contentW * mSizeCompatScale));
         // Above coordinates are in "@" space, now place "*" and "#" to screen space.
-        final int screenPosX = (fillContainer ? parentBounds.left : parentAppBounds.left) + offsetX;
-        final int screenPosY = parentBounds.top;
+        final int screenPosX = (fillContainer
+                ? containerBounds.left : containerAppBounds.left) + offsetX;
+        final int screenPosY = containerBounds.top;
         if (screenPosX != 0 || screenPosY != 0) {
             if (mSizeCompatBounds != null) {
                 mSizeCompatBounds.offset(screenPosX, screenPosY);
@@ -7138,6 +7248,52 @@
             final int dy = screenPosY - resolvedBounds.top;
             offsetBounds(resolvedConfig, dx, dy);
         }
+
+        mInSizeCompatModeForBounds =
+                isInSizeCompatModeForBounds(resolvedAppBounds, containerAppBounds);
+    }
+
+    private boolean isInSizeCompatModeForBounds(final Rect appBounds, final Rect containerBounds) {
+        final int appWidth = appBounds.width();
+        final int appHeight = appBounds.height();
+        final int containerAppWidth = containerBounds.width();
+        final int containerAppHeight = containerBounds.height();
+
+        if (containerAppWidth == appWidth && containerAppHeight == appHeight) {
+            // Matched the container bounds.
+            return false;
+        }
+        if (containerAppWidth > appWidth && containerAppHeight > appHeight) {
+            // Both sides are smaller than the container.
+            return true;
+        }
+        if (containerAppWidth < appWidth || containerAppHeight < appHeight) {
+            // One side is larger than the container.
+            return true;
+        }
+
+        // The rest of the condition is that only one side is smaller than the container, but it
+        // still needs to exclude the cases where the size is limited by the fixed aspect ratio.
+        if (info.maxAspectRatio > 0) {
+            final float aspectRatio = (0.5f + Math.max(appWidth, appHeight))
+                    / Math.min(appWidth, appHeight);
+            if (aspectRatio >= info.maxAspectRatio) {
+                // The current size has reached the max aspect ratio.
+                return false;
+            }
+        }
+        if (info.minAspectRatio > 0) {
+            // The activity should have at least the min aspect ratio, so this checks if the
+            // container still has available space to provide larger aspect ratio.
+            final float containerAspectRatio =
+                    (0.5f + Math.max(containerAppWidth, containerAppHeight))
+                            / Math.min(containerAppWidth, containerAppHeight);
+            if (containerAspectRatio <= info.minAspectRatio) {
+                // The long side has reached the parent.
+                return false;
+            }
+        }
+        return true;
     }
 
     /** @return The horizontal offset of putting the content in the center of viewport. */
@@ -7289,7 +7445,8 @@
         final Task rootTask = getRootTask();
         final float minAspectRatio = info.minAspectRatio;
 
-        if (task == null || rootTask == null || (inMultiWindowMode() && !shouldUseSizeCompatMode())
+        if (task == null || rootTask == null
+                || (inMultiWindowMode() && !shouldCreateCompatDisplayInsets())
                 || (maxAspectRatio == 0 && minAspectRatio == 0)
                 || isInVrUiMode(getConfiguration())) {
             // We don't enforce aspect ratio if the activity task is in multiwindow unless it
@@ -7427,8 +7584,6 @@
         if (displayChanged) {
             mLastReportedDisplayId = newDisplayId;
         }
-        // TODO(b/36505427): Is there a better place to do this?
-        updateSizeCompatMode();
 
         // Short circuit: if the two full configurations are equal (the common case), then there is
         // nothing to do.  We test the full configuration instead of the global and merged override
@@ -7707,11 +7862,6 @@
         // Reset the existing override configuration so it can be updated according to the latest
         // configuration.
         clearSizeCompatMode();
-        if (mVisibleRequested) {
-            // Configuration will be ensured when becoming visible, so if it is already visible,
-            // then the manual update is needed.
-            updateSizeCompatMode();
-        }
 
         if (!attachedToProcess()) {
             return;
@@ -8118,8 +8268,11 @@
         private final int mHeight;
         /** Whether the {@link Task} windowingMode represents a floating window*/
         final boolean mIsFloating;
-        /** Whether the {@link Task} is letterboxed when the unresizable activity is first shown. */
-        final boolean mIsTaskLetterboxed;
+        /**
+         * Whether is letterboxed because of fixed orientation when the unresizable activity is
+         * first shown.
+         */
+        final boolean mIsInFixedOrientationLetterbox;
         /**
          * The nonDecorInsets for each rotation. Includes the navigation bar and cutout insets. It
          * is used to compute the appBounds.
@@ -8133,7 +8286,8 @@
         final Rect[] mStableInsets = new Rect[4];
 
         /** Constructs the environment to simulate the bounds behavior of the given container. */
-        CompatDisplayInsets(DisplayContent display, ActivityRecord container) {
+        CompatDisplayInsets(DisplayContent display, ActivityRecord container,
+                @Nullable Rect fixedOrientationBounds) {
             mIsFloating = container.getWindowConfiguration().tasksAreFloating();
             if (mIsFloating) {
                 final Rect containerBounds = container.getWindowConfiguration().getBounds();
@@ -8146,24 +8300,34 @@
                     mNonDecorInsets[rotation] = emptyRect;
                     mStableInsets[rotation] = emptyRect;
                 }
-                mIsTaskLetterboxed = false;
+                mIsInFixedOrientationLetterbox = false;
                 return;
             }
 
             final Task task = container.getTask();
-            mIsTaskLetterboxed = task != null && task.isTaskLetterboxed();
+
+            mIsInFixedOrientationLetterbox = fixedOrientationBounds != null;
 
             // Store the bounds of the Task for the non-resizable activity to use in size compat
             // mode so that the activity will not be resized regardless the windowing mode it is
             // currently in.
-            final WindowContainer filledContainer = task != null ? task : display;
-            final Point dimensions = getRotationZeroDimensions(filledContainer);
+            // When an activity needs to be letterboxed because of fixed orientation, use fixed
+            // orientation bounds instead of task bounds since the activity will be displayed
+            // within these even if it is in size compat mode.
+            final Rect filledContainerBounds = mIsInFixedOrientationLetterbox
+                    ? fixedOrientationBounds
+                    : task != null ? task.getBounds() : display.getBounds();
+            final int filledContainerRotation = task != null
+                    ? task.getConfiguration().windowConfiguration.getRotation()
+                    : display.getConfiguration().windowConfiguration.getRotation();
+            final Point dimensions = getRotationZeroDimensions(
+                    filledContainerBounds, filledContainerRotation);
             mWidth = dimensions.x;
             mHeight = dimensions.y;
 
             // Bounds of the filled container if it doesn't fill the display.
             final Rect unfilledContainerBounds =
-                    filledContainer.getBounds().equals(display.getBounds()) ? null : new Rect();
+                    filledContainerBounds.equals(display.getBounds()) ? null : new Rect();
             final DisplayPolicy policy = display.getDisplayPolicy();
             for (int rotation = 0; rotation < 4; rotation++) {
                 mNonDecorInsets[rotation] = new Rect();
@@ -8183,9 +8347,9 @@
                 // The insets is based on the display, but the container may be smaller than the
                 // display, so update the insets to exclude parts that are not intersected with the
                 // container.
-                unfilledContainerBounds.set(filledContainer.getBounds());
+                unfilledContainerBounds.set(filledContainerBounds);
                 display.rotateBounds(
-                        filledContainer.getConfiguration().windowConfiguration.getRotation(),
+                        filledContainerRotation,
                         rotation,
                         unfilledContainerBounds);
                 updateInsetsForBounds(unfilledContainerBounds, dw, dh, mNonDecorInsets[rotation]);
@@ -8198,9 +8362,7 @@
          * the display is rotated, we can calculate the bounds by rotating the dimensions.
          * @see #getBoundsByRotation
          */
-        private static Point getRotationZeroDimensions(WindowContainer container) {
-            final Rect bounds = container.getBounds();
-            final int rotation = container.getConfiguration().windowConfiguration.getRotation();
+        private static Point getRotationZeroDimensions(final Rect bounds, int rotation) {
             final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
             final int width = bounds.width();
             final int height = bounds.height();
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 37fda4c..6ce9048 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1708,7 +1708,7 @@
 
         // If the activity being launched is the same as the one currently at the top, then
         // we need to check if it should only be launched once.
-        final Task topRootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();
+        final Task topRootTask = mPreferredTaskDisplayArea.getFocusedRootTask();
         if (topRootTask != null) {
             startResult = deliverToCurrentTopIfNeeded(topRootTask, intentGrants);
             if (startResult != START_SUCCESS) {
@@ -1989,6 +1989,13 @@
             return START_SUCCESS;
         }
 
+        // The reusedActivity could be finishing, for example of starting an activity with
+        // FLAG_ACTIVITY_CLEAR_TOP flag. In that case, use the top running activity in the
+        // task instead.
+        targetTaskTop = targetTaskTop.finishing
+                ? targetTask.getTopNonFinishingActivity()
+                : targetTaskTop;
+
         // At this point we are certain we want the task moved to the front. If we need to dismiss
         // any other always-on-top root tasks, now is the time to do it.
         if (targetTaskTop.canTurnScreenOn() && mService.mInternal.isDreaming()) {
@@ -2005,11 +2012,8 @@
         // We didn't do anything...  but it was needed (a.k.a., client don't use that intent!)
         // And for paranoia, make sure we have correctly resumed the top activity.
         resumeTargetRootTaskIfNeeded();
-        // The reusedActivity could be finishing, for example of starting an activity with
-        // FLAG_ACTIVITY_CLEAR_TOP flag. In that case, return the top running activity in the
-        // task instead.
-        mLastStartActivityRecord =
-                targetTaskTop.finishing ? targetTask.getTopNonFinishingActivity() : targetTaskTop;
+      
+        mLastStartActivityRecord = targetTaskTop;
         return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 94379b1..e858fe1 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -348,13 +348,16 @@
     public final class ActivityTokens {
         private final @NonNull IBinder mActivityToken;
         private final @NonNull IBinder mAssistToken;
+        private final @NonNull IBinder mShareableActivityToken;
         private final @NonNull IApplicationThread mAppThread;
 
         public ActivityTokens(@NonNull IBinder activityToken,
-                @NonNull IBinder assistToken, @NonNull IApplicationThread appThread) {
+                @NonNull IBinder assistToken, @NonNull IApplicationThread appThread,
+                @NonNull IBinder shareableActivityToken) {
             mActivityToken = activityToken;
             mAssistToken = assistToken;
             mAppThread = appThread;
+            mShareableActivityToken = shareableActivityToken;
         }
 
         /**
@@ -372,6 +375,13 @@
         }
 
         /**
+         * @return The sharable activity token..
+         */
+        public @NonNull IBinder getShareableActivityToken() {
+            return mShareableActivityToken;
+        }
+
+        /**
          * @return The assist token.
          */
         public @NonNull IApplicationThread getApplicationThread() {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 2e98c2c..a874dee 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -58,7 +58,6 @@
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW;
-import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RTL;
 import static android.provider.Settings.Global.HIDE_ERROR_DIALOGS;
@@ -318,6 +317,7 @@
     public static final String DUMP_CONTAINERS_CMD = "containers";
     public static final String DUMP_RECENTS_CMD = "recents";
     public static final String DUMP_RECENTS_SHORT_CMD = "r";
+    public static final String DUMP_TOP_RESUMED_ACTIVITY = "top-resumed";
 
     /** This activity is not being relaunched, or being relaunched for a non-resize reason. */
     public static final int RELAUNCH_REASON_NONE = 0;
@@ -556,7 +556,6 @@
     boolean mSupportsPictureInPicture;
     boolean mSupportsMultiDisplay;
     boolean mForceResizableActivities;
-    boolean mSizeCompatFreeform;
     boolean mSupportsNonResizableMultiWindow;
 
     final List<ActivityTaskManagerInternal.ScreenObserver> mScreenObservers = new ArrayList<>();
@@ -787,8 +786,6 @@
         final boolean forceRtl = Settings.Global.getInt(resolver, DEVELOPMENT_FORCE_RTL, 0) != 0;
         final boolean forceResizable = Settings.Global.getInt(
                 resolver, DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0;
-        final boolean sizeCompatFreeform = Settings.Global.getInt(
-                resolver, DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM, 0) != 0;
         final boolean supportsNonResizableMultiWindow = Settings.Global.getInt(
                 resolver, DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW, 1) != 0;
 
@@ -804,7 +801,6 @@
 
         synchronized (mGlobalLock) {
             mForceResizableActivities = forceResizable;
-            mSizeCompatFreeform = sizeCompatFreeform;
             mSupportsNonResizableMultiWindow = supportsNonResizableMultiWindow;
             final boolean multiWindowFormEnabled = freeformWindowManagement
                     || supportsSplitScreenMultiWindow
@@ -863,7 +859,8 @@
 
         mTaskChangeNotificationController =
                 new TaskChangeNotificationController(mGlobalLock, mTaskSupervisor, mH);
-        mLockTaskController = new LockTaskController(mContext, mTaskSupervisor, mH);
+        mLockTaskController = new LockTaskController(mContext, mTaskSupervisor, mH,
+                mTaskChangeNotificationController);
         mActivityStartController = new ActivityStartController(this);
         setRecentTasks(new RecentTasks(this, mTaskSupervisor));
         mVrController = new VrController(mGlobalLock);
@@ -2093,10 +2090,14 @@
         }
     }
 
-    /** @return the max ANR delay from all registered {@link AnrController} instances */
-    public long getMaxAnrDelayMillis(ApplicationInfo info) {
+    /**
+     * @return the controller with the max ANR delay from all registered
+     * {@link AnrController} instances
+     */
+    @Nullable
+    public AnrController getAnrController(ApplicationInfo info) {
         if (info == null || info.packageName == null) {
-            return 0;
+            return null;
         }
 
         final ArrayList<AnrController> controllers;
@@ -2105,12 +2106,19 @@
         }
 
         final String packageName = info.packageName;
+        final int uid = info.uid;
         long maxDelayMs = 0;
+        AnrController controllerWithMaxDelay = null;
+
         for (AnrController controller : controllers) {
-            maxDelayMs = Math.max(maxDelayMs, controller.getAnrDelayMillis(packageName, info.uid));
+            long delayMs = controller.getAnrDelayMillis(packageName, uid);
+            if (delayMs > 0 && delayMs > maxDelayMs) {
+                controllerWithMaxDelay = controller;
+                maxDelayMs = delayMs;
+            }
         }
-        maxDelayMs = Math.max(maxDelayMs, 0);
-        return maxDelayMs;
+
+        return controllerWithMaxDelay;
     }
 
     @Override
@@ -3756,6 +3764,14 @@
         }
     }
 
+    void dumpTopResumedActivityLocked(PrintWriter pw) {
+        pw.println("ACTIVITY MANAGER TOP-RESUMED (dumpsys activity top-resumed)");
+        ActivityRecord topRecord = mRootWindowContainer.getTopResumedActivity();
+        if (topRecord != null) {
+            topRecord.dump(pw, "", true);
+        }
+    }
+
     void dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
             int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
         dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage,
@@ -4005,8 +4021,7 @@
         deferWindowLayout();
         try {
             if (values != null) {
-                changes = updateGlobalConfigurationLocked(values, initLocale, persistent, userId,
-                        deferResume);
+                changes = updateGlobalConfigurationLocked(values, initLocale, persistent, userId);
             }
 
             if (!deferResume) {
@@ -4025,7 +4040,7 @@
 
     /** Update default (global) configuration and notify listeners about changes. */
     int updateGlobalConfigurationLocked(@NonNull Configuration values, boolean initLocale,
-            boolean persistent, int userId, boolean deferResume) {
+            boolean persistent, int userId) {
 
         final DisplayContent defaultDisplay =
                 mRootWindowContainer.getDisplayContent(DEFAULT_DISPLAY);
@@ -4037,7 +4052,7 @@
             // setting WindowManagerService.mWaitingForConfig to true, it is important that we call
             // performDisplayOverrideConfigUpdate in order to send the new display configuration
             // (even if there are no actual changes) to unfreeze the window.
-            defaultDisplay.performDisplayOverrideConfigUpdate(values, deferResume);
+            defaultDisplay.performDisplayOverrideConfigUpdate(values);
             return 0;
         }
 
@@ -4085,9 +4100,6 @@
 
         mTempConfig.seq = increaseConfigurationSeqLocked();
 
-        // Update stored global config and notify everyone about the change.
-        mRootWindowContainer.onConfigurationChanged(mTempConfig);
-
         Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + mTempConfig);
         // TODO(multi-display): Update UsageEvents#Event to include displayId.
         mUsageStatsInternal.reportConfigurationChange(mTempConfig, mAmInternal.getCurrentUserId());
@@ -4106,13 +4118,10 @@
         // resources have that config before following boot code is executed.
         mSystemThread.applyConfigurationToResources(mTempConfig);
 
-        // We need another copy of global config because we're scheduling some calls instead of
-        // running them in place. We need to be sure that object we send will be handled unchanged.
-        final Configuration configCopy = new Configuration(mTempConfig);
         if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
             final Message msg = PooledLambda.obtainMessage(
                     ActivityTaskManagerService::sendPutConfigurationForUserMsg,
-                    this, userId, configCopy);
+                    this, userId, new Configuration(mTempConfig));
             mH.sendMessage(msg);
         }
 
@@ -4121,8 +4130,8 @@
             final int pid = pidMap.keyAt(i);
             final WindowProcessController app = pidMap.get(pid);
             ProtoLog.v(WM_DEBUG_CONFIGURATION, "Update process config of %s to new "
-                    + "config %s", app.mName, configCopy);
-            app.onConfigurationChanged(configCopy);
+                    + "config %s", app.mName, mTempConfig);
+            app.onConfigurationChanged(mTempConfig);
         }
 
         final Message msg = PooledLambda.obtainMessage(
@@ -4130,10 +4139,8 @@
                 mAmInternal, changes, initLocale);
         mH.sendMessage(msg);
 
-        // Override configuration of the default display duplicates global config, so we need to
-        // update it also. This will also notify WindowManager about changes.
-        defaultDisplay.performDisplayOverrideConfigUpdate(mRootWindowContainer.getConfiguration(),
-                deferResume);
+        // Update stored global config and notify everyone about the change.
+        mRootWindowContainer.onConfigurationChanged(mTempConfig);
 
         return changes;
     }
@@ -5543,7 +5550,7 @@
                     return null;
                 }
                 return new ActivityTokens(activity.appToken, activity.assistToken,
-                        activity.app.getThread());
+                        activity.app.getThread(), activity.shareableActivityToken);
             }
         }
 
@@ -5896,6 +5903,8 @@
                     if (getRecentTasks() != null) {
                         getRecentTasks().dump(pw, dumpAll, dumpPackage);
                     }
+                } else if (DUMP_TOP_RESUMED_ACTIVITY.equals(cmd)) {
+                    dumpTopResumedActivityLocked(pw);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 1264d0c..bb0f1f0 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -825,7 +825,7 @@
                         r.getSavedState(), r.getPersistentSavedState(), results, newIntents,
                         r.takeOptions(), dc.isNextTransitionForward(),
                         proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
-                        r.createFixedRotationAdjustmentsIfNeeded()));
+                        r.createFixedRotationAdjustmentsIfNeeded(), r.shareableActivityToken));
 
                 // Set desired final state.
                 final ActivityLifecycleItem lifecycleItem;
@@ -2204,19 +2204,6 @@
                 task.mTaskId, reason, topActivity.info.applicationInfo.packageName);
     }
 
-    void activityRelaunchedLocked(IBinder token) {
-        final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
-        if (r != null) {
-            r.finishRelaunching();
-            if (r.getRootTask().shouldSleepOrShutDownActivities()) {
-                // Activity is always relaunched to either resumed or paused state. If it was
-                // relaunched while hidden (by keyguard or smth else), it should be stopped.
-                r.getRootTask().ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
-                        false /* preserveWindows */);
-            }
-        }
-    }
-
     void logRootTaskState() {
         mActivityMetricsLogger.logWindowState();
     }
diff --git a/services/core/java/com/android/server/wm/BlurController.java b/services/core/java/com/android/server/wm/BlurController.java
new file mode 100644
index 0000000..13295e8
--- /dev/null
+++ b/services/core/java/com/android/server/wm/BlurController.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.view.CrossWindowBlurListeners.CROSS_WINDOW_BLUR_SUPPORTED;
+
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.view.ICrossWindowBlurEnabledListener;
+
+final class BlurController {
+
+    private final RemoteCallbackList<ICrossWindowBlurEnabledListener>
+            mBlurEnabledListeners = new RemoteCallbackList<>();
+    private final Object mLock = new Object();
+    boolean mBlurEnabled;
+
+    BlurController() {
+        mBlurEnabled = CROSS_WINDOW_BLUR_SUPPORTED;
+    }
+
+    boolean registerCrossWindowBlurEnabledListener(ICrossWindowBlurEnabledListener listener) {
+        if (listener == null) return false;
+        mBlurEnabledListeners.register(listener);
+        synchronized (mLock) {
+            return mBlurEnabled;
+        }
+    }
+
+    void unregisterCrossWindowBlurEnabledListener(ICrossWindowBlurEnabledListener listener) {
+        if (listener == null) return;
+        mBlurEnabledListeners.unregister(listener);
+    }
+
+    private void updateBlurEnabled() {
+        // TODO: add other factors disabling blurs
+        final boolean newEnabled = CROSS_WINDOW_BLUR_SUPPORTED;
+        synchronized (mLock) {
+            if (mBlurEnabled == newEnabled) {
+                return;
+            }
+            mBlurEnabled = newEnabled;
+            notifyBlurEnabledChanged(newEnabled);
+        }
+    }
+
+    private void notifyBlurEnabledChanged(boolean enabled) {
+        int i = mBlurEnabledListeners.beginBroadcast();
+        while (i > 0) {
+            i--;
+            ICrossWindowBlurEnabledListener listener =
+                    mBlurEnabledListeners.getBroadcastItem(i);
+            try {
+                listener.onCrossWindowBlurEnabledChanged(enabled);
+            } catch (RemoteException e) {
+            }
+        }
+        mBlurEnabledListeners.finishBroadcast();
+    }
+
+
+}
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index efcaaa4..309b5ec 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -141,6 +141,10 @@
             mChangeListeners.get(i).onMergedOverrideConfigurationChanged(
                     mMergedOverrideConfiguration);
         }
+        dispatchConfigurationToChildren();
+    }
+
+    void dispatchConfigurationToChildren() {
         for (int i = getChildCount() - 1; i >= 0; --i) {
             final ConfigurationContainer child = getChildAt(i);
             child.onConfigurationChanged(mFullConfiguration);
diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
index f505daa..a7312b3 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
@@ -67,39 +67,40 @@
  *              .setImeContainer(imeContainer)
  *              .setTaskDisplayAreas(rootTdaList);
  *
- *      // Build root hierarchy of front and rear DisplayAreaGroup.
- *      RootDisplayArea frontRoot = new RootDisplayArea(wmService, "FrontRoot", FEATURE_FRONT_ROOT);
- *      DisplayAreaPolicyBuilder.HierarchyBuilder frontGroupHierarchy =
- *          new DisplayAreaPolicyBuilder.HierarchyBuilder(frontRoot)
+ *      // Build root hierarchy of first and second DisplayAreaGroup.
+ *      RootDisplayArea firstRoot = new RootDisplayArea(wmService, "FirstRoot", FEATURE_FIRST_ROOT);
+ *      DisplayAreaPolicyBuilder.HierarchyBuilder firstGroupHierarchy =
+ *          new DisplayAreaPolicyBuilder.HierarchyBuilder(firstRoot)
  *              // (Optional) .addFeature(...)
- *              .setTaskDisplayAreas(frontTdaList);
+ *              .setTaskDisplayAreas(firstTdaList);
  *
- *      RootDisplayArea rearRoot = new RootDisplayArea(wmService, "RearRoot", FEATURE_REAR_ROOT);
- *      DisplayAreaPolicyBuilder.HierarchyBuilder rearGroupHierarchy =
- *          new DisplayAreaPolicyBuilder.HierarchyBuilder(rearRoot)
+ *      RootDisplayArea secondRoot = new RootDisplayArea(wmService, "SecondRoot",
+ *          FEATURE_REAR_ROOT);
+ *      DisplayAreaPolicyBuilder.HierarchyBuilder secondGroupHierarchy =
+ *          new DisplayAreaPolicyBuilder.HierarchyBuilder(secondRoot)
  *              // (Optional) .addFeature(...)
- *              .setTaskDisplayAreas(rearTdaList);
+ *              .setTaskDisplayAreas(secondTdaList);
  *
  *      // Define the function to select root for window to attach.
  *      BiFunction<WindowToken, Bundle, RootDisplayArea> selectRootForWindowFunc =
- *                (windowToken, bundle) -> {
- *                    if (bundle == null) {
+ *                (windowToken, options) -> {
+ *                    if (options == null) {
  *                        return root;
  *                    }
  *                    // OEMs need to define the condition.
  *                    if (...) {
- *                        return frontRoot;
+ *                        return firstRoot;
  *                    }
  *                    if (...) {
- *                        return rearRoot;
+ *                        return secondRoot;
  *                    }
  *                    return root;
  *                };
  *
  *      return new DisplayAreaPolicyBuilder()
  *                .setRootHierarchy(rootHierarchy)
- *                .addDisplayAreaGroupHierarchy(frontGroupHierarchy)
- *                .addDisplayAreaGroupHierarchy(rearGroupHierarchy)
+ *                .addDisplayAreaGroupHierarchy(firstGroupHierarchy)
+ *                .addDisplayAreaGroupHierarchy(secondGroupHierarchy)
  *                .setSelectRootForWindowFunc(selectRootForWindowFunc)
  *                .build(wmService, content);
  * </pre>
@@ -110,12 +111,12 @@
  *          - WindowedMagnification
  *              - DisplayArea.Tokens (Wallpapers can be attached here)
  *              - TaskDisplayArea
- *              - RootDisplayArea (FrontRoot)
+ *              - RootDisplayArea (FirstRoot)
  *                  - DisplayArea.Tokens (Wallpapers can be attached here)
  *                  - TaskDisplayArea
  *                  - DisplayArea.Tokens (windows above Tasks up to IME can be attached here)
  *                  - DisplayArea.Tokens (windows above IME can be attached here)
- *              - RootDisplayArea (RearRoot)
+ *              - RootDisplayArea (SecondRoot)
  *                  - DisplayArea.Tokens (Wallpapers can be attached here)
  *                  - TaskDisplayArea
  *                  - DisplayArea.Tokens (windows above Tasks up to IME can be attached here)
@@ -133,14 +134,23 @@
  * {@link RootDisplayArea}.
  */
 class DisplayAreaPolicyBuilder {
+
+    /**
+     * Key to specify the {@link RootDisplayArea} to attach the window to. Should be used by the
+     * function passed in from {@link #setSelectRootForWindowFunc(BiFunction)}
+     */
+    static final String KEY_ROOT_DISPLAY_AREA_ID = "root_display_area_id";
+
     @Nullable private HierarchyBuilder mRootHierarchyBuilder;
-    private ArrayList<HierarchyBuilder> mDisplayAreaGroupHierarchyBuilders = new ArrayList<>();
+    private final ArrayList<HierarchyBuilder> mDisplayAreaGroupHierarchyBuilders =
+            new ArrayList<>();
 
     /**
      * When a window is created, the policy will use this function, which takes window type and
      * options, to select the {@link RootDisplayArea} to place that window in. The selected root
      * can be either the one of the {@link #mRootHierarchyBuilder} or the one of any of the
      * {@link #mDisplayAreaGroupHierarchyBuilders}.
+     * @see DefaultSelectRootForWindowFunction as an example.
      **/
     @Nullable private BiFunction<Integer, Bundle, RootDisplayArea> mSelectRootForWindowFunc;
 
@@ -160,7 +170,10 @@
         return this;
     }
 
-    /** The policy will use this function to find the root to place windows in. */
+    /**
+     * The policy will use this function to find the root to place windows in.
+     * @see DefaultSelectRootForWindowFunction as an example.
+     */
     DisplayAreaPolicyBuilder setSelectRootForWindowFunc(
             BiFunction<Integer, Bundle, RootDisplayArea> selectRootForWindowFunc) {
         mSelectRootForWindowFunc = selectRootForWindowFunc;
@@ -169,7 +182,7 @@
 
     /**
      * Makes sure the setting meets the requirement:
-     * 1. {@link mRootHierarchyBuilder} must be set.
+     * 1. {@link #mRootHierarchyBuilder} must be set.
      * 2. {@link RootDisplayArea} and {@link TaskDisplayArea} must have unique ids.
      * 3. {@link Feature} below the same {@link RootDisplayArea} must have unique ids.
      * 4. There must be exactly one {@link HierarchyBuilder} that contains the IME container.
@@ -309,11 +322,57 @@
             hierarchyBuilder.build();
             displayAreaGroupRoots.add(hierarchyBuilder.mRoot);
         }
+        // Use the default function if it is not specified otherwise.
+        if (mSelectRootForWindowFunc == null) {
+            mSelectRootForWindowFunc = new DefaultSelectRootForWindowFunction(
+                    mRootHierarchyBuilder.mRoot, displayAreaGroupRoots);
+        }
         return new Result(wmService, mRootHierarchyBuilder.mRoot, displayAreaGroupRoots,
                 mSelectRootForWindowFunc);
     }
 
     /**
+     * The default function to be used for finding {@link RootDisplayArea} for window to be attached
+     * to if there is no other function set through {@link #setSelectRootForWindowFunc(BiFunction)}.
+     *
+     * When a window is created with {@link Bundle} options, this function will select the
+     * {@link RootDisplayArea} based on the options. Returns {@link #mDisplayRoot} if there is no
+     * match found.
+     */
+    private static class DefaultSelectRootForWindowFunction implements
+            BiFunction<Integer, Bundle, RootDisplayArea> {
+        final RootDisplayArea mDisplayRoot;
+        final List<RootDisplayArea> mDisplayAreaGroupRoots;
+
+        DefaultSelectRootForWindowFunction(RootDisplayArea displayRoot,
+                List<RootDisplayArea> displayAreaGroupRoots) {
+            mDisplayRoot = displayRoot;
+            mDisplayAreaGroupRoots = Collections.unmodifiableList(displayAreaGroupRoots);
+        }
+
+        @Override
+        public RootDisplayArea apply(Integer windowType, Bundle options) {
+            if (mDisplayAreaGroupRoots.isEmpty()) {
+                return mDisplayRoot;
+            }
+
+            // Select the RootDisplayArea set in options.
+            if (options != null && options.containsKey(KEY_ROOT_DISPLAY_AREA_ID)) {
+                final int rootId = options.getInt(KEY_ROOT_DISPLAY_AREA_ID);
+                if (mDisplayRoot.mFeatureId == rootId) {
+                    return mDisplayRoot;
+                }
+                for (int i = mDisplayAreaGroupRoots.size() - 1; i >= 0; i--) {
+                    if (mDisplayAreaGroupRoots.get(i).mFeatureId == rootId) {
+                        return mDisplayAreaGroupRoots.get(i);
+                    }
+                }
+            }
+            return mDisplayRoot;
+        }
+    }
+
+    /**
      *  Builder to define {@link Feature} and {@link DisplayArea} hierarchy under a
      * {@link RootDisplayArea}
      */
@@ -672,15 +731,10 @@
 
         Result(WindowManagerService wmService, RootDisplayArea root,
                 List<RootDisplayArea> displayAreaGroupRoots,
-                @Nullable BiFunction<Integer, Bundle, RootDisplayArea>
-                        selectRootForWindowFunc) {
+                BiFunction<Integer, Bundle, RootDisplayArea> selectRootForWindowFunc) {
             super(wmService, root);
             mDisplayAreaGroupRoots = Collections.unmodifiableList(displayAreaGroupRoots);
-            mSelectRootForWindowFunc = selectRootForWindowFunc == null
-                    // Always return the highest level root of the logical display when the func is
-                    // not specified.
-                    ? (type, options) -> mRoot
-                    : selectRootForWindowFunc;
+            mSelectRootForWindowFunc = selectRootForWindowFunc;
 
             // Cache the default TaskDisplayArea for quick access.
             mDefaultTaskDisplayArea = mRoot.getItemFromTaskDisplayAreas(taskDisplayArea ->
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 86968ed..eff4ea6 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -36,6 +36,7 @@
 import static android.os.Build.VERSION_CODES.N;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.util.DisplayMetrics.DENSITY_DEFAULT;
+import static android.util.RotationUtils.deltaRotation;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
 import static android.view.Display.FLAG_PRIVATE;
@@ -47,7 +48,6 @@
 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
 import static android.view.InsetsState.ITYPE_RIGHT_GESTURES;
 import static android.view.Surface.ROTATION_0;
-import static android.view.Surface.ROTATION_180;
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
 import static android.view.View.GONE;
@@ -150,7 +150,6 @@
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
-import android.app.WindowConfiguration;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ActivityInfo.ScreenOrientation;
@@ -158,10 +157,8 @@
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.Insets;
-import android.graphics.Matrix;
 import android.graphics.Point;
 import android.graphics.Rect;
-import android.graphics.RectF;
 import android.graphics.Region;
 import android.graphics.Region.Op;
 import android.hardware.HardwareBuffer;
@@ -206,6 +203,7 @@
 import android.view.RemoteAnimationDefinition;
 import android.view.RoundedCorners;
 import android.view.Surface;
+import android.view.Surface.Rotation;
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Transaction;
 import android.view.SurfaceSession;
@@ -449,8 +447,6 @@
     /** Save allocating when calculating rects */
     private final Rect mTmpRect = new Rect();
     private final Rect mTmpRect2 = new Rect();
-    private final RectF mTmpRectF = new RectF();
-    private final Matrix mTmpMatrix = new Matrix();
     private final Region mTmpRegion = new Region();
 
     /** Used for handing back size of display */
@@ -461,8 +457,8 @@
     /** Remove this display when animation on it has completed. */
     private boolean mDeferredRemoval;
 
-    final DockedStackDividerController mDividerControllerLocked;
-    final PinnedStackController mPinnedStackControllerLocked;
+    final DockedTaskDividerController mDividerControllerLocked;
+    final PinnedTaskController mPinnedTaskControllerLocked;
 
     final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
     /** A collection of windows that provide tap exclude regions inside of them. */
@@ -673,10 +669,6 @@
     // Used in updating override configurations
     private final Configuration mTempConfig = new Configuration();
 
-    // Used in performing layout, to record the insets provided by other windows above the current
-    // window.
-    private InsetsState mTmpAboveInsetsState = new InsetsState();
-
     /**
      * Used to prevent recursions when calling
      * {@link #ensureActivitiesVisible(ActivityRecord, int, boolean, boolean)}
@@ -778,13 +770,6 @@
                     + " parentHidden=" + w.isParentWindowHidden());
         }
 
-        // Sets mAboveInsets for each window. Windows behind the window providing the insets can
-        // receive the insets.
-        if (!w.mAboveInsetsState.equals(mTmpAboveInsetsState)) {
-            w.mAboveInsetsState.set(mTmpAboveInsetsState);
-            mWinInsetsChanged.add(w);
-        }
-
         // If this view is GONE, then skip it -- keep the current frame, and let the caller know
         // so they can ignore it if they want.  (We do the normal layout for INVISIBLE windows,
         // since that means "perform layout as normal, just don't display").
@@ -818,16 +803,8 @@
                     + " mContainingFrame=" + w.getContainingFrame()
                     + " mDisplayFrame=" + w.getDisplayFrame());
         }
-        provideInsetsByWindow(w);
     };
 
-    private void provideInsetsByWindow(WindowState w) {
-        for (int i = 0; i < w.mProvidedInsetsSources.size(); i++) {
-            final InsetsSource providedSource = w.mProvidedInsetsSources.valueAt(i);
-            mTmpAboveInsetsState.addSource(providedSource);
-        }
-    }
-
     private final Consumer<WindowState> mPerformLayoutAttached = w -> {
         if (w.mLayoutAttached) {
             if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + w + " mHaveFrame=" + w.mHaveFrame
@@ -1002,7 +979,7 @@
 
         final InputChannel inputChannel = mWmService.mInputManager.monitorInput(
                 "PointerEventDispatcher" + mDisplayId, mDisplayId);
-        mPointerEventDispatcher = new PointerEventDispatcher(inputChannel);
+        mPointerEventDispatcher = new PointerEventDispatcher(inputChannel, this);
 
         // Tap Listeners are supported for:
         // 1. All physical displays (multi-display).
@@ -1031,8 +1008,8 @@
             mDisplayPolicy.systemReady();
         }
         mWindowCornerRadius = mDisplayPolicy.getWindowCornerRadius();
-        mDividerControllerLocked = new DockedStackDividerController(this);
-        mPinnedStackControllerLocked = new PinnedStackController(mWmService, this);
+        mDividerControllerLocked = new DockedTaskDividerController(this);
+        mPinnedTaskControllerLocked = new PinnedTaskController(mWmService, this);
 
         final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(mSession)
                 .setOpaque(true)
@@ -1308,7 +1285,7 @@
         return mInsetsPolicy;
     }
 
-    @Surface.Rotation
+    @Rotation
     int getRotation() {
         return mDisplayRotation.getRotation();
     }
@@ -1498,7 +1475,7 @@
      * Returns a valid rotation if the activity can use different orientation than the display.
      * Otherwise {@link #ROTATION_UNDEFINED}.
      */
-    @Surface.Rotation
+    @Rotation
     int rotationForActivityInDifferentOrientation(@NonNull ActivityRecord r) {
         if (!WindowManagerService.ENABLE_FIXED_ROTATION_TRANSFORM) {
             return ROTATION_UNDEFINED;
@@ -1572,12 +1549,12 @@
         }
         final int rotation = rotationForActivityInDifferentOrientation(r);
         if (rotation == ROTATION_UNDEFINED) {
-            // The display rotation won't be changed by current top activity. If there was fixed
-            // rotation activity, its rotated state should be cleared to cancel the adjustments.
-            if (hasTopFixedRotationLaunchingApp()
-                    // Avoid breaking recents animation.
-                    && !mFixedRotationLaunchingApp.getTask().isAnimatingByRecents()) {
-                clearFixedRotationLaunchingApp();
+            // The display rotation won't be changed by current top activity. The client side
+            // adjustments of previous rotated activity should be cleared earlier. Otherwise if
+            // the current top is in the same process, it may get the rotated state. The transform
+            // will be cleared later with transition callback to ensure smooth animation.
+            if (hasTopFixedRotationLaunchingApp()) {
+                mFixedRotationLaunchingApp.notifyFixedRotationTransform(false /* enabled */);
             }
             return false;
         }
@@ -1586,7 +1563,7 @@
             // has it own policy for bounds, the activity bounds based on parent is unknown.
             return false;
         }
-        if (mPinnedStackControllerLocked.isPipActiveOrWindowingModeChanging()) {
+        if (mPinnedTaskControllerLocked.isPipActiveOrWindowingModeChanging()) {
             // Use normal rotation animation because seamless PiP rotation is not supported yet.
             return false;
         }
@@ -1633,7 +1610,7 @@
      * Sets the provided record to {@link #mFixedRotationLaunchingApp} if possible to apply fixed
      * rotation transform to it and indicate that the display may be rotated after it is launched.
      */
-    void setFixedRotationLaunchingApp(@NonNull ActivityRecord r, @Surface.Rotation int rotation) {
+    void setFixedRotationLaunchingApp(@NonNull ActivityRecord r, @Rotation int rotation) {
         final WindowToken prevRotatedLaunchingApp = mFixedRotationLaunchingApp;
         if (prevRotatedLaunchingApp == r
                 && r.getWindowConfiguration().getRotation() == rotation) {
@@ -2315,12 +2292,12 @@
         }
     }
 
-    DockedStackDividerController getDockedDividerController() {
+    DockedTaskDividerController getDockedDividerController() {
         return mDividerControllerLocked;
     }
 
-    PinnedStackController getPinnedStackController() {
-        return mPinnedStackControllerLocked;
+    PinnedTaskController getPinnedTaskController() {
+        return mPinnedTaskControllerLocked;
     }
 
     /**
@@ -2401,10 +2378,10 @@
      * for bounds calculations.
      */
     void preOnConfigurationChanged() {
-        final PinnedStackController pinnedStackController = getPinnedStackController();
+        final PinnedTaskController pinnedTaskController = getPinnedTaskController();
 
-        if (pinnedStackController != null) {
-            getPinnedStackController().onConfigurationChanged();
+        if (pinnedTaskController != null) {
+            getPinnedTaskController().onConfigurationChanged();
         }
     }
 
@@ -2511,8 +2488,13 @@
 
     void onDisplayInfoChanged() {
         final DisplayInfo info = mDisplayInfo;
-        mDisplayFrames.onDisplayInfoUpdated(info, calculateDisplayCutoutForRotation(info.rotation),
-                calculateRoundedCornersForRotation(info.rotation));
+        if (mDisplayFrames.onDisplayInfoUpdated(info,
+                calculateDisplayCutoutForRotation(info.rotation),
+                calculateRoundedCornersForRotation(info.rotation))) {
+            // TODO(b/161810301): Set notifyInsetsChange to true while the server no longer performs
+            //                    layout.
+            mInsetsStateController.onDisplayInfoUpdated(false /* notifyInsetsChange */);
+        }
         mInputMonitor.layoutInputConsumers(info.logicalWidth, info.logicalHeight);
         mDisplayPolicy.onDisplayInfoChanged(info);
     }
@@ -2943,7 +2925,7 @@
         final boolean imeVisible = imeWin != null && imeWin.isVisible()
                 && imeWin.isDisplayed();
         final int imeHeight = getInputMethodWindowVisibleHeight();
-        mPinnedStackControllerLocked.setAdjustedForIme(imeVisible, imeHeight);
+        mPinnedTaskControllerLocked.setAdjustedForIme(imeVisible, imeHeight);
     }
 
     int getInputMethodWindowVisibleHeight() {
@@ -2965,27 +2947,10 @@
         forAllRootTasks(Task::prepareFreezingTaskBounds);
     }
 
-    void rotateBounds(int oldRotation, int newRotation, Rect bounds) {
-        getBounds(mTmpRect, newRotation);
-        rotateBounds(mTmpRect, oldRotation, newRotation, bounds);
-    }
-
-    void rotateBounds(Rect parentBounds, int oldRotation, int newRotation, Rect bounds) {
-        // Compute a transform matrix to undo the coordinate space transformation,
-        // and present the window at the same physical position it previously occupied.
-        final int deltaRotation = deltaRotation(newRotation, oldRotation);
-        createRotationMatrix(
-                deltaRotation, parentBounds.width(), parentBounds.height(), mTmpMatrix);
-
-        mTmpRectF.set(bounds);
-        mTmpMatrix.mapRect(mTmpRectF);
-        mTmpRectF.round(bounds);
-    }
-
-    static int deltaRotation(int oldRotation, int newRotation) {
-        int delta = newRotation - oldRotation;
-        if (delta < 0) delta += 4;
-        return delta;
+    void rotateBounds(@Rotation int oldRotation, @Rotation int newRotation, Rect inOutBounds) {
+        // Get display bounds on oldRotation as parent bounds for the rotation.
+        getBounds(mTmpRect, oldRotation);
+        RotationUtils.rotateBounds(inOutBounds, mTmpRect, oldRotation, newRotation);
     }
 
     public void setRotationAnimation(ScreenRotationAnimation screenRotationAnimation) {
@@ -2999,35 +2964,6 @@
         return mScreenRotationAnimation;
     }
 
-    private static void createRotationMatrix(int rotation, float displayWidth, float displayHeight,
-            Matrix outMatrix) {
-        // For rotations without Z-ordering we don't need the target rectangle's position.
-        createRotationMatrix(rotation, 0 /* rectLeft */, 0 /* rectTop */, displayWidth,
-                displayHeight, outMatrix);
-    }
-
-    static void createRotationMatrix(int rotation, float rectLeft, float rectTop,
-            float displayWidth, float displayHeight, Matrix outMatrix) {
-        switch (rotation) {
-            case ROTATION_0:
-                outMatrix.reset();
-                break;
-            case ROTATION_270:
-                outMatrix.setRotate(270, 0, 0);
-                outMatrix.postTranslate(0, displayHeight);
-                outMatrix.postTranslate(rectTop, 0);
-                break;
-            case ROTATION_180:
-                outMatrix.reset();
-                break;
-            case ROTATION_90:
-                outMatrix.setRotate(90, 0, 0);
-                outMatrix.postTranslate(displayWidth, 0);
-                outMatrix.postTranslate(-rectTop, rectLeft);
-                break;
-        }
-    }
-
     @Override
     public void dumpDebug(ProtoOutputStream proto, long fieldId,
             @WindowTraceLogLevel int logLevel) {
@@ -3214,7 +3150,7 @@
         }
 
         pw.println();
-        mPinnedStackControllerLocked.dump(prefix, pw);
+        mPinnedTaskControllerLocked.dump(prefix, pw);
 
         pw.println();
         mDisplayFrames.dump(prefix, pw);
@@ -3653,8 +3589,7 @@
     }
 
     private boolean isImeControlledByApp() {
-        return mImeInputTarget != null && !WindowConfiguration.isSplitScreenWindowingMode(
-                        mImeInputTarget.getWindowingMode());
+        return mImeInputTarget != null && !mImeInputTarget.inMultiWindowMode();
     }
 
     boolean isImeAttachedToApp() {
@@ -3767,8 +3702,11 @@
         // 2. Assign window layers based on the IME surface parent to make sure it is on top of the
         // app.
         assignWindowLayers(true /* setLayoutNeeded */);
-        // 3. Update the IME control target to apply any inset change and animation.
-        // 4. Reparent the IME container surface to either the input target app, or the IME window
+        // 3. The z-order of IME might have been changed. Update the above insets state.
+        mInsetsStateController.updateAboveInsetsState(
+                mInputMethodWindow, true /* notifyInsetsChange */);
+        // 4. Update the IME control target to apply any inset change and animation.
+        // 5. Reparent the IME container surface to either the input target app, or the IME window
         // parent.
         updateImeControlTarget();
     }
@@ -4300,17 +4238,14 @@
         out.set(left, top, left + width, top + height);
     }
 
-    private void getBounds(Rect out, int orientation) {
+    private void getBounds(Rect out, @Rotation int rotation) {
         getBounds(out);
 
         // Rotate the Rect if needed.
         final int currentRotation = mDisplayInfo.rotation;
-        final int rotationDelta = deltaRotation(currentRotation, orientation);
+        final int rotationDelta = deltaRotation(currentRotation, rotation);
         if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) {
-            createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix);
-            mTmpRectF.set(out);
-            mTmpMatrix.mapRect(mTmpRectF);
-            mTmpRectF.round(out);
+            out.set(0, 0, out.height(), out.width());
         }
     }
 
@@ -4341,14 +4276,6 @@
                     + " dh=" + mDisplayInfo.logicalHeight);
         }
 
-        // Used to indicate that we have processed the insets windows. This needs to be after
-        // beginLayoutLw to ensure the raw insets state display related info is initialized.
-        final InsetsState rawInsetsState = getInsetsStateController().getRawInsetsState();
-        mTmpAboveInsetsState = new InsetsState();
-        mTmpAboveInsetsState.setDisplayFrame(rawInsetsState.getDisplayFrame());
-        mTmpAboveInsetsState.setDisplayCutout(rawInsetsState.getDisplayCutout());
-        mTmpAboveInsetsState.mirrorAlwaysVisibleInsetsSources(rawInsetsState);
-
         int seq = mLayoutSeq + 1;
         if (seq < 0) seq = 0;
         mLayoutSeq = seq;
@@ -5467,9 +5394,9 @@
                     // apply the correct override config.
                     changes = mAtmService.updateGlobalConfigurationLocked(values,
                             false /* initLocale */, false /* persistent */,
-                            UserHandle.USER_NULL /* userId */, deferResume);
+                            UserHandle.USER_NULL /* userId */);
                 } else {
-                    changes = performDisplayOverrideConfigUpdate(values, deferResume);
+                    changes = performDisplayOverrideConfigUpdate(values);
                 }
             }
 
@@ -5487,7 +5414,7 @@
         return kept;
     }
 
-    int performDisplayOverrideConfigUpdate(Configuration values, boolean deferResume) {
+    int performDisplayOverrideConfigUpdate(Configuration values) {
         mTempConfig.setTo(getRequestedOverrideConfiguration());
         final int changes = mTempConfig.updateFrom(values);
         if (changes != 0) {
diff --git a/services/core/java/com/android/server/wm/DisplayFrames.java b/services/core/java/com/android/server/wm/DisplayFrames.java
index e4230a2..a37f3f2 100644
--- a/services/core/java/com/android/server/wm/DisplayFrames.java
+++ b/services/core/java/com/android/server/wm/DisplayFrames.java
@@ -21,6 +21,7 @@
 import static android.view.InsetsState.ITYPE_RIGHT_DISPLAY_CUTOUT;
 import static android.view.InsetsState.ITYPE_TOP_DISPLAY_CUTOUT;
 
+import android.annotation.NonNull;
 import android.graphics.Rect;
 import android.util.proto.ProtoOutputStream;
 import android.view.DisplayCutout;
@@ -70,25 +71,28 @@
      * @param info the updated {@link DisplayInfo}.
      * @param displayCutout the updated {@link DisplayCutout}.
      * @param roundedCorners the updated {@link RoundedCorners}.
+     * @return {@code true} if the insets state has been changed; {@code false} otherwise.
      */
-    public void onDisplayInfoUpdated(DisplayInfo info, WmDisplayCutout displayCutout,
-            RoundedCorners roundedCorners) {
-        mDisplayWidth = info.logicalWidth;
-        mDisplayHeight = info.logicalHeight;
+    public boolean onDisplayInfoUpdated(DisplayInfo info, @NonNull WmDisplayCutout displayCutout,
+            @NonNull RoundedCorners roundedCorners) {
         mRotation = info.rotation;
-        final WmDisplayCutout wmDisplayCutout =
-                displayCutout != null ? displayCutout : WmDisplayCutout.NO_CUTOUT;
 
         final InsetsState state = mInsetsState;
-        final Rect unrestricted = mUnrestricted;
         final Rect safe = mDisplayCutoutSafe;
-        final DisplayCutout cutout = wmDisplayCutout.getDisplayCutout();
+        final DisplayCutout cutout = displayCutout.getDisplayCutout();
+        if (mDisplayWidth == info.logicalWidth && mDisplayHeight == info.logicalHeight
+                && state.getDisplayCutout().equals(cutout)
+                && state.getRoundedCorners().equals(roundedCorners)) {
+            return false;
+        }
+        mDisplayWidth = info.logicalWidth;
+        mDisplayHeight = info.logicalHeight;
+        final Rect unrestricted = mUnrestricted;
         unrestricted.set(0, 0, mDisplayWidth, mDisplayHeight);
         safe.set(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
         state.setDisplayFrame(unrestricted);
         state.setDisplayCutout(cutout);
-        state.setRoundedCorners(roundedCorners != null ? roundedCorners
-                : RoundedCorners.NO_ROUNDED_CORNERS);
+        state.setRoundedCorners(roundedCorners);
         if (!cutout.isEmpty()) {
             if (cutout.getSafeInsetLeft() > 0) {
                 safe.left = unrestricted.left + cutout.getSafeInsetLeft();
@@ -116,6 +120,7 @@
             state.removeSource(ITYPE_RIGHT_DISPLAY_CUTOUT);
             state.removeSource(ITYPE_BOTTOM_DISPLAY_CUTOUT);
         }
+        return true;
     }
 
     public void dumpDebug(ProtoOutputStream proto, long fieldId) {
diff --git a/services/core/java/com/android/server/wm/ScreenshotHashController.java b/services/core/java/com/android/server/wm/DisplayHashController.java
similarity index 77%
rename from services/core/java/com/android/server/wm/ScreenshotHashController.java
rename to services/core/java/com/android/server/wm/DisplayHashController.java
index 03f4e28..7e16c22 100644
--- a/services/core/java/com/android/server/wm/ScreenshotHashController.java
+++ b/services/core/java/com/android/server/wm/DisplayHashController.java
@@ -16,9 +16,8 @@
 
 package com.android.server.wm;
 
-import static android.service.screenshot.ScreenshotHasherService.EXTRA_SCREENSHOT_HASH;
-import static android.service.screenshot.ScreenshotHasherService.EXTRA_VERIFICATION_STATUS;
-import static android.service.screenshot.ScreenshotHasherService.SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS;
+import static android.service.displayhash.DisplayHasherService.EXTRA_VERIFIED_DISPLAY_HASH;
+import static android.service.displayhash.DisplayHasherService.SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS;
 
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -46,11 +45,12 @@
 import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.service.screenshot.IScreenshotHasherService;
-import android.service.screenshot.ScreenshotHash;
-import android.service.screenshot.ScreenshotHasherService;
+import android.service.displayhash.DisplayHasherService;
+import android.service.displayhash.IDisplayHasherService;
 import android.util.Slog;
 import android.view.MagnificationSpec;
+import android.view.displayhash.DisplayHash;
+import android.view.displayhash.VerifiedDisplayHash;
 
 import com.android.internal.annotations.GuardedBy;
 
@@ -61,29 +61,29 @@
 import java.util.function.BiConsumer;
 
 /**
- * Handles requests into {@link android.service.screenshot.ScreenshotHasherService}
+ * Handles requests into {@link android.service.displayhash.DisplayHasherService}
  *
  * Do not hold the {@link WindowManagerService#mGlobalLock} when calling methods since they are
  * blocking calls into another service.
  */
-public class ScreenshotHashController {
-    private static final String TAG = TAG_WITH_CLASS_NAME ? "ScreenshotHashController" : TAG_WM;
+public class DisplayHashController {
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayHashController" : TAG_WM;
     private static final boolean DEBUG = false;
 
     private final Object mServiceConnectionLock = new Object();
 
     @GuardedBy("mServiceConnectionLock")
-    private ScreenshotHasherServiceConnection mServiceConnection;
+    private DisplayHasherServiceConnection mServiceConnection;
 
     private final Context mContext;
 
     /**
-     * Lock used for the cached {@link #mHashingAlgorithms} array
+     * Lock used for the cached {@link #mHashAlgorithms} array
      */
-    private final Object mHashingAlgorithmsLock = new Object();
+    private final Object mHashAlgorithmsLock = new Object();
 
     @GuardedBy("mHashingAlgorithmsLock")
-    private String[] mHashingAlgorithms;
+    private String[] mHashAlgorithms;
 
     private final Handler mHandler;
 
@@ -94,24 +94,24 @@
     private final RectF mTmpRectF = new RectF();
 
     private interface Command {
-        void run(IScreenshotHasherService service) throws RemoteException;
+        void run(IDisplayHasherService service) throws RemoteException;
     }
 
-    ScreenshotHashController(Context context) {
+    DisplayHashController(Context context) {
         mContext = context;
         mHandler = new Handler(Looper.getMainLooper());
         mSalt = UUID.randomUUID().toString().getBytes();
     }
 
-    String[] getSupportedHashingAlgorithms() {
+    String[] getSupportedHashAlgorithms() {
         // We have a separate lock for the hashing algorithm array since it doesn't need to make
         // the request through the service connection. Instead, we have a lock to ensure we can
         // properly cache the hashing algorithms array so we don't need to call into the
         // ExtServices process for each request.
-        synchronized (mHashingAlgorithmsLock) {
+        synchronized (mHashAlgorithmsLock) {
             // Already have cached values
-            if (mHashingAlgorithms != null) {
-                return mHashingAlgorithms;
+            if (mHashAlgorithms != null) {
+                return mHashAlgorithms;
             }
 
             final ServiceInfo serviceInfo = getServiceInfo();
@@ -128,55 +128,48 @@
 
             final int resourceId = serviceInfo.metaData.getInt(
                     SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS);
-            mHashingAlgorithms = res.getStringArray(resourceId);
+            mHashAlgorithms = res.getStringArray(resourceId);
 
-            return mHashingAlgorithms;
+            return mHashAlgorithms;
         }
     }
 
-    boolean verifyScreenshotHash(ScreenshotHash screenshotHash) {
+    @Nullable
+    VerifiedDisplayHash verifyDisplayHash(DisplayHash displayHash) {
         final SyncCommand syncCommand = new SyncCommand();
         Bundle results = syncCommand.run((service, remoteCallback) -> {
             try {
-                service.verifyScreenshotHash(mSalt, screenshotHash, remoteCallback);
+                service.verifyDisplayHash(mSalt, displayHash, remoteCallback);
             } catch (RemoteException e) {
-                Slog.e(TAG, "Failed to invoke verifyScreenshotHash command");
+                Slog.e(TAG, "Failed to invoke verifyDisplayHash command");
             }
         });
 
-        return results.getBoolean(EXTRA_VERIFICATION_STATUS);
+        return results.getParcelable(EXTRA_VERIFIED_DISPLAY_HASH);
     }
 
-    ScreenshotHash generateScreenshotHash(HardwareBuffer screenshot, Rect bounds,
-            String hashAlgorithm) {
-        final SyncCommand syncCommand = new SyncCommand();
-        Bundle results = syncCommand.run((service, remoteCallback) -> {
-            try {
-                service.generateScreenshotHash(mSalt, screenshot, bounds, hashAlgorithm,
-                        remoteCallback);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Failed to invoke generateScreenshotHash command", e);
-            }
-        });
-
-        return results.getParcelable(EXTRA_SCREENSHOT_HASH);
+    void generateDisplayHash(HardwareBuffer buffer, Rect bounds,
+            String hashAlgorithm, RemoteCallback callback) {
+        connectAndRun(
+                service -> service.generateDisplayHash(mSalt, buffer, bounds, hashAlgorithm,
+                        callback));
     }
 
     /**
-     * Calculate the bounds to take the screenshot when generating the ScreenshotHash. This
-     * takes into account window transform, magnification, and display bounds.
+     * Calculate the bounds to generate the hash for. This takes into account window transform,
+     * magnification, and display bounds.
      *
      * Call while holding {@link WindowManagerService#mGlobalLock}
      *
-     * @param win Window that the ScreenshotHash is generated for.
-     * @param boundsInWindow The bounds passed in about where in the window to take the screenshot.
-     * @param outBounds The result of the calculated bounds
+     * @param win            Window that the DisplayHash is generated for.
+     * @param boundsInWindow The bounds in the window where to generate the hash.
+     * @param outBounds      The result of the calculated bounds
      */
-    void calculateScreenshotHashBoundsLocked(WindowState win, Rect boundsInWindow,
+    void calculateDisplayHashBoundsLocked(WindowState win, Rect boundsInWindow,
             Rect outBounds) {
         if (DEBUG) {
             Slog.d(TAG,
-                    "calculateScreenshotHashBoundsLocked: boundsInWindow=" + boundsInWindow);
+                    "calculateDisplayHashBoundsLocked: boundsInWindow=" + boundsInWindow);
         }
         outBounds.set(boundsInWindow);
 
@@ -195,7 +188,7 @@
 
         if (DEBUG) {
             Slog.d(TAG,
-                    "calculateScreenshotHashBoundsLocked: boundsIntersectWindow=" + outBounds);
+                    "calculateDisplayHashBoundsLocked: boundsIntersectWindow=" + outBounds);
         }
 
         if (outBounds.isEmpty()) {
@@ -210,7 +203,7 @@
         outBounds.set((int) mTmpRectF.left, (int) mTmpRectF.top, (int) mTmpRectF.right,
                 (int) mTmpRectF.bottom);
         if (DEBUG) {
-            Slog.d(TAG, "calculateScreenshotHashBoundsLocked: boundsInDisplay=" + outBounds);
+            Slog.d(TAG, "calculateDisplayHashBoundsLocked: boundsInDisplay=" + outBounds);
         }
 
         // Apply the magnification spec values to the bounds since the content could be magnified
@@ -221,7 +214,7 @@
         }
 
         if (DEBUG) {
-            Slog.d(TAG, "calculateScreenshotHashBoundsLocked: boundsWithMagnification="
+            Slog.d(TAG, "calculateDisplayHashBoundsLocked: boundsWithMagnification="
                     + outBounds);
         }
 
@@ -229,12 +222,12 @@
             return;
         }
 
-        // Intersect with the display bounds since it shouldn't take a screenshot of content
-        // outside the display since it's not visible to the user.
+        // Intersect with the display bounds since content outside the display are not visible to
+        // the user.
         final Rect displayBounds = displayContent.getBounds();
         outBounds.intersectUnchecked(displayBounds);
         if (DEBUG) {
-            Slog.d(TAG, "calculateScreenshotHashBoundsLocked: finalBounds=" + outBounds);
+            Slog.d(TAG, "calculateDisplayHashBoundsLocked: finalBounds=" + outBounds);
         }
     }
 
@@ -248,7 +241,7 @@
                 if (DEBUG) Slog.v(TAG, "creating connection");
 
                 // Create the connection
-                mServiceConnection = new ScreenshotHasherServiceConnection();
+                mServiceConnection = new DisplayHasherServiceConnection();
 
                 final ComponentName component = getServiceComponentName();
                 if (DEBUG) Slog.v(TAG, "binding to: " + component);
@@ -279,7 +272,7 @@
             return null;
         }
 
-        final Intent intent = new Intent(ScreenshotHasherService.SERVICE_INTERFACE);
+        final Intent intent = new Intent(DisplayHasherService.SERVICE_INTERFACE);
         intent.setPackage(packageName);
         final ResolveInfo resolveInfo = mContext.getPackageManager().resolveService(intent,
                 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
@@ -296,10 +289,10 @@
         if (serviceInfo == null) return null;
 
         final ComponentName name = new ComponentName(serviceInfo.packageName, serviceInfo.name);
-        if (!Manifest.permission.BIND_SCREENSHOT_HASHER_SERVICE
+        if (!Manifest.permission.BIND_DISPLAY_HASHER_SERVICE
                 .equals(serviceInfo.permission)) {
             Slog.w(TAG, name.flattenToShortString() + " requires permission "
-                    + Manifest.permission.BIND_SCREENSHOT_HASHER_SERVICE);
+                    + Manifest.permission.BIND_DISPLAY_HASHER_SERVICE);
             return null;
         }
 
@@ -312,7 +305,7 @@
         private Bundle mResult;
         private final CountDownLatch mCountDownLatch = new CountDownLatch(1);
 
-        public Bundle run(BiConsumer<IScreenshotHasherService, RemoteCallback> func) {
+        public Bundle run(BiConsumer<IDisplayHasherService, RemoteCallback> func) {
             connectAndRun(service -> {
                 RemoteCallback callback = new RemoteCallback(result -> {
                     mResult = result;
@@ -331,9 +324,9 @@
         }
     }
 
-    private class ScreenshotHasherServiceConnection implements ServiceConnection {
+    private class DisplayHasherServiceConnection implements ServiceConnection {
         @GuardedBy("mServiceConnectionLock")
-        private IScreenshotHasherService mRemoteService;
+        private IDisplayHasherService mRemoteService;
 
         @GuardedBy("mServiceConnectionLock")
         private ArrayList<Command> mQueuedCommands;
@@ -342,7 +335,7 @@
         public void onServiceConnected(ComponentName name, IBinder service) {
             if (DEBUG) Slog.v(TAG, "onServiceConnected(): " + name);
             synchronized (mServiceConnectionLock) {
-                mRemoteService = IScreenshotHasherService.Stub.asInterface(service);
+                mRemoteService = IDisplayHasherService.Stub.asInterface(service);
                 if (mQueuedCommands != null) {
                     final int size = mQueuedCommands.size();
                     if (DEBUG) Slog.d(TAG, "running " + size + " queued commands");
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 5460e36..af9cdeb 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -24,6 +24,8 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
 import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
+import static android.util.RotationUtils.deltaRotation;
+import static android.util.RotationUtils.rotateBounds;
 import static android.view.Display.TYPE_INTERNAL;
 import static android.view.InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES;
 import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
@@ -67,6 +69,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
+import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
 import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
@@ -240,7 +243,7 @@
         }
     }
 
-    private final SystemGesturesPointerEventListener mSystemGestures;
+    private SystemGesturesPointerEventListener mSystemGestures;
 
     private volatile int mLidState = LID_ABSENT;
     private volatile int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
@@ -382,7 +385,7 @@
     private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
     private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
 
-    private final GestureNavigationSettingsObserver mGestureNavigationSettingsObserver;
+    private GestureNavigationSettingsObserver mGestureNavigationSettingsObserver;
 
     private final WindowManagerInternal.AppTransitionListener mAppTransitionListener;
 
@@ -446,119 +449,6 @@
 
         final Looper looper = UiThread.getHandler().getLooper();
         mHandler = new PolicyHandler(looper);
-        mSystemGestures = new SystemGesturesPointerEventListener(mContext, mHandler,
-                new SystemGesturesPointerEventListener.Callbacks() {
-                    @Override
-                    public void onSwipeFromTop() {
-                        synchronized (mLock) {
-                            if (mStatusBar != null) {
-                                requestTransientBars(mStatusBar);
-                            }
-                            checkAltBarSwipeForTransientBars(ALT_BAR_TOP);
-                        }
-                    }
-
-                    @Override
-                    public void onSwipeFromBottom() {
-                        synchronized (mLock) {
-                            if (mNavigationBar != null
-                                    && mNavigationBarPosition == NAV_BAR_BOTTOM) {
-                                requestTransientBars(mNavigationBar);
-                            }
-                            checkAltBarSwipeForTransientBars(ALT_BAR_BOTTOM);
-                        }
-                    }
-
-                    @Override
-                    public void onSwipeFromRight() {
-                        final Region excludedRegion = Region.obtain();
-                        synchronized (mLock) {
-                            mDisplayContent.calculateSystemGestureExclusion(
-                                    excludedRegion, null /* outUnrestricted */);
-                            final boolean excluded =
-                                    mSystemGestures.currentGestureStartedInRegion(excludedRegion);
-                            if (mNavigationBar != null && (mNavigationBarPosition == NAV_BAR_RIGHT
-                                    || !excluded && mNavigationBarAlwaysShowOnSideGesture)) {
-                                requestTransientBars(mNavigationBar);
-                            }
-                            checkAltBarSwipeForTransientBars(ALT_BAR_RIGHT);
-                        }
-                        excludedRegion.recycle();
-                    }
-
-                    @Override
-                    public void onSwipeFromLeft() {
-                        final Region excludedRegion = Region.obtain();
-                        synchronized (mLock) {
-                            mDisplayContent.calculateSystemGestureExclusion(
-                                    excludedRegion, null /* outUnrestricted */);
-                            final boolean excluded =
-                                    mSystemGestures.currentGestureStartedInRegion(excludedRegion);
-                            if (mNavigationBar != null && (mNavigationBarPosition == NAV_BAR_LEFT
-                                    || !excluded && mNavigationBarAlwaysShowOnSideGesture)) {
-                                requestTransientBars(mNavigationBar);
-                            }
-                            checkAltBarSwipeForTransientBars(ALT_BAR_LEFT);
-                        }
-                        excludedRegion.recycle();
-                    }
-
-                    @Override
-                    public void onFling(int duration) {
-                        if (mService.mPowerManagerInternal != null) {
-                            mService.mPowerManagerInternal.setPowerBoost(
-                                    Boost.INTERACTION, duration);
-                        }
-                    }
-
-                    @Override
-                    public void onDebug() {
-                        // no-op
-                    }
-
-                    private WindowOrientationListener getOrientationListener() {
-                        final DisplayRotation rotation = mDisplayContent.getDisplayRotation();
-                        return rotation != null ? rotation.getOrientationListener() : null;
-                    }
-
-                    @Override
-                    public void onDown() {
-                        final WindowOrientationListener listener = getOrientationListener();
-                        if (listener != null) {
-                            listener.onTouchStart();
-                        }
-                    }
-
-                    @Override
-                    public void onUpOrCancel() {
-                        final WindowOrientationListener listener = getOrientationListener();
-                        if (listener != null) {
-                            listener.onTouchEnd();
-                        }
-                    }
-
-                    @Override
-                    public void onMouseHoverAtTop() {
-                        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
-                        Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
-                        msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS;
-                        mHandler.sendMessageDelayed(msg, 500 /* delayMillis */);
-                    }
-
-                    @Override
-                    public void onMouseHoverAtBottom() {
-                        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
-                        Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
-                        msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION;
-                        mHandler.sendMessageDelayed(msg, 500 /* delayMillis */);
-                    }
-
-                    @Override
-                    public void onMouseLeaveFromEdge() {
-                        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
-                    }
-                });
-        displayContent.registerPointerEventListener(mSystemGestures);
         mAppTransitionListener = new WindowManagerInternal.AppTransitionListener() {
 
             private Runnable mAppTransitionPending = () -> {
@@ -614,7 +504,7 @@
         mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext, looper,
                 mService.mVrModeEnabled);
 
-        // TODO: Make it can take screenshot on external display
+        // TODO(b/180986447): Make it can take screenshot on external display
         mScreenshotHelper = displayContent.isDefaultDisplay
                 ? new ScreenshotHelper(mContext) : null;
 
@@ -638,16 +528,6 @@
         mRefreshRatePolicy = new RefreshRatePolicy(mService,
                 mDisplayContent.getDisplayInfo(),
                 mService.mHighRefreshRateDenylist);
-
-        mGestureNavigationSettingsObserver = new GestureNavigationSettingsObserver(mHandler,
-                mContext, () -> {
-            synchronized (mLock) {
-                onConfigurationChanged();
-                mSystemGestures.onConfigurationChanged();
-                mDisplayContent.updateSystemGestureExclusion();
-            }
-        });
-        mHandler.post(mGestureNavigationSettingsObserver::register);
     }
 
     private void checkAltBarSwipeForTransientBars(@WindowManagerPolicy.AltBarPosition int pos) {
@@ -666,12 +546,154 @@
     }
 
     void systemReady() {
-        mSystemGestures.systemReady();
         if (mService.mPointerLocationEnabled) {
             setPointerLocationEnabled(true);
         }
     }
 
+    @NonNull
+    private GestureNavigationSettingsObserver getGestureNavigationSettingsObserver() {
+        if (mGestureNavigationSettingsObserver == null) {
+            mGestureNavigationSettingsObserver = new GestureNavigationSettingsObserver(mHandler,
+                    mContext, () -> {
+                synchronized (mLock) {
+                    onConfigurationChanged();
+                    getSystemGestures().onConfigurationChanged();
+                    mDisplayContent.updateSystemGestureExclusion();
+                }
+            });
+            mHandler.post(mGestureNavigationSettingsObserver::register);
+        }
+        return mGestureNavigationSettingsObserver;
+    }
+
+    @NonNull
+    private SystemGesturesPointerEventListener getSystemGestures() {
+        if (mSystemGestures == null) {
+            final Context gestureContext = mUiContext.createWindowContext(
+                    mDisplayContent.getDisplay(), TYPE_POINTER, null /* options */);
+            mSystemGestures = new SystemGesturesPointerEventListener(gestureContext, mHandler,
+                    new SystemGesturesPointerEventListener.Callbacks() {
+                        @Override
+                        public void onSwipeFromTop() {
+                            synchronized (mLock) {
+                                if (mStatusBar != null) {
+                                    requestTransientBars(mStatusBar);
+                                }
+                                checkAltBarSwipeForTransientBars(ALT_BAR_TOP);
+                            }
+                        }
+
+                        @Override
+                        public void onSwipeFromBottom() {
+                            synchronized (mLock) {
+                                if (mNavigationBar != null
+                                        && mNavigationBarPosition == NAV_BAR_BOTTOM) {
+                                    requestTransientBars(mNavigationBar);
+                                }
+                                checkAltBarSwipeForTransientBars(ALT_BAR_BOTTOM);
+                            }
+                        }
+
+                        @Override
+                        public void onSwipeFromRight() {
+                            final Region excludedRegion = Region.obtain();
+                            synchronized (mLock) {
+                                mDisplayContent.calculateSystemGestureExclusion(
+                                        excludedRegion, null /* outUnrestricted */);
+                                final boolean excluded = mSystemGestures
+                                        .currentGestureStartedInRegion(excludedRegion);
+                                if (mNavigationBar != null
+                                        && (mNavigationBarPosition == NAV_BAR_RIGHT
+                                        || !excluded && mNavigationBarAlwaysShowOnSideGesture)) {
+                                    requestTransientBars(mNavigationBar);
+                                }
+                                checkAltBarSwipeForTransientBars(ALT_BAR_RIGHT);
+                            }
+                            excludedRegion.recycle();
+                        }
+
+                        @Override
+                        public void onSwipeFromLeft() {
+                            final Region excludedRegion = Region.obtain();
+                            synchronized (mLock) {
+                                mDisplayContent.calculateSystemGestureExclusion(
+                                        excludedRegion, null /* outUnrestricted */);
+                                final boolean excluded = mSystemGestures
+                                        .currentGestureStartedInRegion(excludedRegion);
+                                if (mNavigationBar != null
+                                        && (mNavigationBarPosition == NAV_BAR_LEFT
+                                        || !excluded && mNavigationBarAlwaysShowOnSideGesture)) {
+                                    requestTransientBars(mNavigationBar);
+                                }
+                                checkAltBarSwipeForTransientBars(ALT_BAR_LEFT);
+                            }
+                            excludedRegion.recycle();
+                        }
+
+                        @Override
+                        public void onFling(int duration) {
+                            if (mService.mPowerManagerInternal != null) {
+                                mService.mPowerManagerInternal.setPowerBoost(
+                                        Boost.INTERACTION, duration);
+                            }
+                        }
+
+                        @Override
+                        public void onDebug() {
+                            // no-op
+                        }
+
+                        private WindowOrientationListener getOrientationListener() {
+                            final DisplayRotation rotation = mDisplayContent.getDisplayRotation();
+                            return rotation != null ? rotation.getOrientationListener() : null;
+                        }
+
+                        @Override
+                        public void onDown() {
+                            final WindowOrientationListener listener = getOrientationListener();
+                            if (listener != null) {
+                                listener.onTouchStart();
+                            }
+                        }
+
+                        @Override
+                        public void onUpOrCancel() {
+                            final WindowOrientationListener listener = getOrientationListener();
+                            if (listener != null) {
+                                listener.onTouchEnd();
+                            }
+                        }
+
+                        @Override
+                        public void onMouseHoverAtTop() {
+                            mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
+                            Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
+                            msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS;
+                            mHandler.sendMessageDelayed(msg, 500 /* delayMillis */);
+                        }
+
+                        @Override
+                        public void onMouseHoverAtBottom() {
+                            mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
+                            Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
+                            msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION;
+                            mHandler.sendMessageDelayed(msg, 500 /* delayMillis */);
+                        }
+
+                        @Override
+                        public void onMouseLeaveFromEdge() {
+                            mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
+                        }
+                    });
+            mDisplayContent.registerPointerEventListener(getSystemGestures());
+            if (mService.mSystemReady) {
+                mSystemGestures.systemReady();
+            }
+        }
+        return mSystemGestures;
+    }
+
     private int getDisplayId() {
         return mDisplayContent.getDisplayId();
     }
@@ -1046,11 +1068,17 @@
             return;
         }
 
-        // Get displayFrames bounds
-        sTmpDisplayFrameBounds.set(0, 0, displayFrames.mDisplayWidth, displayFrames.mDisplayHeight);
+        // Get displayFrames bounds as it is on WindowState's rotation.
+        final int deltaRotation = deltaRotation(windowRotation, displayFrames.mRotation);
+        if (deltaRotation == Surface.ROTATION_90 || deltaRotation == Surface.ROTATION_270) {
+            sTmpDisplayFrameBounds.set(
+                    0, 0, displayFrames.mDisplayHeight, displayFrames.mDisplayWidth);
+        } else {
+            sTmpDisplayFrameBounds.set(
+                    0, 0, displayFrames.mDisplayWidth, displayFrames.mDisplayHeight);
+        }
         // Rotate the WindowState's bounds based on the displayFrames rotation
-        mDisplayContent.rotateBounds(sTmpDisplayFrameBounds, windowRotation,
-                displayFrames.mRotation, outBounds);
+        rotateBounds(outBounds, sTmpDisplayFrameBounds, deltaRotation);
     }
 
     /**
@@ -1447,8 +1475,7 @@
     }
 
     void onDisplayInfoChanged(DisplayInfo info) {
-        mSystemGestures.screenWidth = info.logicalWidth;
-        mSystemGestures.screenHeight = info.logicalHeight;
+        getSystemGestures().onDisplayInfoChanged(info);
     }
 
     private void layoutStatusBar(DisplayFrames displayFrames, Rect contentFrame) {
@@ -1961,7 +1988,7 @@
     public void onOverlayChangedLw() {
         updateCurrentUserResources();
         onConfigurationChanged();
-        mSystemGestures.onConfigurationChanged();
+        getSystemGestures().onConfigurationChanged();
     }
 
     /**
@@ -2032,10 +2059,10 @@
         }
 
         mNavBarOpacityMode = res.getInteger(R.integer.config_navBarOpacityMode);
-        mLeftGestureInset = mGestureNavigationSettingsObserver.getLeftSensitivity(res);
-        mRightGestureInset = mGestureNavigationSettingsObserver.getRightSensitivity(res);
-        mNavButtonForcedVisible =
-                mGestureNavigationSettingsObserver.areNavigationButtonForcedVisible();
+        final GestureNavigationSettingsObserver observer = getGestureNavigationSettingsObserver();
+        mLeftGestureInset = observer.getLeftSensitivity(res);
+        mRightGestureInset = observer.getRightSensitivity(res);
+        mNavButtonForcedVisible = observer.areNavigationButtonForcedVisible();
         mNavigationBarLetsThroughTaps = res.getBoolean(R.bool.config_navBarTapThrough);
         mNavigationBarAlwaysShowOnSideGesture =
                 res.getBoolean(R.bool.config_navBarAlwaysShowOnSideEdgeGesture);
@@ -2678,8 +2705,9 @@
         boolean newImmersiveMode = isImmersiveMode(win);
         if (oldImmersiveMode != newImmersiveMode) {
             mLastImmersiveMode = newImmersiveMode;
-            final String pkg = win.getOwningPackage();
-            mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
+            // The immersive confirmation window should be attached to the immersive window root.
+            final int rootDisplayAreaId = win.getRootDisplayArea().mFeatureId;
+            mImmersiveModeConfirmation.immersiveModeChangedLw(rootDisplayAreaId, newImmersiveMode,
                     mService.mPolicy.isUserSetupComplete(),
                     isNavBarEmpty(disableFlags));
         }
@@ -3047,7 +3075,7 @@
     }
 
     void release() {
-        mHandler.post(mGestureNavigationSettingsObserver::unregister);
+        mHandler.post(getGestureNavigationSettingsObserver()::unregister);
     }
 
     @VisibleForTesting
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index b106657..63cb38a 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -17,6 +17,7 @@
 package com.android.server.wm;
 
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.util.RotationUtils.deltaRotation;
 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT;
 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
@@ -475,7 +476,7 @@
                 "Display id=%d rotation changed to %d from %d, lastOrientation=%d",
                         displayId, rotation, oldRotation, lastOrientation);
 
-        if (DisplayContent.deltaRotation(rotation, oldRotation) != 2) {
+        if (deltaRotation(oldRotation, rotation) != Surface.ROTATION_180) {
             mDisplayContent.mWaitingForConfig = true;
         }
 
@@ -788,8 +789,13 @@
 
         mFixedToUserRotation = fixedToUserRotation;
         mDisplayWindowSettings.setFixedToUserRotation(mDisplayContent, fixedToUserRotation);
-        mService.updateRotation(true /* alwaysSendConfiguration */,
-                false /* forceRelayout */);
+        if (mDisplayContent.mFocusedApp != null) {
+            // We record the last focused TDA that respects orientation request, check if this
+            // change may affect it.
+            mDisplayContent.onLastFocusedTaskDisplayAreaChanged(
+                    mDisplayContent.mFocusedApp.getDisplayArea());
+        }
+        mDisplayContent.updateOrientation();
     }
 
     @VisibleForTesting
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedTaskDividerController.java
similarity index 89%
rename from services/core/java/com/android/server/wm/DockedStackDividerController.java
rename to services/core/java/com/android/server/wm/DockedTaskDividerController.java
index de4bdaa..fb9d064 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedTaskDividerController.java
@@ -19,16 +19,16 @@
 import android.graphics.Rect;
 
 /**
- * Keeps information about the docked stack divider.
+ * Keeps information about the docked task divider.
  */
-public class DockedStackDividerController {
+public class DockedTaskDividerController {
 
     private final DisplayContent mDisplayContent;
     private boolean mResizing;
 
     private final Rect mTouchRegion = new Rect();
 
-    DockedStackDividerController(DisplayContent displayContent) {
+    DockedTaskDividerController(DisplayContent displayContent) {
         mDisplayContent = displayContent;
     }
 
@@ -58,6 +58,6 @@
 
     private void resetDragResizingChangeReported() {
         mDisplayContent.forAllWindows(WindowState::resetDragResizingChangeReported,
-                true /* traverseTopToBottom */ );
+                true /* traverseTopToBottom */);
     }
 }
diff --git a/services/core/java/com/android/server/wm/FactoryErrorDialog.java b/services/core/java/com/android/server/wm/FactoryErrorDialog.java
index 88b5475..afdf1ee 100644
--- a/services/core/java/com/android/server/wm/FactoryErrorDialog.java
+++ b/services/core/java/com/android/server/wm/FactoryErrorDialog.java
@@ -41,6 +41,11 @@
     public void onStop() {
     }
 
+    @Override
+    protected void closeDialog() {
+        /* Do nothing */
+    }
+
     private final Handler mHandler = new Handler() {
         public void handleMessage(Message msg) {
             throw new RuntimeException("Rebooting from failed factory test");
diff --git a/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java
index 9286a46..567b6c2 100644
--- a/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java
+++ b/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java
@@ -19,9 +19,11 @@
 import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
 import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;
 
 import android.animation.ArgbEvaluator;
 import android.animation.ValueAnimator;
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityThread;
 import android.content.BroadcastReceiver;
@@ -32,10 +34,12 @@
 import android.graphics.PixelFormat;
 import android.graphics.drawable.ColorDrawable;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -43,6 +47,7 @@
 import android.util.Slog;
 import android.view.Display;
 import android.view.Gravity;
+import android.view.IWindowManager;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
@@ -50,6 +55,7 @@
 import android.view.WindowInsets;
 import android.view.WindowInsets.Type;
 import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
@@ -67,6 +73,8 @@
     private static final boolean DEBUG = false;
     private static final boolean DEBUG_SHOW_EVERY_TIME = false; // super annoying, use with caution
     private static final String CONFIRMED = "confirmed";
+    private static final int IMMERSIVE_MODE_CONFIRMATION_WINDOW_TYPE =
+            WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
 
     private static boolean sConfirmed;
 
@@ -78,7 +86,15 @@
 
     private ClingWindowView mClingWindow;
     private long mPanicTime;
+    /** The last {@link WindowManager} that is used to add the confirmation window. */
+    @Nullable
     private WindowManager mWindowManager;
+    /**
+     * The WindowContext that is registered with {@link #mWindowManager} with options to specify the
+     * {@link RootDisplayArea} to attach the confirmation window.
+     */
+    @Nullable
+    private Context mWindowContext;
     // Local copy of vr mode enabled state, to avoid calling into VrManager with
     // the lock held.
     private boolean mVrModeEnabled;
@@ -132,7 +148,7 @@
         }
     }
 
-    void immersiveModeChangedLw(String pkg, boolean isImmersiveMode,
+    void immersiveModeChangedLw(int rootDisplayAreaId, boolean isImmersiveMode,
             boolean userSetupComplete, boolean navBarEmpty) {
         mHandler.removeMessages(H.SHOW);
         if (isImmersiveMode) {
@@ -143,7 +159,9 @@
                     && !navBarEmpty
                     && !UserManager.isDeviceInDemoMode(mContext)
                     && (mLockTaskState != LOCK_TASK_MODE_LOCKED)) {
-                mHandler.sendEmptyMessageDelayed(H.SHOW, mShowDelayMs);
+                final Message msg = mHandler.obtainMessage(H.SHOW);
+                msg.arg1 = rootDisplayAreaId;
+                mHandler.sendMessageDelayed(msg, mShowDelayMs);
             }
         } else {
             mHandler.sendEmptyMessage(H.HIDE);
@@ -175,7 +193,8 @@
     private void handleHide() {
         if (mClingWindow != null) {
             if (DEBUG) Slog.d(TAG, "Hiding immersive mode confirmation");
-            getWindowManager().removeView(mClingWindow);
+            // We don't care which root display area the window manager is specifying for removal.
+            getWindowManager(FEATURE_UNDEFINED).removeView(mClingWindow);
             mClingWindow = null;
         }
     }
@@ -184,7 +203,7 @@
         final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.MATCH_PARENT,
-                WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL,
+                IMMERSIVE_MODE_CONFIRMATION_WINDOW_TYPE,
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                         | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
                         | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
@@ -353,23 +372,57 @@
      * DO HOLD THE WINDOW MANAGER LOCK WHEN CALLING THIS METHOD
      * The reason why we add this method is to avoid the deadlock of WMG->WMS and WMS->WMG
      * when ImmersiveModeConfirmation object is created.
+     *
+     * @return the WindowManager specifying with the {@code rootDisplayAreaId} to attach the
+     *         confirmation window.
      */
-    private WindowManager getWindowManager() {
-        if (mWindowManager == null) {
-            mWindowManager = (WindowManager)
-                      mContext.getSystemService(Context.WINDOW_SERVICE);
+    private WindowManager getWindowManager(int rootDisplayAreaId) {
+        if (mWindowManager == null || mWindowContext == null) {
+            // Create window context to specify the RootDisplayArea
+            final Bundle options = getOptionsForWindowContext(rootDisplayAreaId);
+            mWindowContext = mContext.createWindowContext(
+                    IMMERSIVE_MODE_CONFIRMATION_WINDOW_TYPE, options);
+            mWindowManager = mWindowContext.getSystemService(WindowManager.class);
+            return mWindowManager;
         }
+
+        // Update the window context and window manager to specify the RootDisplayArea
+        final Bundle options = getOptionsForWindowContext(rootDisplayAreaId);
+        final IWindowManager wms = WindowManagerGlobal.getWindowManagerService();
+        try {
+            wms.registerWindowContextListener(mWindowContext.getWindowContextToken(),
+                    IMMERSIVE_MODE_CONFIRMATION_WINDOW_TYPE, mContext.getDisplayId(), options);
+        }  catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+
         return mWindowManager;
     }
 
-    private void handleShow() {
+    /**
+     * Returns options that specify the {@link RootDisplayArea} to attach the confirmation window.
+     *         {@code null} if the {@code rootDisplayAreaId} is {@link FEATURE_UNDEFINED}.
+     */
+    @Nullable
+    private Bundle getOptionsForWindowContext(int rootDisplayAreaId) {
+        // In case we don't care which root display area the window manager is specifying.
+        if (rootDisplayAreaId == FEATURE_UNDEFINED) {
+            return null;
+        }
+
+        final Bundle options = new Bundle();
+        options.putInt(DisplayAreaPolicyBuilder.KEY_ROOT_DISPLAY_AREA_ID, rootDisplayAreaId);
+        return options;
+    }
+
+    private void handleShow(int rootDisplayAreaId) {
         if (DEBUG) Slog.d(TAG, "Showing immersive mode confirmation");
 
         mClingWindow = new ClingWindowView(mContext, mConfirm);
 
         // show the confirmation
         WindowManager.LayoutParams lp = getClingWindowLayoutParams();
-        getWindowManager().addView(mClingWindow, lp);
+        getWindowManager(rootDisplayAreaId).addView(mClingWindow, lp);
     }
 
     private final Runnable mConfirm = new Runnable() {
@@ -396,7 +449,7 @@
         public void handleMessage(Message msg) {
             switch(msg.what) {
                 case SHOW:
-                    handleShow();
+                    handleShow(msg.arg1);
                     break;
                 case HIDE:
                     handleHide();
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 580d328..75176df 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -27,6 +27,9 @@
 import static android.view.InsetsState.ITYPE_INVALID;
 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
 import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.view.WindowInsets.Type.displayCutout;
+import static android.view.WindowInsets.Type.mandatorySystemGestures;
+import static android.view.WindowInsets.Type.systemGestures;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
@@ -293,6 +296,76 @@
         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
     }
 
+    /**
+     * Updates {@link WindowState#mAboveInsetsState} for all windows in the display while the
+     * z-order of a window is changed.
+     *
+     * @param win The window whose z-order has changed.
+     * @param notifyInsetsChange {@code true} if the clients should be notified about the change.
+     */
+    void updateAboveInsetsState(WindowState win, boolean notifyInsetsChange) {
+        if (win == null || win.getDisplayContent() != mDisplayContent) {
+            return;
+        }
+        final boolean[] aboveWin = { true };
+        final InsetsState aboveInsetsState = new InsetsState();
+        aboveInsetsState.set(mState,
+                displayCutout() | systemGestures() | mandatorySystemGestures());
+        final SparseArray<InsetsSource> winProvidedSources = win.mProvidedInsetsSources;
+        final ArrayList<WindowState> insetsChangedWindows = new ArrayList<>();
+        mDisplayContent.forAllWindows(w -> {
+            if (aboveWin[0]) {
+                if (w == win) {
+                    aboveWin[0] = false;
+                    if (!win.mAboveInsetsState.equals(aboveInsetsState)) {
+                        win.mAboveInsetsState.set(aboveInsetsState);
+                        insetsChangedWindows.add(win);
+                    }
+                    return winProvidedSources.size() == 0;
+                } else {
+                    final SparseArray<InsetsSource> providedSources = w.mProvidedInsetsSources;
+                    for (int i = providedSources.size() - 1; i >= 0; i--) {
+                        aboveInsetsState.addSource(providedSources.valueAt(i));
+                    }
+                    if (winProvidedSources.size() == 0) {
+                        return false;
+                    }
+                    boolean changed = false;
+                    for (int i = winProvidedSources.size() - 1; i >= 0; i--) {
+                        changed |= w.mAboveInsetsState.removeSource(winProvidedSources.keyAt(i));
+                    }
+                    if (changed) {
+                        insetsChangedWindows.add(w);
+                    }
+                }
+            } else {
+                for (int i = winProvidedSources.size() - 1; i >= 0; i--) {
+                    w.mAboveInsetsState.addSource(winProvidedSources.valueAt(i));
+                }
+                insetsChangedWindows.add(w);
+            }
+            return false;
+        }, true /* traverseTopToBottom */);
+        if (notifyInsetsChange) {
+            for (int i = insetsChangedWindows.size() - 1; i >= 0; i--) {
+                mDispatchInsetsChanged.accept(insetsChangedWindows.get(i));
+            }
+        }
+    }
+
+    void onDisplayInfoUpdated(boolean notifyInsetsChange) {
+        final ArrayList<WindowState> insetsChangedWindows = new ArrayList<>();
+        mDisplayContent.forAllWindows(w -> {
+            w.mAboveInsetsState.set(mState, displayCutout());
+            insetsChangedWindows.add(w);
+        }, true /* traverseTopToBottom */);
+        if (notifyInsetsChange) {
+            for (int i = insetsChangedWindows.size() - 1; i >= 0; i--) {
+                mDispatchInsetsChanged.accept(insetsChangedWindows.get(i));
+            }
+        }
+    }
+
     void onInsetsModified(InsetsControlTarget caller) {
         boolean changed = false;
         for (int i = mProviders.size() - 1; i >= 0; i--) {
diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java
index 4b3a434..e18516d 100644
--- a/services/core/java/com/android/server/wm/LockTaskController.java
+++ b/services/core/java/com/android/server/wm/LockTaskController.java
@@ -141,6 +141,7 @@
     private final IBinder mToken = new LockTaskToken();
     private final ActivityTaskSupervisor mSupervisor;
     private final Context mContext;
+    private final TaskChangeNotificationController mTaskChangeNotificationController;
 
     // The following system services cannot be final, because they do not exist when this class
     // is instantiated during device boot
@@ -204,10 +205,11 @@
     private int mPendingDisableFromDismiss = UserHandle.USER_NULL;
 
     LockTaskController(Context context, ActivityTaskSupervisor supervisor,
-            Handler handler) {
+            Handler handler, TaskChangeNotificationController taskChangeNotificationController) {
         mContext = context;
         mSupervisor = supervisor;
         mHandler = handler;
+        mTaskChangeNotificationController = taskChangeNotificationController;
     }
 
     /**
@@ -532,6 +534,7 @@
         // thread, which makes it guarded by ATMS#mGlobalLock as ATMS#getLockTaskModeState.
         final int oldLockTaskModeState = mLockTaskModeState;
         mLockTaskModeState = LOCK_TASK_MODE_NONE;
+        mTaskChangeNotificationController.notifyLockTaskModeChanged(mLockTaskModeState);
         // When lock task ends, we enable the status bars.
         try {
             setStatusBarState(mLockTaskModeState, userId);
@@ -661,6 +664,7 @@
             }
             mWindowManager.onLockTaskStateChanged(lockTaskModeState);
             mLockTaskModeState = lockTaskModeState;
+            mTaskChangeNotificationController.notifyLockTaskModeChanged(mLockTaskModeState);
             setStatusBarState(lockTaskModeState, userId);
             setKeyguardState(lockTaskModeState, userId);
             if (getDevicePolicyManager() != null) {
diff --git a/services/core/java/com/android/server/wm/NonAppWindowAnimationAdapter.java b/services/core/java/com/android/server/wm/NonAppWindowAnimationAdapter.java
new file mode 100644
index 0000000..5d6d513
--- /dev/null
+++ b/services/core/java/com/android/server/wm/NonAppWindowAnimationAdapter.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS;
+import static com.android.server.wm.AnimationAdapterProto.REMOTE;
+import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
+
+import android.graphics.Rect;
+import android.os.SystemClock;
+import android.util.proto.ProtoOutputStream;
+import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControl;
+
+import com.android.internal.protolog.common.ProtoLog;
+import com.android.server.policy.WindowManagerPolicy;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+class NonAppWindowAnimationAdapter implements AnimationAdapter {
+
+    private final WindowState mWindow;
+    private RemoteAnimationTarget mTarget;
+    private SurfaceControl mCapturedLeash;
+
+    private long mDurationHint;
+    private long mStatusBarTransitionDelay;
+
+    @Override
+    public boolean getShowWallpaper() {
+        return false;
+    }
+
+    NonAppWindowAnimationAdapter(WindowState w,
+            long durationHint, long statusBarTransitionDelay) {
+        mWindow = w;
+        mDurationHint = durationHint;
+        mStatusBarTransitionDelay = statusBarTransitionDelay;
+    }
+
+    /**
+     * Creates and starts remote animations for all the visible non app windows.
+     *
+     * @return RemoteAnimationTarget[] targets for all the visible non app windows
+     */
+    public static RemoteAnimationTarget[] startNonAppWindowAnimationsForKeyguardExit(
+            WindowManagerService service, long durationHint, long statusBarTransitionDelay) {
+        final ArrayList<RemoteAnimationTarget> targets = new ArrayList<>();
+
+        final WindowManagerPolicy policy = service.mPolicy;
+        service.mRoot.forAllWindows(nonAppWindow -> {
+            if (nonAppWindow.mActivityRecord == null && policy.canBeHiddenByKeyguardLw(nonAppWindow)
+                    && nonAppWindow.wouldBeVisibleIfPolicyIgnored() && !nonAppWindow.isVisible()) {
+                final NonAppWindowAnimationAdapter nonAppAdapter = new NonAppWindowAnimationAdapter(
+                        nonAppWindow, durationHint, statusBarTransitionDelay);
+                nonAppWindow.startAnimation(nonAppWindow.getPendingTransaction(),
+                        nonAppAdapter, false /* hidden */, ANIMATION_TYPE_WINDOW_ANIMATION);
+                targets.add(nonAppAdapter.createRemoteAnimationTarget());
+            }
+        }, true /* traverseTopToBottom */);
+        return targets.toArray(new RemoteAnimationTarget[targets.size()]);
+    }
+
+    /**
+     * Create a remote animation target for this animation adapter.
+     */
+    RemoteAnimationTarget createRemoteAnimationTarget() {
+        mTarget = new RemoteAnimationTarget(-1, -1, getLeash(), false,
+                new Rect(), null, mWindow.getPrefixOrderIndex(), mWindow.getLastSurfacePosition(),
+                mWindow.getBounds(), null, mWindow.getWindowConfiguration(), true, null, null,
+                null);
+        return mTarget;
+    }
+
+    @Override
+    public void startAnimation(SurfaceControl animationLeash, SurfaceControl.Transaction t,
+            int type, SurfaceAnimator.OnAnimationFinishedCallback finishCallback) {
+        mCapturedLeash = animationLeash;
+    }
+
+    @Override
+    public long getDurationHint() {
+        return mDurationHint;
+    }
+
+    @Override
+    public long getStatusBarTransitionsStartTime() {
+        return SystemClock.uptimeMillis() + mStatusBarTransitionDelay;
+    }
+
+    /**
+     * @return the leash for this animation (only valid after the non app window surface animation
+     * has started).
+     */
+    SurfaceControl getLeash() {
+        return mCapturedLeash;
+    }
+
+    @Override
+    public void onAnimationCancelled(SurfaceControl animationLeash) {
+        ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "onAnimationCancelled");
+    }
+
+    @Override
+    public void dump(PrintWriter pw, String prefix) {
+        pw.print(prefix);
+        pw.print("token=");
+        pw.println(mWindow.mToken);
+        if (mTarget != null) {
+            pw.print(prefix);
+            pw.println("Target:");
+            mTarget.dump(pw, prefix + "  ");
+        } else {
+            pw.print(prefix);
+            pw.println("Target: null");
+        }
+    }
+
+    @Override
+    public void dumpDebug(ProtoOutputStream proto) {
+        final long token = proto.start(REMOTE);
+        if (mTarget != null) {
+            mTarget.dumpDebug(proto, TARGET);
+        }
+        proto.end(token);
+    }
+}
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedTaskController.java
similarity index 79%
rename from services/core/java/com/android/server/wm/PinnedStackController.java
rename to services/core/java/com/android/server/wm/PinnedTaskController.java
index 8fe2481..15e078b 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedTaskController.java
@@ -29,18 +29,18 @@
 import android.util.Log;
 import android.util.Slog;
 import android.view.DisplayInfo;
-import android.view.IPinnedStackListener;
+import android.view.IPinnedTaskListener;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 
 /**
- * Holds the common state of the pinned stack between the system and SystemUI. If SystemUI ever
+ * Holds the common state of the pinned task between the system and SystemUI. If SystemUI ever
  * needs to be restarted, it will be notified with the last known state.
  *
- * Changes to the pinned stack also flow through this controller, and generally, the system only
- * changes the pinned stack bounds through this controller in two ways:
+ * Changes to the pinned task also flow through this controller, and generally, the system only
+ * changes the pinned task bounds through this controller in two ways:
  *
  * 1) When first entering PiP: the controller returns the valid bounds given, taking aspect ratio
  *    and IME state into account.
@@ -49,18 +49,18 @@
  *    SystemUI adjustments (ie. expanded for menu, interaction, etc).
  *
  * Other changes in the system, including adjustment of IME, configuration change, and more are
- * handled by SystemUI (similar to the docked stack divider).
+ * handled by SystemUI (similar to the docked task divider).
  */
-class PinnedStackController {
+class PinnedTaskController {
 
-    private static final String TAG = TAG_WITH_CLASS_NAME ? "PinnedStackController" : TAG_WM;
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "PinnedTaskController" : TAG_WM;
 
     private final WindowManagerService mService;
     private final DisplayContent mDisplayContent;
 
-    private IPinnedStackListener mPinnedStackListener;
-    private final PinnedStackListenerDeathHandler mPinnedStackListenerDeathHandler =
-            new PinnedStackListenerDeathHandler();
+    private IPinnedTaskListener mPinnedTaskListener;
+    private final PinnedTaskListenerDeathHandler mPinnedTaskListenerDeathHandler =
+            new PinnedTaskListenerDeathHandler();
 
     /** Whether the PiP is entering or leaving. */
     private boolean mIsPipWindowingModeChanging;
@@ -72,7 +72,7 @@
     private ArrayList<RemoteAction> mActions = new ArrayList<>();
     private float mAspectRatio = -1f;
 
-    // Used to calculate stack bounds across rotations
+    // Used to calculate task bounds across rotations
     private final DisplayInfo mDisplayInfo = new DisplayInfo();
 
     // The aspect ratio bounds of the PIP.
@@ -85,19 +85,19 @@
     /**
      * Handler for the case where the listener dies.
      */
-    private class PinnedStackListenerDeathHandler implements IBinder.DeathRecipient {
+    private class PinnedTaskListenerDeathHandler implements IBinder.DeathRecipient {
 
         @Override
         public void binderDied() {
             // Clean up the state if the listener dies
-            if (mPinnedStackListener != null) {
-                mPinnedStackListener.asBinder().unlinkToDeath(mPinnedStackListenerDeathHandler, 0);
+            if (mPinnedTaskListener != null) {
+                mPinnedTaskListener.asBinder().unlinkToDeath(mPinnedTaskListenerDeathHandler, 0);
             }
-            mPinnedStackListener = null;
+            mPinnedTaskListener = null;
         }
     }
 
-    PinnedStackController(WindowManagerService service, DisplayContent displayContent) {
+    PinnedTaskController(WindowManagerService service, DisplayContent displayContent) {
         mService = service;
         mDisplayContent = displayContent;
         mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo());
@@ -121,17 +121,17 @@
     }
 
     /**
-     * Registers a pinned stack listener.
+     * Registers a pinned task listener.
      */
-    void registerPinnedStackListener(IPinnedStackListener listener) {
+    void registerPinnedTaskListener(IPinnedTaskListener listener) {
         try {
-            listener.asBinder().linkToDeath(mPinnedStackListenerDeathHandler, 0);
-            mPinnedStackListener = listener;
+            listener.asBinder().linkToDeath(mPinnedTaskListenerDeathHandler, 0);
+            mPinnedTaskListener = listener;
             notifyImeVisibilityChanged(mIsImeShowing, mImeHeight);
             notifyMovementBoundsChanged(false /* fromImeAdjustment */);
             notifyActionsChanged(mActions);
         } catch (RemoteException e) {
-            Log.e(TAG, "Failed to register pinned stack listener", e);
+            Log.e(TAG, "Failed to register pinned task listener", e);
         }
     }
 
@@ -139,8 +139,8 @@
      * @return whether the given {@param aspectRatio} is valid.
      */
     public boolean isValidPictureInPictureAspectRatio(float aspectRatio) {
-        return Float.compare(mMinAspectRatio, aspectRatio) <= 0 &&
-                Float.compare(aspectRatio, mMaxAspectRatio) <= 0;
+        return Float.compare(mMinAspectRatio, aspectRatio) <= 0
+                && Float.compare(aspectRatio, mMaxAspectRatio) <= 0;
     }
 
     /** Returns {@code true} if the PiP is on screen or is changing windowing mode. */
@@ -152,7 +152,7 @@
         return pinnedTask != null && pinnedTask.hasChild();
     }
 
-    /** Sets whether a visible stack is changing from or to pinned mode. */
+    /** Sets whether a visible task is changing from or to pinned mode. */
     void setPipWindowingModeChanging(boolean isPipWindowingModeChanging) {
         mIsPipWindowingModeChanging = isPipWindowingModeChanging;
     }
@@ -162,9 +162,9 @@
      * so that the default bounds will be returned for the next session.
      */
     void onActivityHidden(ComponentName componentName) {
-        if (mPinnedStackListener == null) return;
+        if (mPinnedTaskListener == null) return;
         try {
-            mPinnedStackListener.onActivityHidden(componentName);
+            mPinnedTaskListener.onActivityHidden(componentName);
         } catch (RemoteException e) {
             Slog.e(TAG_WM, "Error delivering reset reentry fraction event.", e);
         }
@@ -223,9 +223,9 @@
      * Notifies listeners that the PIP needs to be adjusted for the IME.
      */
     private void notifyImeVisibilityChanged(boolean imeVisible, int imeHeight) {
-        if (mPinnedStackListener != null) {
+        if (mPinnedTaskListener != null) {
             try {
-                mPinnedStackListener.onImeVisibilityChanged(imeVisible, imeHeight);
+                mPinnedTaskListener.onImeVisibilityChanged(imeVisible, imeHeight);
             } catch (RemoteException e) {
                 Slog.e(TAG_WM, "Error delivering bounds changed event.", e);
             }
@@ -233,9 +233,9 @@
     }
 
     private void notifyAspectRatioChanged(float aspectRatio) {
-        if (mPinnedStackListener == null) return;
+        if (mPinnedTaskListener == null) return;
         try {
-            mPinnedStackListener.onAspectRatioChanged(aspectRatio);
+            mPinnedTaskListener.onAspectRatioChanged(aspectRatio);
         } catch (RemoteException e) {
             Slog.e(TAG_WM, "Error delivering aspect ratio changed event.", e);
         }
@@ -245,9 +245,9 @@
      * Notifies listeners that the PIP actions have changed.
      */
     private void notifyActionsChanged(List<RemoteAction> actions) {
-        if (mPinnedStackListener != null) {
+        if (mPinnedTaskListener != null) {
             try {
-                mPinnedStackListener.onActionsChanged(new ParceledListSlice(actions));
+                mPinnedTaskListener.onActionsChanged(new ParceledListSlice(actions));
             } catch (RemoteException e) {
                 Slog.e(TAG_WM, "Error delivering actions changed event.", e);
             }
@@ -259,11 +259,11 @@
      */
     private void notifyMovementBoundsChanged(boolean fromImeAdjustment) {
         synchronized (mService.mGlobalLock) {
-            if (mPinnedStackListener == null) {
+            if (mPinnedTaskListener == null) {
                 return;
             }
             try {
-                mPinnedStackListener.onMovementBoundsChanged(fromImeAdjustment);
+                mPinnedTaskListener.onMovementBoundsChanged(fromImeAdjustment);
             } catch (RemoteException e) {
                 Slog.e(TAG_WM, "Error delivering actions changed event.", e);
             }
@@ -271,7 +271,7 @@
     }
 
     void dump(String prefix, PrintWriter pw) {
-        pw.println(prefix + "PinnedStackController");
+        pw.println(prefix + "PinnedTaskController");
         pw.println(prefix + "  mIsImeShowing=" + mIsImeShowing);
         pw.println(prefix + "  mImeHeight=" + mImeHeight);
         pw.println(prefix + "  mAspectRatio=" + mAspectRatio);
diff --git a/services/core/java/com/android/server/wm/PointerEventDispatcher.java b/services/core/java/com/android/server/wm/PointerEventDispatcher.java
index 6b8144c..9bc7e93 100644
--- a/services/core/java/com/android/server/wm/PointerEventDispatcher.java
+++ b/services/core/java/com/android/server/wm/PointerEventDispatcher.java
@@ -16,11 +16,15 @@
 
 package com.android.server.wm;
 
+import static com.android.server.input.InputManagerService.ENABLE_PER_WINDOW_INPUT_ROTATION;
+
+import android.graphics.Point;
 import android.view.InputChannel;
 import android.view.InputDevice;
 import android.view.InputEvent;
 import android.view.InputEventReceiver;
 import android.view.MotionEvent;
+import android.view.Surface;
 import android.view.WindowManagerPolicyConstants.PointerEventListener;
 
 import com.android.server.UiThread;
@@ -31,8 +35,12 @@
     private final ArrayList<PointerEventListener> mListeners = new ArrayList<>();
     private PointerEventListener[] mListenersArray = new PointerEventListener[0];
 
-    public PointerEventDispatcher(InputChannel inputChannel) {
+    private final DisplayContent mDisplayContent;
+    private final Point mTmpSize = new Point();
+
+    public PointerEventDispatcher(InputChannel inputChannel, DisplayContent dc) {
         super(inputChannel, UiThread.getHandler().getLooper());
+        mDisplayContent = dc;
     }
 
     @Override
@@ -40,7 +48,16 @@
         try {
             if (event instanceof MotionEvent
                     && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
-                final MotionEvent motionEvent = (MotionEvent) event;
+                MotionEvent motionEvent = (MotionEvent) event;
+                if (ENABLE_PER_WINDOW_INPUT_ROTATION) {
+                    final int rotation = mDisplayContent.getRotation();
+                    if (rotation != Surface.ROTATION_0) {
+                        mDisplayContent.getDisplay().getRealSize(mTmpSize);
+                        motionEvent = MotionEvent.obtain(motionEvent);
+                        motionEvent.transform(MotionEvent.createRotateMatrix(
+                                rotation, mTmpSize.x, mTmpSize.y));
+                    }
+                }
                 PointerEventListener[] listeners;
                 synchronized (mListeners) {
                     if (mListenersArray == null) {
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 392f27e..42cb96f 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -16,6 +16,9 @@
 
 package com.android.server.wm;
 
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY;
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
+
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS;
 import static com.android.server.wm.AnimationAdapterProto.REMOTE;
 import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
@@ -126,7 +129,7 @@
         final RemoteAnimationTarget[] wallpaperTargets = createWallpaperAnimations();
 
         // TODO(bc-unlock): Create the remote non app animation targets (if any)
-        final RemoteAnimationTarget[] nonAppTargets = new RemoteAnimationTarget[0];
+        final RemoteAnimationTarget[] nonAppTargets = createNonAppWindowAnimations(transit);
 
         mService.mAnimator.addAfterPrepareSurfacesRunnable(() -> {
             try {
@@ -215,6 +218,17 @@
                 }, mPendingWallpaperAnimations);
     }
 
+    private RemoteAnimationTarget[] createNonAppWindowAnimations(
+            @WindowManager.TransitionOldType int transit) {
+        ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "createNonAppWindowAnimations()");
+        return (transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY
+                || transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER)
+                ? NonAppWindowAnimationAdapter.startNonAppWindowAnimationsForKeyguardExit(mService,
+                    mRemoteAnimationAdapter.getDuration(),
+                    mRemoteAnimationAdapter.getStatusBarTransitionDelay())
+                : new RemoteAnimationTarget[0];
+    }
+
     private void onAnimationFinished() {
         ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "onAnimationFinished(): mPendingAnimations=%d",
                 mPendingAnimations.size());
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index bb5e8bf..3f9ea1f 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -650,6 +650,20 @@
     }
 
     @Override
+    void dispatchConfigurationToChildren() {
+        final Configuration configuration = getConfiguration();
+        for (int i = getChildCount() - 1; i >= 0; i--) {
+            final DisplayContent displayContent = getChildAt(i);
+            if (displayContent.isDefaultDisplay) {
+                // The global configuration is also the override configuration of default display.
+                displayContent.performDisplayOverrideConfigUpdate(configuration);
+            } else {
+                displayContent.onConfigurationChanged(configuration);
+            }
+        }
+    }
+
+    @Override
     public void onConfigurationChanged(Configuration newParentConfig) {
         prepareFreezingTaskBounds();
         super.onConfigurationChanged(newParentConfig);
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index 533c82e..95a4f69e 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -17,6 +17,7 @@
 package com.android.server.wm;
 
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+import static android.util.RotationUtils.deltaRotation;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
 import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
@@ -174,7 +175,7 @@
         // apply rotation animation because there should be a top app shown as rotated. So the
         // specified original rotation customizes the direction of animation to have better look
         // when restoring the rotated app to the same rotation as current display.
-        final int delta = DisplayContent.deltaRotation(originalRotation, realOriginalRotation);
+        final int delta = deltaRotation(originalRotation, realOriginalRotation);
         final boolean flipped = delta == Surface.ROTATION_90 || delta == Surface.ROTATION_270;
         mOriginalWidth = flipped ? originalHeight : originalWidth;
         mOriginalHeight = flipped ? originalWidth : originalHeight;
@@ -330,7 +331,7 @@
         // Compute the transformation matrix that must be applied
         // to the snapshot to make it stay in the same original position
         // with the current screen rotation.
-        int delta = DisplayContent.deltaRotation(rotation, Surface.ROTATION_0);
+        int delta = deltaRotation(rotation, Surface.ROTATION_0);
         RotationAnimationUtils.createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix);
 
         setRotationTransform(t, mSnapshotInitialMatrix);
@@ -352,8 +353,7 @@
         mStarted = true;
 
         // Figure out how the screen has moved from the original rotation.
-        int delta = DisplayContent.deltaRotation(mCurRotation, mOriginalRotation);
-
+        int delta = deltaRotation(mCurRotation, mOriginalRotation);
 
         final boolean customAnim;
         if (exitAnim != 0 && enterAnim != 0) {
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 8b18679..b82a308 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -54,10 +54,10 @@
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Process;
+import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.Trace;
 import android.os.UserHandle;
-import android.service.screenshot.ScreenshotHash;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.MergedConfiguration;
@@ -850,11 +850,11 @@
     }
 
     @Override
-    public ScreenshotHash generateScreenshotHash(IWindow window, Rect boundsInWindow,
-            String hashAlgorithm) {
+    public void generateDisplayHash(IWindow window, Rect boundsInWindow, String hashAlgorithm,
+            RemoteCallback callback) {
         final long origId = Binder.clearCallingIdentity();
         try {
-            return mService.generateScreenshotHash(this, window, boundsInWindow, hashAlgorithm);
+            mService.generateDisplayHash(this, window, boundsInWindow, hashAlgorithm, callback);
         } finally {
             Binder.restoreCallingIdentity(origId);
         }
diff --git a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java
index f3859b4..a98a478 100644
--- a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java
+++ b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java
@@ -126,11 +126,17 @@
                 Slog.w(TAG, "Cannot create GestureDetector, display removed:" + displayId);
                 return;
             }
+            onDisplayInfoChanged(info);
             mGestureDetector = new GestureDetector(mContext, new FlingGestureDetector(), mHandler) {
             };
         });
     }
 
+    void onDisplayInfoChanged(DisplayInfo info) {
+        screenWidth = info.logicalWidth;
+        screenHeight = info.logicalHeight;
+    }
+
     @Override
     public void onPointerEvent(MotionEvent event) {
         if (mGestureDetector != null && event.isTouchEvent()) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index d360916..80173b5 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -35,7 +35,6 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.app.WindowConfiguration.activityTypeToString;
-import static android.app.WindowConfiguration.isSplitScreenWindowingMode;
 import static android.app.WindowConfiguration.windowingModeToString;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
@@ -148,7 +147,6 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ROOT_TASK;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.WindowManagerService.MIN_TASK_LETTERBOX_ASPECT_RATIO;
 import static com.android.server.wm.WindowManagerService.dipToPixel;
 import static com.android.server.wm.WindowStateAnimator.ROOT_TASK_CLIP_BEFORE_ANIM;
 
@@ -597,10 +595,6 @@
     @Nullable
     private ActivityRecord mResumedActivity = null;
 
-    /** Last activity that is used to compute the Task bounds. */
-    @Nullable
-    private ActivityRecord mLastTaskBoundsComputeActivity;
-
     private boolean mForceShowForAllUsers;
 
     /** When set, will force the task to report as invisible. */
@@ -841,6 +835,9 @@
     // Tracking cookie for the creation of this task.
     IBinder mLaunchCookie;
 
+    // The task will be removed when TaskOrganizer, which is managing the task, is destroyed.
+    boolean mRemoveWithTaskOrganizer;
+
     private Task(ActivityTaskManagerService atmService, int _taskId, Intent _intent,
             Intent _affinityIntent, String _affinity, String _rootAffinity,
             ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
@@ -852,7 +849,8 @@
             boolean supportsPictureInPicture, boolean _realActivitySuspended,
             boolean userSetupComplete, int minWidth, int minHeight, ActivityInfo info,
             IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
-            boolean _createdByOrganizer, IBinder _launchCookie, boolean _deferTaskAppear) {
+            boolean _createdByOrganizer, IBinder _launchCookie, boolean _deferTaskAppear,
+            boolean _removeWithTaskOrganizer) {
         super(atmService.mWindowManager);
 
         mAtmService = atmService;
@@ -911,6 +909,7 @@
         mCreatedByOrganizer = _createdByOrganizer;
         mLaunchCookie = _launchCookie;
         mDeferTaskAppear = _deferTaskAppear;
+        mRemoveWithTaskOrganizer = _removeWithTaskOrganizer;
         EventLogTags.writeWmTaskCreated(mTaskId, isRootTask() ? INVALID_TASK_ID : getRootTaskId());
     }
 
@@ -1261,10 +1260,13 @@
      * @param info The activity info which could be different from {@code r.info} if set.
      */
     void setIntent(ActivityRecord r, @Nullable Intent intent, @Nullable ActivityInfo info) {
-        mCallingUid = r.launchedFromUid;
-        mCallingPackage = r.launchedFromPackage;
-        mCallingFeatureId = r.launchedFromFeatureId;
-        setIntent(intent != null ? intent : r.intent, info != null ? info : r.info);
+        if (this.intent == null || !mNeverRelinquishIdentity) {
+            mCallingUid = r.launchedFromUid;
+            mCallingPackage = r.launchedFromPackage;
+            mCallingFeatureId = r.launchedFromFeatureId;
+            setIntent(intent != null ? intent : r.intent, info != null ? info : r.info);
+            return;
+        }
         setLockTaskAuth(r);
     }
 
@@ -1272,13 +1274,7 @@
     private void setIntent(Intent _intent, ActivityInfo info) {
         if (!isLeafTask()) return;
 
-        if (intent == null) {
-            mNeverRelinquishIdentity =
-                    (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
-        } else if (mNeverRelinquishIdentity) {
-            return;
-        }
-
+        mNeverRelinquishIdentity = (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
         affinity = info.taskAffinity;
         if (intent == null) {
             // If this task already has an intent associated with it, don't set the root
@@ -1496,11 +1492,6 @@
     }
 
     void cleanUpActivityReferences(ActivityRecord r) {
-        // mLastTaskBoundsComputeActivity is set at leaf Task
-        if (mLastTaskBoundsComputeActivity == r) {
-            mLastTaskBoundsComputeActivity = null;
-        }
-
         // mPausingActivity is set at leaf task
         if (mPausingActivity != null && mPausingActivity == r) {
             mPausingActivity = null;
@@ -2267,7 +2258,7 @@
         }
 
         if (pipChanging) {
-            mDisplayContent.getPinnedStackController().setPipWindowingModeChanging(true);
+            mDisplayContent.getPinnedTaskController().setPipWindowingModeChanging(true);
             // If the top activity is using fixed rotation, it should be changing from PiP to
             // fullscreen with display orientation change. Do not notify fullscreen task organizer
             // because the restoration of task surface and the transformation of activity surface
@@ -2297,7 +2288,7 @@
             }
         } finally {
             if (pipChanging) {
-                mDisplayContent.getPinnedStackController().setPipWindowingModeChanging(false);
+                mDisplayContent.getPinnedTaskController().setPipWindowingModeChanging(false);
             }
         }
 
@@ -2361,9 +2352,7 @@
             final int newRotation = getWindowConfiguration().getRotation();
             final boolean rotationChanged = prevRotation != newRotation;
             if (rotationChanged) {
-                mDisplayContent.rotateBounds(
-                        newParentConfig.windowConfiguration.getBounds(), prevRotation, newRotation,
-                        newBounds);
+                mDisplayContent.rotateBounds(prevRotation, newRotation, newBounds);
                 setBounds(newBounds);
             }
         }
@@ -2849,8 +2838,6 @@
                     windowingMode != WINDOWING_MODE_UNDEFINED ? windowingMode : parentWindowingMode;
             if (WindowConfiguration.inMultiWindowMode(candidateWindowingMode)
                     && candidateWindowingMode != WINDOWING_MODE_PINNED
-                    && (candidateWindowingMode != WINDOWING_MODE_FREEFORM
-                            || !mTaskSupervisor.mService.mSizeCompatFreeform)
                     && !mTaskSupervisor.mService.mSupportsNonResizableMultiWindow) {
                 getResolvedOverrideConfiguration().windowConfiguration.setWindowingMode(
                         WINDOWING_MODE_FULLSCREEN);
@@ -2865,7 +2852,6 @@
 
     private void resolveLeafOnlyOverrideConfigs(Configuration newParentConfig,
             Rect previousBounds) {
-        mLastTaskBoundsComputeActivity = getTopNonFinishingActivity(false /* includeOverlays */);
 
         int windowingMode =
                 getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode();
@@ -2879,7 +2865,8 @@
                 getResolvedOverrideConfiguration().windowConfiguration.getBounds();
 
         if (windowingMode == WINDOWING_MODE_FULLSCREEN) {
-            computeFullscreenBounds(outOverrideBounds, newParentConfig);
+            // Use empty bounds to indicate "fill parent".
+            outOverrideBounds.setEmpty();
             // The bounds for fullscreen mode shouldn't be adjusted by minimal size. Otherwise if
             // the parent or display is smaller than the size, the content may be cropped.
             return;
@@ -2890,21 +2877,6 @@
             computeFreeformBounds(outOverrideBounds, newParentConfig);
             return;
         }
-
-        if (isSplitScreenWindowingMode(windowingMode)
-                || windowingMode == WINDOWING_MODE_MULTI_WINDOW) {
-            // This is to compute whether the task should be letterboxed to handle non-resizable app
-            // in multi window. There is no split screen only logic.
-            computeLetterboxBounds(outOverrideBounds, newParentConfig);
-        }
-    }
-
-    /** Computes bounds for {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN}. */
-    @VisibleForTesting
-    void computeFullscreenBounds(@NonNull Rect outBounds, @NonNull Configuration newParentConfig) {
-        // In FULLSCREEN mode, always start with empty bounds to indicate "fill parent".
-        outBounds.setEmpty();
-        computeLetterboxBounds(outBounds, newParentConfig);
     }
 
     /** Computes bounds for {@link WindowConfiguration#WINDOWING_MODE_FREEFORM}. */
@@ -2936,94 +2908,6 @@
         }
     }
 
-    /**
-     * Computes bounds (letterbox or pillarbox) when the parent doesn't handle the orientation
-     * change and the requested orientation is different from the parent.
-     */
-    private void computeLetterboxBounds(@NonNull Rect outBounds,
-            @NonNull Configuration newParentConfig) {
-        if (handlesOrientationChangeFromDescendant()) {
-            // No need to letterbox at task level. Display will handle fixed-orientation requests.
-            return;
-        }
-
-        final int parentOrientation = newParentConfig.orientation;
-        // Use the top activity as the reference of orientation. Don't include overlays because
-        // it is usually not the actual content or just temporarily shown.
-        // E.g. ForcedResizableInfoActivity.
-        final ActivityRecord refActivity = getTopNonFinishingActivity(false /* includeOverlays */);
-
-        // If the task or the reference activity requires a different orientation (either by
-        // override or activityInfo), make it fit the available bounds by scaling down its bounds.
-        final int overrideOrientation = getRequestedOverrideConfiguration().orientation;
-        final int forcedOrientation =
-                (overrideOrientation != ORIENTATION_UNDEFINED || refActivity == null)
-                        ? overrideOrientation : refActivity.getRequestedConfigurationOrientation();
-        if (forcedOrientation == ORIENTATION_UNDEFINED || forcedOrientation == parentOrientation) {
-            return;
-        }
-
-        final ActivityRecord.CompatDisplayInsets compatDisplayInsets =
-                refActivity == null ? null : refActivity.getCompatDisplayInsets();
-        if (compatDisplayInsets != null && !compatDisplayInsets.mIsTaskLetterboxed) {
-            // App prefers to keep its original size.
-            // If the size compat is from previous task letterboxing, we may want to have task
-            // letterbox again, otherwise it will show the size compat restart button even if the
-            // restart bounds will be the same.
-            return;
-        }
-
-        final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
-        final int parentWidth = parentBounds.width();
-        final int parentHeight = parentBounds.height();
-        float aspect = Math.max(parentWidth, parentHeight)
-                / (float) Math.min(parentWidth, parentHeight);
-
-        // Adjust the Task letterbox bounds to fit the app request aspect ratio in order to use the
-        // extra available space.
-        if (refActivity != null) {
-            final float maxAspectRatio = refActivity.info.maxAspectRatio;
-            final float minAspectRatio = refActivity.info.minAspectRatio;
-            if (aspect > maxAspectRatio && maxAspectRatio != 0) {
-                aspect = maxAspectRatio;
-            } else if (aspect < minAspectRatio) {
-                aspect = minAspectRatio;
-            }
-        }
-
-        // Override from config_letterboxAspectRatio or via ADB with set-letterbox-aspect-ratio.
-        final float letterboxAspectRatioOverride = mWmService.getTaskLetterboxAspectRatio();
-        // Activity min/max aspect ratio restrictions will be respected by the activity-level
-        // letterboxing (size-compat mode). Therefore this override can control the maximum screen
-        // area that can be occupied by the app in the letterbox mode.
-        aspect = letterboxAspectRatioOverride > MIN_TASK_LETTERBOX_ASPECT_RATIO
-                ? letterboxAspectRatioOverride : aspect;
-
-        // Store the current bounds to be able to revert to size compat mode values below if needed.
-        mTmpFullBounds.set(outBounds);
-        if (forcedOrientation == ORIENTATION_LANDSCAPE) {
-            final int height = (int) Math.rint(parentWidth / aspect);
-            final int top = parentBounds.centerY() - height / 2;
-            outBounds.set(parentBounds.left, top, parentBounds.right, top + height);
-        } else {
-            final int width = (int) Math.rint(parentHeight / aspect);
-            final int left = parentBounds.centerX() - width / 2;
-            outBounds.set(left, parentBounds.top, left + width, parentBounds.bottom);
-        }
-
-        if (compatDisplayInsets != null) {
-            compatDisplayInsets.getBoundsByRotation(
-                    mTmpBounds, newParentConfig.windowConfiguration.getRotation());
-            if (outBounds.width() != mTmpBounds.width()
-                    || outBounds.height() != mTmpBounds.height()) {
-                // The app shouldn't be resized, we only do task letterboxing if the compat bounds
-                // is also from the same task letterbox. Otherwise, clear the task bounds to show
-                // app in size compat mode.
-                outBounds.set(mTmpFullBounds);
-            }
-        }
-    }
-
     Rect updateOverrideConfigurationFromLaunchBounds() {
         // If the task is controlled by another organized task, do not set override
         // configurations and let its parent (organized task) to control it;
@@ -3038,11 +2922,6 @@
         return bounds;
     }
 
-    @Nullable
-    ActivityRecord getLastTaskBoundsComputeActivity() {
-        return mLastTaskBoundsComputeActivity;
-    }
-
     /** Updates the task's bounds and override configuration to match what is expected for the
      * input root task. */
     void updateOverrideConfigurationForRootTask(Task inRootTask) {
@@ -3941,12 +3820,6 @@
                 || activityType == ACTIVITY_TYPE_ASSISTANT;
     }
 
-    boolean isTaskLetterboxed() {
-        // No letterbox for multi window root task
-        return !matchParentBounds()
-                && (getWindowingMode() == WINDOWING_MODE_FULLSCREEN || !isRootTask());
-    }
-
     @Override
     boolean fillsParent() {
         // From the perspective of policy, we still want to report that this task fills parent
@@ -5373,11 +5246,11 @@
         }
         final boolean wasHidden = isForceHidden();
         mForceHiddenFlags = newFlags;
-        if (wasHidden && isFocusableAndVisible()) {
+        if (wasHidden != isForceHidden() && isTopActivityFocusable()) {
             // The change in force-hidden state will change visibility without triggering a root
             // task order change, so we should reset the preferred top focusable root task to ensure
             // it's not used if a new activity is started from this task.
-            getDisplayArea().resetPreferredTopFocusableRootTaskIfBelow(this);
+            getDisplayArea().resetPreferredTopFocusableRootTaskIfNeeded(this);
         }
         return true;
     }
@@ -7792,18 +7665,18 @@
             return;
         }
 
-        final PinnedStackController pinnedStackController =
-                getDisplayContent().getPinnedStackController();
+        final PinnedTaskController pinnedTaskController =
+                getDisplayContent().getPinnedTaskController();
 
-        if (Float.compare(aspectRatio, pinnedStackController.getAspectRatio()) == 0) {
+        if (Float.compare(aspectRatio, pinnedTaskController.getAspectRatio()) == 0) {
             return;
         }
 
         // Notify the pinned stack controller about aspect ratio change.
         // This would result a callback delivered from SystemUI to WM to start animation,
         // if the bounds are ought to be altered due to aspect ratio change.
-        pinnedStackController.setAspectRatio(
-                pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)
+        pinnedTaskController.setAspectRatio(
+                pinnedTaskController.isValidPictureInPictureAspectRatio(aspectRatio)
                         ? aspectRatio : -1f);
     }
 
@@ -7819,7 +7692,7 @@
             return;
         }
 
-        getDisplayContent().getPinnedStackController().setActions(actions);
+        getDisplayContent().getPinnedTaskController().setActions(actions);
     }
 
     /** Returns true if a removal action is still being deferred. */
@@ -7972,6 +7845,7 @@
         private IBinder mLaunchCookie;
         private boolean mOnTop;
         private boolean mHasBeenVisible;
+        private boolean mRemoveWithTaskOrganizer;
 
         Builder(ActivityTaskManagerService atm) {
             mAtmService = atm;
@@ -8267,6 +8141,9 @@
             mCallingPackage = mActivityInfo.packageName;
             mResizeMode = mActivityInfo.resizeMode;
             mSupportsPictureInPicture = mActivityInfo.supportsPictureInPicture();
+            if (mActivityOptions != null) {
+                mRemoveWithTaskOrganizer = mActivityOptions.getRemoveWithTaskOranizer();
+            }
 
             final Task task = buildInner();
             task.mHasBeenVisible = mHasBeenVisible;
@@ -8305,7 +8182,7 @@
                     mCallingPackage, mCallingFeatureId, mResizeMode, mSupportsPictureInPicture,
                     mRealActivitySuspended, mUserSetupComplete, mMinWidth, mMinHeight,
                     mActivityInfo, mVoiceSession, mVoiceInteractor, mCreatedByOrganizer,
-                    mLaunchCookie, mDeferTaskAppear);
+                    mLaunchCookie, mDeferTaskAppear, mRemoveWithTaskOrganizer);
         }
     }
 }
diff --git a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
index 622fe05..04ec4bd 100644
--- a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
@@ -59,6 +59,7 @@
     private static final int NOTIFY_TASK_REQUESTED_ORIENTATION_CHANGED_MSG = 25;
     private static final int NOTIFY_ACTIVITY_ROTATED_MSG = 26;
     private static final int NOTIFY_TASK_MOVED_TO_BACK_LISTENERS_MSG = 27;
+    private static final int NOTIFY_LOCK_TASK_MODE_CHANGED_MSG = 28;
 
     // Delay in notifying task stack change listeners (in millis)
     private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
@@ -129,8 +130,8 @@
         l.onActivityForcedResizable((String) m.obj, m.arg1, m.arg2);
     };
 
-    private final TaskStackConsumer mNotifyActivityDismissingDockedStack = (l, m) -> {
-        l.onActivityDismissingDockedStack();
+    private final TaskStackConsumer mNotifyActivityDismissingDockedTask = (l, m) -> {
+        l.onActivityDismissingDockedTask();
     };
 
     private final TaskStackConsumer mNotifyActivityLaunchOnSecondaryDisplayFailed = (l, m) -> {
@@ -177,6 +178,10 @@
         l.onTaskMovedToBack((RunningTaskInfo) m.obj);
     };
 
+    private final TaskStackConsumer mNotifyLockTaskModeChanged = (l, m) -> {
+        l.onLockTaskModeChanged(m.arg1);
+    };
+
     @FunctionalInterface
     public interface TaskStackConsumer {
         void accept(ITaskStackListener t, Message m) throws RemoteException;
@@ -230,7 +235,7 @@
                     forAllRemoteListeners(mNotifyActivityForcedResizable, msg);
                     break;
                 case NOTIFY_ACTIVITY_DISMISSING_DOCKED_ROOT_TASK_MSG:
-                    forAllRemoteListeners(mNotifyActivityDismissingDockedStack, msg);
+                    forAllRemoteListeners(mNotifyActivityDismissingDockedTask, msg);
                     break;
                 case NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG:
                     forAllRemoteListeners(mNotifyActivityLaunchOnSecondaryDisplayFailed, msg);
@@ -268,6 +273,9 @@
                 case NOTIFY_TASK_MOVED_TO_BACK_LISTENERS_MSG:
                     forAllRemoteListeners(mNotifyTaskMovedToBack, msg);
                     break;
+                case NOTIFY_LOCK_TASK_MODE_CHANGED_MSG:
+                    forAllRemoteListeners(mNotifyLockTaskModeChanged, msg);
+                    break;
             }
             if (msg.obj instanceof SomeArgs) {
                 ((SomeArgs) msg.obj).recycle();
@@ -383,7 +391,7 @@
     void notifyActivityDismissingDockedRootTask() {
         mHandler.removeMessages(NOTIFY_ACTIVITY_DISMISSING_DOCKED_ROOT_TASK_MSG);
         final Message msg = mHandler.obtainMessage(NOTIFY_ACTIVITY_DISMISSING_DOCKED_ROOT_TASK_MSG);
-        forAllLocalListeners(mNotifyActivityDismissingDockedStack, msg);
+        forAllLocalListeners(mNotifyActivityDismissingDockedTask, msg);
         msg.sendToTarget();
     }
 
@@ -550,4 +558,11 @@
         forAllLocalListeners(mNotifyTaskMovedToBack, msg);
         msg.sendToTarget();
     }
+
+    void notifyLockTaskModeChanged(int lockTaskModeState) {
+        final Message msg = mHandler.obtainMessage(NOTIFY_LOCK_TASK_MODE_CHANGED_MSG,
+                lockTaskModeState, 0 /* unused */);
+        forAllLocalListeners(mNotifyLockTaskModeChanged, msg);
+        msg.sendToTarget();
+    }
 }
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 40248c4..badd7fd 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -974,9 +974,10 @@
         onRootTaskOrderChanged(rootTask);
     }
 
-    void resetPreferredTopFocusableRootTaskIfBelow(Task task) {
+    /** Reset the mPreferredTopFocusableRootTask if it is or below the given task. */
+    void resetPreferredTopFocusableRootTaskIfNeeded(Task task) {
         if (mPreferredTopFocusableRootTask != null
-                && mPreferredTopFocusableRootTask.compareTo(task) < 0) {
+                && mPreferredTopFocusableRootTask.compareTo(task) <= 0) {
             mPreferredTopFocusableRootTask = null;
         }
     }
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index 106db0b..f3b69e3 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -234,19 +234,28 @@
             }
         }
 
-        // STEP 2.3: Adjust launch parameters as needed for freeform display. We enforce the policy
-        // that legacy (pre-D) apps and those apps that can't handle multiple screen density well
-        // are forced to be maximized. The rest of this step is to define the default policy when
-        // there is no initial bounds or a fully resolved current params from callers.
+        // STEP 2.3: Adjust launch parameters as needed for freeform display. We enforce the
+        // policies related to unresizable apps here. If an app is unresizable and the freeform
+        // size-compat mode is enabled, it can be launched in freeform depending on other properties
+        // such as orientation. Otherwise, the app is forcefully launched in maximized. The rest of
+        // this step is to define the default policy when there is no initial bounds or a fully
+        // resolved current params from callers.
         if (display.inFreeformWindowingMode()) {
             if (launchMode == WINDOWING_MODE_PINNED) {
                 if (DEBUG) appendLog("picture-in-picture");
-            } else if (!mSupervisor.mService.mSizeCompatFreeform && !root.isResizeable()) {
-                // We're launching an activity in size-compat mode and they aren't allowed in
-                // freeform, so force it to be maximized.
-                launchMode = WINDOWING_MODE_FULLSCREEN;
-                outParams.mBounds.setEmpty();
-                if (DEBUG) appendLog("forced-maximize");
+            } else if (!root.isResizeable()) {
+                if (shouldLaunchUnresizableAppInFreeform(root, suggestedDisplayArea)) {
+                    launchMode = WINDOWING_MODE_FREEFORM;
+                    if (outParams.mBounds.isEmpty()) {
+                        getTaskBounds(root, display, layout, launchMode, hasInitialBounds,
+                                outParams.mBounds);
+                    }
+                    if (DEBUG) appendLog("unresizable-freeform");
+                } else {
+                    launchMode = WINDOWING_MODE_FULLSCREEN;
+                    outParams.mBounds.setEmpty();
+                    if (DEBUG) appendLog("unresizable-forced-maximize");
+                }
             }
         } else {
             if (DEBUG) appendLog("non-freeform-display");
@@ -322,7 +331,6 @@
             }
             getTaskBounds(root, display, layout, resolvedMode, hasInitialBounds, outParams.mBounds);
         }
-
         return RESULT_CONTINUE;
     }
 
@@ -562,6 +570,27 @@
         outBounds.offset(xOffset, yOffset);
     }
 
+    private boolean shouldLaunchUnresizableAppInFreeform(ActivityRecord activity,
+            TaskDisplayArea displayArea) {
+        if (!mSupervisor.mService.mSupportsNonResizableMultiWindow || activity.isResizeable()) {
+            return false;
+        }
+        final DisplayContent display = displayArea.getDisplayContent();
+        if (display == null) {
+            return false;
+        }
+
+        final int displayOrientation = orientationFromBounds(displayArea.getBounds());
+        final int activityOrientation = resolveOrientation(activity, display,
+                displayArea.getBounds());
+        if (displayArea.getWindowingMode() == WINDOWING_MODE_FREEFORM
+                && displayOrientation != activityOrientation) {
+            return true;
+        }
+
+        return false;
+    }
+
     /**
      * Resolves activity requested orientation to 4 categories:
      * 1) {@link ActivityInfo#SCREEN_ORIENTATION_LOCKED} indicating app wants to lock down
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index c0bce6b..fc6db61 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -285,18 +285,20 @@
             return false;
         }
 
-        private boolean removeTask(Task t) {
+        private boolean removeTask(Task t, boolean removeFromSystem) {
             mOrganizedTasks.remove(t);
             mInterceptBackPressedOnRootTasks.remove(t.mTaskId);
-
-            if (t.mTaskAppearedSent) {
+            boolean taskAppearedSent = t.mTaskAppearedSent;
+            if (taskAppearedSent) {
                 if (t.getSurfaceControl() != null) {
                     t.migrateToNewSurfaceControl();
                 }
                 t.mTaskAppearedSent = false;
-                return true;
             }
-            return false;
+            if (removeFromSystem) {
+                mService.removeTask(t.mTaskId);
+            }
+            return taskAppearedSent;
         }
 
         void dispose() {
@@ -311,7 +313,7 @@
                 if (mOrganizedTasks.contains(t)) {
                     // updateTaskOrganizerState should remove the task from the list, but still
                     // check it again to avoid while-loop isn't terminate.
-                    if (removeTask(t)) {
+                    if (removeTask(t, t.mRemoveWithTaskOrganizer)) {
                         TaskOrganizerController.this.onTaskVanishedInternal(
                                 mOrganizer.mTaskOrganizer, t);
                     }
@@ -527,7 +529,7 @@
 
     void onTaskVanished(ITaskOrganizer organizer, Task task) {
         final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
-        if (state != null && state.removeTask(task)) {
+        if (state != null && state.removeTask(task, false /* removeFromSystem */)) {
             onTaskVanishedInternal(organizer, task);
         }
     }
@@ -596,9 +598,7 @@
         try {
             synchronized (mGlobalLock) {
                 final WindowContainer wc = WindowContainer.fromBinder(token.asBinder());
-                if (wc == null) {
-                    throw new IllegalArgumentException("Can't resolve window from token");
-                }
+                if (wc == null) return false;
                 final Task task = wc.asTask();
                 if (task == null) return false;
                 if (!task.mCreatedByOrganizer) {
diff --git a/services/core/java/com/android/server/wm/WindowFrames.java b/services/core/java/com/android/server/wm/WindowFrames.java
index 361694b..9245f8c 100644
--- a/services/core/java/com/android/server/wm/WindowFrames.java
+++ b/services/core/java/com/android/server/wm/WindowFrames.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static com.android.server.wm.WindowFramesProto.COMPAT_FRAME;
 import static com.android.server.wm.WindowFramesProto.CONTAINING_FRAME;
 import static com.android.server.wm.WindowFramesProto.DISPLAY_FRAME;
 import static com.android.server.wm.WindowFramesProto.FRAME;
@@ -177,7 +178,7 @@
         mDisplayFrame.dumpDebug(proto, DISPLAY_FRAME);
         mContainingFrame.dumpDebug(proto, CONTAINING_FRAME);
         mFrame.dumpDebug(proto, FRAME);
-
+        mCompatFrame.dumpDebug(proto, COMPAT_FRAME);
         proto.end(token);
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 5dc5ab7..cec0321 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -39,7 +39,6 @@
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW;
-import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
 import static android.provider.Settings.Global.DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR;
@@ -83,6 +82,10 @@
 import static android.view.WindowManagerGlobal.RELAYOUT_RES_BLAST_SYNC;
 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID;
+import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW;
+import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN;
+import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_UNKNOWN;
+import static android.view.displayhash.DisplayHashResultCallback.EXTRA_DISPLAY_HASH_ERROR_CODE;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT;
@@ -187,6 +190,7 @@
 import android.os.PowerManager.ServiceType;
 import android.os.PowerManagerInternal;
 import android.os.PowerSaveState;
+import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
@@ -199,7 +203,6 @@
 import android.os.UserHandle;
 import android.os.WorkSource;
 import android.provider.Settings;
-import android.service.screenshot.ScreenshotHash;
 import android.service.vr.IVrManager;
 import android.service.vr.IVrStateCallbacks;
 import android.sysprop.SurfaceFlingerProperties;
@@ -220,13 +223,14 @@
 import android.view.DisplayInfo;
 import android.view.Gravity;
 import android.view.IAppTransitionAnimationSpecsFuture;
+import android.view.ICrossWindowBlurEnabledListener;
 import android.view.IDisplayFoldListener;
 import android.view.IDisplayWindowInsetsController;
 import android.view.IDisplayWindowListener;
 import android.view.IDisplayWindowRotationController;
 import android.view.IInputFilter;
 import android.view.IOnKeyguardExitResult;
-import android.view.IPinnedStackListener;
+import android.view.IPinnedTaskListener;
 import android.view.IRecentsAnimationRunner;
 import android.view.IRotationWatcher;
 import android.view.IScrollCaptureCallbacks;
@@ -249,6 +253,7 @@
 import android.view.MotionEvent;
 import android.view.PointerIcon;
 import android.view.RemoteAnimationAdapter;
+import android.view.ScrollCaptureResponse;
 import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
@@ -261,6 +266,8 @@
 import android.view.WindowManager.RemoveContentMode;
 import android.view.WindowManagerGlobal;
 import android.view.WindowManagerPolicyConstants.PointerEventListener;
+import android.view.displayhash.DisplayHash;
+import android.view.displayhash.VerifiedDisplayHash;
 import android.window.ClientWindowFrames;
 import android.window.TaskSnapshot;
 
@@ -750,6 +757,8 @@
 
     final TaskSnapshotController mTaskSnapshotController;
 
+    final BlurController mBlurController = new BlurController();
+
     boolean mIsTouchDevice;
     boolean mIsFakeTouchDevice;
 
@@ -768,7 +777,8 @@
     final EmbeddedWindowController mEmbeddedWindowController;
     final AnrController mAnrController;
 
-    private final ScreenshotHashController mScreenshotHashController;
+    private final DisplayHashController mDisplayHashController;
+
     @VisibleForTesting
     final WindowContextListenerController mWindowContextListenerController =
             new WindowContextListenerController();
@@ -795,8 +805,6 @@
                 Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT);
         private final Uri mForceResizableUri = Settings.Global.getUriFor(
                 DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES);
-        private final Uri mSizeCompatFreeformUri = Settings.Global.getUriFor(
-                DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM);
         private final Uri mSupportsNonResizableMultiWindowUri = Settings.Global.getUriFor(
                 DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW);
         private final Uri mRenderShadowsInCompositorUri = Settings.Global.getUriFor(
@@ -823,8 +831,6 @@
                     UserHandle.USER_ALL);
             resolver.registerContentObserver(mFreeformWindowUri, false, this, UserHandle.USER_ALL);
             resolver.registerContentObserver(mForceResizableUri, false, this, UserHandle.USER_ALL);
-            resolver.registerContentObserver(mSizeCompatFreeformUri, false, this,
-                    UserHandle.USER_ALL);
             resolver.registerContentObserver(mSupportsNonResizableMultiWindowUri, false, this,
                     UserHandle.USER_ALL);
             resolver.registerContentObserver(mRenderShadowsInCompositorUri, false, this,
@@ -864,11 +870,6 @@
                 return;
             }
 
-            if (mSizeCompatFreeformUri.equals(uri)) {
-                updateSizeCompatFreeform();
-                return;
-            }
-
             if (mSupportsNonResizableMultiWindowUri.equals(uri)) {
                 updateSupportsNonResizableMultiWindow();
                 return;
@@ -966,14 +967,6 @@
             mAtmService.mForceResizableActivities = forceResizable;
         }
 
-        void updateSizeCompatFreeform() {
-            ContentResolver resolver = mContext.getContentResolver();
-            final boolean sizeCompatFreeform = Settings.Global.getInt(resolver,
-                    DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM, 0) != 0;
-
-            mAtmService.mSizeCompatFreeform = sizeCompatFreeform;
-        }
-
         void updateSupportsNonResizableMultiWindow() {
             ContentResolver resolver = mContext.getContentResolver();
             final boolean supportsNonResizableMultiWindow = Settings.Global.getInt(resolver,
@@ -1419,7 +1412,7 @@
         mDisplayAreaPolicyProvider = DisplayAreaPolicy.Provider.fromResources(
                 mContext.getResources());
 
-        mScreenshotHashController = new ScreenshotHashController(mContext);
+        mDisplayHashController = new DisplayHashController(mContext);
         setGlobalShadowSettings();
         mAnrController = new AnrController(this);
         mStartingSurfaceController = new StartingSurfaceController(this);
@@ -1874,6 +1867,10 @@
                 displayContent.sendNewConfiguration();
             }
 
+            // This window doesn't have a frame yet. Don't let this window cause the insets change.
+            displayContent.getInsetsStateController().updateAboveInsetsState(
+                    win, false /* notifyInsetsChanged */);
+
             getInsetsSourceControls(win, outActiveControls);
         }
 
@@ -2382,15 +2379,9 @@
                 }
             }
 
-            // We may be deferring layout passes at the moment, but since the client is interested
-            // in the new out values right now we need to force a layout.
-            mWindowPlacerLocked.performSurfacePlacement(true /* force */);
-
+            // Create surfaceControl before surface placement otherwise layout will be skipped
+            // (because WS.isGoneForLayout() is true when there is no surface.
             if (shouldRelayout) {
-                Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_1");
-
-                result = win.relayoutVisibleWindow(result);
-
                 try {
                     result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
                 } catch (Exception e) {
@@ -2402,6 +2393,17 @@
                     Binder.restoreCallingIdentity(origId);
                     return 0;
                 }
+            }
+
+            // We may be deferring layout passes at the moment, but since the client is interested
+            // in the new out values right now we need to force a layout.
+            mWindowPlacerLocked.performSurfacePlacement(true /* force */);
+
+            if (shouldRelayout) {
+                Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_1");
+
+                result = win.relayoutVisibleWindow(result);
+
                 if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
                     focusMayChange = true;
                 }
@@ -2970,7 +2972,7 @@
     }
 
     boolean isValidPictureInPictureAspectRatio(DisplayContent displayContent, float aspectRatio) {
-        return displayContent.getPinnedStackController().isValidPictureInPictureAspectRatio(
+        return displayContent.getPinnedTaskController().isValidPictureInPictureAspectRatio(
                 aspectRatio);
     }
 
@@ -5673,6 +5675,18 @@
         return mWindowTracing.isEnabled();
     }
 
+    @Override
+    public boolean registerCrossWindowBlurEnabledListener(
+                ICrossWindowBlurEnabledListener listener) {
+        return mBlurController.registerCrossWindowBlurEnabledListener(listener);
+    }
+
+    @Override
+    public void unregisterCrossWindowBlurEnabledListener(
+                ICrossWindowBlurEnabledListener listener) {
+        mBlurController.unregisterCrossWindowBlurEnabledListener(listener);
+    }
+
     // -------------------------------------------------------------
     // Internals
     // -------------------------------------------------------------
@@ -6412,6 +6426,7 @@
             }
         });
         pw.print("  mInTouchMode="); pw.println(mInTouchMode);
+        pw.print("  mBlurEnabled="); pw.println(mBlurController.mBlurEnabled);
         pw.print("  mLastDisplayFreezeDuration=");
                 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
                 if ( mLastFinishedFreezeSource != null) {
@@ -6869,7 +6884,7 @@
     }
 
     @Override
-    public void setDockedStackDividerTouchRegion(Rect touchRegion) {
+    public void setDockedTaskDividerTouchRegion(Rect touchRegion) {
         synchronized (mGlobalLock) {
             final DisplayContent dc = getDefaultDisplayContentLocked();
             dc.getDockedDividerController().setTouchRegion(touchRegion);
@@ -6894,10 +6909,9 @@
         return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, displayMetrics);
     }
 
-    @Override
-    public void registerPinnedStackListener(int displayId, IPinnedStackListener listener) {
+    public void registerPinnedTaskListener(int displayId, IPinnedTaskListener listener) {
         if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS,
-                "registerPinnedStackListener()")) {
+                "registerPinnedTaskListener()")) {
             return;
         }
         if (!mAtmService.mSupportsPictureInPicture) {
@@ -6905,7 +6919,7 @@
         }
         synchronized (mGlobalLock) {
             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
-            displayContent.getPinnedStackController().registerPinnedStackListener(listener);
+            displayContent.getPinnedTaskController().registerPinnedTaskListener(listener);
         }
     }
 
@@ -7144,12 +7158,14 @@
         }
         final long token = Binder.clearCallingIdentity();
         try {
+            ScrollCaptureResponse.Builder responseBuilder = new ScrollCaptureResponse.Builder();
             synchronized (mGlobalLock) {
                 DisplayContent dc = mRoot.getDisplayContent(displayId);
                 if (dc == null) {
                     ProtoLog.e(WM_ERROR,
                             "Invalid displayId for requestScrollCapture: %d", displayId);
-                    callbacks.onUnavailable();
+                    responseBuilder.setDescription(String.format("bad displayId: %d", displayId));
+                    callbacks.onScrollCaptureResponse(responseBuilder.build());
                     return;
                 }
                 WindowState topWindow = null;
@@ -7158,17 +7174,20 @@
                 }
                 WindowState targetWindow = dc.findScrollCaptureTargetWindow(topWindow, taskId);
                 if (targetWindow == null) {
-                    callbacks.onUnavailable();
+                    responseBuilder.setDescription("findScrollCaptureTargetWindow returned null");
+                    callbacks.onScrollCaptureResponse(responseBuilder.build());
                     return;
                 }
-                // Forward to the window for handling.
                 try {
+                    // Forward to the window for handling, which will respond using the callback.
                     targetWindow.mClient.requestScrollCapture(callbacks);
                 } catch (RemoteException e) {
                     ProtoLog.w(WM_ERROR,
                             "requestScrollCapture: caught exception dispatching to window."
                                     + "token=%s", targetWindow.mClient.asBinder());
-                    callbacks.onUnavailable();
+                    responseBuilder.setWindowTitle(targetWindow.getName());
+                    responseBuilder.setDescription(String.format("caught exception: %s", e));
+                    callbacks.onScrollCaptureResponse(responseBuilder.build());
                 }
             }
         } catch (RemoteException e) {
@@ -8599,39 +8618,42 @@
     }
 
     @Override
-    public String[] getSupportedScreenshotHashingAlgorithms() {
-        return mScreenshotHashController.getSupportedHashingAlgorithms();
+    public String[] getSupportedDisplayHashAlgorithms() {
+        return mDisplayHashController.getSupportedHashAlgorithms();
     }
 
     @Override
-    public boolean verifyScreenshotHash(ScreenshotHash screenshotHash) {
-        return mScreenshotHashController.verifyScreenshotHash(screenshotHash);
+    public VerifiedDisplayHash verifyDisplayHash(DisplayHash displayHash) {
+        return mDisplayHashController.verifyDisplayHash(displayHash);
     }
 
-    ScreenshotHash generateScreenshotHash(Session session, IWindow window,
-            Rect boundsInWindow, String hashAlgorithm) {
+    void generateDisplayHash(Session session, IWindow window, Rect boundsInWindow,
+            String hashAlgorithm, RemoteCallback callback) {
         final SurfaceControl displaySurfaceControl;
         final Rect boundsInDisplay = new Rect(boundsInWindow);
         synchronized (mGlobalLock) {
             final WindowState win = windowForClientLocked(session, window, false);
             if (win == null) {
-                Slog.w(TAG, "Failed to generate ScreenshotHash. Invalid window");
-                return null;
+                Slog.w(TAG, "Failed to generate DisplayHash. Invalid window");
+                sendDisplayHashError(callback, DISPLAY_HASH_ERROR_MISSING_WINDOW);
+                return;
             }
 
             DisplayContent displayContent = win.getDisplayContent();
             if (displayContent == null) {
-                Slog.w(TAG, "Failed to generate ScreenshotHash. Window is not on a display");
-                return null;
+                Slog.w(TAG, "Failed to generate DisplayHash. Window is not on a display");
+                sendDisplayHashError(callback, DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN);
+                return;
             }
 
             displaySurfaceControl = displayContent.getSurfaceControl();
-            mScreenshotHashController.calculateScreenshotHashBoundsLocked(win,
-                    boundsInWindow, boundsInDisplay);
+            mDisplayHashController.calculateDisplayHashBoundsLocked(win, boundsInWindow,
+                    boundsInDisplay);
 
             if (boundsInDisplay.isEmpty()) {
-                Slog.w(TAG, "Failed to generate ScreenshotHash. Bounds are not on screen");
-                return null;
+                Slog.w(TAG, "Failed to generate DisplayHash. Bounds are not on screen");
+                sendDisplayHashError(callback, DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN);
+                return;
             }
         }
 
@@ -8650,11 +8672,18 @@
                 SurfaceControl.captureLayers(args);
         if (screenshotHardwareBuffer == null
                 || screenshotHardwareBuffer.getHardwareBuffer() == null) {
-            Slog.w(TAG, "Failed to generate ScreenshotHash. Failed to take screenshot");
-            return null;
+            Slog.w(TAG, "Failed to generate DisplayHash. Couldn't capture content");
+            sendDisplayHashError(callback, DISPLAY_HASH_ERROR_UNKNOWN);
+            return;
         }
 
-        return mScreenshotHashController.generateScreenshotHash(
-                screenshotHardwareBuffer.getHardwareBuffer(), boundsInWindow, hashAlgorithm);
+        mDisplayHashController.generateDisplayHash(screenshotHardwareBuffer.getHardwareBuffer(),
+                boundsInWindow, hashAlgorithm, callback);
+    }
+
+    private void sendDisplayHashError(RemoteCallback callback, int errorCode) {
+        Bundle bundle = new Bundle();
+        bundle.putInt(EXTRA_DISPLAY_HASH_ERROR_CODE, errorCode);
+        callback.sendResult(bundle);
     }
 }
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 63a0832..9973664 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -17,7 +17,6 @@
 package com.android.server.wm;
 
 import static android.Manifest.permission.READ_FRAME_BUFFER;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT;
 import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;
 import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REPARENT;
@@ -426,8 +425,9 @@
         }
 
         if (windowingMode > -1) {
-            if (mService.isInLockTaskMode() && windowingMode != WINDOWING_MODE_FULLSCREEN) {
-                throw new UnsupportedOperationException("Not supported to set non-fullscreen"
+            if (mService.isInLockTaskMode()
+                    && WindowConfiguration.inMultiWindowMode(windowingMode)) {
+                throw new UnsupportedOperationException("Not supported to set multi-window"
                         + " windowing mode during locked task mode.");
             }
             container.setWindowingMode(windowingMode);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index a94b0aa..2a9e08e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -169,7 +169,9 @@
 import static com.android.server.wm.WindowStateProto.FINISHED_SEAMLESS_ROTATION_FRAME;
 import static com.android.server.wm.WindowStateProto.FORCE_SEAMLESS_ROTATION;
 import static com.android.server.wm.WindowStateProto.GIVEN_CONTENT_INSETS;
+import static com.android.server.wm.WindowStateProto.GLOBAL_SCALE;
 import static com.android.server.wm.WindowStateProto.HAS_SURFACE;
+import static com.android.server.wm.WindowStateProto.IN_SIZE_COMPAT_MODE;
 import static com.android.server.wm.WindowStateProto.IS_ON_SCREEN;
 import static com.android.server.wm.WindowStateProto.IS_READY_FOR_DISPLAY;
 import static com.android.server.wm.WindowStateProto.IS_VISIBLE;
@@ -211,11 +213,11 @@
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.text.TextUtils;
-import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.MergedConfiguration;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 import android.view.Display;
@@ -533,6 +535,9 @@
      */
     private boolean mOrientationChanging;
 
+    /** The time when the window was last requested to redraw for orientation change. */
+    private long mOrientationChangeRedrawRequestTime;
+
     /**
      * Sometimes in addition to the mOrientationChanging
      * flag we report that the orientation is changing
@@ -648,12 +653,12 @@
     /**
      * The insets state of sources provided by windows above the current window.
      */
-    InsetsState mAboveInsetsState = new InsetsState();
+    final InsetsState mAboveInsetsState = new InsetsState();
 
     /**
      * The insets sources provided by this window.
      */
-    ArrayMap<Integer, InsetsSource> mProvidedInsetsSources = new ArrayMap<>();
+    final SparseArray<InsetsSource> mProvidedInsetsSources = new SparseArray<>();
 
     /**
      * Surface insets from the previous call to relayout(), used to track
@@ -1219,7 +1224,7 @@
                     // But in docked we want to behave like fullscreen and behave as if the task
                     // were given smaller bounds for the purposes of layout. Skip adjustments for
                     // the root pinned task, they are handled separately in the
-                    // PinnedStackController.
+                    // PinnedTaskController.
                     windowFrames.mContainingFrame.bottom = windowFrames.mParentFrame.bottom;
                 }
             }
@@ -1441,11 +1446,6 @@
             // redrawn; to do that, we need to go through the process of getting informed by the
             // application when it has finished drawing.
             if (getOrientationChanging() || dragResizingChanged) {
-                if (getOrientationChanging()) {
-                    Slog.v(TAG_WM, "Orientation start waiting for draw"
-                            + ", mDrawState=DRAW_PENDING in " + this
-                            + ", surfaceController " + winAnimator.mSurfaceController);
-                }
                 if (dragResizingChanged) {
                     ProtoLog.v(WM_DEBUG_RESIZE,
                             "Resize start waiting for draw, "
@@ -2204,7 +2204,7 @@
         }
     }
 
-  @Override
+    @Override
     void removeImmediately() {
         super.removeImmediately();
 
@@ -3651,7 +3651,8 @@
 
         ProtoLog.v(WM_DEBUG_RESIZE, "Reporting new frame to %s: %s", this,
                 mWindowFrames.mCompatFrame);
-        if (mWinAnimator.mDrawState == DRAW_PENDING) {
+        final boolean drawPending = mWinAnimator.mDrawState == DRAW_PENDING;
+        if (drawPending) {
             ProtoLog.i(WM_DEBUG_ORIENTATION, "Resizing %s WITH DRAW PENDING", this);
         }
 
@@ -3668,7 +3669,7 @@
         mWindowFrames.clearReportResizeHints();
 
         final MergedConfiguration mergedConfiguration = mLastReportedConfiguration;
-        final boolean reportDraw = mWinAnimator.mDrawState == DRAW_PENDING || useBLASTSync() || !mRedrawForSyncReported;
+        final boolean reportDraw = drawPending || useBLASTSync() || !mRedrawForSyncReported;
         final boolean forceRelayout = reportOrientation || isDragResizeChanged() || !mRedrawForSyncReported;
         final int displayId = getDisplayId();
         fillClientWindowFrames(mClientWindowFrames);
@@ -3679,6 +3680,11 @@
             mClient.resized(mClientWindowFrames, reportDraw, mergedConfiguration, forceRelayout,
                     getDisplayContent().getDisplayPolicy().areSystemBarsForcedShownLw(this),
                     displayId);
+            if (drawPending && reportOrientation && mOrientationChanging) {
+                mOrientationChangeRedrawRequestTime = SystemClock.elapsedRealtime();
+                ProtoLog.v(WM_DEBUG_ORIENTATION,
+                        "Requested redraw for orientation change: %s", this);
+            }
 
             if (mWmService.mAccessibilityController != null) {
                 mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(displayId);
@@ -3821,13 +3827,21 @@
     /** @return true when the window should be letterboxed. */
     boolean isLetterboxedAppWindow() {
         // Fullscreen mode but doesn't fill display area.
-        return (!inMultiWindowMode() && !matchesDisplayAreaBounds())
-                // Activity in size compat.
-                || (mActivityRecord != null && mActivityRecord.inSizeCompatMode())
-                // Task letterboxed.
-                || (getTask() != null && getTask().isTaskLetterboxed())
-                // Letterboxed for display cutout.
-                || isLetterboxedForDisplayCutout();
+        if (!inMultiWindowMode() && !matchesDisplayAreaBounds()) {
+            return true;
+        }
+        if (mActivityRecord != null) {
+            // Activity in size compat.
+            if (mActivityRecord.inSizeCompatMode()) {
+                return true;
+            }
+            // Letterbox for fixed orientation.
+            if (mActivityRecord.isLetterboxedForFixedOrientationAndAspectRatio()) {
+                return true;
+            }
+        }
+        // Letterboxed for display cutout.
+        return isLetterboxedForDisplayCutout();
     }
 
     /** Returns {@code true} if the window is letterboxed for the display cutout. */
@@ -3998,6 +4012,8 @@
         proto.write(PENDING_SEAMLESS_ROTATION, mPendingSeamlessRotate != null);
         proto.write(FINISHED_SEAMLESS_ROTATION_FRAME, mFinishSeamlessRotateFrameNumber);
         proto.write(FORCE_SEAMLESS_ROTATION, mForceSeamlesslyRotate);
+        proto.write(IN_SIZE_COMPAT_MODE, inSizeCompatMode());
+        proto.write(GLOBAL_SCALE, mGlobalScale);
         proto.end(token);
     }
 
@@ -5257,22 +5273,24 @@
         if (!mAnimatingExit && mAppDied) {
             mIsDimming = true;
             getDimmer().dimAbove(getSyncTransaction(), this, DEFAULT_DIM_AMOUNT_DEAD_WINDOW);
-        } else if (((mAttrs.flags & FLAG_DIM_BEHIND) != 0 || (mAttrs.flags & FLAG_BLUR_BEHIND) != 0)
+        } else if (((mAttrs.flags & FLAG_DIM_BEHIND) != 0 || shouldDrawBlurBehind())
                    && isVisibleNow() && !mHidden) {
             // Only show the Dimmer when the following is satisfied:
-            // 1. The window has the flag FLAG_DIM_BEHIND or background blur is requested
+            // 1. The window has the flag FLAG_DIM_BEHIND or blur behind is requested
             // 2. The WindowToken is not hidden so dims aren't shown when the window is exiting.
             // 3. The WS is considered visible according to the isVisible() method
             // 4. The WS is not hidden.
             mIsDimming = true;
             final float dimAmount = (mAttrs.flags & FLAG_DIM_BEHIND) != 0 ? mAttrs.dimAmount : 0;
-            final int blurRadius =
-                    (mAttrs.flags & FLAG_BLUR_BEHIND) != 0 ? mAttrs.blurBehindRadius : 0;
-            getDimmer().dimBelow(
-                    getSyncTransaction(), this, mAttrs.dimAmount, mAttrs.blurBehindRadius);
+            final int blurRadius = shouldDrawBlurBehind() ? mAttrs.getBlurBehindRadius() : 0;
+            getDimmer().dimBelow(getSyncTransaction(), this, mAttrs.dimAmount, blurRadius);
         }
     }
 
+    private boolean shouldDrawBlurBehind() {
+        return (mAttrs.flags & FLAG_BLUR_BEHIND) != 0 && mWmService.mBlurController.mBlurEnabled;
+    }
+
     /**
      * Notifies SF about the priority of the window, if it changed. SF then uses this information
      * to decide which window's desired rendering rate should have a priority when deciding about
@@ -5732,6 +5750,18 @@
     }
 
     boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction) {
+        if (mOrientationChangeRedrawRequestTime > 0) {
+            final long duration =
+                    SystemClock.elapsedRealtime() - mOrientationChangeRedrawRequestTime;
+            Slog.i(TAG, "finishDrawing of orientation change: " + this + " " + duration + "ms");
+            mOrientationChangeRedrawRequestTime = 0;
+        } else if (mActivityRecord != null && mActivityRecord.mRelaunchStartTime != 0
+                && mActivityRecord.findMainWindow() == this) {
+            final long duration =
+                    SystemClock.elapsedRealtime() - mActivityRecord.mRelaunchStartTime;
+            Slog.i(TAG, "finishDrawing of relaunch: " + this + " " + duration + "ms");
+            mActivityRecord.mRelaunchStartTime = 0;
+        }
         if (!onSyncFinishedDrawing()) {
             return mWinAnimator.finishDrawingLocked(postDrawTransaction);
         }
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 1c3fe02..e87ee91 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -549,7 +549,7 @@
     }
 
     /** Notifies application side to enable or disable the rotation adjustment of display info. */
-    private void notifyFixedRotationTransform(boolean enabled) {
+    void notifyFixedRotationTransform(boolean enabled) {
         FixedRotationAdjustments adjustments = null;
         // A token may contain windows of the same processes or different processes. The list is
         // used to avoid sending the same adjustments to a process multiple times.
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 11e3ecf..29bce79 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_library_static {
     name: "libservices.core",
     defaults: ["libservices.core-libs"],
@@ -88,6 +97,7 @@
         "libbase",
         "libappfuse",
         "libbinder",
+        "libbinder_ndk",
         "libcutils",
         "libcrypto",
         "liblog",
@@ -163,6 +173,7 @@
         "android.frameworks.schedulerservice@1.0",
         "android.frameworks.sensorservice@1.0",
         "android.frameworks.stats@1.0",
+        "android.frameworks.stats-V1-ndk_platform",
         "android.system.suspend.control-V1-cpp",
         "android.system.suspend.control.internal-cpp",
         "android.system.suspend@1.0",
diff --git a/services/core/jni/com_android_server_SystemServer.cpp b/services/core/jni/com_android_server_SystemServer.cpp
index 729fa71..a73f6c6 100644
--- a/services/core/jni/com_android_server_SystemServer.cpp
+++ b/services/core/jni/com_android_server_SystemServer.cpp
@@ -23,6 +23,7 @@
 #include <jni.h>
 #include <nativehelper/JNIHelp.h>
 
+#include <android/binder_manager.h>
 #include <android/hidl/manager/1.2/IServiceManager.h>
 #include <binder/IServiceManager.h>
 #include <hidl/HidlTransportSupport.h>
@@ -31,6 +32,7 @@
 #include <schedulerservice/SchedulingPolicyService.h>
 #include <sensorservice/SensorService.h>
 #include <sensorservicehidl/SensorManager.h>
+#include <stats/StatsAidl.h>
 #include <stats/StatsHal.h>
 
 #include <bionic/malloc.h>
@@ -45,6 +47,31 @@
 using android::base::GetIntProperty;
 using namespace std::chrono_literals;
 
+namespace {
+
+static void startStatsAidlService() {
+    using aidl::android::frameworks::stats::IStats;
+    using aidl::android::frameworks::stats::StatsHal;
+
+    std::shared_ptr<StatsHal> statsService = ndk::SharedRefBase::make<StatsHal>();
+
+    const std::string instance = std::string() + IStats::descriptor + "/default";
+    const binder_exception_t err =
+            AServiceManager_addService(statsService->asBinder().get(), instance.c_str());
+    LOG_ALWAYS_FATAL_IF(err != EX_NONE, "Cannot register %s: %d", instance.c_str(), err);
+}
+
+static void startStatsHidlService() {
+    using android::frameworks::stats::V1_0::IStats;
+    using android::frameworks::stats::V1_0::implementation::StatsHal;
+
+    android::sp<IStats> statsHal = new StatsHal();
+    const android::status_t err = statsHal->registerAsService();
+    LOG_ALWAYS_FATAL_IF(err != android::OK, "Cannot register %s: %d", IStats::descriptor, err);
+}
+
+} // namespace
+
 namespace android {
 
 static void android_server_SystemServer_startSensorService(JNIEnv* /* env */, jobject /* clazz */) {
@@ -54,7 +81,6 @@
         SensorService::publish(false /* allowIsolated */,
                                IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
     }
-
 }
 
 static void android_server_SystemServer_startHidlServices(JNIEnv* env, jobject /* clazz */) {
@@ -62,8 +88,6 @@
     using ::android::frameworks::schedulerservice::V1_0::implementation::SchedulingPolicyService;
     using ::android::frameworks::sensorservice::V1_0::ISensorManager;
     using ::android::frameworks::sensorservice::V1_0::implementation::SensorManager;
-    using ::android::frameworks::stats::V1_0::IStats;
-    using ::android::frameworks::stats::V1_0::implementation::StatsHal;
     using ::android::hardware::configureRpcThreadpool;
     using ::android::hidl::manager::V1_0::IServiceManager;
 
@@ -89,9 +113,8 @@
         ALOGW("%s is deprecated. Skipping registration.", ISchedulingPolicyService::descriptor);
     }
 
-    sp<IStats> statsHal = new StatsHal();
-    err = statsHal->registerAsService();
-    LOG_ALWAYS_FATAL_IF(err != OK, "Cannot register %s: %d", IStats::descriptor, err);
+    startStatsAidlService();
+    startStatsHidlService();
 }
 
 static void android_server_SystemServer_initZygoteChildHeapProfiling(JNIEnv* /* env */,
diff --git a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
index 4551d49..8c6d084 100644
--- a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
+++ b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
@@ -86,7 +86,7 @@
 
     int pidfd = syscall(__NR_pidfd_open, pid, 0);
     err = -errno;
-    if (err < 0) {
+    if (pidfd < 0) {
         // Skip compaction if failed to open pidfd with any error
         return err;
     }
@@ -232,21 +232,6 @@
     compactProcessOrFallback(pid, compactionFlags);
 }
 
-static void com_android_server_am_CachedAppOptimizer_enableFreezerInternal(
-        JNIEnv *env, jobject clazz, jboolean enable) {
-    bool success = true;
-
-    if (enable) {
-        success = SetTaskProfiles(0, {"FreezerEnabled"}, true);
-    } else {
-        success = SetTaskProfiles(0, {"FreezerDisabled"}, true);
-    }
-
-    if (!success) {
-        jniThrowException(env, "java/lang/RuntimeException", "Unknown error");
-    }
-}
-
 static void com_android_server_am_CachedAppOptimizer_freezeBinder(
         JNIEnv *env, jobject clazz, jint pid, jboolean freeze) {
 
@@ -280,15 +265,19 @@
 
 static jstring com_android_server_am_CachedAppOptimizer_getFreezerCheckPath(JNIEnv* env,
                                                                             jobject clazz) {
-    return env->NewStringUTF(CGROUP_FREEZE_PATH);
+    std::string path;
+
+    if (!getAttributePathForTask("FreezerState", getpid(), &path)) {
+        path = "";
+    }
+
+    return env->NewStringUTF(path.c_str());
 }
 
 static const JNINativeMethod sMethods[] = {
         /* name, signature, funcPtr */
         {"compactSystem", "()V", (void*)com_android_server_am_CachedAppOptimizer_compactSystem},
         {"compactProcess", "(II)V", (void*)com_android_server_am_CachedAppOptimizer_compactProcess},
-        {"enableFreezerInternal", "(Z)V",
-         (void*)com_android_server_am_CachedAppOptimizer_enableFreezerInternal},
         {"freezeBinder", "(IZ)V", (void*)com_android_server_am_CachedAppOptimizer_freezeBinder},
         {"getBinderFreezeInfo", "(I)I",
          (void*)com_android_server_am_CachedAppOptimizer_getBinderFreezeInfo},
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 643503d..10705af 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -158,6 +158,20 @@
 static struct {
     jclass clazz;
     jmethodID constructor;
+    jfieldID lightTypeSingle;
+    jfieldID lightTypePlayerId;
+    jfieldID lightTypeRgb;
+} gLightClassInfo;
+
+static struct {
+    jclass clazz;
+    jmethodID constructor;
+    jmethodID add;
+} gArrayListClassInfo;
+
+static struct {
+    jclass clazz;
+    jmethodID constructor;
     jmethodID keyAt;
     jmethodID valueAt;
     jmethodID size;
@@ -317,7 +331,7 @@
                                           uint32_t policyFlags) override;
     bool dispatchUnhandledKey(const sp<IBinder>& token, const KeyEvent* keyEvent,
                               uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) override;
-    void pokeUserActivity(nsecs_t eventTime, int32_t eventType) override;
+    void pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) override;
     bool checkInjectEventsPermissionNonReentrant(int32_t injectorPid, int32_t injectorUid) override;
     void onPointerDownOutsideFocus(const sp<IBinder>& touchedToken) override;
     void setPointerCapture(bool enabled) override;
@@ -1311,9 +1325,9 @@
     return result;
 }
 
-void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
+void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) {
     ATRACE_CALL();
-    android_server_PowerManagerService_userActivity(eventTime, eventType);
+    android_server_PowerManagerService_userActivity(eventTime, eventType, displayId);
 }
 
 bool NativeInputManager::checkInjectEventsPermissionNonReentrant(
@@ -1923,6 +1937,79 @@
     return vibIdArray;
 }
 
+static jobject nativeGetLights(JNIEnv* env, jclass clazz, jlong ptr, jint deviceId) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+    jobject jLights = env->NewObject(gArrayListClassInfo.clazz, gArrayListClassInfo.constructor);
+
+    std::vector<int> lightIds = im->getInputManager()->getReader()->getLightIds(deviceId);
+
+    for (size_t i = 0; i < lightIds.size(); i++) {
+        const InputDeviceLightInfo* lightInfo =
+                im->getInputManager()->getReader()->getLightInfo(deviceId, lightIds[i]);
+        if (lightInfo == nullptr) {
+            ALOGW("Failed to get input device %d light info for id %d", deviceId, lightIds[i]);
+            continue;
+        }
+
+        jint jTypeId = 0;
+        if (lightInfo->type == InputDeviceLightType::SINGLE) {
+            jTypeId =
+                    env->GetStaticIntField(gLightClassInfo.clazz, gLightClassInfo.lightTypeSingle);
+        } else if (lightInfo->type == InputDeviceLightType::PLAYER_ID) {
+            jTypeId = env->GetStaticIntField(gLightClassInfo.clazz,
+                                             gLightClassInfo.lightTypePlayerId);
+        } else if (lightInfo->type == InputDeviceLightType::RGB ||
+                   lightInfo->type == InputDeviceLightType::MULTI_COLOR) {
+            jTypeId = env->GetStaticIntField(gLightClassInfo.clazz, gLightClassInfo.lightTypeRgb);
+        } else {
+            ALOGW("Unknown light type %d", lightInfo->type);
+            continue;
+        }
+        ScopedLocalRef<jobject>
+                lightObj(env,
+                         env->NewObject(gLightClassInfo.clazz, gLightClassInfo.constructor,
+                                        (jint)lightInfo->id, (jint)lightInfo->ordinal, jTypeId,
+                                        env->NewStringUTF(lightInfo->name.c_str())));
+        // Add light object to list
+        env->CallBooleanMethod(jLights, gArrayListClassInfo.add, lightObj.get());
+    }
+
+    return jLights;
+}
+
+static jint nativeGetLightPlayerId(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId,
+                                   jint lightId) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+    std::optional<int32_t> ret =
+            im->getInputManager()->getReader()->getLightPlayerId(deviceId, lightId);
+
+    return static_cast<jint>(ret.value_or(0));
+}
+
+static jint nativeGetLightColor(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId,
+                                jint lightId) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+    std::optional<int32_t> ret =
+            im->getInputManager()->getReader()->getLightColor(deviceId, lightId);
+    return static_cast<jint>(ret.value_or(0));
+}
+
+static void nativeSetLightPlayerId(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId,
+                                   jint lightId, jint playerId) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+    im->getInputManager()->getReader()->setLightPlayerId(deviceId, lightId, playerId);
+}
+
+static void nativeSetLightColor(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId,
+                                jint lightId, jint color) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+    im->getInputManager()->getReader()->setLightColor(deviceId, lightId, color);
+}
+
 static jint nativeGetBatteryCapacity(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId) {
     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
@@ -2192,6 +2279,11 @@
         {"nativeCancelVibrate", "(JII)V", (void*)nativeCancelVibrate},
         {"nativeIsVibrating", "(JI)Z", (void*)nativeIsVibrating},
         {"nativeGetVibratorIds", "(JI)[I", (void*)nativeGetVibratorIds},
+        {"nativeGetLights", "(JI)Ljava/util/List;", (void*)nativeGetLights},
+        {"nativeGetLightPlayerId", "(JII)I", (void*)nativeGetLightPlayerId},
+        {"nativeGetLightColor", "(JII)I", (void*)nativeGetLightColor},
+        {"nativeSetLightPlayerId", "(JIII)V", (void*)nativeSetLightPlayerId},
+        {"nativeSetLightColor", "(JIII)V", (void*)nativeSetLightColor},
         {"nativeGetBatteryCapacity", "(JI)I", (void*)nativeGetBatteryCapacity},
         {"nativeGetBatteryStatus", "(JI)I", (void*)nativeGetBatteryStatus},
         {"nativeReloadKeyboardLayouts", "(J)V", (void*)nativeReloadKeyboardLayouts},
@@ -2386,6 +2478,27 @@
     GET_METHOD_ID(gTouchCalibrationClassInfo.getAffineTransform, gTouchCalibrationClassInfo.clazz,
             "getAffineTransform", "()[F");
 
+    // Light
+    FIND_CLASS(gLightClassInfo.clazz, "android/hardware/lights/Light");
+    gLightClassInfo.clazz = jclass(env->NewGlobalRef(gLightClassInfo.clazz));
+    GET_METHOD_ID(gLightClassInfo.constructor, gLightClassInfo.clazz, "<init>",
+                  "(IIILjava/lang/String;)V");
+
+    gLightClassInfo.clazz = jclass(env->NewGlobalRef(gLightClassInfo.clazz));
+    gLightClassInfo.lightTypeSingle =
+            env->GetStaticFieldID(gLightClassInfo.clazz, "LIGHT_TYPE_INPUT_SINGLE", "I");
+    gLightClassInfo.lightTypePlayerId =
+            env->GetStaticFieldID(gLightClassInfo.clazz, "LIGHT_TYPE_INPUT_PLAYER_ID", "I");
+    gLightClassInfo.lightTypeRgb =
+            env->GetStaticFieldID(gLightClassInfo.clazz, "LIGHT_TYPE_INPUT_RGB", "I");
+
+    // ArrayList
+    FIND_CLASS(gArrayListClassInfo.clazz, "java/util/ArrayList");
+    gArrayListClassInfo.clazz = jclass(env->NewGlobalRef(gArrayListClassInfo.clazz));
+    GET_METHOD_ID(gArrayListClassInfo.constructor, gArrayListClassInfo.clazz, "<init>", "()V");
+    GET_METHOD_ID(gArrayListClassInfo.add, gArrayListClassInfo.clazz, "add",
+                  "(Ljava/lang/Object;)Z");
+
     // SparseArray
     FIND_CLASS(gSparseArrayClassInfo.clazz, "android/util/SparseArray");
     gSparseArrayClassInfo.clazz = jclass(env->NewGlobalRef(gSparseArrayClassInfo.clazz));
diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
index 5a5b0a8..7b78b8d 100644
--- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
+++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
@@ -44,7 +44,6 @@
 namespace {
 
 using android::base::borrowed_fd;
-using android::base::ReadFully;
 using android::base::unique_fd;
 
 using namespace std::literals;
@@ -173,7 +172,7 @@
 static inline std::vector<char> readBytes(borrowed_fd fd) {
     int32_t size = readLEInt32(fd);
     std::vector<char> result(size);
-    ReadFully(fd, result.data(), size);
+    android::base::ReadFully(fd, result.data(), size);
     return result;
 }
 
@@ -569,7 +568,7 @@
         // Awaiting adb handshake.
         char okay_buf[OKAY.size()];
         if (!android::base::ReadFully(inout, okay_buf, OKAY.size())) {
-            ALOGE("Failed to receive OKAY. Abort.");
+            ALOGE("Failed to receive OKAY. Abort. Error %d", errno);
             return false;
         }
         if (std::string_view(okay_buf, OKAY.size()) != OKAY) {
@@ -693,12 +692,12 @@
                 continue;
             }
             if (res < 0) {
-                ALOGE("Failed to poll. Abort.");
+                ALOGE("Failed to poll. Abort. Error %d", res);
                 mStatusListener->reportStatus(DATA_LOADER_UNRECOVERABLE);
                 break;
             }
             if (res == mEventFd) {
-                ALOGE("Received stop signal. Sending EXIT to server.");
+                ALOGE("DataLoader requested to stop. Sending EXIT to server.");
                 sendRequest(inout, EXIT);
                 break;
             }
@@ -712,7 +711,7 @@
                 auto header = readHeader(remainingData);
                 if (header.fileIdx == -1 && header.blockType == 0 && header.compressionType == 0 &&
                     header.blockIdx == 0 && header.blockSize == 0) {
-                    ALOGI("Stop signal received. Sending exit command (remaining bytes: %d).",
+                    ALOGI("Stop command received. Sending exit command (remaining bytes: %d).",
                           int(remainingData.size()));
 
                     sendRequest(inout, EXIT);
@@ -721,16 +720,15 @@
                 }
                 if (header.fileIdx < 0 || header.blockSize <= 0 || header.blockType < 0 ||
                     header.compressionType < 0 || header.blockIdx < 0) {
-                    ALOGE("invalid header received. Abort.");
+                    ALOGE("Invalid header received. Abort.");
                     mStopReceiving = true;
                     break;
                 }
+
                 const FileIdx fileIdx = header.fileIdx;
                 const android::dataloader::FileId fileId = convertFileIndexToFileId(mode, fileIdx);
                 if (!android::incfs::isValidFileId(fileId)) {
-                    ALOGE("Unknown data destination for file ID %d. "
-                          "Ignore.",
-                          header.fileIdx);
+                    ALOGE("Unknown data destination for file ID %d. Ignore.", header.fileIdx);
                     continue;
                 }
 
@@ -738,7 +736,7 @@
                 if (writeFd < 0) {
                     writeFd.reset(this->mIfs->openForSpecialOps(fileId).release());
                     if (writeFd < 0) {
-                        ALOGE("Failed to open file %d for writing (%d). Aborting.", header.fileIdx,
+                        ALOGE("Failed to open file %d for writing (%d). Abort.", header.fileIdx,
                               -writeFd);
                         break;
                     }
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
index 63a6eed..9b7e27d 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp
@@ -103,7 +103,8 @@
     return result == power::HalResult::SUCCESSFUL;
 }
 
-void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType) {
+void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType,
+                                                     int32_t displayId) {
     if (gPowerManagerServiceObj) {
         // Throttle calls into user activity by event type.
         // We're a little conservative about argument checking here in case the caller
@@ -127,7 +128,7 @@
 
         env->CallVoidMethod(gPowerManagerServiceObj,
                 gPowerManagerServiceClassInfo.userActivityFromNative,
-                nanoseconds_to_milliseconds(eventTime), eventType, 0);
+                nanoseconds_to_milliseconds(eventTime), eventType, displayId, 0);
         checkAndClearExceptionFromCallback(env, "userActivityFromNative");
     }
 }
@@ -285,7 +286,7 @@
     FIND_CLASS(clazz, "com/android/server/power/PowerManagerService");
 
     GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivityFromNative, clazz,
-            "userActivityFromNative", "(JII)V");
+            "userActivityFromNative", "(JIII)V");
 
     // Initialize
     for (int i = 0; i <= USER_ACTIVITY_EVENT_LAST; i++) {
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.h b/services/core/jni/com_android_server_power_PowerManagerService.h
index a17fd65..a2f335c 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.h
+++ b/services/core/jni/com_android_server_power_PowerManagerService.h
@@ -24,7 +24,8 @@
 
 namespace android {
 
-extern void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType);
+extern void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType,
+                                                            int32_t displayId);
 
 } // namespace android
 
diff --git a/services/core/jni/com_android_server_powerstats_PowerStatsService.cpp b/services/core/jni/com_android_server_powerstats_PowerStatsService.cpp
index 3f54529..0e21aaf 100644
--- a/services/core/jni/com_android_server_powerstats_PowerStatsService.cpp
+++ b/services/core/jni/com_android_server_powerstats_PowerStatsService.cpp
@@ -217,41 +217,30 @@
     jobjectArray stateResidencyResultArray = nullptr;
     Return<void> ret = gPowerStatsHalV1_0_ptr->getPowerEntityStateResidencyData(
             powerEntityIdVector, [&env, &stateResidencyResultArray](auto results, auto status) {
-                if (status != Status::SUCCESS) {
-                    ALOGE("Error getting power entity state residency data");
-                } else {
-                    stateResidencyResultArray =
-                            env->NewObjectArray(results.size(), class_SRR, nullptr);
-                    for (int i = 0; i < results.size(); i++) {
-                        jobjectArray stateResidencyArray =
-                                env->NewObjectArray(results[i].stateResidencyData.size(), class_SR,
-                                                    nullptr);
-                        for (int j = 0; j < results[i].stateResidencyData.size(); j++) {
-                            jobject stateResidency = env->NewObject(class_SR, method_SR_init);
-                            env->SetIntField(stateResidency, field_SR_id,
-                                             results[i].stateResidencyData[j].powerEntityStateId);
-                            env->SetLongField(stateResidency, field_SR_totalTimeInStateMs,
-                                              results[i].stateResidencyData[j].totalTimeInStateMs);
-                            env->SetLongField(stateResidency, field_SR_totalStateEntryCount,
-                                              results[i]
-                                                      .stateResidencyData[j]
-                                                      .totalStateEntryCount);
-                            env->SetLongField(stateResidency, field_SR_lastEntryTimestampMs,
-                                              results[i]
-                                                      .stateResidencyData[j]
-                                                      .lastEntryTimestampMs);
-                            env->SetObjectArrayElement(stateResidencyArray, j, stateResidency);
-                            env->DeleteLocalRef(stateResidency);
-                        }
-                        jobject stateResidencyResult = env->NewObject(class_SRR, method_SRR_init);
-                        env->SetIntField(stateResidencyResult, field_SRR_id,
-                                         results[i].powerEntityId);
-                        env->SetObjectField(stateResidencyResult, field_SRR_stateResidencyData,
-                                            stateResidencyArray);
-                        env->SetObjectArrayElement(stateResidencyResultArray, i,
-                                                   stateResidencyResult);
-                        env->DeleteLocalRef(stateResidencyResult);
+                stateResidencyResultArray = env->NewObjectArray(results.size(), class_SRR, nullptr);
+                for (int i = 0; i < results.size(); i++) {
+                    jobjectArray stateResidencyArray =
+                            env->NewObjectArray(results[i].stateResidencyData.size(), class_SR,
+                                                nullptr);
+                    for (int j = 0; j < results[i].stateResidencyData.size(); j++) {
+                        jobject stateResidency = env->NewObject(class_SR, method_SR_init);
+                        env->SetIntField(stateResidency, field_SR_id,
+                                         results[i].stateResidencyData[j].powerEntityStateId);
+                        env->SetLongField(stateResidency, field_SR_totalTimeInStateMs,
+                                          results[i].stateResidencyData[j].totalTimeInStateMs);
+                        env->SetLongField(stateResidency, field_SR_totalStateEntryCount,
+                                          results[i].stateResidencyData[j].totalStateEntryCount);
+                        env->SetLongField(stateResidency, field_SR_lastEntryTimestampMs,
+                                          results[i].stateResidencyData[j].lastEntryTimestampMs);
+                        env->SetObjectArrayElement(stateResidencyArray, j, stateResidency);
+                        env->DeleteLocalRef(stateResidency);
                     }
+                    jobject stateResidencyResult = env->NewObject(class_SRR, method_SRR_init);
+                    env->SetIntField(stateResidencyResult, field_SRR_id, results[i].powerEntityId);
+                    env->SetObjectField(stateResidencyResult, field_SRR_stateResidencyData,
+                                        stateResidencyArray);
+                    env->SetObjectArrayElement(stateResidencyResultArray, i, stateResidencyResult);
+                    env->DeleteLocalRef(stateResidencyResult);
                 }
             });
     if (!checkResult(ret, __func__)) {
@@ -320,30 +309,25 @@
             gPowerStatsHalV1_0_ptr
                     ->getEnergyData(channelIdVector,
                                     [&env, &energyMeasurementArray](auto energyData, auto status) {
-                                        if (status != Status::SUCCESS) {
-                                            ALOGW("Error getting energy data");
-                                        } else {
-                                            energyMeasurementArray =
-                                                    env->NewObjectArray(energyData.size(), class_EM,
-                                                                        nullptr);
-                                            for (int i = 0; i < energyData.size(); i++) {
-                                                jobject energyMeasurement =
-                                                        env->NewObject(class_EM, method_EM_init);
-                                                env->SetIntField(energyMeasurement, field_EM_id,
-                                                                 energyData[i].index);
-                                                env->SetLongField(energyMeasurement,
-                                                                  field_EM_timestampMs,
-                                                                  energyData[i].timestamp);
-                                                env->SetLongField(energyMeasurement,
-                                                                  field_EM_durationMs,
-                                                                  energyData[i].timestamp);
-                                                env->SetLongField(energyMeasurement,
-                                                                  field_EM_energyUWs,
-                                                                  energyData[i].energy);
-                                                env->SetObjectArrayElement(energyMeasurementArray,
-                                                                           i, energyMeasurement);
-                                                env->DeleteLocalRef(energyMeasurement);
-                                            }
+                                        energyMeasurementArray =
+                                                env->NewObjectArray(energyData.size(), class_EM,
+                                                                    nullptr);
+                                        for (int i = 0; i < energyData.size(); i++) {
+                                            jobject energyMeasurement =
+                                                    env->NewObject(class_EM, method_EM_init);
+                                            env->SetIntField(energyMeasurement, field_EM_id,
+                                                             energyData[i].index);
+                                            env->SetLongField(energyMeasurement,
+                                                              field_EM_timestampMs,
+                                                              energyData[i].timestamp);
+                                            env->SetLongField(energyMeasurement,
+                                                              field_EM_durationMs,
+                                                              energyData[i].timestamp);
+                                            env->SetLongField(energyMeasurement, field_EM_energyUWs,
+                                                              energyData[i].energy);
+                                            env->SetObjectArrayElement(energyMeasurementArray, i,
+                                                                       energyMeasurement);
+                                            env->DeleteLocalRef(energyMeasurement);
                                         }
                                     });
 
diff --git a/services/core/xsd/Android.bp b/services/core/xsd/Android.bp
index bdccf45..c285ef5 100644
--- a/services/core/xsd/Android.bp
+++ b/services/core/xsd/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 xsd_config {
     name: "default-permissions",
     srcs: ["default-permissions.xsd"],
diff --git a/services/core/xsd/vts/Android.bp b/services/core/xsd/vts/Android.bp
index a942108..4d3c79e 100644
--- a/services/core/xsd/vts/Android.bp
+++ b/services/core/xsd/vts/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_test {
     name: "vts_defaultPermissions_validate_test",
     srcs: [
diff --git a/services/coverage/Android.bp b/services/coverage/Android.bp
index b3cee37..82feafe 100644
--- a/services/coverage/Android.bp
+++ b/services/coverage/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.coverage-sources",
     srcs: ["java/**/*.java"],
diff --git a/services/devicepolicy/Android.bp b/services/devicepolicy/Android.bp
index 5de48ae..3a9853d 100644
--- a/services/devicepolicy/Android.bp
+++ b/services/devicepolicy/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.devicepolicy-sources",
     srcs: ["java/**/*.java"],
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index b52347f..ef7afc8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -129,6 +129,15 @@
             FullyManagedDeviceProvisioningParams provisioningParams, String callerPackage) {
     }
 
+    @Override
+    public void setDeviceOwnerType(@NonNull ComponentName admin, int deviceOwnerType) {
+    }
+
+    @Override
+    public int getDeviceOwnerType(@NonNull ComponentName admin) {
+        return 0;
+    }
+
     public void resetDefaultCrossProfileIntentFilters(@UserIdInt int userId) {}
 
     public boolean canAdminGrantSensorsPermissionsForUser(int userId) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 1cf4ce1..28e9acf 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -156,6 +156,7 @@
 import android.app.admin.DevicePolicyCache;
 import android.app.admin.DevicePolicyEventLogger;
 import android.app.admin.DevicePolicyManager;
+import android.app.admin.DevicePolicyManager.DeviceOwnerType;
 import android.app.admin.DevicePolicyManager.DevicePolicyOperation;
 import android.app.admin.DevicePolicyManager.OperationSafetyReason;
 import android.app.admin.DevicePolicyManager.PasswordComplexity;
@@ -222,6 +223,7 @@
 import android.net.IIpConnectivityMetrics;
 import android.net.ProxyInfo;
 import android.net.Uri;
+import android.net.VpnManager;
 import android.net.metrics.IpConnectivityLog;
 import android.net.wifi.WifiManager;
 import android.os.Binder;
@@ -332,6 +334,7 @@
 
 import org.xmlpull.v1.XmlPullParserException;
 
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
@@ -339,6 +342,9 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.lang.reflect.Constructor;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
 import java.text.DateFormat;
 import java.time.LocalDate;
 import java.util.ArrayList;
@@ -709,6 +715,9 @@
     @Nullable
     private DevicePolicySafetyChecker mSafetyChecker;
 
+    @GuardedBy("getLockObject()")
+    private final ArrayList<Object> mPendingUserCreatedCallbackTokens = new ArrayList<>();
+
     public static final class Lifecycle extends SystemService {
         private BaseIDevicePolicyManager mService;
 
@@ -747,21 +756,25 @@
 
         @Override
         public void onUserStarting(@NonNull TargetUser user) {
+            if (user.isPreCreated()) return;
             mService.handleStartUser(user.getUserIdentifier());
         }
 
         @Override
         public void onUserUnlocking(@NonNull TargetUser user) {
+            if (user.isPreCreated()) return;
             mService.handleUnlockUser(user.getUserIdentifier());
         }
 
         @Override
         public void onUserStopping(@NonNull TargetUser user) {
+            if (user.isPreCreated()) return;
             mService.handleStopUser(user.getUserIdentifier());
         }
 
         @Override
         public void onUserUnlocked(@NonNull TargetUser user) {
+            if (user.isPreCreated()) return;
             mService.handleOnUserUnlocked(user.getUserIdentifier());
         }
     }
@@ -959,8 +972,8 @@
     private final class UserLifecycleListener implements UserManagerInternal.UserLifecycleListener {
 
         @Override
-        public void onUserCreated(UserInfo user) {
-            mHandler.post(() -> handleNewUserCreated(user));
+        public void onUserCreated(UserInfo user, Object token) {
+            mHandler.post(() -> handleNewUserCreated(user, token));
         }
     }
 
@@ -1138,6 +1151,11 @@
 
     @Override
     public boolean isSafeOperation(@OperationSafetyReason int reason) {
+        if (VERBOSE_LOG) {
+            Slog.v(LOG_TAG, "checking isSafeOperation("
+                    + DevicePolicyManager.operationSafetyReasonToString(reason)
+                    + ") using mSafetyChecker " + mSafetyChecker);
+        }
         return mSafetyChecker == null ? true : mSafetyChecker.isSafeOperation(reason);
     }
 
@@ -1267,6 +1285,10 @@
             return mContext.getSystemService(ConnectivityManager.class);
         }
 
+        VpnManager getVpnManager() {
+            return mContext.getSystemService(VpnManager.class);
+        }
+
         LocationManager getLocationManager() {
             return mContext.getSystemService(LocationManager.class);
         }
@@ -3136,11 +3158,6 @@
         if (!mHasFeature) {
             return;
         }
-        setActiveAdmin(adminReceiver, refreshing, userHandle, null);
-    }
-
-    private void setActiveAdmin(ComponentName adminReceiver, boolean refreshing, int userHandle,
-            Bundle onEnableData) {
         Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
 
         final CallerIdentity caller = getCallerIdentity();
@@ -3183,7 +3200,7 @@
                 }
                 saveSettingsLocked(userHandle);
                 sendAdminCommandLocked(newAdmin, DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED,
-                        onEnableData, null);
+                        /* adminExtras= */ null, /* result= */ null);
             });
         }
     }
@@ -3389,8 +3406,10 @@
             return;
         }
         Objects.requireNonNull(adminReceiver, "ComponentName is null");
-        Preconditions.checkCallAuthorization(isAdb(getCallerIdentity()),
-                "Non-shell user attempted to call forceRemoveActiveAdmin");
+        Preconditions.checkCallAuthorization(isAdb(getCallerIdentity())
+                        || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS),
+                "Caller must be shell or hold MANAGE_PROFILE_AND_DEVICE_OWNERS to call "
+                        + "forceRemoveActiveAdmin");
         mInjector.binderWithCleanCallingIdentity(() -> {
             synchronized (getLockObject()) {
                 if (!isAdminTestOnlyLocked(adminReceiver, userHandle)) {
@@ -5612,7 +5631,7 @@
         // Get attestation flags, if any.
         final int[] attestationUtilsFlags = translateIdAttestationFlags(idAttestationFlags);
         final boolean deviceIdAttestationRequired = attestationUtilsFlags != null;
-        final KeyGenParameterSpec keySpec = parcelableKeySpec.getSpec();
+        KeyGenParameterSpec keySpec = parcelableKeySpec.getSpec();
         final String alias = keySpec.getKeystoreAlias();
 
         Preconditions.checkStringNotEmpty(alias, "Empty alias provided");
@@ -5633,6 +5652,9 @@
                     || (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
         }
 
+        if (TextUtils.isEmpty(alias)) {
+            throw new IllegalArgumentException("Empty alias provided.");
+        }
         // As the caller will be granted access to the key, ensure no UID was specified, as
         // it will not have the desired effect.
         if (keySpec.getUid() != KeyStore.UID_SELF) {
@@ -5641,19 +5663,26 @@
             return false;
         }
 
+        if (deviceIdAttestationRequired) {
+            if (keySpec.getAttestationChallenge() == null) {
+                throw new IllegalArgumentException(
+                        "Requested Device ID attestation but challenge is empty.");
+            }
+            KeyGenParameterSpec.Builder specBuilder = new KeyGenParameterSpec.Builder(keySpec);
+            specBuilder.setAttestationIds(attestationUtilsFlags);
+            specBuilder.setDevicePropertiesAttestationIncluded(true);
+            keySpec = specBuilder.build();
+        }
+
+        final UserHandle userHandle = mInjector.binderGetCallingUserHandle();
         final long id = mInjector.binderClearCallingIdentity();
         try {
             try (KeyChainConnection keyChainConnection =
-                    KeyChain.bindAsUser(mContext, caller.getUserHandle())) {
+                    KeyChain.bindAsUser(mContext, userHandle)) {
                 IKeyChainService keyChain = keyChainConnection.getService();
 
-                // Copy the provided keySpec, excluding the attestation challenge, which will be
-                // used later for requesting key attestation record.
-                final KeyGenParameterSpec noAttestationSpec = new KeyGenParameterSpec.Builder(
-                        keySpec).setAttestationChallenge(null).build();
-
                 final int generationResult = keyChain.generateKeyPair(algorithm,
-                    new ParcelableKeyGenParameterSpec(noAttestationSpec));
+                        new ParcelableKeyGenParameterSpec(keySpec));
                 if (generationResult != KeyChain.KEY_GEN_SUCCESS) {
                     Log.e(LOG_TAG, String.format(
                             "KeyChain failed to generate a keypair, error %d.", generationResult));
@@ -5662,6 +5691,9 @@
                             throw new ServiceSpecificException(
                                     DevicePolicyManager.KEY_GEN_STRONGBOX_UNAVAILABLE,
                                     String.format("KeyChain error: %d", generationResult));
+                        case KeyChain.KEY_ATTESTATION_CANNOT_ATTEST_IDS:
+                            throw new UnsupportedOperationException(
+                                "Device does not support Device ID attestation.");
                         default:
                             logGenerateKeyPairFailure(caller, isCredentialManagementApp);
                             return false;
@@ -5675,23 +5707,27 @@
                 // that UID.
                 keyChain.setGrant(caller.getUid(), alias, true);
 
-                final byte[] attestationChallenge = keySpec.getAttestationChallenge();
-                if (attestationChallenge != null) {
-                    final int attestationResult = keyChain.attestKey(
-                            alias, attestationChallenge, attestationUtilsFlags, attestationChain);
-                    if (attestationResult != KeyChain.KEY_ATTESTATION_SUCCESS) {
-                        Log.e(LOG_TAG, String.format(
-                                "Attestation for %s failed (rc=%d), deleting key.",
-                                alias, attestationResult));
-                        keyChain.removeKeyPair(alias);
-                        if (attestationResult == KeyChain.KEY_ATTESTATION_CANNOT_ATTEST_IDS) {
-                            throw new UnsupportedOperationException(
-                                    "Device does not support Device ID attestation.");
+                try {
+                    final List<byte[]> encodedCerts = new ArrayList();
+                    final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+                    final byte[] certChainBytes = keyChain.getCaCertificates(alias);
+                    encodedCerts.add(keyChain.getCertificate(alias));
+                    if (certChainBytes != null) {
+                        final Collection<X509Certificate> certs =
+                                (Collection<X509Certificate>) certFactory.generateCertificates(
+                                    new ByteArrayInputStream(certChainBytes));
+                        for (X509Certificate cert : certs) {
+                            encodedCerts.add(cert.getEncoded());
                         }
-                        logGenerateKeyPairFailure(caller, isCredentialManagementApp);
-                        return false;
                     }
+
+                    attestationChain.shallowCopyFrom(new KeymasterCertificateChain(encodedCerts));
+                } catch (CertificateException e) {
+                    logGenerateKeyPairFailure(caller, isCredentialManagementApp);
+                    Log.e(LOG_TAG, "While retrieving certificate chain.", e);
+                    return false;
                 }
+
                 DevicePolicyEventLogger
                         .createEvent(DevicePolicyEnums.GENERATE_KEY_PAIR)
                         .setAdmin(caller.getPackageName())
@@ -6302,7 +6338,7 @@
                 }
             }
             // If some package is uninstalled after the check above, it will be ignored by CM.
-            if (!mInjector.getConnectivityManager().setAlwaysOnVpnPackageForUser(
+            if (!mInjector.getVpnManager().setAlwaysOnVpnPackageForUser(
                     userId, vpnPackage, lockdown, lockdownAllowlist)) {
                 throw new UnsupportedOperationException();
             }
@@ -6334,8 +6370,7 @@
         Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
 
         return mInjector.binderWithCleanCallingIdentity(
-                () -> mInjector.getConnectivityManager().getAlwaysOnVpnPackageForUser(
-                        caller.getUserId()));
+                () -> mInjector.getVpnManager().getAlwaysOnVpnPackageForUser(caller.getUserId()));
     }
 
     @Override
@@ -6361,7 +6396,7 @@
         }
 
         return mInjector.binderWithCleanCallingIdentity(
-                () -> mInjector.getConnectivityManager().isVpnLockdownEnabled(caller.getUserId()));
+                () -> mInjector.getVpnManager().isVpnLockdownEnabled(caller.getUserId()));
     }
 
     @Override
@@ -6382,8 +6417,7 @@
         Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
 
         return mInjector.binderWithCleanCallingIdentity(
-                () -> mInjector.getConnectivityManager().getVpnLockdownAllowlist(
-                        caller.getUserId()));
+                () -> mInjector.getVpnManager().getVpnLockdownAllowlist(caller.getUserId()));
     }
 
     private void forceWipeDeviceNoLock(boolean wipeExtRequested, String reason, boolean wipeEuicc,
@@ -7552,8 +7586,7 @@
     }
 
     private void sendProfileOwnerCommand(String action, Bundle extras, @UserIdInt int userId) {
-        sendActiveAdminCommand(action, extras, userId,
-                mOwners.getProfileOwnerComponent(userId));
+        sendActiveAdminCommand(action, extras, userId, mOwners.getProfileOwnerComponent(userId));
     }
 
     private void sendActiveAdminCommand(String action, Bundle extras,
@@ -8081,7 +8114,8 @@
             return null;
         }
         if (!callingUserOnly) {
-            Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
+            Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())
+                    || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
         }
         synchronized (getLockObject()) {
             if (!mOwners.hasDeviceOwner()) {
@@ -9155,13 +9189,24 @@
                 pw.println();
                 mStatLogger.dump(pw);
                 pw.println();
-
                 pw.println("Encryption Status: " + getEncryptionStatusName(getEncryptionStatus()));
                 pw.println();
+
+                if (mPendingUserCreatedCallbackTokens.isEmpty()) {
+                    pw.println("no pending user created callback tokens");
+                } else {
+                    int size = mPendingUserCreatedCallbackTokens.size();
+                    pw.printf("%d pending user created callback token%s\n", size,
+                            (size == 1 ? "" : "s"));
+                }
+                pw.println();
+
                 mPolicyCache.dump(pw);
                 pw.println();
                 mStateCache.dump(pw);
+                pw.println();
             }
+            dumpResources(pw);
         }
     }
 
@@ -9172,8 +9217,33 @@
         pw.printf("mIsWatch=%b\n", mIsWatch);
         pw.printf("mIsAutomotive=%b\n", mIsAutomotive);
         pw.printf("mHasTelephonyFeature=%b\n", mHasTelephonyFeature);
-        String safetyChecker = mSafetyChecker == null ? "N/A" : mSafetyChecker.getClass().getName();
-        pw.printf("mSafetyChecker=%b\n", safetyChecker);
+        pw.printf("mSafetyChecker=%s\n", mSafetyChecker);
+        pw.decreaseIndent();
+    }
+
+    private void dumpResources(IndentingPrintWriter pw) {
+        mOverlayPackagesProvider.dump(pw);
+        pw.println();
+
+        pw.println("Other overlayable app resources");
+        pw.increaseIndent();
+        dumpResources(pw, mContext, "cross_profile_apps", R.array.cross_profile_apps);
+        dumpResources(pw, mContext, "vendor_cross_profile_apps", R.array.vendor_cross_profile_apps);
+        pw.decreaseIndent();
+        pw.println();
+    }
+
+    static void dumpResources(IndentingPrintWriter pw, Context context, String resName, int resId) {
+        String[] apps = context.getResources().getStringArray(resId);
+        if (apps == null || apps.length == 0) {
+            pw.printf("%s: empty\n", resName);
+            return;
+        }
+        pw.printf("%s: %d app%s\n", resName, apps.length, apps.length == 1 ? "" : "s");
+        pw.increaseIndent();
+        for (int i = 0; i < apps.length; i++) {
+            pw.printf("%d: %s\n", i, apps[i]);
+        }
         pw.decreaseIndent();
     }
 
@@ -9915,8 +9985,8 @@
                 clearInitBundle = sendAdminCommandLocked(admin,
                         DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED,
                         initBundle == null ? null : new Bundle(initBundle),
-                        null /* result receiver */,
-                        true /* send in foreground */);
+                        /* result= */ null ,
+                        /* inForeground= */ true);
             }
             if (clearInitBundle) {
                 // If there's no admin or we've successfully called the admin, clear the init bundle
@@ -9989,9 +10059,13 @@
                             UserHandle.myUserId(), ACTION_PROVISION_MANAGED_USER).toArray(
                             new String[0]);
                 }
+
+                Object token = new Object();
+                Slog.d(LOG_TAG, "Adding new pending token: " + token);
+                mPendingUserCreatedCallbackTokens.add(token);
                 try {
                     UserInfo userInfo = mUserManagerInternal.createUserEvenWhenDisallowed(name,
-                            userType, userInfoFlags, disallowedPackages);
+                            userType, userInfoFlags, disallowedPackages, token);
                     if (userInfo != null) {
                         user = userInfo.getUserHandle();
                     }
@@ -10001,7 +10075,8 @@
             } finally {
                 mInjector.binderRestoreCallingIdentity(id);
             }
-        }
+        } // synchronized
+
         if (user == null) {
             if (targetSdkVersion >= Build.VERSION_CODES.P) {
                 throw new ServiceSpecificException(UserManager.USER_OPERATION_ERROR_UNKNOWN,
@@ -10023,14 +10098,8 @@
 
         final long id = mInjector.binderClearCallingIdentity();
         try {
-            if (!mInjector.userManagerIsHeadlessSystemUserMode()) {
-                manageUserUnchecked(admin, profileOwner, userHandle, adminExtras,
-                        /* showDisclaimer= */ true);
-            } else if (VERBOSE_LOG) {
-                Slog.v(LOG_TAG, "createAndManageUser(): skipping manageUserUnchecked() on user "
-                        + userHandle + " on headless system user as it will be called by "
-                                + "handleNewUserCreated()");
-            }
+            manageUserUnchecked(admin, profileOwner, userHandle, adminExtras,
+                    /* showDisclaimer= */ true);
 
             if ((flags & DevicePolicyManager.SKIP_SETUP_WIZARD) != 0) {
                 Settings.Secure.putIntForUser(mContext.getContentResolver(),
@@ -10052,7 +10121,15 @@
     }
 
     private void manageUserUnchecked(ComponentName admin, ComponentName profileOwner,
-            @UserIdInt int userId, PersistableBundle adminExtras, boolean showDisclaimer) {
+            @UserIdInt int userId, @Nullable PersistableBundle adminExtras,
+            boolean showDisclaimer) {
+        synchronized (getLockObject()) {
+            if (VERBOSE_LOG) {
+                Slog.v(LOG_TAG, "manageUserUnchecked(): admin=" + admin + ", po=" + profileOwner
+                        + ", userId=" + userId + ", hasAdminExtras=" + (adminExtras != null)
+                        + ", showDisclaimer=" + showDisclaimer);
+            }
+        }
         final String adminPkg = admin.getPackageName();
         try {
             // Install the profile owner if not present.
@@ -10082,24 +10159,37 @@
                     ? DevicePolicyData.NEW_USER_DISCLAIMER_NEEDED
                     : DevicePolicyData.NEW_USER_DISCLAIMER_NOT_NEEDED;
             saveSettingsLocked(userId);
+
         }
     }
 
-    private void handleNewUserCreated(UserInfo user) {
-        if (VERBOSE_LOG) Slog.v(LOG_TAG, "handleNewUserCreated(): " + user.toFullString());
+    private void handleNewUserCreated(UserInfo user, @Nullable Object token) {
+        if (VERBOSE_LOG) {
+            Slog.v(LOG_TAG, "handleNewUserCreated(): user=" + user.toFullString()
+                    + ", token=" + token);
+        }
+
+        final int userId = user.id;
+        if (token != null) {
+            synchronized (getLockObject()) {
+                if (mPendingUserCreatedCallbackTokens.contains(token)) {
+                    // Ignore because it was triggered by createAndManageUser()
+                    Slog.d(LOG_TAG, "handleNewUserCreated(): ignoring for user " + userId
+                            + " due to token" + token);
+                    mPendingUserCreatedCallbackTokens.remove(token);
+                    return;
+                }
+            }
+        }
 
         if (!mOwners.hasDeviceOwner() || !user.isFull() || user.isManagedProfile()) return;
 
-        final int userId = user.id;
-
-        // TODO(b/177547285): add CTS test
         if (mInjector.userManagerIsHeadlessSystemUserMode()) {
             ComponentName admin = mOwners.getDeviceOwnerComponent();
             Slog.i(LOG_TAG, "Automatically setting profile owner (" + admin + ") on new user "
                     + userId);
             manageUserUnchecked(/* deviceOwner= */ admin, /* profileOwner= */ admin,
-                    /* managedUser= */ userId, /* adminExtras= */ null,
-                    /* showDisclaimer= */ true);
+                    /* managedUser= */ userId, /* adminExtras= */ null, /* showDisclaimer= */ true);
         } else {
             Log.i(LOG_TAG, "User " + userId + " added on DO mode; setting ShowNewUserDisclaimer");
             setShowNewUserDisclaimer(userId, DevicePolicyData.NEW_USER_DISCLAIMER_NEEDED);
@@ -10220,11 +10310,12 @@
         final long id = mInjector.binderClearCallingIdentity();
         try {
             if (!mInjector.getActivityManagerInternal().canStartMoreUsers()) {
-                Log.w(LOG_TAG, "Cannot start more users in background");
+                Log.w(LOG_TAG, "Cannot start user " + userId + ", too many users in background");
                 return UserManager.USER_OPERATION_ERROR_MAX_RUNNING_USERS;
             }
 
             if (mInjector.getIActivityManager().startUserInBackground(userId)) {
+                Log.i(LOG_TAG, "Started used " + userId + " in background");
                 return UserManager.USER_OPERATION_SUCCESS;
             } else {
                 return UserManager.USER_OPERATION_ERROR_UNKNOWN;
@@ -12338,7 +12429,6 @@
                 Slog.v(LOG_TAG, String.format("notifyUnsafeOperationStateChanged(): %s=%b",
                         DevicePolicyManager.operationSafetyReasonToString(reason), isSafe));
             }
-
             Preconditions.checkArgument(mSafetyChecker == checker,
                     "invalid checker: should be %s, was %s", mSafetyChecker, checker);
 
@@ -12346,9 +12436,10 @@
             extras.putInt(DeviceAdminReceiver.EXTRA_OPERATION_SAFETY_REASON, reason);
             extras.putBoolean(DeviceAdminReceiver.EXTRA_OPERATION_SAFETY_STATE, isSafe);
 
-            // TODO(b/178494483): add CTS test
-            sendDeviceOwnerCommand(DeviceAdminReceiver.ACTION_OPERATION_SAFETY_STATE_CHANGED,
-                    extras);
+            if (mOwners.hasDeviceOwner()) {
+                sendDeviceOwnerCommand(DeviceAdminReceiver.ACTION_OPERATION_SAFETY_STATE_CHANGED,
+                        extras);
+            }
             for (int profileOwnerId : mOwners.getProfileOwnerKeys()) {
                 sendProfileOwnerCommand(DeviceAdminReceiver.ACTION_OPERATION_SAFETY_STATE_CHANGED,
                         extras, profileOwnerId);
@@ -12539,8 +12630,10 @@
 
     @Override
     public void clearSystemUpdatePolicyFreezePeriodRecord() {
-        Preconditions.checkCallAuthorization(isAdb(getCallerIdentity()),
-                "Non-shell user attempted to call clearSystemUpdatePolicyFreezePeriodRecord");
+        Preconditions.checkCallAuthorization(isAdb(getCallerIdentity())
+                        || hasCallingOrSelfPermission(permission.CLEAR_FREEZE_PERIOD),
+                "Caller must be shell, or hold CLEAR_FREEZE_PERIOD permission to call "
+                        + "clearSystemUpdatePolicyFreezePeriodRecord");
         synchronized (getLockObject()) {
             // Print out current record to help diagnosed CTS failures
             Slog.i(LOG_TAG, "Clear freeze period record: "
@@ -12911,8 +13004,10 @@
         if (mOwners.hasProfileOwner(deviceOwnerUserId)) {
             return CODE_USER_HAS_PROFILE_OWNER;
         }
+
+        boolean isHeadlessSystemUserMode = mInjector.userManagerIsHeadlessSystemUserMode();
         // System user is always running in headless system user mode.
-        if (!mInjector.userManagerIsHeadlessSystemUserMode()
+        if (!isHeadlessSystemUserMode
                 && !mUserManager.isUserRunning(new UserHandle(deviceOwnerUserId))) {
             return CODE_USER_NOT_RUNNING;
         }
@@ -12920,7 +13015,7 @@
             return CODE_HAS_PAIRED;
         }
 
-        if (mInjector.userManagerIsHeadlessSystemUserMode()) {
+        if (isHeadlessSystemUserMode) {
             if (deviceOwnerUserId != UserHandle.USER_SYSTEM) {
                 Slog.e(LOG_TAG, "In headless system user mode, "
                         + "device owner can only be set on headless system user.");
@@ -12932,9 +13027,13 @@
             // If shell command runs after user setup completed check device status. Otherwise, OK.
             if (mIsWatch || hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
                 // In non-headless system user mode, DO can be setup only if
-                // there's no non-system user
-                if (!mInjector.userManagerIsHeadlessSystemUserMode()
-                        && mUserManager.getUserCount() > 1) {
+                // there's no non-system user.
+                // In headless system user mode, DO can be setup only if there are
+                // two users: the headless system user and the foreground user.
+                // If there could be multiple foreground users, this constraint should be modified.
+
+                int maxNumberOfExistingUsers = isHeadlessSystemUserMode ? 2 : 1;
+                if (mUserManager.getUserCount() > maxNumberOfExistingUsers) {
                     return CODE_NONSYSTEM_USER_EXISTS;
                 }
 
@@ -13477,7 +13576,8 @@
         final CallerIdentity caller = getCallerIdentity();
         // Only adb or system apps with the right permission can mark a profile owner on
         // organization-owned device.
-        if (!(isAdb(caller) || hasCallingPermission(permission.MARK_DEVICE_ORGANIZATION_OWNED))) {
+        if (!(isAdb(caller) || hasCallingPermission(permission.MARK_DEVICE_ORGANIZATION_OWNED)
+                || hasCallingPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS))) {
             throw new SecurityException(
                     "Only the system can mark a profile owner of organization-owned device.");
         }
@@ -13796,8 +13896,10 @@
 
     @Override
     public long forceSecurityLogs() {
-        Preconditions.checkCallAuthorization(isAdb(getCallerIdentity()),
-                "Non-shell user attempted to call forceSecurityLogs");
+        Preconditions.checkCallAuthorization(isAdb(getCallerIdentity())
+                        || hasCallingOrSelfPermission(permission.FORCE_DEVICE_POLICY_MANAGER_LOGS),
+                "Caller must be shell or hold FORCE_DEVICE_POLICY_MANAGER_LOGS to call "
+                        + "forceSecurityLogs");
         if (!mInjector.securityLogGetLoggingEnabledProperty()) {
             throw new IllegalStateException("logging is not available");
         }
@@ -14317,8 +14419,10 @@
 
     @Override
     public long forceNetworkLogs() {
-        Preconditions.checkCallAuthorization(isAdb(getCallerIdentity()),
-                "Non-shell user attempted to call forceNetworkLogs");
+        Preconditions.checkCallAuthorization(isAdb(getCallerIdentity())
+                || hasCallingOrSelfPermission(permission.FORCE_DEVICE_POLICY_MANAGER_LOGS),
+                "Caller must be shell or hold FORCE_DEVICE_POLICY_MANAGER_LOGS to call "
+                        + "forceNetworkLogs");
         synchronized (getLockObject()) {
             if (!isNetworkLoggingEnabledInternalLocked()) {
                 throw new IllegalStateException("logging is not available");
@@ -16721,6 +16825,37 @@
     }
 
     @Override
+    public void setDeviceOwnerType(@NonNull ComponentName admin,
+            @DeviceOwnerType int deviceOwnerType) {
+        Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(
+                permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
+        verifyDeviceOwnerTypePreconditions(admin);
+
+        final String packageName = admin.getPackageName();
+        Preconditions.checkState(!mOwners.isDeviceOwnerTypeSetForDeviceOwner(packageName),
+                "The device owner type has already been set for " + packageName);
+
+        synchronized (getLockObject()) {
+            mOwners.setDeviceOwnerType(packageName, deviceOwnerType);
+        }
+    }
+
+    @Override
+    @DeviceOwnerType
+    public int getDeviceOwnerType(@NonNull ComponentName admin) {
+        verifyDeviceOwnerTypePreconditions(admin);
+        synchronized (getLockObject()) {
+            return mOwners.getDeviceOwnerType(admin.getPackageName());
+        }
+    }
+
+    private void verifyDeviceOwnerTypePreconditions(@NonNull ComponentName admin) {
+        Preconditions.checkState(mOwners.hasDeviceOwner(), "there is no device owner");
+        Preconditions.checkState(mOwners.getDeviceOwnerComponent().equals(admin),
+                "admin is not the device owner");
+    }
+
+    @Override
     public void setUsbDataSignalingEnabled(String packageName, boolean enabled) {
         Objects.requireNonNull(packageName, "Admin package name must be provided");
         final CallerIdentity caller = getCallerIdentity(packageName);
@@ -16784,7 +16919,7 @@
         synchronized (getLockObject()) {
             final ActiveAdmin admin = getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceLocked(
                     UserHandle.USER_SYSTEM);
-            return admin != null && admin.mUsbDataSignalingEnabled;
+            return admin == null || admin.mUsbDataSignalingEnabled;
         }
     }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/OneTimeSafetyChecker.java b/services/devicepolicy/java/com/android/server/devicepolicy/OneTimeSafetyChecker.java
index 7de1bd5..257fc64 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/OneTimeSafetyChecker.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/OneTimeSafetyChecker.java
@@ -23,6 +23,8 @@
 import android.app.admin.DevicePolicyManager.OperationSafetyReason;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.app.admin.DevicePolicySafetyChecker;
+import android.os.Handler;
+import android.os.Looper;
 import android.util.Slog;
 
 import com.android.internal.os.IResultReceiver;
@@ -42,10 +44,15 @@
 
     private static final String TAG = OneTimeSafetyChecker.class.getSimpleName();
 
+    private static final long SELF_DESTRUCT_TIMEOUT_MS = 10_000;
+
     private final DevicePolicyManagerService mService;
     private final DevicePolicySafetyChecker mRealSafetyChecker;
     private final @DevicePolicyOperation int mOperation;
     private final @OperationSafetyReason int mReason;
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
+
+    private boolean mDone;
 
     OneTimeSafetyChecker(DevicePolicyManagerService service,
             @DevicePolicyOperation int operation, @OperationSafetyReason int reason) {
@@ -53,7 +60,11 @@
         mOperation = operation;
         mReason = reason;
         mRealSafetyChecker = service.getDevicePolicySafetyChecker();
-        Slog.i(TAG, "Saving real DevicePolicySafetyChecker as " + mRealSafetyChecker);
+        Slog.i(TAG, "OneTimeSafetyChecker constructor: operation= " + operationToString(operation)
+                + ", reason=" + operationSafetyReasonToString(reason)
+                + ", realChecker=" + mRealSafetyChecker
+                + ", maxDuration=" + SELF_DESTRUCT_TIMEOUT_MS + "ms");
+        mHandler.postDelayed(() -> selfDestruct(), SELF_DESTRUCT_TIMEOUT_MS);
     }
 
     @Override
@@ -72,15 +83,15 @@
         DevicePolicyManagerInternal dpmi = LocalServices
                 .getService(DevicePolicyManagerInternal.class);
 
-        Slog.i(TAG, "notifying " + reasonName + " is active");
-        dpmi.notifyUnsafeOperationStateChanged(this, reason, true);
+        Slog.i(TAG, "notifying " + reasonName + " is UNSAFE");
+        dpmi.notifyUnsafeOperationStateChanged(this, reason, /* isSafe= */ false);
 
-        Slog.i(TAG, "notifying " + reasonName + " is inactive");
-        dpmi.notifyUnsafeOperationStateChanged(this, reason, false);
+        Slog.i(TAG, "notifying " + reasonName + " is SAFE");
+        dpmi.notifyUnsafeOperationStateChanged(this, reason, /* isSafe= */ true);
 
-        Slog.i(TAG, "returning " + reasonName
-                + " and restoring DevicePolicySafetyChecker to " + mRealSafetyChecker);
-        mService.setDevicePolicySafetyCheckerUnchecked(mRealSafetyChecker);
+        Slog.i(TAG, "returning " + reasonName);
+
+        disableSelf();
         return reason;
     }
 
@@ -89,6 +100,7 @@
         boolean safe = mReason != reason;
         Slog.i(TAG, "isSafeOperation(" + operationSafetyReasonToString(reason) + "): " + safe);
 
+        disableSelf();
         return safe;
     }
 
@@ -96,4 +108,29 @@
     public void onFactoryReset(IResultReceiver callback) {
         throw new UnsupportedOperationException();
     }
+
+    private void disableSelf() {
+        if (mDone) {
+            Slog.w(TAG, "disableSelf(): already disabled");
+            return;
+        }
+        Slog.i(TAG, "restoring DevicePolicySafetyChecker to " + mRealSafetyChecker);
+        mService.setDevicePolicySafetyCheckerUnchecked(mRealSafetyChecker);
+        mDone = true;
+    }
+
+    private void selfDestruct() {
+        if (mDone) return;
+
+        // Usually happens when a CTS failed before calling the DPM method that would clear it
+        Slog.e(TAG, "Self destructing " + this + ", as it was not automatically disabled");
+        disableSelf();
+    }
+
+    @Override
+    public String toString() {
+        return "OneTimeSafetyChecker[id=" + System.identityHashCode(this)
+                + ", reason=" + operationSafetyReasonToString(mReason)
+                + ", operation=" + operationToString(mOperation) + ']';
+    }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java b/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java
index 261a83c..280f12f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java
@@ -21,6 +21,7 @@
 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
 
 import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.server.devicepolicy.DevicePolicyManagerService.dumpResources;
 
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
@@ -32,6 +33,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.util.ArraySet;
+import android.util.IndentingPrintWriter;
 import android.view.inputmethod.InputMethodInfo;
 
 import com.android.internal.R;
@@ -224,4 +226,39 @@
         }
         return new ArraySet<>(Arrays.asList(mContext.getResources().getStringArray(resId)));
     }
+
+    void dump(IndentingPrintWriter pw) {
+        pw.println("OverlayPackagesProvider");
+        pw.increaseIndent();
+
+        dumpResources(pw, mContext, "required_apps_managed_device",
+                R.array.required_apps_managed_device);
+        dumpResources(pw, mContext, "required_apps_managed_user",
+                R.array.required_apps_managed_user);
+        dumpResources(pw, mContext, "required_apps_managed_profile",
+                R.array.required_apps_managed_profile);
+
+        dumpResources(pw, mContext, "disallowed_apps_managed_device",
+                R.array.disallowed_apps_managed_device);
+        dumpResources(pw, mContext, "disallowed_apps_managed_user",
+                R.array.disallowed_apps_managed_user);
+        dumpResources(pw, mContext, "disallowed_apps_managed_device",
+                R.array.disallowed_apps_managed_device);
+
+        dumpResources(pw, mContext, "vendor_required_apps_managed_device",
+                R.array.vendor_required_apps_managed_device);
+        dumpResources(pw, mContext, "vendor_required_apps_managed_user",
+                R.array.vendor_required_apps_managed_user);
+        dumpResources(pw, mContext, "vendor_required_apps_managed_profile",
+                R.array.vendor_required_apps_managed_profile);
+
+        dumpResources(pw, mContext, "vendor_disallowed_apps_managed_user",
+                R.array.vendor_disallowed_apps_managed_user);
+        dumpResources(pw, mContext, "vendor_disallowed_apps_managed_device",
+                R.array.vendor_disallowed_apps_managed_device);
+        dumpResources(pw, mContext, "vendor_disallowed_apps_managed_profile",
+                R.array.vendor_disallowed_apps_managed_profile);
+
+        pw.decreaseIndent();
+    }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
index 1e70d59..7fdd6ee 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
@@ -16,10 +16,13 @@
 
 package com.android.server.devicepolicy;
 
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT;
+
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManagerInternal;
 import android.app.AppOpsManagerInternal;
+import android.app.admin.DevicePolicyManager.DeviceOwnerType;
 import android.app.admin.SystemUpdateInfo;
 import android.app.admin.SystemUpdatePolicy;
 import android.content.ComponentName;
@@ -93,6 +96,7 @@
     private static final String TAG_PROFILE_OWNER = "profile-owner";
     // Holds "context" for device-owner, this must not be show up before device-owner.
     private static final String TAG_DEVICE_OWNER_CONTEXT = "device-owner-context";
+    private static final String TAG_DEVICE_OWNER_TYPE = "device-owner-type";
 
     private static final String ATTR_NAME = "name";
     private static final String ATTR_PACKAGE = "package";
@@ -109,6 +113,7 @@
     // New attribute for profile owner of organization-owned device.
     private static final String ATTR_PROFILE_OWNER_OF_ORG_OWNED_DEVICE =
             "isPoOrganizationOwnedDevice";
+    private static final String ATTR_DEVICE_OWNER_TYPE_VALUE = "value";
 
     private final UserManager mUserManager;
     private final UserManagerInternal mUserManagerInternal;
@@ -121,6 +126,9 @@
     // Internal state for the device owner package.
     private OwnerInfo mDeviceOwner;
 
+    // Device owner type for a managed device.
+    private final ArrayMap<String, Integer> mDeviceOwnerTypes = new ArrayMap<>();
+
     private int mDeviceOwnerUserId = UserHandle.USER_NULL;
 
     // Internal state for the profile owner packages.
@@ -334,6 +342,7 @@
 
     void clearDeviceOwner() {
         synchronized (mLock) {
+            mDeviceOwnerTypes.remove(mDeviceOwner.packageName);
             mDeviceOwner = null;
             mDeviceOwnerUserId = UserHandle.USER_NULL;
 
@@ -384,12 +393,16 @@
 
     void transferDeviceOwnership(ComponentName target) {
         synchronized (mLock) {
+            Integer previousDeviceOwnerType = mDeviceOwnerTypes.remove(mDeviceOwner.packageName);
             // We don't set a name because it's not used anyway.
             // See DevicePolicyManagerService#getDeviceOwnerName
             mDeviceOwner = new OwnerInfo(null, target,
                     mDeviceOwner.userRestrictionsMigrated, mDeviceOwner.remoteBugreportUri,
                     mDeviceOwner.remoteBugreportHash, /* isOrganizationOwnedDevice =*/
                     mDeviceOwner.isOrganizationOwnedDevice);
+            if (previousDeviceOwnerType != null) {
+                mDeviceOwnerTypes.put(mDeviceOwner.packageName, previousDeviceOwnerType);
+            }
             pushToPackageManagerLocked();
             pushToActivityTaskManagerLocked();
             pushToActivityManagerLocked();
@@ -596,6 +609,37 @@
         }
     }
 
+    void setDeviceOwnerType(String packageName, @DeviceOwnerType int deviceOwnerType) {
+        synchronized (mLock) {
+            if (!hasDeviceOwner()) {
+                Slog.e(TAG, "Attempting to set a device owner type when there is no device owner");
+                return;
+            } else if (isDeviceOwnerTypeSetForDeviceOwner(packageName)) {
+                Slog.e(TAG, "Device owner type for " + packageName + " has already been set");
+                return;
+            }
+
+            mDeviceOwnerTypes.put(packageName, deviceOwnerType);
+            writeDeviceOwner();
+        }
+    }
+
+    @DeviceOwnerType
+    int getDeviceOwnerType(String packageName) {
+        synchronized (mLock) {
+            if (isDeviceOwnerTypeSetForDeviceOwner(packageName)) {
+                return mDeviceOwnerTypes.get(packageName);
+            }
+            return DEVICE_OWNER_TYPE_DEFAULT;
+        }
+    }
+
+    boolean isDeviceOwnerTypeSetForDeviceOwner(String packageName) {
+        synchronized (mLock) {
+            return !mDeviceOwnerTypes.isEmpty() && mDeviceOwnerTypes.containsKey(packageName);
+        }
+    }
+
     private boolean readLegacyOwnerFileLocked(File file) {
         if (!file.exists()) {
             // Already migrated or the device has no owners.
@@ -880,6 +924,16 @@
                 out.startTag(null, TAG_DEVICE_OWNER_CONTEXT);
                 out.attributeInt(null, ATTR_USERID, mDeviceOwnerUserId);
                 out.endTag(null, TAG_DEVICE_OWNER_CONTEXT);
+
+            }
+
+            if (!mDeviceOwnerTypes.isEmpty()) {
+                for (ArrayMap.Entry<String, Integer> entry : mDeviceOwnerTypes.entrySet()) {
+                    out.startTag(null, TAG_DEVICE_OWNER_TYPE);
+                    out.attribute(null, ATTR_PACKAGE, entry.getKey());
+                    out.attributeInt(null, ATTR_DEVICE_OWNER_TYPE_VALUE, entry.getValue());
+                    out.endTag(null, TAG_DEVICE_OWNER_TYPE);
+                }
             }
 
             if (mSystemUpdatePolicy != null) {
@@ -942,6 +996,12 @@
                         }
                     }
                     break;
+                case TAG_DEVICE_OWNER_TYPE:
+                    String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
+                    int deviceOwnerType = parser.getAttributeInt(null, ATTR_DEVICE_OWNER_TYPE_VALUE,
+                            DEVICE_OWNER_TYPE_DEFAULT);
+                    mDeviceOwnerTypes.put(packageName, deviceOwnerType);
+                    break;
                 default:
                     Slog.e(TAG, "Unexpected tag: " + tag);
                     return false;
diff --git a/services/incremental/Android.bp b/services/incremental/Android.bp
index 7534c7c..5ffbd77 100644
--- a/services/incremental/Android.bp
+++ b/services/incremental/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_defaults {
     name: "service.incremental-proto-defaults",
 
@@ -124,5 +133,8 @@
     ],
     static_libs: [
         "libgmock",
-    ]
+    ],
+    test_options: {
+        unit_test: true,
+    },
 }
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index 886c1e5..ce6e6ab 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -66,6 +66,8 @@
     static constexpr auto blockSize = 4096;
     static constexpr auto systemPackage = "android"sv;
 
+    static constexpr auto userStatusDelay = 100ms;
+
     static constexpr auto progressUpdateInterval = 1000ms;
     static constexpr auto perUidTimeoutOffset = progressUpdateInterval * 2;
     static constexpr auto minPerUidTimeout = progressUpdateInterval * 3;
@@ -1615,7 +1617,7 @@
     // Need a shared pointer: will be passing it into all unpacking jobs.
     std::shared_ptr<ZipArchive> zipFile(zipFileHandle, [](ZipArchiveHandle h) { CloseArchive(h); });
     void* cookie = nullptr;
-    const auto libFilePrefix = path::join(constants().libDir, abi) + "/";
+    const auto libFilePrefix = path::join(constants().libDir, abi) += "/";
     if (StartIteration(zipFile.get(), &cookie, libFilePrefix, constants().libSuffix)) {
         LOG(ERROR) << "Failed to start zip iteration for " << apkFullPath;
         return false;
@@ -1625,6 +1627,17 @@
 
     auto openZipTs = Clock::now();
 
+    auto mapFiles = (mIncFs->features() & incfs::Features::v2);
+    incfs::FileId sourceId;
+    if (mapFiles) {
+        sourceId = mIncFs->getFileId(ifs->control, apkFullPath);
+        if (!incfs::isValidFileId(sourceId)) {
+            LOG(WARNING) << "Error getting IncFS file ID for apk path '" << apkFullPath
+                         << "', mapping disabled";
+            mapFiles = false;
+        }
+    }
+
     std::vector<Job> jobQueue;
     ZipEntry entry;
     std::string_view fileName;
@@ -1633,13 +1646,16 @@
             continue;
         }
 
+        const auto entryUncompressed = entry.method == kCompressStored;
+        const auto entryPageAligned = (entry.offset & (constants().blockSize - 1)) == 0;
+
         if (!extractNativeLibs) {
             // ensure the file is properly aligned and unpacked
-            if (entry.method != kCompressStored) {
+            if (!entryUncompressed) {
                 LOG(WARNING) << "Library " << fileName << " must be uncompressed to mmap it";
                 return false;
             }
-            if ((entry.offset & (constants().blockSize - 1)) != 0) {
+            if (!entryPageAligned) {
                 LOG(WARNING) << "Library " << fileName
                              << " must be page-aligned to mmap it, offset = 0x" << std::hex
                              << entry.offset;
@@ -1663,6 +1679,28 @@
             continue;
         }
 
+        if (mapFiles && entryUncompressed && entryPageAligned && entry.uncompressed_length > 0) {
+            incfs::NewMappedFileParams mappedFileParams = {
+                    .sourceId = sourceId,
+                    .sourceOffset = entry.offset,
+                    .size = entry.uncompressed_length,
+            };
+
+            if (auto res = mIncFs->makeMappedFile(ifs->control, targetLibPathAbsolute, 0755,
+                                                  mappedFileParams);
+                res == 0) {
+                if (perfLoggingEnabled()) {
+                    auto doneTs = Clock::now();
+                    LOG(INFO) << "incfs: Mapped " << libName << ": "
+                              << elapsedMcs(startFileTs, doneTs) << "mcs";
+                }
+                continue;
+            } else {
+                LOG(WARNING) << "Failed to map file for: '" << targetLibPath << "' errno: " << res
+                             << "; falling back to full extraction";
+            }
+        }
+
         // Create new lib file without signature info
         incfs::NewFileParams libFileParams = {
                 .size = entry.uncompressed_length,
@@ -1671,7 +1709,7 @@
                 .metadata = {targetLibPath.c_str(), (IncFsSize)targetLibPath.size()},
         };
         incfs::FileId libFileId = idFromMetadata(targetLibPath);
-        if (auto res = mIncFs->makeFile(ifs->control, targetLibPathAbsolute, 0777, libFileId,
+        if (auto res = mIncFs->makeFile(ifs->control, targetLibPathAbsolute, 0755, libFileId,
                                         libFileParams)) {
             LOG(ERROR) << "Failed to make file for: " << targetLibPath << " errno: " << res;
             // If one lib file fails to be created, abort others as well
@@ -1898,25 +1936,33 @@
 }
 
 IncrementalService::LoadingProgress IncrementalService::getLoadingProgressFromPath(
-        const IncFsMount& ifs, std::string_view storagePath, bool stopOnFirstIncomplete) const {
-    ssize_t totalBlocks = 0, filledBlocks = 0;
-    const auto filePaths = mFs->listFilesRecursive(storagePath);
-    for (const auto& filePath : filePaths) {
+        const IncFsMount& ifs, std::string_view storagePath,
+        const bool stopOnFirstIncomplete) const {
+    ssize_t totalBlocks = 0, filledBlocks = 0, error = 0;
+    mFs->listFilesRecursive(storagePath, [&, this](auto filePath) {
         const auto [filledBlocksCount, totalBlocksCount] =
                 mIncFs->countFilledBlocks(ifs.control, filePath);
+        if (filledBlocksCount == -EOPNOTSUPP || filledBlocksCount == -ENOTSUP ||
+            filledBlocksCount == -ENOENT) {
+            // a kind of a file that's not really being loaded, e.g. a mapped range
+            // an older IncFS used to return ENOENT in this case, so handle it the same way
+            return true;
+        }
         if (filledBlocksCount < 0) {
             LOG(ERROR) << "getLoadingProgress failed to get filled blocks count for: " << filePath
                        << " errno: " << filledBlocksCount;
-            return {filledBlocksCount, filledBlocksCount};
+            error = filledBlocksCount;
+            return false;
         }
         totalBlocks += totalBlocksCount;
         filledBlocks += filledBlocksCount;
         if (stopOnFirstIncomplete && filledBlocks < totalBlocks) {
-            break;
+            return false;
         }
-    }
+        return true;
+    });
 
-    return {filledBlocks, totalBlocks};
+    return error ? LoadingProgress{error, error} : LoadingProgress{filledBlocks, totalBlocks};
 }
 
 bool IncrementalService::updateLoadingProgress(
@@ -2306,13 +2352,24 @@
         LOG(ERROR) << "Mount ID mismatch: expected " << id() << ", but got: " << mountId;
         return binder::Status::fromServiceSpecificError(-EPERM, "Mount ID mismatch.");
     }
+    if (newStatus == IDataLoaderStatusListener::DATA_LOADER_UNRECOVERABLE) {
+        // User-provided status, let's postpone the handling to avoid possible deadlocks.
+        mService.addTimedJob(*mService.mTimedQueue, id(), Constants::userStatusDelay,
+                             [this, newStatus]() { setCurrentStatus(newStatus); });
+        return binder::Status::ok();
+    }
 
+    setCurrentStatus(newStatus);
+    return binder::Status::ok();
+}
+
+void IncrementalService::DataLoaderStub::setCurrentStatus(int newStatus) {
     int targetStatus, oldStatus;
     DataLoaderStatusListener listener;
     {
         std::unique_lock lock(mMutex);
         if (mCurrentStatus == newStatus) {
-            return binder::Status::ok();
+            return;
         }
 
         oldStatus = mCurrentStatus;
@@ -2332,14 +2389,12 @@
                << newStatus << " (target " << targetStatus << ")";
 
     if (listener) {
-        listener->onStatusChanged(mountId, newStatus);
+        listener->onStatusChanged(id(), newStatus);
     }
 
     fsmStep();
 
     mStatusCondition.notify_all();
-
-    return binder::Status::ok();
 }
 
 binder::Status IncrementalService::DataLoaderStub::reportStreamHealth(MountId mountId,
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index 459ed32..d8f2c91 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -234,6 +234,8 @@
         binder::Status onStatusChanged(MountId mount, int newStatus) final;
         binder::Status reportStreamHealth(MountId mount, int newStatus) final;
 
+        void setCurrentStatus(int newStatus);
+
         sp<content::pm::IDataLoader> getDataLoader();
 
         bool bind();
diff --git a/services/incremental/ServiceWrappers.cpp b/services/incremental/ServiceWrappers.cpp
index 659d650..d613289 100644
--- a/services/incremental/ServiceWrappers.cpp
+++ b/services/incremental/ServiceWrappers.cpp
@@ -134,10 +134,11 @@
     } mLooper;
 };
 
-class RealIncFs : public IncFsWrapper {
+class RealIncFs final : public IncFsWrapper {
 public:
     RealIncFs() = default;
     ~RealIncFs() final = default;
+    Features features() const final { return incfs::features(); }
     void listExistingMounts(const ExistingMountCallback& cb) const final {
         for (auto mount : incfs::defaultMountRegistry().copyMounts()) {
             auto binds = mount.binds(); // span() doesn't like rvalue containers, needs to save it.
@@ -153,6 +154,10 @@
                        incfs::NewFileParams params) const final {
         return incfs::makeFile(control, path, mode, id, params);
     }
+    ErrorCode makeMappedFile(const Control& control, std::string_view path, int mode,
+                             incfs::NewMappedFileParams params) const final {
+        return incfs::makeMappedFile(control, path, mode, params);
+    }
     ErrorCode makeDir(const Control& control, std::string_view path, int mode) const final {
         return incfs::makeDir(control, path, mode);
     }
@@ -282,11 +287,10 @@
             auto it = mJobs.begin();
             // Always acquire begin(). We can't use it after unlock as mTimedJobs can change.
             for (; it != mJobs.end() && it->when <= now; it = mJobs.begin()) {
-                auto job = std::move(it->what);
-                mJobs.erase(it);
+                auto jobNode = mJobs.extract(it);
 
                 lock.unlock();
-                job();
+                jobNode.value().what();
                 lock.lock();
             }
             nextJobTs = it != mJobs.end() ? it->when : kInfinityTs;
@@ -308,20 +312,20 @@
     std::thread mThread;
 };
 
-class RealFsWrapper : public FsWrapper {
+class RealFsWrapper final : public FsWrapper {
 public:
     RealFsWrapper() = default;
     ~RealFsWrapper() = default;
 
-    std::vector<std::string> listFilesRecursive(std::string_view directoryPath) const final {
-        std::vector<std::string> files;
+    void listFilesRecursive(std::string_view directoryPath, FileCallback onFile) const final {
         for (const auto& entry : std::filesystem::recursive_directory_iterator(directoryPath)) {
             if (!entry.is_regular_file()) {
                 continue;
             }
-            files.push_back(entry.path().c_str());
+            if (!onFile(entry.path().native())) {
+                break;
+            }
         }
-        return files;
     }
 };
 
diff --git a/services/incremental/ServiceWrappers.h b/services/incremental/ServiceWrappers.h
index d60035a..245bb31 100644
--- a/services/incremental/ServiceWrappers.h
+++ b/services/incremental/ServiceWrappers.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <android-base/function_ref.h>
 #include <android-base/unique_fd.h>
 #include <android/content/pm/DataLoaderParamsParcel.h>
 #include <android/content/pm/FileSystemControlParcel.h>
@@ -77,18 +78,22 @@
     using ErrorCode = incfs::ErrorCode;
     using UniqueFd = incfs::UniqueFd;
     using WaitResult = incfs::WaitResult;
+    using Features = incfs::Features;
 
-    using ExistingMountCallback =
-            std::function<void(std::string_view root, std::string_view backingDir,
-                               std::span<std::pair<std::string_view, std::string_view>> binds)>;
+    using ExistingMountCallback = android::base::function_ref<
+            void(std::string_view root, std::string_view backingDir,
+                 std::span<std::pair<std::string_view, std::string_view>> binds)>;
 
     virtual ~IncFsWrapper() = default;
+    virtual Features features() const = 0;
     virtual void listExistingMounts(const ExistingMountCallback& cb) const = 0;
     virtual Control openMount(std::string_view path) const = 0;
     virtual Control createControl(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs,
                                   IncFsFd blocksWritten) const = 0;
     virtual ErrorCode makeFile(const Control& control, std::string_view path, int mode, FileId id,
                                incfs::NewFileParams params) const = 0;
+    virtual ErrorCode makeMappedFile(const Control& control, std::string_view path, int mode,
+                                     incfs::NewMappedFileParams params) const = 0;
     virtual ErrorCode makeDir(const Control& control, std::string_view path, int mode) const = 0;
     virtual ErrorCode makeDirs(const Control& control, std::string_view path, int mode) const = 0;
     virtual incfs::RawMetadata getMetadata(const Control& control, FileId fileid) const = 0;
@@ -148,7 +153,9 @@
 class FsWrapper {
 public:
     virtual ~FsWrapper() = default;
-    virtual std::vector<std::string> listFilesRecursive(std::string_view directoryPath) const = 0;
+
+    using FileCallback = android::base::function_ref<bool(std::string_view)>;
+    virtual void listFilesRecursive(std::string_view directoryPath, FileCallback onFile) const = 0;
 };
 
 class ServiceManagerWrapper {
diff --git a/services/incremental/TEST_MAPPING b/services/incremental/TEST_MAPPING
new file mode 100644
index 0000000..d935256
--- /dev/null
+++ b/services/incremental/TEST_MAPPING
@@ -0,0 +1,32 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsContentTestCases",
+      "options": [
+        {
+          "include-filter": "android.content.pm.cts.PackageManagerShellCommandTest"
+        },
+        {
+          "include-filter": "android.content.pm.cts.PackageManagerShellCommandIncrementalTest"
+        },
+        {
+          "include-filter": "android.content.pm.cts.ChecksumsTest"
+        }
+      ]
+    },
+    {
+      "name": "CtsPackageManagerStatsHostTestCases",
+      "options": [
+        {
+          "include-filter": "com.android.cts.packagemanager.stats.host.PackageInstallerV2StatsTests"
+        }
+      ]
+    },
+    {
+      "name": "CtsIncrementalInstallHostTestCases"
+    },
+    {
+      "name": "CtsInstalledLoadingProgressHostTests"
+    }
+  ]
+}
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index ab491ef..b00a84f 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -322,6 +322,7 @@
 
 class MockIncFs : public IncFsWrapper {
 public:
+    MOCK_CONST_METHOD0(features, Features());
     MOCK_CONST_METHOD1(listExistingMounts, void(const ExistingMountCallback& cb));
     MOCK_CONST_METHOD1(openMount, Control(std::string_view path));
     MOCK_CONST_METHOD4(createControl,
@@ -330,6 +331,9 @@
     MOCK_CONST_METHOD5(makeFile,
                        ErrorCode(const Control& control, std::string_view path, int mode, FileId id,
                                  NewFileParams params));
+    MOCK_CONST_METHOD4(makeMappedFile,
+                       ErrorCode(const Control& control, std::string_view path, int mode,
+                                 NewMappedFileParams params));
     MOCK_CONST_METHOD3(makeDir, ErrorCode(const Control& control, std::string_view path, int mode));
     MOCK_CONST_METHOD3(makeDirs,
                        ErrorCode(const Control& control, std::string_view path, int mode));
@@ -539,16 +543,16 @@
 
 class MockFsWrapper : public FsWrapper {
 public:
-    MOCK_CONST_METHOD1(listFilesRecursive, std::vector<std::string>(std::string_view));
-    void hasNoFile() {
-        ON_CALL(*this, listFilesRecursive(_)).WillByDefault(Return(std::vector<std::string>()));
-    }
+    MOCK_CONST_METHOD2(listFilesRecursive, void(std::string_view, FileCallback));
+    void hasNoFile() { ON_CALL(*this, listFilesRecursive(_, _)).WillByDefault(Return()); }
     void hasFiles() {
-        ON_CALL(*this, listFilesRecursive(_))
+        ON_CALL(*this, listFilesRecursive(_, _))
                 .WillByDefault(Invoke(this, &MockFsWrapper::fakeFiles));
     }
-    std::vector<std::string> fakeFiles(std::string_view directoryPath) {
-        return {"base.apk", "split.apk", "lib/a.so"};
+    void fakeFiles(std::string_view directoryPath, FileCallback onFile) {
+        for (auto file : {"base.apk", "split.apk", "lib/a.so"}) {
+            if (!onFile(file)) break;
+        }
     }
 };
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index dd2dd81..a3d3353 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -104,7 +104,6 @@
 import com.android.internal.widget.ILockSettings;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.appbinding.AppBindingService;
-import com.android.server.apphibernation.AppHibernationService;
 import com.android.server.attention.AttentionManagerService;
 import com.android.server.audio.AudioService;
 import com.android.server.biometrics.AuthService;
@@ -163,6 +162,7 @@
 import com.android.server.pm.UserManagerService;
 import com.android.server.pm.dex.SystemServerDexLoadReporter;
 import com.android.server.pm.verify.domain.DomainVerificationService;
+import com.android.server.policy.AppOpsPolicy;
 import com.android.server.policy.PermissionPolicyService;
 import com.android.server.policy.PhoneWindowManager;
 import com.android.server.policy.role.RoleServicePlatformHelperImpl;
@@ -1718,14 +1718,9 @@
             startTextToSpeechManagerService(context, t);
 
             // System Speech Recognition Service
-            if (deviceHasConfigString(context,
-                    R.string.config_defaultOnDeviceSpeechRecognitionService)) {
-                t.traceBegin("StartSpeechRecognitionManagerService");
-                mSystemServiceManager.startService(SPEECH_RECOGNITION_MANAGER_SERVICE_CLASS);
-                t.traceEnd();
-            } else {
-                Slog.d(TAG, "System speech recognition is not defined by OEM");
-            }
+            t.traceBegin("StartSpeechRecognitionManagerService");
+            mSystemServiceManager.startService(SPEECH_RECOGNITION_MANAGER_SERVICE_CLASS);
+            t.traceEnd();
 
             // App prediction manager service
             if (deviceHasConfigString(context, R.string.config_defaultAppPredictionService)) {
@@ -1785,7 +1780,7 @@
 
             t.traceBegin("StartIpSecService");
             try {
-                ipSecService = IpSecService.create(context, networkManagement);
+                ipSecService = IpSecService.create(context);
                 ServiceManager.addService(Context.IPSEC_SERVICE, ipSecService);
             } catch (Throwable e) {
                 reportWtf("starting IpSec Service", e);
@@ -2150,11 +2145,9 @@
             mSystemServiceManager.startService(VOICE_RECOGNITION_MANAGER_SERVICE_CLASS);
             t.traceEnd();
 
-            if (AppHibernationService.isAppHibernationEnabled()) {
-                t.traceBegin("StartAppHibernationService");
-                mSystemServiceManager.startService(APP_HIBERNATION_SERVICE_CLASS);
-                t.traceEnd();
-            }
+            t.traceBegin("StartAppHibernationService");
+            mSystemServiceManager.startService(APP_HIBERNATION_SERVICE_CLASS);
+            t.traceEnd();
 
             if (GestureLauncherService.isGestureLauncherEnabled(context.getResources())) {
                 t.traceBegin("StartGestureLauncher");
@@ -2664,6 +2657,14 @@
             }
             t.traceEnd();
 
+            t.traceBegin("RegisterAppOpsPolicy");
+            try {
+                mActivityManagerService.setAppOpsPolicy(new AppOpsPolicy());
+            } catch (Throwable e) {
+                reportWtf("registering app ops policy", e);
+            }
+            t.traceEnd();
+
             // No dependency on Webview preparation in system server. But this should
             // be completed before allowing 3rd party
             final String WEBVIEW_PREPARATION = "WebViewFactoryPreparation";
diff --git a/services/midi/Android.bp b/services/midi/Android.bp
index 013f23d..5adcfba 100644
--- a/services/midi/Android.bp
+++ b/services/midi/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.midi-sources",
     srcs: ["java/**/*.java"],
diff --git a/services/musicrecognition/Android.bp b/services/musicrecognition/Android.bp
index fea9efa..8298dec 100644
--- a/services/musicrecognition/Android.bp
+++ b/services/musicrecognition/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.musicsearch-sources",
     srcs: ["java/**/*.java"],
@@ -10,4 +19,4 @@
     defaults: ["platform_service_defaults"],
     srcs: [":services.musicsearch-sources"],
     libs: ["services.core", "app-compat-annotations"],
-}
\ No newline at end of file
+}
diff --git a/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerPerUserService.java b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerPerUserService.java
index 0cb729d..87b2c84 100644
--- a/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerPerUserService.java
+++ b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerPerUserService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.musicrecognition;
 
+import static android.Manifest.permission.RECORD_AUDIO;
 import static android.media.musicrecognition.MusicRecognitionManager.RECOGNITION_FAILED_AUDIO_UNAVAILABLE;
 import static android.media.musicrecognition.MusicRecognitionManager.RECOGNITION_FAILED_SERVICE_KILLED;
 import static android.media.musicrecognition.MusicRecognitionManager.RECOGNITION_FAILED_SERVICE_UNAVAILABLE;
@@ -25,6 +26,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AppGlobals;
+import android.app.AppOpsManager;
 import android.content.ComponentName;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
@@ -45,6 +47,7 @@
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.util.Objects;
 
 /**
  * Handles per-user requests received by
@@ -64,11 +67,20 @@
     @Nullable
     @GuardedBy("mLock")
     private RemoteMusicRecognitionService mRemoteService;
+    private final AppOpsManager mAppOpsManager;
+
+    private String mAttributionTag;
+    private String mAttributionMessage;
+    private ServiceInfo mServiceInfo;
 
     MusicRecognitionManagerPerUserService(
             @NonNull MusicRecognitionManagerService primary,
             @NonNull Object lock, int userId) {
         super(primary, lock, userId);
+        mAppOpsManager = getContext().getSystemService(AppOpsManager.class);
+        mAttributionMessage = String.format("MusicRecognitionManager.invokedByUid.%s", userId);
+        mAttributionTag = null;
+        mServiceInfo = null;
     }
 
     @NonNull
@@ -114,6 +126,13 @@
                     new MusicRecognitionServiceCallback(clientCallback),
                     mMaster.isBindInstantServiceAllowed(),
                     mMaster.verbose);
+            try {
+                mServiceInfo =
+                        getContext().getPackageManager().getServiceInfo(
+                                mRemoteService.getComponentName(), 0);
+            } catch (PackageManager.NameNotFoundException e) {
+                Slog.e(TAG, "Service was not found.", e);
+            }
         }
 
         return mRemoteService;
@@ -127,12 +146,8 @@
     public void beginRecognitionLocked(
             @NonNull RecognitionRequest recognitionRequest,
             @NonNull IBinder callback) {
-        int maxAudioLengthSeconds = Math.min(recognitionRequest.getMaxAudioLengthSeconds(),
-                MAX_STREAMING_SECONDS);
         IMusicRecognitionManagerCallback clientCallback =
                 IMusicRecognitionManagerCallback.Stub.asInterface(callback);
-        AudioRecord audioRecord = createAudioRecord(recognitionRequest, maxAudioLengthSeconds);
-
         mRemoteService = ensureRemoteServiceLocked(clientCallback);
         if (mRemoteService == null) {
             try {
@@ -158,52 +173,92 @@
         ParcelFileDescriptor clientRead = clientPipe.first;
 
         mMaster.mExecutorService.execute(() -> {
-            try (OutputStream fos =
-                        new ParcelFileDescriptor.AutoCloseOutputStream(audioSink)) {
-                int halfSecondBufferSize =
-                        audioRecord.getBufferSizeInFrames() / maxAudioLengthSeconds;
-                byte[] byteBuffer = new byte[halfSecondBufferSize];
-                int bytesRead = 0;
-                int totalBytesRead = 0;
-                int ignoreBytes =
-                        recognitionRequest.getIgnoreBeginningFrames() * BYTES_PER_SAMPLE;
-                audioRecord.startRecording();
-                while (bytesRead >= 0 && totalBytesRead
-                        < audioRecord.getBufferSizeInFrames() * BYTES_PER_SAMPLE
-                        && mRemoteService != null) {
-                    bytesRead = audioRecord.read(byteBuffer, 0, byteBuffer.length);
-                    if (bytesRead > 0) {
-                        totalBytesRead += bytesRead;
-                        // If we are ignoring the first x bytes, update that counter.
-                        if (ignoreBytes > 0) {
-                            ignoreBytes -= bytesRead;
-                            // If we've dipped negative, we've skipped through all ignored bytes
-                            // and then some.  Write out the bytes we shouldn't have skipped.
-                            if (ignoreBytes < 0) {
-                                fos.write(byteBuffer, bytesRead + ignoreBytes, -ignoreBytes);
-                            }
-                        } else {
-                            fos.write(byteBuffer);
-                        }
-                    }
-                }
-                Slog.i(TAG, String.format("Streamed %s bytes from audio record", totalBytesRead));
-            } catch (IOException e) {
-                Slog.e(TAG, "Audio streaming stopped.", e);
-            } finally {
-                audioRecord.release();
-                try {
-                    clientCallback.onAudioStreamClosed();
-                } catch (RemoteException ignored) {
-                    // Ignored.
-                }
-            }
+            streamAudio(recognitionRequest, clientCallback, audioSink);
         });
         // Send the pipe down to the lookup service while we write to it asynchronously.
         mRemoteService.writeAudioToPipe(clientRead, recognitionRequest.getAudioFormat());
     }
 
     /**
+     * Streams audio based on given request to the given audioSink. Notifies callback of errors.
+     *
+     * @param recognitionRequest the recognition request specifying audio parameters.
+     * @param clientCallback the callback to notify on errors.
+     * @param audioSink the sink to which to stream audio to.
+     */
+    private void streamAudio(@NonNull RecognitionRequest recognitionRequest,
+            IMusicRecognitionManagerCallback clientCallback, ParcelFileDescriptor audioSink) {
+        try {
+            startRecordAudioOp();
+        } catch (SecurityException e) {
+            // A security exception can occur if the MusicRecognitionService (receiving the audio)
+            // does not (or does no longer) hold the necessary permissions to record audio.
+            Slog.e(TAG, "RECORD_AUDIO op not permitted on behalf of "
+                    + mServiceInfo.getComponentName(), e);
+            try {
+                clientCallback.onRecognitionFailed(
+                        RECOGNITION_FAILED_AUDIO_UNAVAILABLE);
+            } catch (RemoteException ignored) {
+                // Ignored.
+            }
+            return;
+        }
+
+        int maxAudioLengthSeconds = Math.min(recognitionRequest.getMaxAudioLengthSeconds(),
+                MAX_STREAMING_SECONDS);
+        AudioRecord audioRecord = createAudioRecord(recognitionRequest, maxAudioLengthSeconds);
+        try (OutputStream fos =
+                     new ParcelFileDescriptor.AutoCloseOutputStream(audioSink)) {
+            streamAudio(recognitionRequest, maxAudioLengthSeconds, audioRecord, fos);
+        } catch (IOException e) {
+            Slog.e(TAG, "Audio streaming stopped.", e);
+        } finally {
+            audioRecord.release();
+            finishRecordAudioOp();
+            try {
+                clientCallback.onAudioStreamClosed();
+            } catch (RemoteException ignored) {
+                // Ignored.
+            }
+        }
+    }
+
+    /** Performs the actual streaming from audioRecord into outputStream. **/
+    private void streamAudio(@NonNull RecognitionRequest recognitionRequest,
+            int maxAudioLengthSeconds, AudioRecord audioRecord, OutputStream outputStream)
+            throws IOException {
+        int halfSecondBufferSize =
+                audioRecord.getBufferSizeInFrames() / maxAudioLengthSeconds;
+        byte[] byteBuffer = new byte[halfSecondBufferSize];
+        int bytesRead = 0;
+        int totalBytesRead = 0;
+        int ignoreBytes =
+                recognitionRequest.getIgnoreBeginningFrames() * BYTES_PER_SAMPLE;
+        audioRecord.startRecording();
+        while (bytesRead >= 0 && totalBytesRead
+                < audioRecord.getBufferSizeInFrames() * BYTES_PER_SAMPLE
+                && mRemoteService != null) {
+            bytesRead = audioRecord.read(byteBuffer, 0, byteBuffer.length);
+            if (bytesRead > 0) {
+                totalBytesRead += bytesRead;
+                // If we are ignoring the first x bytes, update that counter.
+                if (ignoreBytes > 0) {
+                    ignoreBytes -= bytesRead;
+                    // If we've dipped negative, we've skipped through all ignored bytes
+                    // and then some.  Write out the bytes we shouldn't have skipped.
+                    if (ignoreBytes < 0) {
+                        outputStream.write(byteBuffer, bytesRead + ignoreBytes, -ignoreBytes);
+                    }
+                } else {
+                    outputStream.write(byteBuffer);
+                }
+            }
+        }
+        Slog.i(TAG,
+                String.format("Streamed %s bytes from audio record", totalBytesRead));
+    }
+
+    /**
      * Callback invoked by {@link android.service.musicrecognition.MusicRecognitionService} to pass
      * back the music search result.
      */
@@ -264,6 +319,29 @@
         }
     }
 
+    /**
+     * Tracks that the RECORD_AUDIO operation started (attributes it to the service receiving the
+     * audio).
+     */
+    private void startRecordAudioOp() {
+        mAppOpsManager.startProxyOp(
+                Objects.requireNonNull(AppOpsManager.permissionToOp(RECORD_AUDIO)),
+                mServiceInfo.applicationInfo.uid,
+                mServiceInfo.packageName,
+                mAttributionTag,
+                mAttributionMessage);
+    }
+
+
+    /** Tracks that the RECORD_AUDIO operation finished. */
+    private void finishRecordAudioOp() {
+        mAppOpsManager.finishProxyOp(
+                Objects.requireNonNull(AppOpsManager.permissionToOp(RECORD_AUDIO)),
+                mServiceInfo.applicationInfo.uid,
+                mServiceInfo.packageName,
+                mAttributionTag);
+    }
+
     /** Establishes an audio stream from the DSP audio source. */
     private static AudioRecord createAudioRecord(
             @NonNull RecognitionRequest recognitionRequest,
diff --git a/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerService.java b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerService.java
index 38f43138..e145d33 100644
--- a/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerService.java
+++ b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerService.java
@@ -45,7 +45,7 @@
 import java.util.concurrent.Executors;
 
 /**
- * Service which allows a DSP audio event to be securely streamed to a designated {@link
+ * Service which allows audio to be securely streamed to a designated {@link
  * MusicRecognitionService}.
  */
 public class MusicRecognitionManagerService extends
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 7036ccf..b01e425 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.net-sources",
     srcs: ["java/**/*.java"],
@@ -43,6 +52,7 @@
     libs: [
         "unsupportedappusage",
         "framework-wifi-util-lib",
+        "framework-connectivity"
     ],
     static_libs: [
         // All the classes in netd_aidl_interface must be jarjar so they do not conflict with the
diff --git a/services/people/Android.bp b/services/people/Android.bp
index 9bdf488..c0188ec 100644
--- a/services/people/Android.bp
+++ b/services/people/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library_static {
     name: "services.people",
     defaults: ["platform_service_defaults"],
diff --git a/services/print/Android.bp b/services/print/Android.bp
index be5f082..5b4349a 100644
--- a/services/print/Android.bp
+++ b/services/print/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.print-sources",
     srcs: ["java/**/*.java"],
diff --git a/services/profcollect/Android.bp b/services/profcollect/Android.bp
index 7f5f623..2040bb6 100644
--- a/services/profcollect/Android.bp
+++ b/services/profcollect/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
   name: "services.profcollect-javasources",
   srcs: ["src/**/*.java"],
diff --git a/services/restrictions/Android.bp b/services/restrictions/Android.bp
index 60d161d..62316f1 100644
--- a/services/restrictions/Android.bp
+++ b/services/restrictions/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.restrictions-sources",
     srcs: ["java/**/*.java"],
diff --git a/services/robotests/Android.bp b/services/robotests/Android.bp
index 1ae2aec..52eae21 100644
--- a/services/robotests/Android.bp
+++ b/services/robotests/Android.bp
@@ -16,6 +16,15 @@
 // FrameworksServicesLib app just for Robolectric test target      #
 //##################################################################
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "FrameworksServicesLib",
     platform_apis: true,
diff --git a/services/robotests/backup/Android.bp b/services/robotests/backup/Android.bp
index 32587ac..506e156 100644
--- a/services/robotests/backup/Android.bp
+++ b/services/robotests/backup/Android.bp
@@ -15,6 +15,15 @@
 //##################################################################
 // BackupFrameworksServicesLib app just for Robolectric test target      #
 //##################################################################
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "BackupFrameworksServicesLib",
     platform_apis: true,
diff --git a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java
index cbebe69..2219d47 100644
--- a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java
@@ -38,7 +38,6 @@
 
 import android.annotation.UserIdInt;
 import android.app.Application;
-import android.app.backup.BackupManager.OperationType;
 import android.app.backup.IBackupManagerMonitor;
 import android.app.backup.IBackupObserver;
 import android.app.backup.IFullBackupRestoreObserver;
@@ -874,8 +873,7 @@
                 SecurityException.class,
                 () ->
                         backupManagerService.requestBackup(
-                                mUserTwoId, packages, observer, monitor, 0,
-                                OperationType.BACKUP));
+                                mUserTwoId, packages, observer, monitor, 0));
     }
 
     /**
@@ -893,11 +891,9 @@
         IBackupManagerMonitor monitor = mock(IBackupManagerMonitor.class);
         setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ true);
 
-        backupManagerService.requestBackup(mUserTwoId, packages, observer, monitor, /* flags */ 0,
-                OperationType.BACKUP);
+        backupManagerService.requestBackup(mUserTwoId, packages, observer, monitor, /* flags */ 0);
 
-        verify(mUserTwoService).requestBackup(packages, observer, monitor, /* flags */ 0,
-                OperationType.BACKUP);
+        verify(mUserTwoService).requestBackup(packages, observer, monitor, /* flags */ 0);
     }
 
     /** Test that the backup service routes methods correctly to the user that requests it. */
@@ -910,11 +906,9 @@
         IBackupManagerMonitor monitor = mock(IBackupManagerMonitor.class);
         setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
 
-        backupManagerService.requestBackup(mUserOneId, packages, observer, monitor, /* flags */ 0,
-                OperationType.BACKUP);
+        backupManagerService.requestBackup(mUserOneId, packages, observer, monitor, /* flags */ 0);
 
-        verify(mUserOneService).requestBackup(packages, observer, monitor, /* flags */ 0,
-                OperationType.BACKUP);
+        verify(mUserOneService).requestBackup(packages, observer, monitor, /* flags */ 0);
     }
 
     /** Test that the backup service routes methods correctly to the user that requests it. */
@@ -927,11 +921,9 @@
         IBackupManagerMonitor monitor = mock(IBackupManagerMonitor.class);
         setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
 
-        backupManagerService.requestBackup(mUserTwoId, packages, observer, monitor, /* flags */ 0,
-                OperationType.BACKUP);
+        backupManagerService.requestBackup(mUserTwoId, packages, observer, monitor, /* flags */ 0);
 
-        verify(mUserOneService, never()).requestBackup(packages, observer, monitor, /* flags */ 0,
-                OperationType.BACKUP);
+        verify(mUserOneService, never()).requestBackup(packages, observer, monitor, /* flags */ 0);
     }
 
     /**
@@ -1092,11 +1084,9 @@
         registerUser(backupManagerService, mUserOneId, mUserOneService);
         setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
 
-        backupManagerService.beginRestoreSession(mUserOneId, TEST_PACKAGE, TEST_TRANSPORT,
-                OperationType.BACKUP);
+        backupManagerService.beginRestoreSession(mUserOneId, TEST_PACKAGE, TEST_TRANSPORT);
 
-        verify(mUserOneService).beginRestoreSession(TEST_PACKAGE, TEST_TRANSPORT,
-                OperationType.BACKUP);
+        verify(mUserOneService).beginRestoreSession(TEST_PACKAGE, TEST_TRANSPORT);
     }
 
     /** Test that the backup service does not route methods for non-registered users. */
@@ -1106,11 +1096,9 @@
         registerUser(backupManagerService, mUserOneId, mUserOneService);
         setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
 
-        backupManagerService.beginRestoreSession(mUserTwoId, TEST_PACKAGE, TEST_TRANSPORT,
-                OperationType.BACKUP);
+        backupManagerService.beginRestoreSession(mUserTwoId, TEST_PACKAGE, TEST_TRANSPORT);
 
-        verify(mUserOneService, never()).beginRestoreSession(TEST_PACKAGE, TEST_TRANSPORT,
-                OperationType.BACKUP);
+        verify(mUserOneService, never()).beginRestoreSession(TEST_PACKAGE, TEST_TRANSPORT);
     }
 
     /** Test that the backup service routes methods correctly to the user that requests it. */
diff --git a/services/searchui/Android.bp b/services/searchui/Android.bp
index cc63294..3081a51 100644
--- a/services/searchui/Android.bp
+++ b/services/searchui/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.searchui-sources",
     srcs: ["java/**/*.java"],
diff --git a/services/smartspace/Android.bp b/services/smartspace/Android.bp
index fcf780d..640a88d 100644
--- a/services/smartspace/Android.bp
+++ b/services/smartspace/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.smartspace-sources",
     srcs: ["java/**/*.java"],
diff --git a/services/startop/Android.bp b/services/startop/Android.bp
index 157408f..c56c463 100644
--- a/services/startop/Android.bp
+++ b/services/startop/Android.bp
@@ -14,6 +14,17 @@
  * limitations under the License.
  */
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library_static {
     name: "services.startop",
     defaults: ["platform_service_defaults"],
diff --git a/services/systemcaptions/Android.bp b/services/systemcaptions/Android.bp
index 54a5a79..4cb58cb 100644
--- a/services/systemcaptions/Android.bp
+++ b/services/systemcaptions/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.systemcaptions-sources",
     srcs: ["java/**/*.java"],
diff --git a/services/tests/PackageManagerComponentOverrideTests/Android.bp b/services/tests/PackageManagerComponentOverrideTests/Android.bp
index a2668a1..19fdf60 100644
--- a/services/tests/PackageManagerComponentOverrideTests/Android.bp
+++ b/services/tests/PackageManagerComponentOverrideTests/Android.bp
@@ -17,6 +17,15 @@
 // NOTE: This test is separate from service tests since it relies on same vs different calling UID,
 // and this is more representative of a real caller. It also uses Mockito extended, and this
 // prevents converting the entire services test module.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "PackageManagerComponentOverrideTests",
     srcs: [
diff --git a/services/tests/PackageManagerServiceTests/host/Android.bp b/services/tests/PackageManagerServiceTests/host/Android.bp
index a941331..06313da 100644
--- a/services/tests/PackageManagerServiceTests/host/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_test_host {
     name: "PackageManagerServiceHostTests",
     srcs: ["src/**/*.kt"],
diff --git a/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/Android.bp b/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/Android.bp
index b7a0624..e70a734 100644
--- a/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library {
     name: "PackageManagerServiceHostTestsIntentVerifyUtils",
     srcs: ["src/**/*.kt"],
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
index af0ac77..7e4f0e7 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "PackageManagerServiceDeviceSideTests",
     sdk_version: "test_current",
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/Generic/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/Android.bp
index 4a3076e..1cc7ccc 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/Generic/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "PackageManagerTestAppStub",
     manifest: "AndroidManifestVersion1.xml",
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/Android.bp
index e82f57d..4f3f2eb 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "PackageManagerTestIntentVerifier",
     srcs: [ "src/**/*.kt" ],
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/Android.bp
index 7161fdd..9f9ed24 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "PackageManagerTestIntentVerifierTarget1",
     manifest: "AndroidManifest1.xml",
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/Android.bp
index 58f17f2..ebad5af 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "PackageManagerTestAppDeclaresStaticLibrary",
     manifest: "AndroidManifestDeclaresStaticLibrary.xml",
diff --git a/services/tests/PackageManagerServiceTests/unit/Android.bp b/services/tests/PackageManagerServiceTests/unit/Android.bp
index 4aa8abc..334e53a 100644
--- a/services/tests/PackageManagerServiceTests/unit/Android.bp
+++ b/services/tests/PackageManagerServiceTests/unit/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "PackageManagerServiceUnitTests",
     srcs: ["src/**/*.kt"],
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationCollectorTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationCollectorTest.kt
index e99b071..0fa9a1d 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationCollectorTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationCollectorTest.kt
@@ -52,8 +52,10 @@
         val collector = mockCollector()
         assertThat(collector.collectAllWebDomains(pkg))
                 .containsExactly("example1.com", "example2.com", "example3.com")
-        assertThat(collector.collectAutoVerifyDomains(pkg))
+        assertThat(collector.collectValidAutoVerifyDomains(pkg))
                 .containsExactly("example1.com", "example2.com", "example3.com", "example4.com")
+        assertThat(collector.collectInvalidAutoVerifyDomains(pkg))
+                .containsExactly("invalid1", "invalid2", "invalid3", "invalid4")
     }
 
     @Test
@@ -62,7 +64,8 @@
         val collector = mockCollector()
         assertThat(collector.collectAllWebDomains(pkg))
                 .containsExactly("example1.com", "example2.com", "example3.com")
-        assertThat(collector.collectAutoVerifyDomains(pkg)).isEmpty()
+        assertThat(collector.collectValidAutoVerifyDomains(pkg)).isEmpty()
+        assertThat(collector.collectInvalidAutoVerifyDomains(pkg)).isEmpty()
     }
 
     @Test
@@ -71,8 +74,10 @@
         val collector = mockCollector(linkedApps = setOf(TEST_PKG_NAME))
         assertThat(collector.collectAllWebDomains(pkg))
                 .containsExactly("example1.com", "example2.com", "example3.com")
-        assertThat(collector.collectAutoVerifyDomains(pkg))
+        assertThat(collector.collectValidAutoVerifyDomains(pkg))
                 .containsExactly("example1.com", "example2.com", "example3.com", "example4.com")
+        assertThat(collector.collectInvalidAutoVerifyDomains(pkg))
+                .containsExactly("invalid1", "invalid2", "invalid3", "invalid4")
     }
 
     @Test
@@ -92,6 +97,7 @@
                                     addDataScheme("https")
                                     addDataPath("/sub", PatternMatcher.PATTERN_LITERAL)
                                     addDataAuthority("example1.com", null)
+                                    addDataAuthority("invalid1", null)
                                 }
                         )
                     },
@@ -111,6 +117,7 @@
                                     addDataScheme("nonWebScheme")
                                     addDataPath("/sub", PatternMatcher.PATTERN_LITERAL)
                                     addDataAuthority("example2.com", null)
+                                    addDataAuthority("invalid2", null)
                                 }
                         )
                     },
@@ -122,7 +129,8 @@
         val collector = mockCollector()
         assertThat(collector.collectAllWebDomains(pkg))
                 .containsExactly("example1.com", "example2.com")
-        assertThat(collector.collectAutoVerifyDomains(pkg)).isEmpty()
+        assertThat(collector.collectValidAutoVerifyDomains(pkg)).isEmpty()
+        assertThat(collector.collectInvalidAutoVerifyDomains(pkg)).isEmpty()
     }
 
     @Test
@@ -132,8 +140,10 @@
 
         assertThat(collector.collectAllWebDomains(pkg))
                 .containsExactly("example1.com", "example2.com", "example3.com")
-        assertThat(collector.collectAutoVerifyDomains(pkg))
+        assertThat(collector.collectValidAutoVerifyDomains(pkg))
                 .containsExactly("example1.com", "example3.com")
+        assertThat(collector.collectInvalidAutoVerifyDomains(pkg))
+                .containsExactly("invalid1", "invalid3")
     }
 
     @Test
@@ -143,7 +153,8 @@
 
         assertThat(collector.collectAllWebDomains(pkg))
                 .containsExactly("example1.com", "example2.com", "example3.com")
-        assertThat(collector.collectAutoVerifyDomains(pkg)).isEmpty()
+        assertThat(collector.collectValidAutoVerifyDomains(pkg)).isEmpty()
+        assertThat(collector.collectInvalidAutoVerifyDomains(pkg)).isEmpty()
     }
 
     @Test
@@ -153,7 +164,8 @@
 
         assertThat(collector.collectAllWebDomains(pkg))
                 .containsExactly("example1.com", "example2.com", "example3.com")
-        assertThat(collector.collectAutoVerifyDomains(pkg)).isEmpty()
+        assertThat(collector.collectValidAutoVerifyDomains(pkg)).isEmpty()
+        assertThat(collector.collectInvalidAutoVerifyDomains(pkg)).isEmpty()
     }
 
     private fun mockCollector(linkedApps: Set<String> = emptySet()): DomainVerificationCollector {
@@ -178,6 +190,7 @@
                     <data android:scheme="https"/>
                     <data android:path="/sub"/>
                     <data android:host="example1.com"/>
+                    <data android:host="invalid1"/>
                 </intent-filter>
                 <intent-filter>
                     <action android:name="android.intent.action.VIEW"/>
@@ -186,6 +199,7 @@
                     <data android:scheme="http"/>
                     <data android:path="/sub2"/>
                     <data android:host="example2.com"/>
+                    <data android:host="invalid2."/>
                 </intent-filter>
                 <intent-filter android:autoVerify="$autoVerify">
                     <action android:name="android.intent.action.VIEW"/>
@@ -194,6 +208,7 @@
                     <data android:scheme="https"/>
                     <data android:path="/sub3"/>
                     <data android:host="example3.com"/>
+                    <data android:host=".invalid3"/>
                 </intent-filter>
                 <intent-filter android:autoVerify="$autoVerify">
                     <action android:name="android.intent.action.VIEW"/>
@@ -201,6 +216,7 @@
                     <data android:scheme="https"/>
                     <data android:path="/sub4"/>
                     <data android:host="example4.com"/>
+                    <data android:host="invalid4"/>
                 </intent-filter>
                 <intent-filter android:autoVerify="$autoVerify">
                     <action android:name="android.intent.action.VIEW"/>
@@ -208,6 +224,7 @@
                     <data android:scheme="https"/>
                     <data android:path="/sub5"/>
                     <data android:host="example5.com"/>
+                    <data android:host="invalid5"/>
                 </intent-filter>
                 <intent-filter android:autoVerify="$autoVerify">
                     <category android:name="android.intent.category.BROWSABLE"/>
@@ -215,11 +232,12 @@
                     <data android:scheme="https"/>
                     <data android:path="/sub5"/>
                     <data android:host="example5.com"/>
+                    <data android:host="invalid5"/>
                 </intent-filter>
             </xml>
         """.trimIndent()
 
-        return mockThrowOnUnmocked<AndroidPackage> {
+        return mockThrowOnUnmocked {
             whenever(packageName) { TEST_PKG_NAME }
             whenever(targetSdkVersion) {
                 if (useV2) Build.VERSION_CODES.S else Build.VERSION_CODES.R
@@ -238,6 +256,7 @@
                                     addDataScheme("https")
                                     addDataPath("/sub", PatternMatcher.PATTERN_LITERAL)
                                     addDataAuthority("example1.com", null)
+                                    addDataAuthority("invalid1", null)
                                 }
                         )
                         addIntent(
@@ -248,6 +267,7 @@
                                     addDataScheme("http")
                                     addDataPath("/sub2", PatternMatcher.PATTERN_LITERAL)
                                     addDataAuthority("example2.com", null)
+                                    addDataAuthority("invalid2", null)
                                 }
                         )
                     },
@@ -261,6 +281,7 @@
                                     addDataScheme("https")
                                     addDataPath("/sub3", PatternMatcher.PATTERN_LITERAL)
                                     addDataAuthority("example3.com", null)
+                                    addDataAuthority("invalid3", null)
                                 }
                         )
                     },
@@ -273,6 +294,7 @@
                                     addDataScheme("https")
                                     addDataPath("/sub4", PatternMatcher.PATTERN_LITERAL)
                                     addDataAuthority("example4.com", null)
+                                    addDataAuthority("invalid4", null)
                                 }
                         )
                         addIntent(
@@ -283,6 +305,7 @@
                                     addDataScheme("https")
                                     addDataPath("/sub5", PatternMatcher.PATTERN_LITERAL)
                                     addDataAuthority("example5.com", null)
+                                    addDataAuthority("invalid5", null)
                                 }
                         )
                         addIntent(
@@ -293,6 +316,7 @@
                                     addDataScheme("https")
                                     addDataPath("/sub6", PatternMatcher.PATTERN_LITERAL)
                                     addDataAuthority("example6.com", null)
+                                    addDataAuthority("invalid6", null)
                                 }
                         )
                     },
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationCoreApiTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationCoreApiTest.kt
index deb3147..9447f39 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationCoreApiTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationCoreApiTest.kt
@@ -16,8 +16,9 @@
 
 package com.android.server.pm.test.verify.domain
 
-import android.content.pm.verify.domain.DomainVerificationRequest
+import android.content.pm.verify.domain.DomainSet
 import android.content.pm.verify.domain.DomainVerificationInfo
+import android.content.pm.verify.domain.DomainVerificationRequest
 import android.content.pm.verify.domain.DomainVerificationUserSelection
 import android.os.Parcel
 import android.os.Parcelable
@@ -27,6 +28,7 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 import java.util.UUID
+import kotlin.random.Random
 
 @RunWith(Parameterized::class)
 class DomainVerificationCoreApiTest {
@@ -40,18 +42,25 @@
             assertThat(value).containsExactlyEntriesIn(other)
         }
 
+        private val massiveSet by lazy {
+            val fragmentOf21 = ".com.example.test.app"
+            val list = mutableListOf("prefix$fragmentOf21")
+            var totalSize = 0
+            // Slightly overshoot a size of 1MB
+            while (totalSize < (1024 * 512)) {
+                val nextValue = "${list.last()}$fragmentOf21"
+                totalSize += nextValue.length
+                list += nextValue
+            }
+            list.toSet()
+        }
+
         @JvmStatic
-        @Parameterized.Parameters
+        @Parameterized.Parameters(name = "{0}")
         fun parameters() = arrayOf(
             Parameter(
-                initial = {
-                    DomainVerificationRequest(
-                        setOf(
-                            "com.test.pkg.one",
-                            "com.test.pkg.two"
-                        )
-                    )
-                },
+                testName = "DomainVerificationRequest",
+                initial = { DomainVerificationRequest(massiveSet) },
                 unparcel = { DomainVerificationRequest.CREATOR.createFromParcel(it) },
                 assertion = { first, second ->
                     assertAll<DomainVerificationRequest, Set<String>>(first, second,
@@ -61,15 +70,12 @@
                 }
             ),
             Parameter(
+                testName = "DomainVerificationInfo",
                 initial = {
                     DomainVerificationInfo(
                         UUID.fromString("703f6d34-6241-4cfd-8176-2e1d23355811"),
                         "com.test.pkg",
-                        mapOf(
-                            "example.com" to 0,
-                            "example.org" to 1,
-                            "example.new" to 1000
-                        )
+                        massiveSet.withIndex().associate { it.value to it.index }
                     )
                 },
                 unparcel = { DomainVerificationInfo.CREATOR.createFromParcel(it) },
@@ -86,17 +92,15 @@
                 }
             ),
             Parameter(
+                testName = "DomainVerificationUserSelection",
                 initial = {
                     DomainVerificationUserSelection(
                         UUID.fromString("703f6d34-6241-4cfd-8176-2e1d23355811"),
                         "com.test.pkg",
                         UserHandle.of(10),
                         true,
-                        mapOf(
-                            "example.com" to true,
-                            "example.org" to false,
-                            "example.new" to true
-                        )
+                        massiveSet.withIndex()
+                            .associate { it.value to (it.index % 3) }
                     )
                 },
                 unparcel = { DomainVerificationUserSelection.CREATOR.createFromParcel(it) },
@@ -114,21 +118,35 @@
                         first, second, { it.isLinkHandlingAllowed },
                         { it.component4() }, IS_EQUAL_TO
                     )
-                    assertAll<DomainVerificationUserSelection, Map<String, Boolean>>(
-                        first, second, { it.hostToUserSelectionMap },
+                    assertAll<DomainVerificationUserSelection, Map<String, Int>>(
+                        first, second, { it.hostToStateMap },
                         { it.component5() }, IS_MAP_EQUAL_TO
                     )
                 }
+            ),
+            Parameter(
+                testName = "DomainSet",
+                initial = { DomainSet(massiveSet) },
+                unparcel = { DomainSet.CREATOR.createFromParcel(it) },
+                assertion = { first, second ->
+                    assertAll<DomainSet, Set<String>>(
+                        first, second,
+                        { it.domains }, assertion = IS_EQUAL_TO
+                    )
+                }
             )
         )
 
         class Parameter<T : Parcelable>(
+            val testName: String,
             val initial: () -> T,
             val unparcel: (Parcel) -> T,
             private val assertion: (first: T, second: T) -> Unit
         ) {
             @Suppress("UNCHECKED_CAST")
             fun assert(first: Any, second: Any) = assertion(first as T, second as T)
+
+            override fun toString() = testName
         }
 
         private fun <T> assertAll(vararg values: T, block: (value: T, other: T) -> Unit) {
@@ -141,11 +159,17 @@
             first: T,
             second: T,
             fieldValue: (T) -> V,
-            componentValue: (T) -> V,
+            componentValue: ((T) -> V)? = null,
             assertion: (value: V, other: V) -> Unit
         ) {
-            val values = arrayOf<Any>(fieldValue(first), fieldValue(second),
-                    componentValue(first), componentValue(second))
+            val values = mutableListOf<Any>(fieldValue(first), fieldValue(second))
+                .apply {
+                    componentValue?.let {
+                        add(it(first))
+                        add(it(second))
+                    }
+                }
+                .toTypedArray()
             values.indices.drop(1).forEach {
                 @Suppress("UNCHECKED_CAST")
                 assertion(values[0] as V, values[it] as V)
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt
index 2d23fb4..89394837 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt
@@ -244,6 +244,14 @@
                 service(Type.LEGACY_QUERENT, "getLegacyUserState") {
                     getLegacyState(it.targetPackageName, it.userId)
                 },
+                service(Type.OWNER_QUERENT, "getOwnersForDomain") {
+                    // Re-use package name, since the result itself isn't relevant
+                    getOwnersForDomain(it.targetPackageName)
+                },
+                service(Type.OWNER_QUERENT_USER, "getOwnersForDomainUserId") {
+                    // Re-use package name, since the result itself isn't relevant
+                    getOwnersForDomain(it.targetPackageName, it.userId)
+                },
             )
         }
 
@@ -327,6 +335,7 @@
                 domainSetId
             )
         ) {
+            whenever(getName()) { packageName }
             whenever(getPkg()) { mockPkg(packageName) }
             whenever(this.domainSetId) { domainSetId }
             whenever(userState) {
@@ -357,6 +366,8 @@
             Type.SELECTOR_USER -> approvedUserSelector(verifyCrossUser = true)
             Type.LEGACY_QUERENT -> legacyQuerent()
             Type.LEGACY_SELECTOR -> legacyUserSelector()
+            Type.OWNER_QUERENT -> ownerQuerent(verifyCrossUser = false)
+            Type.OWNER_QUERENT_USER -> ownerQuerent(verifyCrossUser = true)
         }.run { /*exhaust*/ }
     }
 
@@ -628,6 +639,80 @@
         runTestCases(callingUserId, notCallingUserId, throws = false)
     }
 
+    private fun ownerQuerent(verifyCrossUser: Boolean) {
+        val allowQueryAll = AtomicBoolean(false)
+        val allowUserSelection = AtomicBoolean(false)
+        val allowInteractAcrossUsers = AtomicBoolean(false)
+        val context: Context = mockThrowOnUnmocked {
+            initPermission(
+                allowQueryAll,
+                android.Manifest.permission.QUERY_ALL_PACKAGES
+            )
+            initPermission(
+                allowUserSelection,
+                android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION
+            )
+            initPermission(
+                allowInteractAcrossUsers,
+                android.Manifest.permission.INTERACT_ACROSS_USERS
+            )
+        }
+        val target = params.construct(context)
+
+        fun runTestCases(callingUserId: Int, targetUserId: Int, throws: Boolean) {
+            // Owner querent makes no distinction by UID
+            val allUids = INTERNAL_UIDS + VERIFIER_UID + NON_VERIFIER_UID
+            if (throws) {
+                allUids.forEach {
+                    assertFails {
+                        runMethod(target, it, visible = true, callingUserId, targetUserId)
+                    }
+                }
+            } else {
+                allUids.forEach {
+                    runMethod(target, it, visible = true, callingUserId, targetUserId)
+                }
+            }
+        }
+
+        val callingUserId = 0
+        val notCallingUserId = 1
+
+        runTestCases(callingUserId, callingUserId, throws = true)
+        if (verifyCrossUser) {
+            runTestCases(callingUserId, notCallingUserId, throws = true)
+        }
+
+        allowQueryAll.set(true)
+
+        runTestCases(callingUserId, callingUserId, throws = true)
+        if (verifyCrossUser) {
+            runTestCases(callingUserId, notCallingUserId, throws = true)
+        }
+
+        allowUserSelection.set(true)
+
+        runTestCases(callingUserId, callingUserId, throws = false)
+        if (verifyCrossUser) {
+            runTestCases(callingUserId, notCallingUserId, throws = true)
+        }
+
+        allowQueryAll.set(false)
+
+        runTestCases(callingUserId, callingUserId, throws = true)
+        if (verifyCrossUser) {
+            runTestCases(callingUserId, notCallingUserId, throws = true)
+        }
+
+        allowQueryAll.set(true)
+        allowInteractAcrossUsers.set(true)
+
+        runTestCases(callingUserId, callingUserId, throws = false)
+        if (verifyCrossUser) {
+            runTestCases(callingUserId, notCallingUserId, throws = false)
+        }
+    }
+
     private fun Context.initPermission(boolean: AtomicBoolean, permission: String) {
         whenever(enforcePermission(eq(permission), anyInt(), anyInt(), anyString())) {
             if (!boolean.get()) {
@@ -694,6 +779,12 @@
         LEGACY_QUERENT,
 
         // Holding the legacy preferred apps permission
-        LEGACY_SELECTOR
+        LEGACY_SELECTOR,
+
+        // Holding user setting permission, but not targeting a package
+        OWNER_QUERENT,
+
+        // Holding user setting permission, but not targeting a package, but targeting cross user
+        OWNER_QUERENT_USER,
     }
 }
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerUserSelectionOverrideTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerUserSelectionOverrideTest.kt
new file mode 100644
index 0000000..48056a2
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerUserSelectionOverrideTest.kt
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.verify.domain
+
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.content.pm.parsing.component.ParsedActivity
+import android.content.pm.parsing.component.ParsedIntentInfo
+import android.content.pm.verify.domain.DomainVerificationManager
+import android.content.pm.verify.domain.DomainVerificationUserSelection
+import android.os.Build
+import android.os.PatternMatcher
+import android.os.Process
+import android.util.ArraySet
+import androidx.test.InstrumentationRegistry
+import com.android.server.pm.PackageSetting
+import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.pm.verify.domain.DomainVerificationService
+import com.android.server.testutils.mockThrowOnUnmocked
+import com.android.server.testutils.whenever
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyLong
+import org.mockito.ArgumentMatchers.anyString
+import java.util.UUID
+
+class DomainVerificationManagerUserSelectionOverrideTest {
+
+    companion object {
+        private const val PKG_ONE = "com.test.one"
+        private const val PKG_TWO = "com.test.two"
+        private val UUID_ONE = UUID.fromString("1b041c96-8d37-4932-a858-561bfac5947c")
+        private val UUID_TWO = UUID.fromString("a3389c16-7f9f-4e86-85e3-500d1249c74c")
+
+        private val DOMAIN_ONE =
+            DomainVerificationManagerUserSelectionOverrideTest::class.java.packageName
+
+        private const val STATE_NONE = DomainVerificationUserSelection.DOMAIN_STATE_NONE
+        private const val STATE_SELECTED = DomainVerificationUserSelection.DOMAIN_STATE_SELECTED
+        private const val STATE_VERIFIED = DomainVerificationUserSelection.DOMAIN_STATE_VERIFIED
+    }
+
+    private val pkg1 = mockPkgSetting(PKG_ONE, UUID_ONE)
+    private val pkg2 = mockPkgSetting(PKG_TWO, UUID_TWO)
+
+    fun makeManager(): DomainVerificationManager =
+        DomainVerificationService(mockThrowOnUnmocked {
+            // Assume the test has every permission necessary
+            whenever(enforcePermission(anyString(), anyInt(), anyInt(), anyString()))
+            whenever(checkPermission(anyString(), anyInt(), anyInt())) {
+                PackageManager.PERMISSION_GRANTED
+            }
+        }, mockThrowOnUnmocked {
+            whenever(linkedApps) { ArraySet<String>() }
+        }, mockThrowOnUnmocked {
+            whenever(isChangeEnabled(anyLong(), any())) { true }
+        }).apply {
+            setConnection(mockThrowOnUnmocked {
+                whenever(filterAppAccess(anyString(), anyInt(), anyInt())) { false }
+                whenever(scheduleWriteSettings())
+
+                // Need to provide an internal UID so some permission checks are ignored
+                whenever(callingUid) { Process.ROOT_UID }
+                whenever(callingUserId) { 0 }
+                whenever(getPackageSettingLocked(PKG_ONE)) { pkg1 }
+                whenever(getPackageSettingLocked(PKG_TWO)) { pkg2 }
+                whenever(getPackageLocked(PKG_ONE)) { pkg1.getPkg() }
+                whenever(getPackageLocked(PKG_TWO)) { pkg2.getPkg() }
+            })
+            addPackage(pkg1)
+            addPackage(pkg2)
+
+            // Starting state for all tests is to have domain 1 enabled for the first package
+            setDomainVerificationUserSelection(UUID_ONE, setOf(DOMAIN_ONE), true)
+
+            assertThat(stateFor(PKG_ONE, DOMAIN_ONE)).isEqualTo(STATE_SELECTED)
+        }
+
+    fun mockPkgSetting(pkgName: String, domainSetId: UUID) = mockThrowOnUnmocked<PackageSetting> {
+        val pkg = mockThrowOnUnmocked<AndroidPackage> {
+            whenever(packageName) { pkgName }
+            whenever(targetSdkVersion) { Build.VERSION_CODES.S }
+
+            val activityList = listOf(
+                ParsedActivity().apply {
+                    addIntent(
+                        ParsedIntentInfo().apply {
+                            autoVerify = true
+                            addAction(Intent.ACTION_VIEW)
+                            addCategory(Intent.CATEGORY_BROWSABLE)
+                            addCategory(Intent.CATEGORY_DEFAULT)
+                            addDataScheme("http")
+                            addDataScheme("https")
+                            addDataPath("/sub", PatternMatcher.PATTERN_LITERAL)
+                            addDataAuthority(DOMAIN_ONE, null)
+                        }
+                    )
+                    addIntent(
+                        ParsedIntentInfo().apply {
+                            autoVerify = true
+                            addAction(Intent.ACTION_VIEW)
+                            addCategory(Intent.CATEGORY_BROWSABLE)
+                            addCategory(Intent.CATEGORY_DEFAULT)
+                            addDataScheme("http")
+                            addDataPath("/sub2", PatternMatcher.PATTERN_LITERAL)
+                            addDataAuthority("example2.com", null)
+                        }
+                    )
+                },
+            )
+
+            whenever(activities) { activityList }
+        }
+
+        whenever(getPkg()) { pkg }
+        whenever(getName()) { pkgName }
+        whenever(this.domainSetId) { domainSetId }
+        whenever(getInstantApp(anyInt())) { false }
+        whenever(firstInstallTime) { 0L }
+    }
+
+    @Test
+    fun anotherPackageTakeoverSuccess() {
+        val manager = makeManager()
+
+        // Attempt override by package 2
+        manager.setDomainVerificationUserSelection(UUID_TWO, setOf(DOMAIN_ONE), true)
+
+        // 1 loses approval
+        assertThat(manager.stateFor(PKG_ONE, DOMAIN_ONE)).isEqualTo(STATE_NONE)
+
+        // 2 gains approval
+        assertThat(manager.stateFor(PKG_TWO, DOMAIN_ONE)).isEqualTo(STATE_SELECTED)
+
+        // 2 is the only owner
+        assertThat(manager.getOwnersForDomain(DOMAIN_ONE).map { it.packageName })
+            .containsExactly(PKG_TWO)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun anotherPackageTakeoverFailure() {
+        val manager = makeManager()
+
+        // Verify 1 to give it a higher approval level
+        manager.setDomainVerificationStatus(UUID_ONE, setOf(DOMAIN_ONE),
+            DomainVerificationManager.STATE_SUCCESS)
+        assertThat(manager.stateFor(PKG_ONE, DOMAIN_ONE)).isEqualTo(STATE_VERIFIED)
+        assertThat(manager.getOwnersForDomain(DOMAIN_ONE).map { it.packageName })
+            .containsExactly(PKG_ONE)
+
+        // Attempt override by package 2
+        manager.setDomainVerificationUserSelection(UUID_TWO, setOf(DOMAIN_ONE), true)
+    }
+
+    private fun DomainVerificationManager.stateFor(pkgName: String, host: String) =
+        getDomainVerificationUserSelection(pkgName)!!.hostToStateMap[host]
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationModelExtensions.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationModelExtensions.kt
index a76d8ce..439048c 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationModelExtensions.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationModelExtensions.kt
@@ -34,7 +34,7 @@
 operator fun DomainVerificationUserSelection.component2() = packageName
 operator fun DomainVerificationUserSelection.component3() = user
 operator fun DomainVerificationUserSelection.component4() = isLinkHandlingAllowed
-operator fun DomainVerificationUserSelection.component5() = hostToUserSelectionMap
+operator fun DomainVerificationUserSelection.component5() = hostToStateMap
 
 operator fun DomainVerificationPersistence.ReadResult.component1() = active
 operator fun DomainVerificationPersistence.ReadResult.component2() = restored
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationProxyTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationProxyTest.kt
index db541f6..91e5bec 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationProxyTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationProxyTest.kt
@@ -122,7 +122,7 @@
             whenever(setDomainVerificationStatusInternal(anyInt(), any(), any(), anyInt()))
         }
         collector = mockThrowOnUnmocked {
-            whenever(collectAutoVerifyDomains(any())) {
+            whenever(collectValidAutoVerifyDomains(any())) {
                 when (val pkgName = (arguments[0] as AndroidPackage).packageName) {
                     TEST_PKG_NAME_TARGET_ONE -> ArraySet(setOf("example1.com", "example2.com"))
                     TEST_PKG_NAME_TARGET_TWO -> ArraySet(setOf("example3.com", "example4.com"))
@@ -477,7 +477,7 @@
                     whenever(
                         addPowerSaveTempWhitelistApp(
                             anyInt(), anyString(), anyLong(), anyInt(),
-                            anyBoolean(), anyString()
+                            anyBoolean(), anyInt(), anyString()
                         )
                     )
                 }
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt
index 48518f46..010eacf 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt
@@ -237,6 +237,7 @@
                 TEST_UUID
             )
         ) {
+            whenever(getName()) { TEST_PKG }
             whenever(getPkg()) { mockPkg() }
             whenever(domainSetId) { TEST_UUID }
             whenever(userState) {
diff --git a/services/tests/inprocesstests/Android.bp b/services/tests/inprocesstests/Android.bp
index 6dd059f..7c237ac 100644
--- a/services/tests/inprocesstests/Android.bp
+++ b/services/tests/inprocesstests/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworksInProcessTests",
     srcs: ["src/**/*.java"],
diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index e7d56a0..64b9a63 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -18,6 +18,15 @@
     ],
 }
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworksMockingServicesTests",
     defaults: ["FrameworkMockingServicesTests-jni-defaults"],
diff --git a/services/tests/mockingservicestests/jni/Android.bp b/services/tests/mockingservicestests/jni/Android.bp
index 928065a..a32bf2c 100644
--- a/services/tests/mockingservicestests/jni/Android.bp
+++ b/services/tests/mockingservicestests/jni/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_library_shared {
     name: "libactivitymanagermockingservicestestjni",
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index 1254df9..9109881 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -18,6 +18,7 @@
 import static android.app.AlarmManager.ELAPSED_REALTIME;
 import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
 import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE;
+import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE_COMPAT;
 import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
 import static android.app.AlarmManager.FLAG_IDLE_UNTIL;
 import static android.app.AlarmManager.FLAG_STANDALONE;
@@ -25,11 +26,14 @@
 import static android.app.AlarmManager.RTC;
 import static android.app.AlarmManager.RTC_WAKEUP;
 import static android.app.AlarmManager.WINDOW_EXACT;
+import static android.app.AlarmManager.WINDOW_HEURISTIC;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RESTRICTED;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
+import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod;
@@ -44,7 +48,7 @@
 import static com.android.server.alarm.AlarmManagerService.AlarmHandler.APP_STANDBY_BUCKET_CHANGED;
 import static com.android.server.alarm.AlarmManagerService.AlarmHandler.CHARGING_STATUS_CHANGED;
 import static com.android.server.alarm.AlarmManagerService.AlarmHandler.REMOVE_FOR_CANCELED;
-import static com.android.server.alarm.AlarmManagerService.Constants.ALLOW_WHILE_IDLE_WINDOW;
+import static com.android.server.alarm.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_COMPAT_QUOTA;
 import static com.android.server.alarm.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_QUOTA;
 import static com.android.server.alarm.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION;
 import static com.android.server.alarm.AlarmManagerService.Constants.KEY_LAZY_BATCHING;
@@ -61,6 +65,7 @@
 import static com.android.server.alarm.Constants.TEST_CALLING_UID;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
@@ -75,20 +80,29 @@
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.never;
 
+import android.Manifest;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
+import android.app.AlarmManager;
+import android.app.AppOpsManager;
 import android.app.IActivityManager;
 import android.app.IAlarmCompleteListener;
 import android.app.IAlarmListener;
+import android.app.IAlarmManager;
 import android.app.PendingIntent;
+import android.app.compat.CompatChanges;
 import android.app.usage.UsageStatsManagerInternal;
 import android.content.Context;
 import android.content.Intent;
+import android.content.PermissionChecker;
 import android.os.BatteryManager;
+import android.os.Bundle;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
@@ -102,9 +116,12 @@
 
 import com.android.dx.mockito.inline.extended.MockedVoidMethod;
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.app.IAppOpsCallback;
+import com.android.internal.app.IAppOpsService;
 import com.android.server.AlarmManagerInternal;
 import com.android.server.AppStateTracker;
 import com.android.server.AppStateTrackerImpl;
+import com.android.server.DeviceIdleInternal;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.usage.AppStandbyInternal;
@@ -125,6 +142,7 @@
 import java.util.HashSet;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.LongConsumer;
 
 @Presubmit
 @RunWith(AndroidJUnit4.class)
@@ -134,14 +152,21 @@
     private static final int TEST_CALLING_USER = UserHandle.getUserId(TEST_CALLING_UID);
 
     private long mAppStandbyWindow;
+    private long mAllowWhileIdleWindow;
     private AlarmManagerService mService;
     private AppStandbyInternal.AppIdleStateChangeListener mAppStandbyListener;
     private AlarmManagerService.ChargingReceiver mChargingReceiver;
+    private IAppOpsCallback mIAppOpsCallback;
+    private IAlarmManager mBinder;
     @Mock
     private Context mMockContext;
     @Mock
     private IActivityManager mIActivityManager;
     @Mock
+    private IAppOpsService mIAppOpsService;
+    @Mock
+    private DeviceIdleInternal mDeviceIdleInternal;
+    @Mock
     private UsageStatsManagerInternal mUsageStatsManagerInternal;
     @Mock
     private AppStandbyInternal mAppStandbyInternal;
@@ -280,6 +305,11 @@
             // "IllegalStateException: Querying activity state off main thread is not allowed."
             // when AlarmManager calls DeviceConfig.addOnPropertiesChangedListener().
         }
+
+        @Override
+        IAppOpsService getAppOpsService() {
+            return mIAppOpsService;
+        }
     }
 
     @Before
@@ -287,15 +317,20 @@
         mMockingSession = mockitoSession()
                 .initMocks(this)
                 .spyStatic(ActivityManager.class)
+                .mockStatic(CompatChanges.class)
                 .spyStatic(DeviceConfig.class)
                 .mockStatic(LocalServices.class)
                 .spyStatic(Looper.class)
+                .mockStatic(PermissionChecker.class)
                 .mockStatic(Settings.Global.class)
                 .mockStatic(ServiceManager.class)
                 .spyStatic(UserHandle.class)
                 .strictness(Strictness.WARN)
                 .startMocking();
+
         doReturn(mIActivityManager).when(ActivityManager::getService);
+        doReturn(mDeviceIdleInternal).when(
+                () -> LocalServices.getService(DeviceIdleInternal.class));
         doReturn(mActivityManagerInternal).when(
                 () -> LocalServices.getService(ActivityManagerInternal.class));
         doReturn(mAppStateTracker).when(() -> LocalServices.getService(AppStateTracker.class));
@@ -330,6 +365,9 @@
                 () -> DeviceConfig.getProperties(
                         eq(DeviceConfig.NAMESPACE_ALARM_MANAGER), ArgumentMatchers.<String>any()));
 
+        when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(
+                mock(AppOpsManager.class));
+
         mInjector = new Injector(mMockContext);
         mService = new AlarmManagerService(mMockContext, mInjector);
         spyOn(mService);
@@ -346,6 +384,7 @@
         // Other boot phases don't matter
         mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
         mAppStandbyWindow = mService.mConstants.APP_STANDBY_WINDOW;
+        mAllowWhileIdleWindow = mService.mConstants.ALLOW_WHILE_IDLE_WINDOW;
         ArgumentCaptor<AppStandbyInternal.AppIdleStateChangeListener> captor =
                 ArgumentCaptor.forClass(AppStandbyInternal.AppIdleStateChangeListener.class);
         verify(mAppStandbyInternal).addListener(captor.capture());
@@ -358,6 +397,20 @@
                         && filter.hasAction(BatteryManager.ACTION_DISCHARGING)));
         mChargingReceiver = chargingReceiverCaptor.getValue();
 
+        ArgumentCaptor<IBinder> binderCaptor = ArgumentCaptor.forClass(IBinder.class);
+        verify(() -> ServiceManager.addService(eq(Context.ALARM_SERVICE), binderCaptor.capture(),
+                anyBoolean(), anyInt()));
+        mBinder = IAlarmManager.Stub.asInterface(binderCaptor.getValue());
+
+        ArgumentCaptor<IAppOpsCallback> appOpsCallbackCaptor = ArgumentCaptor.forClass(
+                IAppOpsCallback.class);
+        try {
+            verify(mIAppOpsService).startWatchingMode(eq(AppOpsManager.OP_SCHEDULE_EXACT_ALARM),
+                    isNull(), appOpsCallbackCaptor.capture());
+        } catch (RemoteException e) {
+            // Not expected on a mock.
+        }
+        mIAppOpsCallback = appOpsCallbackCaptor.getValue();
         setTestableQuotas();
     }
 
@@ -389,13 +442,18 @@
 
     private void setTestAlarm(int type, long triggerTime, PendingIntent operation, long interval,
             int flags, int callingUid) {
+        setTestAlarm(type, triggerTime, operation, interval, flags, callingUid, null);
+    }
+
+    private void setTestAlarm(int type, long triggerTime, PendingIntent operation, long interval,
+            int flags, int callingUid, Bundle idleOptions) {
         mService.setImpl(type, triggerTime, WINDOW_EXACT, interval, operation, null, "test", flags,
-                null, null, callingUid, TEST_CALLING_PACKAGE);
+                null, null, callingUid, TEST_CALLING_PACKAGE, idleOptions);
     }
 
     private void setTestAlarmWithListener(int type, long triggerTime, IAlarmListener listener) {
         mService.setImpl(type, triggerTime, WINDOW_EXACT, 0, null, listener, "test",
-                FLAG_STANDALONE, null, null, TEST_CALLING_UID, TEST_CALLING_PACKAGE);
+                FLAG_STANDALONE, null, null, TEST_CALLING_UID, TEST_CALLING_PACKAGE, null);
     }
 
 
@@ -506,14 +564,27 @@
         setDeviceConfigLong(KEY_MIN_INTERVAL, 10);
         setDeviceConfigLong(KEY_MAX_INTERVAL, 15);
         setDeviceConfigInt(KEY_ALLOW_WHILE_IDLE_QUOTA, 20);
+        setDeviceConfigInt(KEY_ALLOW_WHILE_IDLE_COMPAT_QUOTA, 25);
         setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION, 30);
         setDeviceConfigLong(KEY_LISTENER_TIMEOUT, 35);
         assertEquals(5, mService.mConstants.MIN_FUTURITY);
         assertEquals(10, mService.mConstants.MIN_INTERVAL);
         assertEquals(15, mService.mConstants.MAX_INTERVAL);
         assertEquals(20, mService.mConstants.ALLOW_WHILE_IDLE_QUOTA);
+        assertEquals(25, mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA);
         assertEquals(30, mService.mConstants.ALLOW_WHILE_IDLE_WHITELIST_DURATION);
         assertEquals(35, mService.mConstants.LISTENER_TIMEOUT);
+
+        // Test safeguards.
+        setDeviceConfigInt(KEY_ALLOW_WHILE_IDLE_QUOTA, -3);
+        assertEquals(1, mService.mConstants.ALLOW_WHILE_IDLE_QUOTA);
+        setDeviceConfigInt(KEY_ALLOW_WHILE_IDLE_QUOTA, 0);
+        assertEquals(1, mService.mConstants.ALLOW_WHILE_IDLE_QUOTA);
+
+        setDeviceConfigInt(KEY_ALLOW_WHILE_IDLE_COMPAT_QUOTA, -8);
+        assertEquals(1, mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA);
+        setDeviceConfigInt(KEY_ALLOW_WHILE_IDLE_COMPAT_QUOTA, 0);
+        assertEquals(1, mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA);
     }
 
     @Test
@@ -559,56 +630,45 @@
         assertEquals(mNowElapsedTest + 9, mTestTimer.getElapsed());
     }
 
-    private void testQuotasDeferralOnSet(int standbyBucket) throws Exception {
-        final int quota = mService.getQuotaForBucketLocked(standbyBucket);
-        when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
-                anyLong())).thenReturn(standbyBucket);
+    private void testQuotasDeferralOnSet(LongConsumer alarmSetter, int quota, long window)
+            throws Exception {
         final long firstTrigger = mNowElapsedTest + 10;
         for (int i = 0; i < quota; i++) {
-            setTestAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i,
-                    getNewMockPendingIntent());
+            alarmSetter.accept(firstTrigger + i);
             mNowElapsedTest = mTestTimer.getElapsed();
             mTestTimer.expire();
         }
         // This one should get deferred on set
-        setTestAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + quota,
-                getNewMockPendingIntent());
-        final long expectedNextTrigger = firstTrigger + mAppStandbyWindow;
+        alarmSetter.accept(firstTrigger + quota);
+        final long expectedNextTrigger = firstTrigger + window;
         assertEquals("Incorrect next alarm trigger", expectedNextTrigger, mTestTimer.getElapsed());
     }
 
-    private void testQuotasDeferralOnExpiration(int standbyBucket) throws Exception {
-        final int quota = mService.getQuotaForBucketLocked(standbyBucket);
-        when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
-                anyLong())).thenReturn(standbyBucket);
+    private void testQuotasDeferralOnExpiration(LongConsumer alarmSetter, int quota, long window)
+            throws Exception {
         final long firstTrigger = mNowElapsedTest + 10;
         for (int i = 0; i < quota; i++) {
-            setTestAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i,
-                    getNewMockPendingIntent());
+            alarmSetter.accept(firstTrigger + i);
         }
-        // This one should get deferred after the latest alarm expires
-        setTestAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + quota,
-                getNewMockPendingIntent());
+        // This one should get deferred after the latest alarm expires.
+        alarmSetter.accept(firstTrigger + quota);
         for (int i = 0; i < quota; i++) {
             mNowElapsedTest = mTestTimer.getElapsed();
             mTestTimer.expire();
         }
-        final long expectedNextTrigger = firstTrigger + mAppStandbyWindow;
+        final long expectedNextTrigger = firstTrigger + window;
         assertEquals("Incorrect next alarm trigger", expectedNextTrigger, mTestTimer.getElapsed());
     }
 
-    private void testQuotasNoDeferral(int standbyBucket) throws Exception {
-        final int quota = mService.getQuotaForBucketLocked(standbyBucket);
-        when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
-                anyLong())).thenReturn(standbyBucket);
+    private void testQuotasNoDeferral(LongConsumer alarmSetter, int quota, long window)
+            throws Exception {
         final long firstTrigger = mNowElapsedTest + 10;
         for (int i = 0; i < quota; i++) {
-            setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 10 + i,
-                    getNewMockPendingIntent());
+            alarmSetter.accept(firstTrigger + i);
         }
         // This delivery time maintains the quota invariant. Should not be deferred.
-        final long expectedNextTrigger = firstTrigger + mAppStandbyWindow + 5;
-        setTestAlarm(ELAPSED_REALTIME_WAKEUP, expectedNextTrigger, getNewMockPendingIntent());
+        final long expectedNextTrigger = firstTrigger + window + 5;
+        alarmSetter.accept(expectedNextTrigger);
         for (int i = 0; i < quota; i++) {
             mNowElapsedTest = mTestTimer.getElapsed();
             mTestTimer.expire();
@@ -616,64 +676,88 @@
         assertEquals("Incorrect next alarm trigger", expectedNextTrigger, mTestTimer.getElapsed());
     }
 
+    private void testStandbyQuotasDeferralOnSet(int standbyBucket) throws Exception {
+        final int quota = mService.getQuotaForBucketLocked(standbyBucket);
+        when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
+                anyLong())).thenReturn(standbyBucket);
+        testQuotasDeferralOnSet(trigger -> setTestAlarm(ELAPSED_REALTIME_WAKEUP, trigger,
+                getNewMockPendingIntent()), quota, mAppStandbyWindow);
+    }
+
+    private void testStandbyQuotasDeferralOnExpiration(int standbyBucket) throws Exception {
+        final int quota = mService.getQuotaForBucketLocked(standbyBucket);
+        when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
+                anyLong())).thenReturn(standbyBucket);
+        testQuotasDeferralOnExpiration(trigger -> setTestAlarm(ELAPSED_REALTIME_WAKEUP, trigger,
+                getNewMockPendingIntent()), quota, mAppStandbyWindow);
+    }
+
+    private void testStandbyQuotasNoDeferral(int standbyBucket) throws Exception {
+        final int quota = mService.getQuotaForBucketLocked(standbyBucket);
+        when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
+                anyLong())).thenReturn(standbyBucket);
+        testQuotasNoDeferral(trigger -> setTestAlarm(ELAPSED_REALTIME_WAKEUP, trigger,
+                getNewMockPendingIntent()), quota, mAppStandbyWindow);
+    }
+
     @Test
     public void testActiveQuota_deferredOnSet() throws Exception {
-        testQuotasDeferralOnSet(STANDBY_BUCKET_ACTIVE);
+        testStandbyQuotasDeferralOnSet(STANDBY_BUCKET_ACTIVE);
     }
 
     @Test
     public void testActiveQuota_deferredOnExpiration() throws Exception {
-        testQuotasDeferralOnExpiration(STANDBY_BUCKET_ACTIVE);
+        testStandbyQuotasDeferralOnExpiration(STANDBY_BUCKET_ACTIVE);
     }
 
     @Test
     public void testActiveQuota_notDeferred() throws Exception {
-        testQuotasNoDeferral(STANDBY_BUCKET_ACTIVE);
+        testStandbyQuotasNoDeferral(STANDBY_BUCKET_ACTIVE);
     }
 
     @Test
     public void testWorkingQuota_deferredOnSet() throws Exception {
-        testQuotasDeferralOnSet(STANDBY_BUCKET_WORKING_SET);
+        testStandbyQuotasDeferralOnSet(STANDBY_BUCKET_WORKING_SET);
     }
 
     @Test
     public void testWorkingQuota_deferredOnExpiration() throws Exception {
-        testQuotasDeferralOnExpiration(STANDBY_BUCKET_WORKING_SET);
+        testStandbyQuotasDeferralOnExpiration(STANDBY_BUCKET_WORKING_SET);
     }
 
     @Test
     public void testWorkingQuota_notDeferred() throws Exception {
-        testQuotasNoDeferral(STANDBY_BUCKET_WORKING_SET);
+        testStandbyQuotasNoDeferral(STANDBY_BUCKET_WORKING_SET);
     }
 
     @Test
     public void testFrequentQuota_deferredOnSet() throws Exception {
-        testQuotasDeferralOnSet(STANDBY_BUCKET_FREQUENT);
+        testStandbyQuotasDeferralOnSet(STANDBY_BUCKET_FREQUENT);
     }
 
     @Test
     public void testFrequentQuota_deferredOnExpiration() throws Exception {
-        testQuotasDeferralOnExpiration(STANDBY_BUCKET_FREQUENT);
+        testStandbyQuotasDeferralOnExpiration(STANDBY_BUCKET_FREQUENT);
     }
 
     @Test
     public void testFrequentQuota_notDeferred() throws Exception {
-        testQuotasNoDeferral(STANDBY_BUCKET_FREQUENT);
+        testStandbyQuotasNoDeferral(STANDBY_BUCKET_FREQUENT);
     }
 
     @Test
     public void testRareQuota_deferredOnSet() throws Exception {
-        testQuotasDeferralOnSet(STANDBY_BUCKET_RARE);
+        testStandbyQuotasDeferralOnSet(STANDBY_BUCKET_RARE);
     }
 
     @Test
     public void testRareQuota_deferredOnExpiration() throws Exception {
-        testQuotasDeferralOnExpiration(STANDBY_BUCKET_RARE);
+        testStandbyQuotasDeferralOnExpiration(STANDBY_BUCKET_RARE);
     }
 
     @Test
     public void testRareQuota_notDeferred() throws Exception {
-        testQuotasNoDeferral(STANDBY_BUCKET_RARE);
+        testStandbyQuotasNoDeferral(STANDBY_BUCKET_RARE);
     }
 
     @Test
@@ -731,7 +815,7 @@
     }
 
     @Test
-    public void testQuotaDowngrade() throws Exception {
+    public void testStandbyQuotaDowngrade() throws Exception {
         final int workingQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_WORKING_SET);
         when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
                 anyLong())).thenReturn(STANDBY_BUCKET_WORKING_SET);
@@ -758,7 +842,7 @@
     }
 
     @Test
-    public void testQuotaUpgrade() throws Exception {
+    public void testStandbyQuotaUpgrade() throws Exception {
         final int frequentQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_FREQUENT);
         when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
                 anyLong())).thenReturn(STANDBY_BUCKET_FREQUENT);
@@ -1308,7 +1392,7 @@
     public void allowWhileIdleAlarmsWhileDeviceIdle() throws Exception {
         doReturn(0).when(mService).fuzzForDuration(anyLong());
 
-        setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + ALLOW_WHILE_IDLE_WINDOW + 1000,
+        setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + mAllowWhileIdleWindow + 1000,
                 getNewMockPendingIntent());
         assertNotNull(mService.mPendingIdleUntil);
 
@@ -1323,7 +1407,7 @@
         // This one should get deferred on set.
         setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + quota,
                 getNewMockPendingIntent(), false);
-        final long expectedNextTrigger = firstTrigger + ALLOW_WHILE_IDLE_WINDOW;
+        final long expectedNextTrigger = firstTrigger + mAllowWhileIdleWindow;
         assertEquals("Incorrect trigger when no quota left", expectedNextTrigger,
                 mTestTimer.getElapsed());
 
@@ -1449,61 +1533,24 @@
         when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID,
                 TEST_CALLING_PACKAGE)).thenReturn(true);
         when(mAppStateTracker.isForceAllAppsStandbyEnabled()).thenReturn(true);
-
         final int quota = mService.mConstants.ALLOW_WHILE_IDLE_QUOTA;
-        long firstTrigger = mNowElapsedTest + 10;
-        for (int i = 0; i < quota; i++) {
-            setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i,
-                    getNewMockPendingIntent(), false);
-            mNowElapsedTest = mTestTimer.getElapsed();
-            mTestTimer.expire();
-        }
-        // This one should get deferred on set.
-        setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + quota,
-                getNewMockPendingIntent(), false);
-        long expectedNextTrigger = firstTrigger + ALLOW_WHILE_IDLE_WINDOW;
-        assertEquals("Incorrect trigger when no quota available", expectedNextTrigger,
-                mTestTimer.getElapsed());
+
+        testQuotasDeferralOnSet(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger,
+                getNewMockPendingIntent(), false), quota, mAllowWhileIdleWindow);
 
         // Refresh the state
         mService.removeLocked(TEST_CALLING_UID);
         mService.mAllowWhileIdleHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER);
 
-        firstTrigger = mNowElapsedTest + 10;
-        for (int i = 0; i < quota; i++) {
-            setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i,
-                    getNewMockPendingIntent(), false);
-        }
-        // This one should get deferred after the latest alarm expires.
-        setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + quota,
-                getNewMockPendingIntent(), false);
-        for (int i = 0; i < quota; i++) {
-            mNowElapsedTest = mTestTimer.getElapsed();
-            mTestTimer.expire();
-        }
-        expectedNextTrigger = firstTrigger + ALLOW_WHILE_IDLE_WINDOW;
-        assertEquals("Incorrect trigger when no quota available", expectedNextTrigger,
-                mTestTimer.getElapsed());
+        testQuotasDeferralOnExpiration(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP,
+                trigger, getNewMockPendingIntent(), false), quota, mAllowWhileIdleWindow);
 
         // Refresh the state
         mService.removeLocked(TEST_CALLING_UID);
         mService.mAllowWhileIdleHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER);
 
-        firstTrigger = mNowElapsedTest + 10;
-        for (int i = 0; i < quota; i++) {
-            setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i,
-                    getNewMockPendingIntent(), false);
-        }
-        // This delivery time maintains the quota invariant. Should not be deferred.
-        expectedNextTrigger = firstTrigger + ALLOW_WHILE_IDLE_WINDOW + 5;
-        setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, expectedNextTrigger,
-                getNewMockPendingIntent(), false);
-        for (int i = 0; i < quota; i++) {
-            mNowElapsedTest = mTestTimer.getElapsed();
-            mTestTimer.expire();
-        }
-        assertEquals("Incorrect trigger when no quota available", expectedNextTrigger,
-                mTestTimer.getElapsed());
+        testQuotasNoDeferral(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger,
+                getNewMockPendingIntent(), false), quota, mAllowWhileIdleWindow);
     }
 
     @Test
@@ -1545,6 +1592,259 @@
     }
 
     @Test
+    public void canScheduleExactAlarms() throws RemoteException {
+        doReturn(PermissionChecker.PERMISSION_GRANTED).when(
+                () -> PermissionChecker.checkCallingOrSelfPermissionForPreflight(mMockContext,
+                        Manifest.permission.SCHEDULE_EXACT_ALARM));
+        assertTrue(mBinder.canScheduleExactAlarms());
+
+        doReturn(PermissionChecker.PERMISSION_HARD_DENIED).when(
+                () -> PermissionChecker.checkCallingOrSelfPermissionForPreflight(mMockContext,
+                        Manifest.permission.SCHEDULE_EXACT_ALARM));
+        assertFalse(mBinder.canScheduleExactAlarms());
+
+        doReturn(PermissionChecker.PERMISSION_SOFT_DENIED).when(
+                () -> PermissionChecker.checkCallingOrSelfPermissionForPreflight(mMockContext,
+                        Manifest.permission.SCHEDULE_EXACT_ALARM));
+        assertFalse(mBinder.canScheduleExactAlarms());
+    }
+
+    @Test
+    public void noPermissionCheckWhenChangeDisabled() throws RemoteException {
+        doReturn(false).when(
+                () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
+                        anyString(), any(UserHandle.class)));
+
+        // alarm clock
+        mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, 0,
+                getNewMockPendingIntent(), null, null, null,
+                mock(AlarmManager.AlarmClockInfo.class));
+
+        // exact, allow-while-idle
+        mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0,
+                FLAG_ALLOW_WHILE_IDLE, getNewMockPendingIntent(), null, null, null, null);
+
+        // inexact, allow-while-idle
+        mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_HEURISTIC, 0,
+                FLAG_ALLOW_WHILE_IDLE, getNewMockPendingIntent(), null, null, null, null);
+
+        verify(() -> PermissionChecker.checkCallingOrSelfPermissionForPreflight(mMockContext,
+                Manifest.permission.SCHEDULE_EXACT_ALARM), never());
+        verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt());
+    }
+
+    @Test
+    public void exactAllowWhileIdleBinderCallWhenChangeDisabled() throws Exception {
+        doReturn(false).when(
+                () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
+                        anyString(), any(UserHandle.class)));
+
+        final PendingIntent alarmPi = getNewMockPendingIntent();
+        mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0,
+                FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null);
+
+        final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L),
+                eq(alarmPi), isNull(), isNull(),
+                eq(FLAG_ALLOW_WHILE_IDLE_COMPAT | FLAG_STANDALONE), isNull(), isNull(),
+                eq(Process.myUid()), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture());
+
+        final Bundle idleOptions = bundleCaptor.getValue();
+        final int type = idleOptions.getInt("android:broadcast.temporaryAppWhitelistType");
+        assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type);
+    }
+
+    @Test
+    public void inexactAllowWhileIdleBinderCallWhenChangeDisabled() throws Exception {
+        doReturn(false).when(
+                () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
+                        anyString(), any(UserHandle.class)));
+
+        final PendingIntent alarmPi = getNewMockPendingIntent();
+        mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_HEURISTIC, 0,
+                FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null);
+
+        final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), anyLong(), eq(0L),
+                eq(alarmPi), isNull(), isNull(), eq(FLAG_ALLOW_WHILE_IDLE_COMPAT), isNull(),
+                isNull(), eq(Process.myUid()), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture());
+
+        final Bundle idleOptions = bundleCaptor.getValue();
+        final int type = idleOptions.getInt("android:broadcast.temporaryAppWhitelistType");
+        assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type);
+    }
+
+    @Test
+    public void alarmClockBinderCallWhenChangeDisabled() throws Exception {
+        doReturn(false).when(
+                () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
+                        anyString(), any(UserHandle.class)));
+
+        final PendingIntent alarmPi = getNewMockPendingIntent();
+        final AlarmManager.AlarmClockInfo alarmClock = mock(AlarmManager.AlarmClockInfo.class);
+        mBinder.set(TEST_CALLING_PACKAGE, RTC_WAKEUP, 1234, WINDOW_EXACT, 0, 0,
+                alarmPi, null, null, null, alarmClock);
+
+        verify(mService).setImpl(eq(RTC_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L),
+                eq(alarmPi), isNull(), isNull(), eq(FLAG_STANDALONE | FLAG_WAKE_FROM_IDLE),
+                isNull(), eq(alarmClock), eq(Process.myUid()), eq(TEST_CALLING_PACKAGE), isNull());
+    }
+
+    @Test
+    public void alarmClockBinderCall() throws RemoteException {
+        doReturn(true).when(
+                () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
+                        anyString(), any(UserHandle.class)));
+
+        doReturn(PermissionChecker.PERMISSION_GRANTED).when(
+                () -> PermissionChecker.checkCallingOrSelfPermissionForPreflight(mMockContext,
+                        Manifest.permission.SCHEDULE_EXACT_ALARM));
+
+        final PendingIntent alarmPi = getNewMockPendingIntent();
+        final AlarmManager.AlarmClockInfo alarmClock = mock(AlarmManager.AlarmClockInfo.class);
+        mBinder.set(TEST_CALLING_PACKAGE, RTC_WAKEUP, 1234, WINDOW_EXACT, 0, 0,
+                alarmPi, null, null, null, alarmClock);
+
+        // Correct permission checks are invoked.
+        verify(() -> PermissionChecker.checkCallingOrSelfPermissionForPreflight(mMockContext,
+                Manifest.permission.SCHEDULE_EXACT_ALARM));
+        verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt());
+
+        final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mService).setImpl(eq(RTC_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L),
+                eq(alarmPi), isNull(), isNull(), eq(FLAG_STANDALONE | FLAG_WAKE_FROM_IDLE),
+                isNull(), eq(alarmClock), eq(Process.myUid()), eq(TEST_CALLING_PACKAGE),
+                bundleCaptor.capture());
+
+        final Bundle idleOptions = bundleCaptor.getValue();
+        final int type = idleOptions.getInt("android:broadcast.temporaryAppWhitelistType");
+        assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type);
+    }
+
+    @Test
+    public void exactAllowWhileIdleBinderCallWithPermission() throws RemoteException {
+        doReturn(true).when(
+                () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
+                        anyString(), any(UserHandle.class)));
+
+        // Permission check is granted by default by the mock.
+        final PendingIntent alarmPi = getNewMockPendingIntent();
+        mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0,
+                FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null);
+
+        verify(() -> PermissionChecker.checkCallingOrSelfPermissionForPreflight(mMockContext,
+                Manifest.permission.SCHEDULE_EXACT_ALARM));
+        verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt());
+
+        final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L),
+                eq(alarmPi), isNull(), isNull(),
+                eq(FLAG_ALLOW_WHILE_IDLE | FLAG_STANDALONE), isNull(), isNull(),
+                eq(Process.myUid()), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture());
+
+        final Bundle idleOptions = bundleCaptor.getValue();
+        final int type = idleOptions.getInt("android:broadcast.temporaryAppWhitelistType");
+        assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type);
+    }
+
+    @Test
+    public void exactAllowWhileIdleBinderCallWithAllowlist() throws RemoteException {
+        doReturn(true).when(
+                () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
+                        anyString(), any(UserHandle.class)));
+        // If permission is denied, only then allowlist will be checked.
+        doReturn(PermissionChecker.PERMISSION_HARD_DENIED).when(
+                () -> PermissionChecker.checkCallingOrSelfPermissionForPreflight(mMockContext,
+                        Manifest.permission.SCHEDULE_EXACT_ALARM));
+        when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(true);
+
+        final PendingIntent alarmPi = getNewMockPendingIntent();
+        mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0,
+                FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null);
+
+        verify(() -> PermissionChecker.checkCallingOrSelfPermissionForPreflight(mMockContext,
+                Manifest.permission.SCHEDULE_EXACT_ALARM));
+        verify(mDeviceIdleInternal).isAppOnWhitelist(UserHandle.getAppId(Process.myUid()));
+
+        final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L),
+                eq(alarmPi), isNull(), isNull(),
+                eq(FLAG_ALLOW_WHILE_IDLE_COMPAT | FLAG_STANDALONE), isNull(), isNull(),
+                eq(Process.myUid()), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture());
+
+        final Bundle idleOptions = bundleCaptor.getValue();
+        final int type = idleOptions.getInt("android:broadcast.temporaryAppWhitelistType");
+        assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type);
+    }
+
+    @Test
+    public void inexactAllowWhileIdleBinderCallWithAllowlist() throws RemoteException {
+        doReturn(true).when(
+                () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
+                        anyString(), any(UserHandle.class)));
+
+        when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(true);
+        final PendingIntent alarmPi = getNewMockPendingIntent();
+        mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 4321, WINDOW_HEURISTIC, 0,
+                FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null);
+
+        verify(() -> PermissionChecker.checkCallingOrSelfPermissionForPreflight(mMockContext,
+                Manifest.permission.SCHEDULE_EXACT_ALARM), never());
+        verify(mDeviceIdleInternal).isAppOnWhitelist(UserHandle.getAppId(Process.myUid()));
+
+        final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(4321L), anyLong(), eq(0L),
+                eq(alarmPi), isNull(), isNull(), eq(FLAG_ALLOW_WHILE_IDLE_COMPAT), isNull(),
+                isNull(), eq(Process.myUid()), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture());
+
+        final Bundle idleOptions = bundleCaptor.getValue();
+        final int type = idleOptions.getInt("android:broadcast.temporaryAppWhitelistType");
+        assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type);
+    }
+
+    @Test
+    public void inexactAllowWhileIdleBinderCallWithoutAllowlist() throws RemoteException {
+        doReturn(true).when(
+                () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
+                        anyString(), any(UserHandle.class)));
+
+        when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(false);
+        final PendingIntent alarmPi = getNewMockPendingIntent();
+        mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 4321, WINDOW_HEURISTIC, 0,
+                FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null);
+
+        verify(() -> PermissionChecker.checkCallingOrSelfPermissionForPreflight(mMockContext,
+                Manifest.permission.SCHEDULE_EXACT_ALARM), never());
+        verify(mDeviceIdleInternal).isAppOnWhitelist(UserHandle.getAppId(Process.myUid()));
+
+        final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(4321L), anyLong(), eq(0L),
+                eq(alarmPi), isNull(), isNull(), eq(FLAG_ALLOW_WHILE_IDLE_COMPAT), isNull(),
+                isNull(), eq(Process.myUid()), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture());
+
+        final Bundle idleOptions = bundleCaptor.getValue();
+        final int type = idleOptions.getInt("android:broadcast.temporaryAppWhitelistType");
+        assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED, type);
+    }
+
+    @Test
+    public void idleOptionsSentOnExpiration() throws Exception {
+        final long triggerTime = mNowElapsedTest + 5000;
+        final PendingIntent alarmPi = getNewMockPendingIntent();
+        final Bundle idleOptions = new Bundle();
+        idleOptions.putChar("TEST_CHAR_KEY", 'x');
+        idleOptions.putInt("TEST_INT_KEY", 53);
+        setTestAlarm(ELAPSED_REALTIME_WAKEUP, triggerTime, alarmPi, 0, 0, TEST_CALLING_UID,
+                idleOptions);
+
+        mNowElapsedTest = mTestTimer.getElapsed();
+        mTestTimer.expire();
+
+        verify(alarmPi).send(eq(mMockContext), eq(0), any(Intent.class),
+                any(), any(Handler.class), isNull(), eq(idleOptions));
+    }
+
+    @Test
     public void alarmStoreMigration() {
         setDeviceConfigBoolean(KEY_LAZY_BATCHING, false);
         final int numAlarms = 10;
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmStoreTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmStoreTest.java
index 42fa3d4..12894ae 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmStoreTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmStoreTest.java
@@ -69,12 +69,12 @@
                 mock(PendingIntent.class));
         return new Alarm(ELAPSED_REALTIME_WAKEUP, whenElapsed, whenElapsed, 0, 0,
                 mock(PendingIntent.class), null, null, null, 0, info, TEST_CALLING_UID,
-                TEST_CALLING_PACKAGE);
+                TEST_CALLING_PACKAGE, null);
     }
 
     private static Alarm createAlarm(int type, long whenElapsed, long windowLength, int flags) {
         return new Alarm(type, whenElapsed, whenElapsed, windowLength, 0, mock(PendingIntent.class),
-                null, null, null, flags, null, TEST_CALLING_UID, TEST_CALLING_PACKAGE);
+                null, null, null, flags, null, TEST_CALLING_UID, TEST_CALLING_PACKAGE, null);
     }
 
     private void addAlarmsToStore(Alarm... alarms) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmTest.java
index e80f065..b64528c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmTest.java
@@ -17,10 +17,17 @@
 package com.android.server.alarm;
 
 import static android.app.AlarmManager.ELAPSED_REALTIME;
+import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE;
+import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE_COMPAT;
+import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
+import static android.app.AlarmManager.FLAG_STANDALONE;
+import static android.app.AlarmManager.FLAG_WAKE_FROM_IDLE;
+import static android.app.AlarmManager.RTC_WAKEUP;
 
 import static com.android.server.alarm.Alarm.APP_STANDBY_POLICY_INDEX;
 import static com.android.server.alarm.Alarm.NUM_POLICIES;
 import static com.android.server.alarm.Alarm.REQUESTER_POLICY_INDEX;
+import static com.android.server.alarm.AlarmManagerService.isExemptFromAppStandby;
 import static com.android.server.alarm.Constants.TEST_CALLING_PACKAGE;
 import static com.android.server.alarm.Constants.TEST_CALLING_UID;
 
@@ -28,7 +35,9 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
+import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.platform.test.annotations.Presubmit;
 
@@ -43,15 +52,29 @@
 @RunWith(AndroidJUnit4.class)
 public class AlarmTest {
 
-    private Alarm createDefaultAlarm(long requestedElapsed, long windowLength) {
+    private Alarm createDefaultAlarm(long requestedElapsed, long windowLength, int flags) {
         return new Alarm(ELAPSED_REALTIME, 0, requestedElapsed, windowLength, 0,
-                mock(PendingIntent.class), null, null, null, 0, null, TEST_CALLING_UID,
-                TEST_CALLING_PACKAGE);
+                createAlarmSender(), null, null, null, flags, null, TEST_CALLING_UID,
+                TEST_CALLING_PACKAGE, null);
+    }
+
+    private Alarm createAlarmClock(long requestedRtc) {
+        final AlarmManager.AlarmClockInfo info = mock(AlarmManager.AlarmClockInfo.class);
+        return new Alarm(RTC_WAKEUP, requestedRtc, requestedRtc, 0, 0, createAlarmSender(),
+                null, null, null, FLAG_WAKE_FROM_IDLE | FLAG_STANDALONE, info, TEST_CALLING_UID,
+                TEST_CALLING_PACKAGE, null);
+    }
+
+    private PendingIntent createAlarmSender() {
+        final PendingIntent alarmPi = mock(PendingIntent.class);
+        when(alarmPi.getCreatorPackage()).thenReturn(TEST_CALLING_PACKAGE);
+        when(alarmPi.getCreatorUid()).thenReturn(TEST_CALLING_UID);
+        return alarmPi;
     }
 
     @Test
     public void initSetsOnlyRequesterPolicy() {
-        final Alarm a = createDefaultAlarm(4567, 2);
+        final Alarm a = createDefaultAlarm(4567, 2, 0);
 
         for (int i = 0; i < NUM_POLICIES; i++) {
             if (i == REQUESTER_POLICY_INDEX) {
@@ -86,7 +109,7 @@
 
     @Test
     public void whenElapsed() {
-        final Alarm a = createDefaultAlarm(0, 0);
+        final Alarm a = createDefaultAlarm(0, 0, 0);
 
         final long[][] uniqueData = generatePolicyTestMatrix(NUM_POLICIES);
         for (int i = 0; i < NUM_POLICIES; i++) {
@@ -104,7 +127,7 @@
 
     @Test
     public void maxWhenElapsed() {
-        final Alarm a = createDefaultAlarm(10, 12);
+        final Alarm a = createDefaultAlarm(10, 12, 0);
         assertEquals(22, a.getMaxWhenElapsed());
 
         a.setPolicyElapsed(REQUESTER_POLICY_INDEX, 15);
@@ -128,7 +151,7 @@
 
     @Test
     public void setPolicyElapsedExact() {
-        final Alarm exactAlarm = createDefaultAlarm(10, 0);
+        final Alarm exactAlarm = createDefaultAlarm(10, 0, 0);
 
         assertTrue(exactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 4));
         assertTrue(exactAlarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 10));
@@ -143,7 +166,7 @@
 
     @Test
     public void setPolicyElapsedInexact() {
-        final Alarm inexactAlarm = createDefaultAlarm(10, 5);
+        final Alarm inexactAlarm = createDefaultAlarm(10, 5, 0);
 
         assertTrue(inexactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 4));
         assertTrue(inexactAlarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 10));
@@ -154,4 +177,20 @@
 
         assertFalse(inexactAlarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 8));
     }
+
+    @Test
+    public void isExemptFromStandby() {
+        final long anything = 35412;    // Arbitrary number, doesn't matter for this test.
+
+        assertFalse("Basic alarm exempt", isExemptFromAppStandby(
+                createDefaultAlarm(anything, anything, 0)));
+        assertFalse("FLAG_ALLOW_WHILE_IDLE_COMPAT exempt", isExemptFromAppStandby(
+                createDefaultAlarm(anything, anything, FLAG_ALLOW_WHILE_IDLE_COMPAT)));
+
+        assertTrue("ALLOW_WHILE_IDLE not exempt", isExemptFromAppStandby(
+                createDefaultAlarm(anything, anything, FLAG_ALLOW_WHILE_IDLE)));
+        assertTrue("ALLOW_WHILE_IDLE_UNRESTRICTED not exempt", isExemptFromAppStandby(
+                createDefaultAlarm(anything, anything, FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED)));
+        assertTrue("Alarm clock not exempt", isExemptFromAppStandby(createAlarmClock(anything)));
+    }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/BackgroundRestrictedAlarmsTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/BackgroundRestrictedAlarmsTest.java
index 5bb6a42..0e795a9 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/BackgroundRestrictedAlarmsTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/BackgroundRestrictedAlarmsTest.java
@@ -45,7 +45,7 @@
         }
         uidAlarms.add(new Alarm(
                 removeIt ? RTC : RTC_WAKEUP,
-                0, 0, 0, 0, null, null, null, null, 0, null, uid, name));
+                0, 0, 0, 0, null, null, null, null, 0, null, uid, name, null));
         return all;
     }
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
index 56d30cc..20a5842 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
@@ -139,7 +139,8 @@
         app.info.uid = packageUid;
         // Exact value does not mater, it can be any state for which compaction is allowed.
         app.mState.setSetProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
-        app.mState.setSetAdj(905);
+        app.mState.setSetAdj(899);
+        app.mState.setCurAdj(940);
         return app;
     }
 
@@ -164,8 +165,6 @@
                 CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE);
         assertThat(mCachedAppOptimizerUnderTest.mFreezerStatsdSampleRate).isEqualTo(
                 CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE);
-        assertThat(mCachedAppOptimizerUnderTest.mFullAnonRssThrottleKb).isEqualTo(
-                CachedAppOptimizer.DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB);
         assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleBFGS).isEqualTo(
                 CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5);
         assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo(
@@ -176,6 +175,11 @@
                 CachedAppOptimizer.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB);
         assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isEqualTo(
                 CachedAppOptimizer.DEFAULT_USE_FREEZER);
+        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMinOomAdj).isEqualTo(
+                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ);
+        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMaxOomAdj).isEqualTo(
+                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ);
+
 
         Set<Integer> expected = new HashSet<>();
         for (String s : TextUtils.split(
@@ -231,6 +235,14 @@
                 Long.toString(
                         CachedAppOptimizer.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB + 1), false);
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                CachedAppOptimizer.KEY_COMPACT_THROTTLE_MIN_OOM_ADJ,
+                Long.toString(
+                        CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ + 10), false);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                CachedAppOptimizer.KEY_COMPACT_THROTTLE_MAX_OOM_ADJ,
+                Long.toString(
+                    CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ - 10), false);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                 CachedAppOptimizer.KEY_COMPACT_PROC_STATE_THROTTLE, "1,2,3", false);
         assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isEqualTo(
                 CachedAppOptimizer.DEFAULT_USE_FREEZER);
@@ -261,6 +273,12 @@
                 CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5 + 1);
         assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo(
                 CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_6 + 1);
+        assertThat(mCachedAppOptimizerUnderTest.mFullDeltaRssThrottleKb).isEqualTo(
+                CachedAppOptimizer.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB + 1);
+        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMinOomAdj).isEqualTo(
+                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ + 10);
+        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMaxOomAdj).isEqualTo(
+                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ - 10);
         assertThat(mCachedAppOptimizerUnderTest.mCompactStatsdSampleRate).isEqualTo(
                 CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE + 0.1f);
         assertThat(mCachedAppOptimizerUnderTest.mFreezerStatsdSampleRate).isEqualTo(
@@ -437,7 +455,7 @@
         mCachedAppOptimizerUnderTest.init();
 
         // When we override new reasonable throttle values after init...
-        mCountDown = new CountDownLatch(6);
+        mCountDown = new CountDownLatch(8);
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                 CachedAppOptimizer.KEY_COMPACT_THROTTLE_1,
                 Long.toString(CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_1 + 1), false);
@@ -456,7 +474,13 @@
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                 CachedAppOptimizer.KEY_COMPACT_THROTTLE_6,
                 Long.toString(CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_6 + 1), false);
-        assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                CachedAppOptimizer.KEY_COMPACT_THROTTLE_MIN_OOM_ADJ,
+                Long.toString(CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ + 1), false);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                CachedAppOptimizer.KEY_COMPACT_THROTTLE_MAX_OOM_ADJ,
+                Long.toString(CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ - 1), false);
+        assertThat(mCountDown.await(7, TimeUnit.SECONDS)).isTrue();
 
         // Then those flags values are reflected in the compactor.
         assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleSomeSome).isEqualTo(
@@ -471,6 +495,10 @@
                 CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5 + 1);
         assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo(
                 CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_6 + 1);
+        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMinOomAdj).isEqualTo(
+                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ + 1);
+        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMaxOomAdj).isEqualTo(
+                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ - 1);
     }
 
     @Test
@@ -902,7 +930,6 @@
         valuesAfter = mCachedAppOptimizerUnderTest.mLastCompactionStats.get(
                 pid).getRssAfterCompaction();
         assertThat(valuesAfter).isEqualTo(rssAfter3);
-
     }
 
     @Test
@@ -954,6 +981,54 @@
         assertThat(valuesAfter).isEqualTo(rssAboveThresholdAfter);
     }
 
+    @Test
+    public void processWithOomAdjTooSmall_notFullCompacted() throws Exception {
+        // Initialize CachedAppOptimizer and set flags to (1) enable compaction, (2) set Min and
+        // Max OOM_Adj throttles.
+        mCachedAppOptimizerUnderTest.init();
+        setFlag(CachedAppOptimizer.KEY_USE_COMPACTION, "true", true);
+        setFlag(CachedAppOptimizer.KEY_COMPACT_THROTTLE_MIN_OOM_ADJ, Long.toString(920), true);
+        setFlag(CachedAppOptimizer.KEY_COMPACT_THROTTLE_MAX_OOM_ADJ, Long.toString(950), true);
+        initActivityManagerService();
+
+        // Simulate RSS memory for which compaction should occur.
+        long[] rssBefore =
+            new long[]{/*Total RSS*/ 15000, /*File RSS*/ 15000, /*Anon RSS*/ 15000,
+                /*Swap*/ 10000};
+        long[] rssAfter =
+            new long[]{/*Total RSS*/ 8000, /*File RSS*/ 9000, /*Anon RSS*/ 6000, /*Swap*/5000};
+        // Process that passes properties.
+        int pid = 1;
+        ProcessRecord processRecord =
+                makeProcessRecord(pid, 2, 3, "p1", "app1");
+        mProcessDependencies.setRss(rssBefore);
+        mProcessDependencies.setRssAfterCompaction(rssAfter);
+
+        // Compaction should occur if (setAdj < min for process || setAdj > max for process) &&
+        // (MIN < curAdj <  MAX)
+        // GIVEN OomAdj score below threshold.
+        processRecord.mState.setSetAdj(899);
+        processRecord.mState.setCurAdj(970);
+        // WHEN we try to run compaction
+        mCachedAppOptimizerUnderTest.compactAppFull(processRecord);
+        waitForHandler();
+        // THEN process IS NOT compacted.
+        assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNull();
+
+        // GIVEN (setAdj < MIN || setAdj > MAX) && (MIN < curAdj <  MAX)
+        processRecord.mState.setSetAdj(910);
+        processRecord.mState.setCurAdj(930);
+        // WHEN we try to run compaction
+        mCachedAppOptimizerUnderTest.compactAppFull(processRecord);
+        waitForHandler();
+        // THEN process IS compacted.
+        assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNotNull();
+        long[] valuesAfter = mCachedAppOptimizerUnderTest.mLastCompactionStats
+            .get(pid)
+            .getRssAfterCompaction();
+        assertThat(valuesAfter).isEqualTo(rssAfter);
+    }
+
 
     private void setFlag(String key, String value, boolean defaultValue) throws Exception {
         mCountDown = new CountDownLatch(1);
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 27825a4..1c45203 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -46,6 +46,7 @@
 import static com.android.server.am.ProcessList.HOME_APP_ADJ;
 import static com.android.server.am.ProcessList.PERCEPTIBLE_APP_ADJ;
 import static com.android.server.am.ProcessList.PERCEPTIBLE_LOW_APP_ADJ;
+import static com.android.server.am.ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ;
 import static com.android.server.am.ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ;
 import static com.android.server.am.ProcessList.PERSISTENT_PROC_ADJ;
 import static com.android.server.am.ProcessList.PERSISTENT_SERVICE_ADJ;
@@ -64,6 +65,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.AdditionalAnswers.answer;
 import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyBoolean;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.anyLong;
 import static org.mockito.Mockito.doAnswer;
@@ -73,6 +75,8 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 
+import android.app.ActivityManager;
+import android.app.AppOpsManager;
 import android.app.IApplicationThread;
 import android.app.IServiceConnection;
 import android.content.ComponentName;
@@ -178,11 +182,20 @@
         setFieldValue(ActivityManagerService.class, sService, "mAppProfiler", profiler);
         setFieldValue(ActivityManagerService.class, sService, "mProcLock",
                 new ActivityManagerProcLock());
+        setFieldValue(ActivityManagerService.class, sService, "mServices",
+                spy(new ActiveServices(sService)));
+        setFieldValue(ActivityManagerService.class, sService, "mInternal",
+                mock(ActivityManagerService.LocalService.class));
+        setFieldValue(ActivityManagerService.class, sService, "mBatteryStatsService",
+                mock(BatteryStatsService.class));
+        doReturn(mock(AppOpsManager.class)).when(sService).getAppOpsManager();
+        doCallRealMethod().when(sService).enqueueOomAdjTargetLocked(any(ProcessRecord.class));
+        doCallRealMethod().when(sService).updateOomAdjPendingTargetsLocked(any(String.class));
         setFieldValue(AppProfiler.class, profiler, "mProfilerLock", new Object());
         doReturn(new ActivityManagerService.ProcessChangeItem()).when(pr)
                 .enqueueProcessChangeItemLocked(anyInt(), anyInt());
         sService.mOomAdjuster = new OomAdjuster(sService, sService.mProcessList,
-                mock(ActiveUids.class));
+                new ActiveUids(sService, false));
         sService.mOomAdjuster.mAdjSeq = 10000;
         sService.mWakefulness = new AtomicInteger(PowerManagerInternal.WAKEFULNESS_AWAKE);
     }
@@ -865,6 +878,39 @@
 
     @SuppressWarnings("GuardedBy")
     @Test
+    public void testUpdateOomAdj_DoOne_Service_MediumPerceptible() {
+        {
+            ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+                    MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+            ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+                    MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+            bindService(app, client, null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
+            client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
+            sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+            sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+            assertEquals(PERCEPTIBLE_MEDIUM_APP_ADJ, app.mState.getSetAdj());
+        }
+
+        {
+            ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+                    MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+            ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+                    MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+            WindowProcessController wpc = client.getWindowProcessController();
+            doReturn(true).when(wpc).isHeavyWeightProcess();
+            bindService(app, client, null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
+            client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
+            sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+            sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+            doReturn(false).when(wpc).isHeavyWeightProcess();
+
+            assertEquals(PERCEPTIBLE_MEDIUM_APP_ADJ, app.mState.getSetAdj());
+        }
+    }
+
+    @SuppressWarnings("GuardedBy")
+    @Test
     public void testUpdateOomAdj_DoOne_Service_Other() {
         ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
@@ -1315,6 +1361,115 @@
 
     @SuppressWarnings("GuardedBy")
     @Test
+    public void testUpdateOomAdj_UidIdle_StopService() {
+        final ProcessRecord app1 = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+                MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+        final ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+                MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+        final ProcessRecord client1 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+                MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+        final ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP3_UID,
+                MOCKAPP4_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+        final ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP5_PID, MOCKAPP5_UID,
+                MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
+        final UidRecord app1UidRecord = new UidRecord(MOCKAPP_UID, sService);
+        final UidRecord app2UidRecord = new UidRecord(MOCKAPP2_UID, sService);
+        final UidRecord app3UidRecord = new UidRecord(MOCKAPP5_UID, sService);
+        final UidRecord clientUidRecord = new UidRecord(MOCKAPP3_UID, sService);
+        app1.setUidRecord(app1UidRecord);
+        app2.setUidRecord(app2UidRecord);
+        app3.setUidRecord(app3UidRecord);
+        client1.setUidRecord(clientUidRecord);
+        client2.setUidRecord(clientUidRecord);
+
+        client1.mServices.setHasForegroundServices(true, 0);
+        client2.mState.setForcingToImportant(new Object());
+        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
+        lru.clear();
+        lru.add(app1);
+        lru.add(app2);
+        lru.add(app3);
+        lru.add(client1);
+        lru.add(client2);
+        sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+
+        final ComponentName cn1 = ComponentName.unflattenFromString(
+                MOCKAPP_PACKAGENAME + "/.TestService");
+        final ServiceRecord s1 = bindService(app1, client1, null, 0, mock(IBinder.class));
+        setFieldValue(ServiceRecord.class, s1, "name", cn1);
+        s1.startRequested = true;
+
+        final ComponentName cn2 = ComponentName.unflattenFromString(
+                MOCKAPP2_PACKAGENAME + "/.TestService");
+        final ServiceRecord s2 = bindService(app2, client2, null, 0, mock(IBinder.class));
+        setFieldValue(ServiceRecord.class, s2, "name", cn2);
+        s2.startRequested = true;
+
+        final ComponentName cn3 = ComponentName.unflattenFromString(
+                MOCKAPP5_PACKAGENAME + "/.TestService");
+        final ServiceRecord s3 = bindService(app3, client1, null, 0, mock(IBinder.class));
+        setFieldValue(ServiceRecord.class, s3, "name", cn3);
+        s3.startRequested = true;
+
+        final ComponentName cn4 = ComponentName.unflattenFromString(
+                MOCKAPP3_PACKAGENAME + "/.TestService");
+        final ServiceRecord c2s = makeServiceRecord(client2);
+        setFieldValue(ServiceRecord.class, c2s, "name", cn4);
+        c2s.startRequested = true;
+
+        try {
+            sService.mOomAdjuster.mActiveUids.put(MOCKAPP_UID, app1UidRecord);
+            sService.mOomAdjuster.mActiveUids.put(MOCKAPP2_UID, app2UidRecord);
+            sService.mOomAdjuster.mActiveUids.put(MOCKAPP5_UID, app3UidRecord);
+            sService.mOomAdjuster.mActiveUids.put(MOCKAPP3_UID, clientUidRecord);
+
+            setServiceMap(s1, MOCKAPP_UID, cn1);
+            setServiceMap(s2, MOCKAPP2_UID, cn2);
+            setServiceMap(s3, MOCKAPP5_UID, cn3);
+            setServiceMap(c2s, MOCKAPP3_UID, cn4);
+            app2UidRecord.setIdle(false);
+            sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
+
+            assertProcStates(app1, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+                    SCHED_GROUP_DEFAULT);
+            assertProcStates(app3, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+                    SCHED_GROUP_DEFAULT);
+            assertProcStates(client1, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+                    SCHED_GROUP_DEFAULT);
+            assertEquals(PROCESS_STATE_TRANSIENT_BACKGROUND, app2.mState.getSetProcState());
+            assertEquals(PROCESS_STATE_TRANSIENT_BACKGROUND, client2.mState.getSetProcState());
+
+            client1.mServices.setHasForegroundServices(false, 0);
+            client2.mState.setForcingToImportant(null);
+            app1UidRecord.reset();
+            app2UidRecord.reset();
+            app3UidRecord.reset();
+            clientUidRecord.reset();
+            app1UidRecord.setIdle(true);
+            app2UidRecord.setIdle(true);
+            app3UidRecord.setIdle(true);
+            clientUidRecord.setIdle(true);
+            doReturn(ActivityManager.APP_START_MODE_DELAYED).when(sService)
+                    .getAppStartModeLOSP(anyInt(), any(String.class), anyInt(),
+                    anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
+            doNothing().when(sService.mServices)
+                    .scheduleServiceTimeoutLocked(any(ProcessRecord.class));
+            sService.mOomAdjuster.updateOomAdjLocked(client1, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+            assertEquals(PROCESS_STATE_CACHED_EMPTY, client1.mState.getSetProcState());
+            assertEquals(PROCESS_STATE_SERVICE, app1.mState.getSetProcState());
+            assertEquals(PROCESS_STATE_SERVICE, client2.mState.getSetProcState());
+        } finally {
+            doCallRealMethod().when(sService)
+                    .getAppStartModeLOSP(anyInt(), any(String.class), anyInt(),
+                    anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
+            sService.mServices.mServiceMap.clear();
+            sService.mOomAdjuster.mActiveUids.clear();
+        }
+    }
+
+    @SuppressWarnings("GuardedBy")
+    @Test
     public void testUpdateOomAdj_DoAll_Unbound() {
         ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
@@ -1815,15 +1970,42 @@
         return app;
     }
 
+    private ServiceRecord makeServiceRecord(ProcessRecord app) {
+        final ServiceRecord record = mock(ServiceRecord.class);
+        record.app = app;
+        setFieldValue(ServiceRecord.class, record, "connections",
+                new ArrayMap<IBinder, ArrayList<ConnectionRecord>>());
+        doCallRealMethod().when(record).getConnections();
+        setFieldValue(ServiceRecord.class, record, "packageName", app.info.packageName);
+        app.mServices.startService(record);
+        record.appInfo = app.info;
+        setFieldValue(ServiceRecord.class, record, "bindings", new ArrayMap<>());
+        setFieldValue(ServiceRecord.class, record, "pendingStarts", new ArrayList<>());
+        return record;
+    }
+
+    private void setServiceMap(ServiceRecord s, int uid, ComponentName cn) {
+        ActiveServices.ServiceMap serviceMap = sService.mServices.mServiceMap.get(
+                UserHandle.getUserId(uid));
+        if (serviceMap == null) {
+            serviceMap = mock(ActiveServices.ServiceMap.class);
+            setFieldValue(ActiveServices.ServiceMap.class, serviceMap, "mServicesByInstanceName",
+                    new ArrayMap<>());
+            setFieldValue(ActiveServices.ServiceMap.class, serviceMap, "mActiveForegroundApps",
+                    new ArrayMap<>());
+            setFieldValue(ActiveServices.ServiceMap.class, serviceMap, "mServicesByIntent",
+                    new ArrayMap<>());
+            setFieldValue(ActiveServices.ServiceMap.class, serviceMap, "mDelayedStartList",
+                    new ArrayList<>());
+            sService.mServices.mServiceMap.put(UserHandle.getUserId(uid), serviceMap);
+        }
+        serviceMap.mServicesByInstanceName.put(cn, s);
+    }
+
     private ServiceRecord bindService(ProcessRecord service, ProcessRecord client,
             ServiceRecord record, int bindFlags, IBinder binder) {
         if (record == null) {
-            record = mock(ServiceRecord.class);
-            record.app = service;
-            setFieldValue(ServiceRecord.class, record, "connections",
-                    new ArrayMap<IBinder, ArrayList<ConnectionRecord>>());
-            service.mServices.startService(record);
-            doCallRealMethod().when(record).getConnections();
+            record = makeServiceRecord(service);
         }
         AppBindRecord binding = new AppBindRecord(record, null, client);
         ConnectionRecord cr = spy(new ConnectionRecord(binding,
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index ca53492..18184b0 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -25,11 +25,16 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.content.res.Resources;
+import android.content.res.TypedArray;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -42,6 +47,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.dx.mockito.inline.extended.StaticMockitoSession;
+import com.android.internal.R;
 import com.android.server.LocalServices;
 import com.android.server.display.LocalDisplayAdapter.BacklightAdapter;
 import com.android.server.lights.LightsManager;
@@ -94,11 +100,16 @@
 
     private Injector mInjector;
 
+    @Mock
+    private LocalDisplayAdapter.SurfaceControlProxy mSurfaceControlProxy;
+    private static final float[] DISPLAY_RANGE_NITS = { 2.685f, 478.5f };
+    private static final int[] BACKLIGHT_RANGE = { 1, 255 };
+    private static final float[] BACKLIGHT_RANGE_ZERO_TO_ONE = { 0.0f, 1.0f };
+
     @Before
     public void setUp() throws Exception {
         mMockitoSession = mockitoSession()
                 .initMocks(this)
-                .mockStatic(SurfaceControl.class)
                 .strictness(Strictness.LENIENT)
                 .startMocking();
         mHandler = new Handler(Looper.getMainLooper());
@@ -110,6 +121,18 @@
                 mListener, mInjector);
         spyOn(mAdapter);
         doReturn(mMockedContext).when(mAdapter).getOverlayContext();
+
+        TypedArray mockNitsRange = createFloatTypedArray(DISPLAY_RANGE_NITS);
+        when(mMockedResources.obtainTypedArray(R.array.config_screenBrightnessNits))
+                .thenReturn(mockNitsRange);
+        when(mMockedResources.getIntArray(R.array.config_screenBrightnessBacklight))
+                .thenReturn(BACKLIGHT_RANGE);
+        when(mMockedResources.getFloat(com.android.internal.R.dimen
+                .config_screenBrightnessSettingMinimumFloat))
+                .thenReturn(BACKLIGHT_RANGE_ZERO_TO_ONE[0]);
+        when(mMockedResources.getFloat(com.android.internal.R.dimen
+                .config_screenBrightnessSettingMaximumFloat))
+                .thenReturn(BACKLIGHT_RANGE_ZERO_TO_ONE[1]);
     }
 
     @After
@@ -223,10 +246,11 @@
         for (int i = 0; i < wrappedModes.length; i++) {
             modes[i] = wrappedModes[i].mode;
         }
-        display.modes = modes;
+        display.dynamicInfo.supportedDisplayModes = modes;
         setUpDisplay(display);
         mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
         waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+        assertTrue(mListener.traversalRequested);
         assertThat(mListener.changedDisplays.size()).isGreaterThan(0);
 
         // Verify the supported modes are updated accordingly.
@@ -252,53 +276,53 @@
 
         testAlternativeRefreshRatesCommon(display, new DisplayModeWrapper[] {
                 new DisplayModeWrapper(
-                        createFakeDisplayMode(1920, 1080, 60f, 0), new float[]{24f, 50f}),
+                        createFakeDisplayMode(0, 1920, 1080, 60f, 0), new float[]{24f, 50f}),
                 new DisplayModeWrapper(
-                        createFakeDisplayMode(1920, 1080, 50f, 0), new float[]{24f, 60f}),
+                        createFakeDisplayMode(1, 1920, 1080, 50f, 0), new float[]{24f, 60f}),
                 new DisplayModeWrapper(
-                        createFakeDisplayMode(1920, 1080, 24f, 0), new float[]{50f, 60f}),
+                        createFakeDisplayMode(2, 1920, 1080, 24f, 0), new float[]{50f, 60f}),
                 new DisplayModeWrapper(
-                        createFakeDisplayMode(3840, 2160, 60f, 0), new float[]{24f, 50f}),
+                        createFakeDisplayMode(3, 3840, 2160, 60f, 0), new float[]{24f, 50f}),
                 new DisplayModeWrapper(
-                        createFakeDisplayMode(3840, 2160, 50f, 0), new float[]{24f, 60f}),
+                        createFakeDisplayMode(4, 3840, 2160, 50f, 0), new float[]{24f, 60f}),
                 new DisplayModeWrapper(
-                        createFakeDisplayMode(3840, 2160, 24f, 0), new float[]{50f, 60f}),
+                        createFakeDisplayMode(5, 3840, 2160, 24f, 0), new float[]{50f, 60f}),
         });
 
         testAlternativeRefreshRatesCommon(display, new DisplayModeWrapper[] {
                 new DisplayModeWrapper(
-                        createFakeDisplayMode(1920, 1080, 60f, 0), new float[]{50f}),
+                        createFakeDisplayMode(0, 1920, 1080, 60f, 0), new float[]{50f}),
                 new DisplayModeWrapper(
-                        createFakeDisplayMode(1920, 1080, 50f, 0), new float[]{60f}),
+                        createFakeDisplayMode(1, 1920, 1080, 50f, 0), new float[]{60f}),
                 new DisplayModeWrapper(
-                        createFakeDisplayMode(1920, 1080, 24f, 1), new float[0]),
+                        createFakeDisplayMode(2, 1920, 1080, 24f, 1), new float[0]),
                 new DisplayModeWrapper(
-                        createFakeDisplayMode(3840, 2160, 60f, 2), new float[0]),
+                        createFakeDisplayMode(3, 3840, 2160, 60f, 2), new float[0]),
                 new DisplayModeWrapper(
-                        createFakeDisplayMode(3840, 2160, 50f, 3), new float[]{24f}),
+                        createFakeDisplayMode(4, 3840, 2160, 50f, 3), new float[]{24f}),
                 new DisplayModeWrapper(
-                        createFakeDisplayMode(3840, 2160, 24f, 3), new float[]{50f}),
+                        createFakeDisplayMode(5, 3840, 2160, 24f, 3), new float[]{50f}),
         });
 
         testAlternativeRefreshRatesCommon(display, new DisplayModeWrapper[] {
                 new DisplayModeWrapper(
-                        createFakeDisplayMode(1920, 1080, 60f, 0), new float[0]),
+                        createFakeDisplayMode(0, 1920, 1080, 60f, 0), new float[0]),
                 new DisplayModeWrapper(
-                        createFakeDisplayMode(1920, 1080, 50f, 1), new float[0]),
+                        createFakeDisplayMode(1, 1920, 1080, 50f, 1), new float[0]),
                 new DisplayModeWrapper(
-                        createFakeDisplayMode(1920, 1080, 24f, 2), new float[0]),
+                        createFakeDisplayMode(2, 1920, 1080, 24f, 2), new float[0]),
                 new DisplayModeWrapper(
-                        createFakeDisplayMode(3840, 2160, 60f, 3), new float[0]),
+                        createFakeDisplayMode(3, 3840, 2160, 60f, 3), new float[0]),
                 new DisplayModeWrapper(
-                        createFakeDisplayMode(3840, 2160, 50f, 4), new float[0]),
+                        createFakeDisplayMode(4, 3840, 2160, 50f, 4), new float[0]),
                 new DisplayModeWrapper(
-                        createFakeDisplayMode(3840, 2160, 24f, 5), new float[0]),
+                        createFakeDisplayMode(5, 3840, 2160, 24f, 5), new float[0]),
         });
     }
 
     @Test
     public void testAfterDisplayChange_DisplayModesAreUpdated() throws Exception {
-        SurfaceControl.DisplayMode displayMode = createFakeDisplayMode(1920, 1080, 60f);
+        SurfaceControl.DisplayMode displayMode = createFakeDisplayMode(0, 1920, 1080, 60f);
         SurfaceControl.DisplayMode[] modes =
                 new SurfaceControl.DisplayMode[]{displayMode};
         FakeDisplay display = new FakeDisplay(PORT_A, modes, 0);
@@ -325,18 +349,15 @@
                 displayMode.refreshRate)).isTrue();
 
         // Change the display
-        SurfaceControl.DisplayMode addedDisplayInfo = createFakeDisplayMode(3840, 2160,
-                60f);
+        SurfaceControl.DisplayMode addedDisplayInfo = createFakeDisplayMode(1, 3840, 2160, 60f);
         modes = new SurfaceControl.DisplayMode[]{displayMode, addedDisplayInfo};
-        display.modes = modes;
-        display.activeMode = 1;
+        display.dynamicInfo.supportedDisplayModes = modes;
+        display.dynamicInfo.activeDisplayModeId = 1;
         setUpDisplay(display);
         mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
         waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
 
-        assertThat(SurfaceControl.getActiveDisplayMode(display.token)).isEqualTo(1);
-        assertThat(SurfaceControl.getDisplayModes(display.token).length).isEqualTo(2);
-
+        assertTrue(mListener.traversalRequested);
         assertThat(mListener.addedDisplays.size()).isEqualTo(1);
         assertThat(mListener.changedDisplays.size()).isEqualTo(1);
 
@@ -360,8 +381,8 @@
     @Test
     public void testAfterDisplayChange_ActiveModeIsUpdated() throws Exception {
         SurfaceControl.DisplayMode[] modes = new SurfaceControl.DisplayMode[]{
-                createFakeDisplayMode(1920, 1080, 60f),
-                createFakeDisplayMode(1920, 1080, 50f)
+                createFakeDisplayMode(0, 1920, 1080, 60f),
+                createFakeDisplayMode(1, 1920, 1080, 50f)
         };
         FakeDisplay display = new FakeDisplay(PORT_A, modes, /* activeMode */ 0);
         setUpDisplay(display);
@@ -379,13 +400,12 @@
         assertThat(activeMode.matches(1920, 1080, 60f)).isTrue();
 
         // Change the display
-        display.activeMode = 1;
+        display.dynamicInfo.activeDisplayModeId = 1;
         setUpDisplay(display);
         mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
         waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
 
-        assertThat(SurfaceControl.getActiveDisplayMode(display.token)).isEqualTo(1);
-
+        assertTrue(mListener.traversalRequested);
         assertThat(mListener.addedDisplays.size()).isEqualTo(1);
         assertThat(mListener.changedDisplays.size()).isEqualTo(1);
 
@@ -402,7 +422,7 @@
         FakeDisplay display = new FakeDisplay(PORT_A);
         Display.HdrCapabilities initialHdrCapabilities = new Display.HdrCapabilities(new int[0],
                 1000, 1000, 0);
-        display.hdrCapabilities = initialHdrCapabilities;
+        display.dynamicInfo.hdrCapabilities = initialHdrCapabilities;
         setUpDisplay(display);
         updateAvailableDisplays();
         mAdapter.registerLocked();
@@ -419,11 +439,12 @@
         // Change the display
         Display.HdrCapabilities changedHdrCapabilities = new Display.HdrCapabilities(
                 new int[Display.HdrCapabilities.HDR_TYPE_HDR10_PLUS], 1000, 1000, 0);
-        display.hdrCapabilities = changedHdrCapabilities;
+        display.dynamicInfo.hdrCapabilities = changedHdrCapabilities;
         setUpDisplay(display);
         mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
         waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
 
+        assertTrue(mListener.traversalRequested);
         assertThat(mListener.addedDisplays.size()).isEqualTo(1);
         assertThat(mListener.changedDisplays.size()).isEqualTo(1);
 
@@ -435,10 +456,78 @@
     }
 
     @Test
+    public void testAfterDisplayChange_AllmSupportIsUpdated() throws Exception {
+        FakeDisplay display = new FakeDisplay(PORT_A);
+        display.dynamicInfo.autoLowLatencyModeSupported = true;
+        setUpDisplay(display);
+        updateAvailableDisplays();
+        mAdapter.registerLocked();
+        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+
+        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
+        assertThat(mListener.changedDisplays).isEmpty();
+
+        DisplayDeviceInfo displayDeviceInfo = mListener.addedDisplays.get(0)
+                .getDisplayDeviceInfoLocked();
+
+        assertThat(displayDeviceInfo.allmSupported).isTrue();
+
+        // Change the display
+        display.dynamicInfo.autoLowLatencyModeSupported = false;
+        setUpDisplay(display);
+        mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
+        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+
+        assertTrue(mListener.traversalRequested);
+        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
+        assertThat(mListener.changedDisplays.size()).isEqualTo(1);
+
+        DisplayDevice displayDevice = mListener.changedDisplays.get(0);
+        displayDevice.applyPendingDisplayDeviceInfoChangesLocked();
+        displayDeviceInfo = displayDevice.getDisplayDeviceInfoLocked();
+
+        assertThat(displayDeviceInfo.allmSupported).isFalse();
+    }
+
+    @Test
+    public void testAfterDisplayChange_GameContentTypeSupportIsUpdated() throws Exception {
+        FakeDisplay display = new FakeDisplay(PORT_A);
+        display.dynamicInfo.gameContentTypeSupported = true;
+        setUpDisplay(display);
+        updateAvailableDisplays();
+        mAdapter.registerLocked();
+        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+
+        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
+        assertThat(mListener.changedDisplays).isEmpty();
+
+        DisplayDeviceInfo displayDeviceInfo = mListener.addedDisplays.get(0)
+                .getDisplayDeviceInfoLocked();
+
+        assertThat(displayDeviceInfo.gameContentTypeSupported).isTrue();
+
+        // Change the display
+        display.dynamicInfo.gameContentTypeSupported = false;
+        setUpDisplay(display);
+        mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
+        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+
+        assertTrue(mListener.traversalRequested);
+        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
+        assertThat(mListener.changedDisplays.size()).isEqualTo(1);
+
+        DisplayDevice displayDevice = mListener.changedDisplays.get(0);
+        displayDevice.applyPendingDisplayDeviceInfoChangesLocked();
+        displayDeviceInfo = displayDevice.getDisplayDeviceInfoLocked();
+
+        assertThat(displayDeviceInfo.gameContentTypeSupported).isFalse();
+    }
+
+    @Test
     public void testAfterDisplayChange_ColorModesAreUpdated() throws Exception {
         FakeDisplay display = new FakeDisplay(PORT_A);
         final int[] initialColorModes = new int[]{Display.COLOR_MODE_BT709};
-        display.colorModes = initialColorModes;
+        display.dynamicInfo.supportedColorModes = initialColorModes;
         setUpDisplay(display);
         updateAvailableDisplays();
         mAdapter.registerLocked();
@@ -455,11 +544,12 @@
 
         // Change the display
         final int[] changedColorModes = new int[]{Display.COLOR_MODE_DEFAULT};
-        display.colorModes = changedColorModes;
+        display.dynamicInfo.supportedColorModes = changedColorModes;
         setUpDisplay(display);
         mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
         waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
 
+        assertTrue(mListener.traversalRequested);
         assertThat(mListener.addedDisplays.size()).isEqualTo(1);
         assertThat(mListener.changedDisplays.size()).isEqualTo(1);
 
@@ -474,8 +564,8 @@
     @Test
     public void testDisplayChange_withStaleDesiredDisplayModeSpecs() throws Exception {
         SurfaceControl.DisplayMode[] modes = new SurfaceControl.DisplayMode[]{
-                createFakeDisplayMode(1920, 1080, 60f),
-                createFakeDisplayMode(1920, 1080, 50f)
+                createFakeDisplayMode(0, 1920, 1080, 60f),
+                createFakeDisplayMode(1, 1920, 1080, 50f)
         };
         final int activeMode = 0;
         FakeDisplay display = new FakeDisplay(PORT_A, modes, activeMode);
@@ -486,58 +576,111 @@
         mAdapter.registerLocked();
         waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
 
+        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
+        DisplayDevice displayDevice = mListener.addedDisplays.get(0);
+
+        int baseModeId = Arrays.stream(displayDevice.getDisplayDeviceInfoLocked().supportedModes)
+                .filter(mode -> mode.getRefreshRate() == 60f)
+                .findFirst()
+                .get()
+                .getModeId();
+
+        displayDevice.setDesiredDisplayModeSpecsLocked(
+                new DisplayModeDirector.DesiredDisplayModeSpecs(
+                        /*baseModeId*/ baseModeId,
+                        /*allowGroupSwitching*/ false,
+                        new DisplayModeDirector.RefreshRateRange(60f, 60f),
+                        new DisplayModeDirector.RefreshRateRange(60f, 60f)
+                ));
+        verify(mSurfaceControlProxy).setDesiredDisplayModeSpecs(display.token,
+                new SurfaceControl.DesiredDisplayModeSpecs(
+                        /* baseModeId */ 0,
+                        /* allowGroupSwitching */ false,
+                        /* primaryRange */ 60f, 60f,
+                        /* appRange */ 60f, 60f
+                ));
+
         // Change the display
-        display.modes = new SurfaceControl.DisplayMode[]{
-                createFakeDisplayMode(1920, 1080, 60f)
+        display.dynamicInfo.supportedDisplayModes = new SurfaceControl.DisplayMode[]{
+                createFakeDisplayMode(2, 1920, 1080, 60f)
         };
-        // SurfaceFlinger can return a stale defaultMode. Make sure this doesn't
-        // trigger ArrayOutOfBoundsException.
+        display.dynamicInfo.activeDisplayModeId = 2;
+        // SurfaceFlinger can return a stale defaultMode. Make sure this doesn't crash.
         display.desiredDisplayModeSpecs.defaultMode = 1;
 
         setUpDisplay(display);
-        updateAvailableDisplays();
         mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
         waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+
+        assertTrue(mListener.traversalRequested);
+
+        displayDevice.applyPendingDisplayDeviceInfoChangesLocked();
+
+        baseModeId = displayDevice.getDisplayDeviceInfoLocked().supportedModes[0].getModeId();
+
+        // The traversal request will call setDesiredDisplayModeSpecsLocked on the display device
+        displayDevice.setDesiredDisplayModeSpecsLocked(
+                new DisplayModeDirector.DesiredDisplayModeSpecs(
+                        /*baseModeId*/ baseModeId,
+                        /*allowGroupSwitching*/ false,
+                        new DisplayModeDirector.RefreshRateRange(60f, 60f),
+                        new DisplayModeDirector.RefreshRateRange(60f, 60f)
+                ));
+
+        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+
+        // Verify that this will reapply the desired modes.
+        verify(mSurfaceControlProxy).setDesiredDisplayModeSpecs(display.token,
+                new SurfaceControl.DesiredDisplayModeSpecs(
+                        /* baseModeId */ 2,
+                        /* allowGroupSwitching */ false,
+                        /* primaryRange */ 60f, 60f,
+                        /* appRange */ 60f, 60f
+                ));
     }
 
     @Test
     public void testBacklightAdapter_withSurfaceControlSupport() {
         final Binder displayToken = new Binder();
-        doReturn(true).when(() -> SurfaceControl.getDisplayBrightnessSupport(displayToken));
+
+        when(mSurfaceControlProxy.getDisplayBrightnessSupport(displayToken)).thenReturn(true);
 
         // Test as default display
-        BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/);
-        ba.setBrightness(0.514f);
-        verify(() -> SurfaceControl.setDisplayBrightness(displayToken, 0.514f));
+        BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/,
+                mSurfaceControlProxy);
+        ba.setBacklight(0.514f);
+        verify(mSurfaceControlProxy).setDisplayBrightness(displayToken, 0.514f);
 
         // Test as not default display
-        BacklightAdapter ba2 = new BacklightAdapter(displayToken,
-                false /*isDefault*/);
-        ba2.setBrightness(0.323f);
-        verify(() -> SurfaceControl.setDisplayBrightness(displayToken, 0.323f));
+        BacklightAdapter ba2 = new BacklightAdapter(displayToken, false /*isDefault*/,
+                mSurfaceControlProxy);
+        ba2.setBacklight(0.323f);
+        verify(mSurfaceControlProxy).setDisplayBrightness(displayToken, 0.323f);
     }
 
     @Test
     public void testBacklightAdapter_withoutSourceControlSupport_defaultDisplay() {
         final Binder displayToken = new Binder();
-        doReturn(false).when(() -> SurfaceControl.getDisplayBrightnessSupport(displayToken));
+        when(mSurfaceControlProxy.getDisplayBrightnessSupport(displayToken)).thenReturn(false);
         doReturn(mMockedBacklight).when(mMockedLightsManager)
                 .getLight(LightsManager.LIGHT_ID_BACKLIGHT);
 
-        BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/);
-        ba.setBrightness(0.123f);
+        BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/,
+                mSurfaceControlProxy);
+        ba.setBacklight(0.123f);
         verify(mMockedBacklight).setBrightness(0.123f);
     }
 
     @Test
     public void testBacklightAdapter_withoutSourceControlSupport_nonDefaultDisplay() {
         final Binder displayToken = new Binder();
-        doReturn(false).when(() -> SurfaceControl.getDisplayBrightnessSupport(displayToken));
+        when(mSurfaceControlProxy.getDisplayBrightnessSupport(displayToken)).thenReturn(false);
         doReturn(mMockedBacklight).when(mMockedLightsManager)
                 .getLight(LightsManager.LIGHT_ID_BACKLIGHT);
 
-        BacklightAdapter ba = new BacklightAdapter(displayToken, false /*isDefault*/);
-        ba.setBrightness(0.456f);
+        BacklightAdapter ba = new BacklightAdapter(displayToken, false /*isDefault*/,
+                mSurfaceControlProxy);
+        ba.setBacklight(0.456f);
 
         // Adapter does not forward any brightness in this case.
         verify(mMockedBacklight, never()).setBrightness(anyFloat());
@@ -588,12 +731,15 @@
     private static class FakeDisplay {
         public final DisplayAddress.Physical address;
         public final IBinder token = new Binder();
-        public final SurfaceControl.DisplayInfo info;
-        public SurfaceControl.DisplayMode[] modes;
-        public int activeMode;
-        public int[] colorModes = new int[]{ Display.COLOR_MODE_DEFAULT };
-        public Display.HdrCapabilities hdrCapabilities = new Display.HdrCapabilities(new int[0],
-                1000, 1000, 0);
+        public final SurfaceControl.StaticDisplayInfo info;
+        public SurfaceControl.DynamicDisplayInfo dynamicInfo =
+                new SurfaceControl.DynamicDisplayInfo();
+        {
+            dynamicInfo.supportedColorModes = new int[]{ Display.COLOR_MODE_DEFAULT };
+            dynamicInfo.hdrCapabilities = new Display.HdrCapabilities(new int[0],
+                    1000, 1000, 0);
+        }
+
         public SurfaceControl.DesiredDisplayModeSpecs desiredDisplayModeSpecs =
                 new SurfaceControl.DesiredDisplayModeSpecs(/* defaultMode */ 0,
                     /* allowGroupSwitching */ false,
@@ -603,37 +749,32 @@
                     /* appRefreshRateMax */60.f);
 
         private FakeDisplay(int port) {
-            this.address = createDisplayAddress(port);
-            this.info = createFakeDisplayInfo();
-            this.modes = new SurfaceControl.DisplayMode[]{
-                    createFakeDisplayMode(800, 600, 60f)
+            address = createDisplayAddress(port);
+            info = createFakeDisplayInfo();
+            dynamicInfo.supportedDisplayModes = new SurfaceControl.DisplayMode[]{
+                    createFakeDisplayMode(0, 800, 600, 60f)
             };
-            this.activeMode = 0;
+            dynamicInfo.activeDisplayModeId = 0;
         }
 
         private FakeDisplay(int port, SurfaceControl.DisplayMode[] modes, int activeMode) {
-            this.address = createDisplayAddress(port);
-            this.info = createFakeDisplayInfo();
-            this.modes = modes;
-            this.activeMode = activeMode;
+            address = createDisplayAddress(port);
+            info = createFakeDisplayInfo();
+            dynamicInfo.supportedDisplayModes = modes;
+            dynamicInfo.activeDisplayModeId = activeMode;
         }
     }
 
     private void setUpDisplay(FakeDisplay display) {
         mAddresses.add(display.address);
-        doReturn(display.token).when(() ->
-                SurfaceControl.getPhysicalDisplayToken(display.address.getPhysicalDisplayId()));
-        doReturn(display.info).when(() -> SurfaceControl.getDisplayInfo(display.token));
-        doReturn(display.modes).when(
-                () -> SurfaceControl.getDisplayModes(display.token));
-        doReturn(display.activeMode).when(() -> SurfaceControl.getActiveDisplayMode(display.token));
-        doReturn(0).when(() -> SurfaceControl.getActiveColorMode(display.token));
-        doReturn(display.colorModes).when(
-                () -> SurfaceControl.getDisplayColorModes(display.token));
-        doReturn(display.hdrCapabilities).when(
-                () -> SurfaceControl.getHdrCapabilities(display.token));
-        doReturn(display.desiredDisplayModeSpecs)
-                .when(() -> SurfaceControl.getDesiredDisplayModeSpecs(display.token));
+        when(mSurfaceControlProxy.getPhysicalDisplayToken(display.address.getPhysicalDisplayId()))
+                .thenReturn(display.token);
+        when(mSurfaceControlProxy.getStaticDisplayInfo(display.token))
+                .thenReturn(display.info);
+        when(mSurfaceControlProxy.getDynamicDisplayInfo(display.token))
+                .thenReturn(display.dynamicInfo);
+        when(mSurfaceControlProxy.getDesiredDisplayModeSpecs(display.token))
+                .thenReturn(display.desiredDisplayModeSpecs);
     }
 
     private void updateAvailableDisplays() {
@@ -643,27 +784,28 @@
             ids[i] = address.getPhysicalDisplayId();
             i++;
         }
-        doReturn(ids).when(() -> SurfaceControl.getPhysicalDisplayIds());
+        when(mSurfaceControlProxy.getPhysicalDisplayIds()).thenReturn(ids);
     }
 
     private static DisplayAddress.Physical createDisplayAddress(int port) {
         return DisplayAddress.fromPortAndModel(port, DISPLAY_MODEL);
     }
 
-    private static SurfaceControl.DisplayInfo createFakeDisplayInfo() {
-        final SurfaceControl.DisplayInfo info = new SurfaceControl.DisplayInfo();
+    private static SurfaceControl.StaticDisplayInfo createFakeDisplayInfo() {
+        final SurfaceControl.StaticDisplayInfo info = new SurfaceControl.StaticDisplayInfo();
         info.density = 100;
         return info;
     }
 
-    private static SurfaceControl.DisplayMode createFakeDisplayMode(int width, int height,
+    private static SurfaceControl.DisplayMode createFakeDisplayMode(int id, int width, int height,
             float refreshRate) {
-        return createFakeDisplayMode(width, height, refreshRate, 0);
+        return createFakeDisplayMode(id, width, height, refreshRate, /* group */ 0);
     }
 
-    private static SurfaceControl.DisplayMode createFakeDisplayMode(int width, int height,
+    private static SurfaceControl.DisplayMode createFakeDisplayMode(int id, int width, int height,
             float refreshRate, int group) {
         final SurfaceControl.DisplayMode mode = new SurfaceControl.DisplayMode();
+        mode.id = id;
         mode.width = width;
         mode.height = height;
         mode.refreshRate = refreshRate;
@@ -710,14 +852,21 @@
                 LocalDisplayAdapter.DisplayEventListener listener) {
             mTransmitter = new HotplugTransmitter(looper, listener);
         }
+
         public HotplugTransmitter getTransmitter() {
             return mTransmitter;
         }
+
+        @Override
+        public LocalDisplayAdapter.SurfaceControlProxy getSurfaceControlProxy() {
+            return mSurfaceControlProxy;
+        }
     }
 
     private class TestListener implements DisplayAdapter.Listener {
         public ArrayList<DisplayDevice> addedDisplays = new ArrayList<>();
         public ArrayList<DisplayDevice> changedDisplays = new ArrayList<>();
+        public boolean traversalRequested = false;
 
         @Override
         public void onDisplayDeviceEvent(DisplayDevice device, int event) {
@@ -730,6 +879,27 @@
 
         @Override
         public void onTraversalRequested() {
+            traversalRequested = true;
         }
     }
+
+    private TypedArray createFloatTypedArray(float[] vals) {
+        TypedArray mockArray = mock(TypedArray.class);
+        when(mockArray.length()).thenAnswer(invocation -> {
+            return vals.length;
+        });
+        when(mockArray.getFloat(anyInt(), anyFloat())).thenAnswer(invocation -> {
+            final float def = (float) invocation.getArguments()[1];
+            if (vals == null) {
+                return def;
+            }
+            int idx = (int) invocation.getArguments()[0];
+            if (idx >= 0 && idx < vals.length) {
+                return vals[idx];
+            } else {
+                return def;
+            }
+        });
+        return mockArray;
+    }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
index 8099eda..f7f5928 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
@@ -19,6 +19,7 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 
@@ -63,7 +64,6 @@
 import com.android.server.LocalServices;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.JobSchedulerService.Constants;
-import com.android.server.job.JobServiceContext;
 import com.android.server.net.NetworkPolicyManagerInternal;
 
 import org.junit.Before;
@@ -144,8 +144,7 @@
                 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
 
         final ConnectivityController controller = new ConnectivityController(mService);
-        when(mService.getMaxJobExecutionTimeMs(any()))
-                .thenReturn(JobServiceContext.DEFAULT_EXECUTING_TIMESLICE_MILLIS);
+        when(mService.getMaxJobExecutionTimeMs(any())).thenReturn(10 * 60_000L);
 
         // Slow network is too slow
         assertFalse(controller.isSatisfied(createJobStatus(job), net,
@@ -613,6 +612,7 @@
 
     private static NetworkCapabilities createCapabilities() {
         return new NetworkCapabilities().addCapability(NET_CAPABILITY_INTERNET)
+                .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
                 .addCapability(NET_CAPABILITY_VALIDATED);
     }
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
index 6d40034..91b3cb7 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
@@ -25,6 +25,7 @@
 import static com.android.server.job.JobSchedulerService.RARE_INDEX;
 import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
 import static com.android.server.job.JobSchedulerService.WORKING_INDEX;
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
 import static com.android.server.job.controllers.JobStatus.CONSTRAINT_BACKGROUND_NOT_RESTRICTED;
 import static com.android.server.job.controllers.JobStatus.CONSTRAINT_BATTERY_NOT_LOW;
 import static com.android.server.job.controllers.JobStatus.CONSTRAINT_CHARGING;
@@ -101,7 +102,7 @@
                 Clock.fixed(Clock.systemUTC().instant(), ZoneOffset.UTC);
         JobSchedulerService.sUptimeMillisClock =
                 Clock.fixed(SystemClock.uptimeClock().instant(), ZoneOffset.UTC);
-        JobSchedulerService.sElapsedRealtimeClock =
+        sElapsedRealtimeClock =
                 Clock.fixed(SystemClock.elapsedRealtimeClock().instant(), ZoneOffset.UTC);
     }
 
@@ -204,7 +205,7 @@
 
     @Test
     public void testFraction() throws Exception {
-        final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
+        final long now = sElapsedRealtimeClock.millis();
 
         assertEquals(1, createJobStatus(0, Long.MAX_VALUE).getFractionRunTime(), DELTA);
 
@@ -261,15 +262,15 @@
         final JobStatus job = createJobStatus(jobInfo);
 
         markImplicitConstraintsSatisfied(job, true);
-        job.setChargingConstraintSatisfied(false);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
-        job.setChargingConstraintSatisfied(true);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
 
         markImplicitConstraintsSatisfied(job, false);
-        job.setChargingConstraintSatisfied(false);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
-        job.setChargingConstraintSatisfied(true);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
     }
 
@@ -282,15 +283,15 @@
         final JobStatus job = createJobStatus(jobInfo);
 
         markImplicitConstraintsSatisfied(job, true);
-        job.setIdleConstraintSatisfied(false);
+        job.setIdleConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_IDLE));
-        job.setIdleConstraintSatisfied(true);
+        job.setIdleConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_IDLE));
 
         markImplicitConstraintsSatisfied(job, false);
-        job.setIdleConstraintSatisfied(false);
+        job.setIdleConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_IDLE));
-        job.setIdleConstraintSatisfied(true);
+        job.setIdleConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_IDLE));
     }
 
@@ -303,15 +304,15 @@
         final JobStatus job = createJobStatus(jobInfo);
 
         markImplicitConstraintsSatisfied(job, true);
-        job.setBatteryNotLowConstraintSatisfied(false);
+        job.setBatteryNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_BATTERY_NOT_LOW));
-        job.setBatteryNotLowConstraintSatisfied(true);
+        job.setBatteryNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_BATTERY_NOT_LOW));
 
         markImplicitConstraintsSatisfied(job, false);
-        job.setBatteryNotLowConstraintSatisfied(false);
+        job.setBatteryNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_BATTERY_NOT_LOW));
-        job.setBatteryNotLowConstraintSatisfied(true);
+        job.setBatteryNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_BATTERY_NOT_LOW));
     }
 
@@ -324,15 +325,15 @@
         final JobStatus job = createJobStatus(jobInfo);
 
         markImplicitConstraintsSatisfied(job, true);
-        job.setStorageNotLowConstraintSatisfied(false);
+        job.setStorageNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_STORAGE_NOT_LOW));
-        job.setStorageNotLowConstraintSatisfied(true);
+        job.setStorageNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_STORAGE_NOT_LOW));
 
         markImplicitConstraintsSatisfied(job, false);
-        job.setStorageNotLowConstraintSatisfied(false);
+        job.setStorageNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_STORAGE_NOT_LOW));
-        job.setStorageNotLowConstraintSatisfied(true);
+        job.setStorageNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_STORAGE_NOT_LOW));
     }
 
@@ -345,15 +346,15 @@
         final JobStatus job = createJobStatus(jobInfo);
 
         markImplicitConstraintsSatisfied(job, true);
-        job.setTimingDelayConstraintSatisfied(false);
+        job.setTimingDelayConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_TIMING_DELAY));
-        job.setTimingDelayConstraintSatisfied(true);
+        job.setTimingDelayConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_TIMING_DELAY));
 
         markImplicitConstraintsSatisfied(job, false);
-        job.setTimingDelayConstraintSatisfied(false);
+        job.setTimingDelayConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_TIMING_DELAY));
-        job.setTimingDelayConstraintSatisfied(true);
+        job.setTimingDelayConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_TIMING_DELAY));
     }
 
@@ -366,15 +367,15 @@
         final JobStatus job = createJobStatus(jobInfo);
 
         markImplicitConstraintsSatisfied(job, true);
-        job.setDeadlineConstraintSatisfied(false);
+        job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
-        job.setDeadlineConstraintSatisfied(true);
+        job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
 
         markImplicitConstraintsSatisfied(job, false);
-        job.setDeadlineConstraintSatisfied(false);
+        job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
-        job.setDeadlineConstraintSatisfied(true);
+        job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
     }
 
@@ -387,15 +388,15 @@
         final JobStatus job = createJobStatus(jobInfo);
 
         markImplicitConstraintsSatisfied(job, true);
-        job.setConnectivityConstraintSatisfied(false);
+        job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
-        job.setConnectivityConstraintSatisfied(true);
+        job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
 
         markImplicitConstraintsSatisfied(job, false);
-        job.setConnectivityConstraintSatisfied(false);
+        job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
-        job.setConnectivityConstraintSatisfied(true);
+        job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
     }
 
@@ -410,15 +411,15 @@
         final JobStatus job = createJobStatus(jobInfo);
 
         markImplicitConstraintsSatisfied(job, true);
-        job.setContentTriggerConstraintSatisfied(false);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
-        job.setContentTriggerConstraintSatisfied(true);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
 
         markImplicitConstraintsSatisfied(job, false);
-        job.setContentTriggerConstraintSatisfied(false);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
-        job.setContentTriggerConstraintSatisfied(true);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
     }
 
@@ -436,15 +437,15 @@
 
         markImplicitConstraintsSatisfied(job, false);
 
-        job.setChargingConstraintSatisfied(false);
-        job.setConnectivityConstraintSatisfied(false);
-        job.setContentTriggerConstraintSatisfied(false);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+        job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
-        job.setChargingConstraintSatisfied(true);
-        job.setConnectivityConstraintSatisfied(true);
-        job.setContentTriggerConstraintSatisfied(true);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+        job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         // Still false because implicit constraints aren't satisfied.
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
@@ -452,61 +453,61 @@
 
         markImplicitConstraintsSatisfied(job, true);
 
-        job.setChargingConstraintSatisfied(false);
-        job.setConnectivityConstraintSatisfied(false);
-        job.setContentTriggerConstraintSatisfied(false);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+        job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
 
         // Turn on constraints one at a time.
-        job.setChargingConstraintSatisfied(true);
-        job.setConnectivityConstraintSatisfied(false);
-        job.setContentTriggerConstraintSatisfied(false);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+        job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
 
-        job.setChargingConstraintSatisfied(false);
-        job.setConnectivityConstraintSatisfied(false);
-        job.setContentTriggerConstraintSatisfied(true);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+        job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
 
-        job.setChargingConstraintSatisfied(false);
-        job.setConnectivityConstraintSatisfied(true);
-        job.setContentTriggerConstraintSatisfied(false);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+        job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
 
         // With two of the 3 constraints satisfied (and implicit constraints also satisfied), only
         // the unsatisfied constraint should return true.
-        job.setChargingConstraintSatisfied(true);
-        job.setConnectivityConstraintSatisfied(false);
-        job.setContentTriggerConstraintSatisfied(true);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+        job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
 
-        job.setChargingConstraintSatisfied(true);
-        job.setConnectivityConstraintSatisfied(true);
-        job.setContentTriggerConstraintSatisfied(false);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+        job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
 
-        job.setChargingConstraintSatisfied(false);
-        job.setConnectivityConstraintSatisfied(true);
-        job.setContentTriggerConstraintSatisfied(true);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+        job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
 
-        job.setChargingConstraintSatisfied(true);
-        job.setConnectivityConstraintSatisfied(true);
-        job.setContentTriggerConstraintSatisfied(true);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+        job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
@@ -526,15 +527,15 @@
 
         markImplicitConstraintsSatisfied(job, false);
 
-        job.setChargingConstraintSatisfied(false);
-        job.setContentTriggerConstraintSatisfied(false);
-        job.setDeadlineConstraintSatisfied(false);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+        job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
-        job.setChargingConstraintSatisfied(true);
-        job.setContentTriggerConstraintSatisfied(true);
-        job.setDeadlineConstraintSatisfied(true);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+        job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         // Still false because implicit constraints aren't satisfied.
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
@@ -542,18 +543,18 @@
 
         markImplicitConstraintsSatisfied(job, true);
 
-        job.setChargingConstraintSatisfied(false);
-        job.setContentTriggerConstraintSatisfied(false);
-        job.setDeadlineConstraintSatisfied(false);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+        job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
         // Once implicit constraint are satisfied, deadline constraint should always return true.
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
 
         // Turn on constraints one at a time.
-        job.setChargingConstraintSatisfied(true);
-        job.setContentTriggerConstraintSatisfied(false);
-        job.setDeadlineConstraintSatisfied(false);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+        job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
         // Deadline should force isReady to be true, but isn't needed for the job to be
         // considered ready.
@@ -561,17 +562,17 @@
         // Once implicit constraint are satisfied, deadline constraint should always return true.
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
 
-        job.setChargingConstraintSatisfied(false);
-        job.setContentTriggerConstraintSatisfied(true);
-        job.setDeadlineConstraintSatisfied(false);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+        job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
         // Once implicit constraint are satisfied, deadline constraint should always return true.
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
 
-        job.setChargingConstraintSatisfied(false);
-        job.setContentTriggerConstraintSatisfied(false);
-        job.setDeadlineConstraintSatisfied(true);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+        job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         // Since the deadline constraint is satisfied, none of the other explicit constraints are
         // needed.
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
@@ -581,33 +582,33 @@
 
         // With two of the 3 constraints satisfied (and implicit constraints also satisfied), only
         // the unsatisfied constraint should return true.
-        job.setChargingConstraintSatisfied(true);
-        job.setContentTriggerConstraintSatisfied(true);
-        job.setDeadlineConstraintSatisfied(false);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+        job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
         // Once implicit constraint are satisfied, deadline constraint should always return true.
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
 
-        job.setChargingConstraintSatisfied(true);
-        job.setContentTriggerConstraintSatisfied(false);
-        job.setDeadlineConstraintSatisfied(true);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+        job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
         // Once implicit constraint are satisfied, deadline constraint should always return true.
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
 
-        job.setChargingConstraintSatisfied(false);
-        job.setContentTriggerConstraintSatisfied(true);
-        job.setDeadlineConstraintSatisfied(true);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+        job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
         // Once implicit constraint are satisfied, deadline constraint should always return true.
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
 
-        job.setChargingConstraintSatisfied(true);
-        job.setContentTriggerConstraintSatisfied(true);
-        job.setDeadlineConstraintSatisfied(true);
+        job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+        job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+        job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
         // Once implicit constraint are satisfied, deadline constraint should always return true.
@@ -621,15 +622,15 @@
                 new JobInfo.Builder(101, new ComponentName("foo", "bar")).build());
 
         markImplicitConstraintsSatisfied(job, false);
-        job.setDeviceNotDozingConstraintSatisfied(false, false);
+        job.setDeviceNotDozingConstraintSatisfied(sElapsedRealtimeClock.millis(), false, false);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEVICE_NOT_DOZING));
-        job.setDeviceNotDozingConstraintSatisfied(true, false);
+        job.setDeviceNotDozingConstraintSatisfied(sElapsedRealtimeClock.millis(), true, false);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEVICE_NOT_DOZING));
 
         markImplicitConstraintsSatisfied(job, true);
-        job.setDeviceNotDozingConstraintSatisfied(false, false);
+        job.setDeviceNotDozingConstraintSatisfied(sElapsedRealtimeClock.millis(), false, false);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEVICE_NOT_DOZING));
-        job.setDeviceNotDozingConstraintSatisfied(true, false);
+        job.setDeviceNotDozingConstraintSatisfied(sElapsedRealtimeClock.millis(), true, false);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEVICE_NOT_DOZING));
     }
 
@@ -640,15 +641,15 @@
                 new JobInfo.Builder(101, new ComponentName("foo", "bar")).build());
 
         markImplicitConstraintsSatisfied(job, false);
-        job.setQuotaConstraintSatisfied(false);
+        job.setQuotaConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_WITHIN_QUOTA));
-        job.setQuotaConstraintSatisfied(true);
+        job.setQuotaConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_WITHIN_QUOTA));
 
         markImplicitConstraintsSatisfied(job, true);
-        job.setQuotaConstraintSatisfied(false);
+        job.setQuotaConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_WITHIN_QUOTA));
-        job.setQuotaConstraintSatisfied(true);
+        job.setQuotaConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_WITHIN_QUOTA));
     }
 
@@ -659,22 +660,24 @@
                 new JobInfo.Builder(101, new ComponentName("foo", "bar")).build());
 
         markImplicitConstraintsSatisfied(job, false);
-        job.setBackgroundNotRestrictedConstraintSatisfied(false);
+        job.setBackgroundNotRestrictedConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
-        job.setBackgroundNotRestrictedConstraintSatisfied(true);
+        job.setBackgroundNotRestrictedConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
 
         markImplicitConstraintsSatisfied(job, true);
-        job.setBackgroundNotRestrictedConstraintSatisfied(false);
+        job.setBackgroundNotRestrictedConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
-        job.setBackgroundNotRestrictedConstraintSatisfied(true);
+        job.setBackgroundNotRestrictedConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
     }
 
     private void markImplicitConstraintsSatisfied(JobStatus job, boolean isSatisfied) {
-        job.setQuotaConstraintSatisfied(isSatisfied);
-        job.setDeviceNotDozingConstraintSatisfied(isSatisfied, false);
-        job.setBackgroundNotRestrictedConstraintSatisfied(isSatisfied);
+        job.setQuotaConstraintSatisfied(sElapsedRealtimeClock.millis(), isSatisfied);
+        job.setDeviceNotDozingConstraintSatisfied(
+                sElapsedRealtimeClock.millis(), isSatisfied, false);
+        job.setBackgroundNotRestrictedConstraintSatisfied(
+                sElapsedRealtimeClock.millis(), isSatisfied);
     }
 
     private static JobStatus createJobStatus(long earliestRunTimeElapsedMillis,
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
index c4c9173..29db740 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
@@ -31,6 +31,7 @@
 import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
 import static com.android.server.job.JobSchedulerService.WORKING_INDEX;
 import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+import static com.android.server.job.JobSchedulerService.sSystemClock;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -58,6 +59,7 @@
 import android.app.IActivityManager;
 import android.app.IUidObserver;
 import android.app.job.JobInfo;
+import android.app.usage.UsageEvents;
 import android.app.usage.UsageStatsManager;
 import android.app.usage.UsageStatsManagerInternal;
 import android.content.BroadcastReceiver;
@@ -82,11 +84,10 @@
 import com.android.server.LocalServices;
 import com.android.server.PowerAllowlistInternal;
 import com.android.server.job.JobSchedulerService;
-import com.android.server.job.JobSchedulerService.Constants;
-import com.android.server.job.JobServiceContext;
 import com.android.server.job.JobStore;
 import com.android.server.job.controllers.QuotaController.ExecutionStats;
 import com.android.server.job.controllers.QuotaController.QcConstants;
+import com.android.server.job.controllers.QuotaController.ShrinkableDebits;
 import com.android.server.job.controllers.QuotaController.TimingSession;
 import com.android.server.usage.AppStandbyInternal;
 
@@ -123,9 +124,11 @@
     private BroadcastReceiver mChargingReceiver;
     private QuotaController mQuotaController;
     private QuotaController.QcConstants mQcConstants;
+    private JobSchedulerService.Constants mConstants = new JobSchedulerService.Constants();
     private int mSourceUid;
     private PowerAllowlistInternal.TempAllowlistChangeListener mTempAllowlistListener;
     private IUidObserver mUidObserver;
+    private UsageStatsManagerInternal.UsageEventListener mUsageEventListener;
     DeviceConfig.Properties.Builder mDeviceConfigPropertiesBuilder;
 
     private MockitoSession mMockingSession;
@@ -158,7 +161,7 @@
         // Called in StateController constructor.
         when(mJobSchedulerService.getTestableContext()).thenReturn(mContext);
         when(mJobSchedulerService.getLock()).thenReturn(mJobSchedulerService);
-        when(mJobSchedulerService.getConstants()).thenReturn(mock(Constants.class));
+        when(mJobSchedulerService.getConstants()).thenReturn(mConstants);
         // Called in QuotaController constructor.
         IActivityManager activityManager = ActivityManager.getService();
         spyOn(activityManager);
@@ -219,6 +222,8 @@
                 ArgumentCaptor.forClass(IUidObserver.class);
         ArgumentCaptor<PowerAllowlistInternal.TempAllowlistChangeListener> taChangeCaptor =
                 ArgumentCaptor.forClass(PowerAllowlistInternal.TempAllowlistChangeListener.class);
+        ArgumentCaptor<UsageStatsManagerInternal.UsageEventListener> ueListenerCaptor =
+                ArgumentCaptor.forClass(UsageStatsManagerInternal.UsageEventListener.class);
         mQuotaController = new QuotaController(mJobSchedulerService,
                 mock(BackgroundJobsController.class), mock(ConnectivityController.class));
 
@@ -230,6 +235,8 @@
         verify(mPowerAllowlistInternal)
                 .registerTempAllowlistChangeListener(taChangeCaptor.capture());
         mTempAllowlistListener = taChangeCaptor.getValue();
+        verify(mUsageStatsManager).registerListener(ueListenerCaptor.capture());
+        mUsageEventListener = ueListenerCaptor.getValue();
         try {
             verify(activityManager).registerUidObserver(
                     uidObserverCaptor.capture(),
@@ -289,7 +296,7 @@
                 verify(foregroundUids, timeout(2 * SECOND_IN_MILLIS).times(1)).delete(eq(uid));
                 assertFalse(foregroundUids.get(uid));
             }
-            waitForQuietBackground();
+            waitForNonDelayedMessagesProcessed();
         } catch (Exception e) {
             fail("exception encountered: " + e.getMessage());
         }
@@ -360,8 +367,9 @@
         // Make sure tests aren't passing just because the default bucket is likely ACTIVE.
         js.setStandbyBucket(FREQUENT_INDEX);
         // Make sure Doze and background-not-restricted don't affect tests.
-        js.setDeviceNotDozingConstraintSatisfied(/* state */ true, /* allowlisted */false);
-        js.setBackgroundNotRestrictedConstraintSatisfied(true);
+        js.setDeviceNotDozingConstraintSatisfied(/* nowElapsed */ sElapsedRealtimeClock.millis(),
+                /* state */ true, /* allowlisted */false);
+        js.setBackgroundNotRestrictedConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
         return js;
     }
 
@@ -385,13 +393,8 @@
         }
     }
 
-    private void waitForQuietBackground() throws Exception {
-        for (int i = 0; i < 5; ++i) {
-            if (!mQuotaController.isActiveBackgroundProcessing()) {
-                break;
-            }
-            Thread.sleep(500);
-        }
+    private void waitForNonDelayedMessagesProcessed() {
+        mQuotaController.getHandler().runWithScissors(() -> {}, 15_000);
     }
 
     @Test
@@ -1282,23 +1285,23 @@
     }
 
     @Test
-    public void testGetMaxJobExecutionTimeLocked() {
+    public void testGetMaxJobExecutionTimeLocked_Regular() {
         mQuotaController.saveTimingSession(0, SOURCE_PACKAGE,
                 createTimingSession(sElapsedRealtimeClock.millis() - (6 * MINUTE_IN_MILLIS),
                         3 * MINUTE_IN_MILLIS, 5), false);
         JobStatus job = createJobStatus("testGetMaxJobExecutionTimeLocked", 0);
-        job.setStandbyBucket(RARE_INDEX);
+        setStandbyBucket(RARE_INDEX, job);
 
         setCharging();
         synchronized (mQuotaController.mLock) {
-            assertEquals(JobServiceContext.DEFAULT_EXECUTING_TIMESLICE_MILLIS,
+            assertEquals(JobSchedulerService.Constants.DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                     mQuotaController.getMaxJobExecutionTimeMsLocked((job)));
         }
 
         setDischarging();
         setProcessState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
         synchronized (mQuotaController.mLock) {
-            assertEquals(JobServiceContext.DEFAULT_EXECUTING_TIMESLICE_MILLIS,
+            assertEquals(JobSchedulerService.Constants.DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                     mQuotaController.getMaxJobExecutionTimeMsLocked((job)));
         }
 
@@ -1310,7 +1313,7 @@
         }
         setProcessState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
         synchronized (mQuotaController.mLock) {
-            assertEquals(JobServiceContext.DEFAULT_EXECUTING_TIMESLICE_MILLIS,
+            assertEquals(JobSchedulerService.Constants.DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                     mQuotaController.getMaxJobExecutionTimeMsLocked((job)));
             mQuotaController.maybeStopTrackingJobLocked(job, null, false);
         }
@@ -1322,6 +1325,123 @@
         }
     }
 
+    @Test
+    public void testGetMaxJobExecutionTimeLocked_Regular_Active() {
+        JobStatus job = createJobStatus("testGetMaxJobExecutionTimeLocked_Regular_Active", 0);
+        setDeviceConfigLong(QcConstants.KEY_ALLOWED_TIME_PER_PERIOD_MS, 10 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_WINDOW_SIZE_ACTIVE_MS, 10 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_MAX_EXECUTION_TIME_MS, 2 * HOUR_IN_MILLIS);
+        setDischarging();
+        setStandbyBucket(ACTIVE_INDEX, job);
+        setProcessState(ActivityManager.PROCESS_STATE_CACHED_ACTIVITY);
+
+        // ACTIVE apps (where allowed time = window size) should be capped at max execution limit.
+        synchronized (mQuotaController.mLock) {
+            assertEquals(2 * HOUR_IN_MILLIS,
+                    mQuotaController.getMaxJobExecutionTimeMsLocked((job)));
+        }
+
+        // Make sure sessions are factored in properly.
+        mQuotaController.saveTimingSession(0, SOURCE_PACKAGE,
+                createTimingSession(sElapsedRealtimeClock.millis() - (6 * HOUR_IN_MILLIS),
+                        30 * MINUTE_IN_MILLIS, 1), false);
+        synchronized (mQuotaController.mLock) {
+            assertEquals(90 * MINUTE_IN_MILLIS,
+                    mQuotaController.getMaxJobExecutionTimeMsLocked((job)));
+        }
+
+        mQuotaController.saveTimingSession(0, SOURCE_PACKAGE,
+                createTimingSession(sElapsedRealtimeClock.millis() - (5 * HOUR_IN_MILLIS),
+                        30 * MINUTE_IN_MILLIS, 1), false);
+        mQuotaController.saveTimingSession(0, SOURCE_PACKAGE,
+                createTimingSession(sElapsedRealtimeClock.millis() - (4 * HOUR_IN_MILLIS),
+                        30 * MINUTE_IN_MILLIS, 1), false);
+        mQuotaController.saveTimingSession(0, SOURCE_PACKAGE,
+                createTimingSession(sElapsedRealtimeClock.millis() - (3 * HOUR_IN_MILLIS),
+                        25 * MINUTE_IN_MILLIS, 1), false);
+        synchronized (mQuotaController.mLock) {
+            assertEquals(5 * MINUTE_IN_MILLIS,
+                    mQuotaController.getMaxJobExecutionTimeMsLocked((job)));
+        }
+    }
+
+    @Test
+    public void testGetMaxJobExecutionTimeLocked_EJ() {
+        final long timeUsedMs = 3 * MINUTE_IN_MILLIS;
+        mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
+                createTimingSession(sElapsedRealtimeClock.millis() - (6 * MINUTE_IN_MILLIS),
+                        timeUsedMs, 5), true);
+        JobStatus job = createExpeditedJobStatus("testGetMaxJobExecutionTimeLocked_EJ", 0);
+        setStandbyBucket(RARE_INDEX, job);
+        synchronized (mQuotaController.mLock) {
+            mQuotaController.maybeStartTrackingJobLocked(job, null);
+        }
+
+        setCharging();
+        synchronized (mQuotaController.mLock) {
+            assertEquals(JobSchedulerService.Constants.DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                    mQuotaController.getMaxJobExecutionTimeMsLocked(job));
+        }
+
+        setDischarging();
+        setProcessState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
+        synchronized (mQuotaController.mLock) {
+            assertEquals(mQcConstants.EJ_LIMIT_WORKING_MS / 2,
+                    mQuotaController.getMaxJobExecutionTimeMsLocked(job));
+        }
+
+        // Top-started job
+        setProcessState(ActivityManager.PROCESS_STATE_TOP);
+        synchronized (mQuotaController.mLock) {
+            mQuotaController.prepareForExecutionLocked(job);
+        }
+        setProcessState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
+        synchronized (mQuotaController.mLock) {
+            assertEquals(mQcConstants.EJ_LIMIT_ACTIVE_MS / 2,
+                    mQuotaController.getMaxJobExecutionTimeMsLocked(job));
+            mQuotaController.maybeStopTrackingJobLocked(job, null, false);
+        }
+
+        setProcessState(ActivityManager.PROCESS_STATE_RECEIVER);
+        synchronized (mQuotaController.mLock) {
+            assertEquals(mQcConstants.EJ_LIMIT_RARE_MS - timeUsedMs,
+                    mQuotaController.getMaxJobExecutionTimeMsLocked(job));
+        }
+
+        // Test used quota rolling out of window.
+        synchronized (mQuotaController.mLock) {
+            mQuotaController.clearAppStatsLocked(SOURCE_USER_ID, SOURCE_PACKAGE);
+        }
+        mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
+                createTimingSession(sElapsedRealtimeClock.millis() - mQcConstants.EJ_WINDOW_SIZE_MS,
+                        timeUsedMs, 5), true);
+
+        setProcessState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
+        synchronized (mQuotaController.mLock) {
+            assertEquals(mQcConstants.EJ_LIMIT_WORKING_MS / 2,
+                    mQuotaController.getMaxJobExecutionTimeMsLocked(job));
+        }
+
+        // Top-started job
+        setProcessState(ActivityManager.PROCESS_STATE_TOP);
+        synchronized (mQuotaController.mLock) {
+            mQuotaController.maybeStartTrackingJobLocked(job, null);
+            mQuotaController.prepareForExecutionLocked(job);
+        }
+        setProcessState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
+        synchronized (mQuotaController.mLock) {
+            assertEquals(mQcConstants.EJ_LIMIT_ACTIVE_MS / 2,
+                    mQuotaController.getMaxJobExecutionTimeMsLocked(job));
+            mQuotaController.maybeStopTrackingJobLocked(job, null, false);
+        }
+
+        setProcessState(ActivityManager.PROCESS_STATE_RECEIVER);
+        synchronized (mQuotaController.mLock) {
+            assertEquals(mQcConstants.EJ_LIMIT_RARE_MS,
+                    mQuotaController.getMaxJobExecutionTimeMsLocked(job));
+        }
+    }
+
     /**
      * Test getTimeUntilQuotaConsumedLocked when the determination is based within the bucket
      * window.
@@ -2508,7 +2628,7 @@
         assertEquals(15 * MINUTE_IN_MILLIS, mQuotaController.getEJLimitsMs()[WORKING_INDEX]);
         assertEquals(10 * MINUTE_IN_MILLIS, mQuotaController.getEJLimitsMs()[FREQUENT_INDEX]);
         assertEquals(10 * MINUTE_IN_MILLIS, mQuotaController.getEJLimitsMs()[RARE_INDEX]);
-        assertEquals(0, mQuotaController.getEJLimitsMs()[RESTRICTED_INDEX]);
+        assertEquals(5 * MINUTE_IN_MILLIS, mQuotaController.getEJLimitsMs()[RESTRICTED_INDEX]);
         assertEquals(0, mQuotaController.getEjLimitSpecialAdditionMs());
         assertEquals(HOUR_IN_MILLIS, mQuotaController.getEJLimitWindowSizeMs());
         assertEquals(1, mQuotaController.getEJTopAppTimeChunkSizeMs());
@@ -5083,4 +5203,257 @@
                 eq(10 * SECOND_IN_MILLIS));
         verify(handler, never()).sendMessageDelayed(any(), eq(remainingTimeMs));
     }
+
+    @Test
+    public void testEJDebitTallying() {
+        setStandbyBucket(RARE_INDEX);
+        setProcessState(ActivityManager.PROCESS_STATE_SERVICE);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RARE_MS, 10 * MINUTE_IN_MILLIS);
+        // 15 seconds for each 30 second chunk.
+        setDeviceConfigLong(QcConstants.KEY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS, 30 * SECOND_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_TOP_APP_MS, 15 * SECOND_IN_MILLIS);
+
+        // No history. Debits should be 0.
+        ShrinkableDebits debit = mQuotaController.getEJDebitsLocked(SOURCE_USER_ID, SOURCE_PACKAGE);
+        assertEquals(0, debit.getTallyLocked());
+        assertEquals(10 * MINUTE_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+        // Regular job shouldn't affect EJ tally.
+        JobStatus regJob = createJobStatus("testEJDebitTallying", 1);
+        synchronized (mQuotaController.mLock) {
+            mQuotaController.maybeStartTrackingJobLocked(regJob, null);
+            mQuotaController.prepareForExecutionLocked(regJob);
+        }
+        advanceElapsedClock(5000);
+        synchronized (mQuotaController.mLock) {
+            mQuotaController.maybeStopTrackingJobLocked(regJob, null, false);
+        }
+        assertEquals(0, debit.getTallyLocked());
+        assertEquals(10 * MINUTE_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+        // EJ job should affect EJ tally.
+        JobStatus eJob = createExpeditedJobStatus("testEJDebitTallying", 2);
+        synchronized (mQuotaController.mLock) {
+            mQuotaController.maybeStartTrackingJobLocked(eJob, null);
+            mQuotaController.prepareForExecutionLocked(eJob);
+        }
+        advanceElapsedClock(5 * MINUTE_IN_MILLIS);
+        synchronized (mQuotaController.mLock) {
+            mQuotaController.maybeStopTrackingJobLocked(eJob, null, false);
+        }
+        assertEquals(5 * MINUTE_IN_MILLIS, debit.getTallyLocked());
+        assertEquals(5 * MINUTE_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+        // Instantaneous event for a different user shouldn't affect tally.
+        advanceElapsedClock(5 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_INTERACTION_MS, MINUTE_IN_MILLIS);
+
+        UsageEvents.Event event =
+                new UsageEvents.Event(UsageEvents.Event.USER_INTERACTION, sSystemClock.millis());
+        event.mPackage = SOURCE_PACKAGE;
+        mUsageEventListener.onUsageEvent(SOURCE_USER_ID + 10, event);
+        assertEquals(5 * MINUTE_IN_MILLIS, debit.getTallyLocked());
+
+        // Instantaneous event for correct user should reduce tally.
+        advanceElapsedClock(5 * MINUTE_IN_MILLIS);
+
+        mUsageEventListener.onUsageEvent(SOURCE_USER_ID, event);
+        waitForNonDelayedMessagesProcessed();
+        assertEquals(4 * MINUTE_IN_MILLIS, debit.getTallyLocked());
+        assertEquals(6 * MINUTE_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+        // Activity start shouldn't reduce tally, but duration with activity started should affect
+        // remaining EJ time.
+        advanceElapsedClock(5 * MINUTE_IN_MILLIS);
+        event = new UsageEvents.Event(UsageEvents.Event.ACTIVITY_RESUMED, sSystemClock.millis());
+        event.mPackage = SOURCE_PACKAGE;
+        mUsageEventListener.onUsageEvent(SOURCE_USER_ID, event);
+        waitForNonDelayedMessagesProcessed();
+        advanceElapsedClock(30 * SECOND_IN_MILLIS);
+        assertEquals(4 * MINUTE_IN_MILLIS, debit.getTallyLocked());
+        assertEquals(6 * MINUTE_IN_MILLIS + 15 * SECOND_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+        advanceElapsedClock(30 * SECOND_IN_MILLIS);
+        assertEquals(4 * MINUTE_IN_MILLIS, debit.getTallyLocked());
+        assertEquals(6 * MINUTE_IN_MILLIS + 30 * SECOND_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+        // With activity pausing/stopping/destroying, tally should be updated.
+        advanceElapsedClock(MINUTE_IN_MILLIS);
+        event = new UsageEvents.Event(UsageEvents.Event.ACTIVITY_DESTROYED, sSystemClock.millis());
+        event.mPackage = SOURCE_PACKAGE;
+        mUsageEventListener.onUsageEvent(SOURCE_USER_ID, event);
+        waitForNonDelayedMessagesProcessed();
+        assertEquals(3 * MINUTE_IN_MILLIS, debit.getTallyLocked());
+        assertEquals(7 * MINUTE_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+    }
+
+    @Test
+    public void testEJDebitTallying_StaleSession() {
+        setStandbyBucket(RARE_INDEX);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RARE_MS, 10 * MINUTE_IN_MILLIS);
+
+        final long nowElapsed = sElapsedRealtimeClock.millis();
+        TimingSession ts = new TimingSession(nowElapsed, nowElapsed + 10 * MINUTE_IN_MILLIS, 5);
+        mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE, ts, true);
+
+        // Make the session stale.
+        advanceElapsedClock(12 * MINUTE_IN_MILLIS + mQcConstants.EJ_WINDOW_SIZE_MS);
+
+        // With lazy deletion, we don't update the tally until getRemainingEJExecutionTimeLocked()
+        // is called, so call that first.
+        assertEquals(10 * MINUTE_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+        ShrinkableDebits debit = mQuotaController.getEJDebitsLocked(SOURCE_USER_ID, SOURCE_PACKAGE);
+        assertEquals(0, debit.getTallyLocked());
+    }
+
+    /**
+     * Tests that rewards are properly accounted when there's no EJ running and the rewards exceed
+     * the accumulated debits.
+     */
+    @Test
+    public void testEJDebitTallying_RewardExceedDebits_NoActiveSession() {
+        setStandbyBucket(WORKING_INDEX);
+        setProcessState(ActivityManager.PROCESS_STATE_SERVICE);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_WORKING_MS, 30 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_INTERACTION_MS, MINUTE_IN_MILLIS);
+
+        final long nowElapsed = sElapsedRealtimeClock.millis();
+        TimingSession ts = new TimingSession(nowElapsed - 5 * MINUTE_IN_MILLIS,
+                nowElapsed - 4 * MINUTE_IN_MILLIS, 2);
+        mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE, ts, true);
+
+        ShrinkableDebits debit = mQuotaController.getEJDebitsLocked(SOURCE_USER_ID, SOURCE_PACKAGE);
+        assertEquals(MINUTE_IN_MILLIS, debit.getTallyLocked());
+        assertEquals(29 * MINUTE_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+        advanceElapsedClock(30 * SECOND_IN_MILLIS);
+        UsageEvents.Event event =
+                new UsageEvents.Event(UsageEvents.Event.USER_INTERACTION, sSystemClock.millis());
+        event.mPackage = SOURCE_PACKAGE;
+        mUsageEventListener.onUsageEvent(SOURCE_USER_ID, event);
+        waitForNonDelayedMessagesProcessed();
+        assertEquals(0, debit.getTallyLocked());
+        assertEquals(30 * MINUTE_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+        advanceElapsedClock(MINUTE_IN_MILLIS);
+        assertEquals(0, debit.getTallyLocked());
+        assertEquals(30 * MINUTE_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+        // Excessive rewards don't increase maximum quota.
+        event = new UsageEvents.Event(UsageEvents.Event.USER_INTERACTION, sSystemClock.millis());
+        event.mPackage = SOURCE_PACKAGE;
+        mUsageEventListener.onUsageEvent(SOURCE_USER_ID, event);
+        waitForNonDelayedMessagesProcessed();
+        assertEquals(0, debit.getTallyLocked());
+        assertEquals(30 * MINUTE_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+    }
+
+    /**
+     * Tests that rewards are properly accounted when there's an active EJ running and the rewards
+     * exceed the accumulated debits.
+     */
+    @Test
+    public void testEJDebitTallying_RewardExceedDebits_ActiveSession() {
+        setStandbyBucket(WORKING_INDEX);
+        setProcessState(ActivityManager.PROCESS_STATE_SERVICE);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_WORKING_MS, 30 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_INTERACTION_MS, MINUTE_IN_MILLIS);
+        // 15 seconds for each 30 second chunk.
+        setDeviceConfigLong(QcConstants.KEY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS, 30 * SECOND_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_TOP_APP_MS, 15 * SECOND_IN_MILLIS);
+
+        final long nowElapsed = sElapsedRealtimeClock.millis();
+        TimingSession ts = new TimingSession(nowElapsed - 5 * MINUTE_IN_MILLIS,
+                nowElapsed - 4 * MINUTE_IN_MILLIS, 2);
+        mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE, ts, true);
+
+        ShrinkableDebits debit = mQuotaController.getEJDebitsLocked(SOURCE_USER_ID, SOURCE_PACKAGE);
+        assertEquals(MINUTE_IN_MILLIS, debit.getTallyLocked());
+        assertEquals(29 * MINUTE_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+        // With rewards coming in while an EJ is running, the remaining execution time should be
+        // adjusted accordingly (decrease due to EJ running + increase from reward).
+        JobStatus eJob =
+                createExpeditedJobStatus("testEJDebitTallying_RewardExceedDebits_ActiveSession", 1);
+        synchronized (mQuotaController.mLock) {
+            mQuotaController.maybeStartTrackingJobLocked(eJob, null);
+            mQuotaController.prepareForExecutionLocked(eJob);
+        }
+        advanceElapsedClock(30 * SECOND_IN_MILLIS);
+        assertEquals(MINUTE_IN_MILLIS, debit.getTallyLocked());
+        assertEquals(28 * MINUTE_IN_MILLIS + 30 * SECOND_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+        advanceElapsedClock(30 * SECOND_IN_MILLIS);
+        UsageEvents.Event event =
+                new UsageEvents.Event(UsageEvents.Event.USER_INTERACTION, sSystemClock.millis());
+        event.mPackage = SOURCE_PACKAGE;
+        mUsageEventListener.onUsageEvent(SOURCE_USER_ID, event);
+        waitForNonDelayedMessagesProcessed();
+        assertEquals(0, debit.getTallyLocked());
+        assertEquals(29 * MINUTE_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+        advanceElapsedClock(MINUTE_IN_MILLIS);
+        assertEquals(0, debit.getTallyLocked());
+        assertEquals(28 * MINUTE_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+        // Activity start shouldn't reduce tally, but duration with activity started should affect
+        // remaining EJ time.
+        event = new UsageEvents.Event(UsageEvents.Event.ACTIVITY_RESUMED, sSystemClock.millis());
+        event.mPackage = SOURCE_PACKAGE;
+        mUsageEventListener.onUsageEvent(SOURCE_USER_ID, event);
+        waitForNonDelayedMessagesProcessed();
+        advanceElapsedClock(30 * SECOND_IN_MILLIS);
+        assertEquals(0, debit.getTallyLocked());
+        // Decrease by 30 seconds for running EJ, increase by 15 seconds due to ongoing activity.
+        assertEquals(27 * MINUTE_IN_MILLIS + 45 * SECOND_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+        advanceElapsedClock(30 * SECOND_IN_MILLIS);
+        assertEquals(0, debit.getTallyLocked());
+        assertEquals(27 * MINUTE_IN_MILLIS + 30 * SECOND_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+        advanceElapsedClock(MINUTE_IN_MILLIS);
+        assertEquals(0, debit.getTallyLocked());
+        assertEquals(27 * MINUTE_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+        event = new UsageEvents.Event(UsageEvents.Event.USER_INTERACTION, sSystemClock.millis());
+        event.mPackage = SOURCE_PACKAGE;
+        mUsageEventListener.onUsageEvent(SOURCE_USER_ID, event);
+        waitForNonDelayedMessagesProcessed();
+        assertEquals(0, debit.getTallyLocked());
+        assertEquals(28 * MINUTE_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+        advanceElapsedClock(MINUTE_IN_MILLIS);
+        assertEquals(0, debit.getTallyLocked());
+        assertEquals(27 * MINUTE_IN_MILLIS + 30 * SECOND_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+        // At this point, with activity pausing/stopping/destroying, since we're giving a reward,
+        // tally should remain 0, and time remaining shouldn't change since it was accounted for
+        // at every step.
+        event = new UsageEvents.Event(UsageEvents.Event.ACTIVITY_DESTROYED, sSystemClock.millis());
+        event.mPackage = SOURCE_PACKAGE;
+        mUsageEventListener.onUsageEvent(SOURCE_USER_ID, event);
+        waitForNonDelayedMessagesProcessed();
+        assertEquals(0, debit.getTallyLocked());
+        assertEquals(27 * MINUTE_IN_MILLIS + 30 * SECOND_IN_MILLIS,
+                mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+    }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/gnss/hal/FakeGnssHal.java b/services/tests/mockingservicestests/src/com/android/server/location/gnss/hal/FakeGnssHal.java
index 69fe140..e0c8b09 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/gnss/hal/FakeGnssHal.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/gnss/hal/FakeGnssHal.java
@@ -500,7 +500,7 @@
     }
 
     @Override
-    protected boolean isAntennaInfoListeningSupported() {
+    protected boolean isAntennaInfoSupported() {
         return mIsAntennaInfoListeningSupported;
     }
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
index 66b037d..1b58e92 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
@@ -123,9 +123,10 @@
             .setPowerUsage(POWER_USAGE_HIGH)
             .setAccuracy(ProviderProperties.ACCURACY_FINE)
             .build();
+    private static final CallerIdentity PROVIDER_IDENTITY = CallerIdentity.forTest(CURRENT_USER, 1,
+            "mypackage", "attribution");
     private static final CallerIdentity IDENTITY = CallerIdentity.forTest(CURRENT_USER, 1,
-            "mypackage",
-            "attribution");
+            "mypackage", "attribution", "listener");
     private static final WorkSource WORK_SOURCE = new WorkSource(IDENTITY.getUid());
 
     private Random mRandom;
@@ -169,7 +170,7 @@
         mPassive.startManager();
         mPassive.setRealProvider(new PassiveLocationProvider(mContext));
 
-        mProvider = new TestProvider(PROPERTIES, IDENTITY);
+        mProvider = new TestProvider(PROPERTIES, PROVIDER_IDENTITY);
         mProvider.setProviderAllowed(true);
 
         mManager = new LocationProviderManager(mContext, mInjector, eventLog, NAME, mPassive);
@@ -351,7 +352,8 @@
 
     @Test
     public void testGetLastLocation_ClearOnMockRemoval() {
-        MockLocationProvider mockProvider = new MockLocationProvider(PROPERTIES, IDENTITY);
+        MockLocationProvider mockProvider = new MockLocationProvider(PROPERTIES, PROVIDER_IDENTITY,
+                Collections.emptySet());
         mockProvider.setAllowed(true);
         mManager.setMockProvider(mockProvider);
 
@@ -441,7 +443,7 @@
     @Test
     public void testRegisterListener_SameProcess() throws Exception {
         CallerIdentity identity = CallerIdentity.forTest(CURRENT_USER, Process.myPid(), "mypackage",
-                "attribution");
+                "attribution", "listener");
 
         ILocationListener listener = createMockLocationListener();
         mManager.registerLocationRequest(
@@ -477,7 +479,7 @@
     @Test
     public void testRegisterListener_Unregister_SameProcess() throws Exception {
         CallerIdentity identity = CallerIdentity.forTest(CURRENT_USER, Process.myPid(), "mypackage",
-                "attribution");
+                "attribution", "listener");
 
         ILocationListener listener = createMockLocationListener();
         mManager.registerLocationRequest(
@@ -604,7 +606,7 @@
     @Test
     public void testRegisterListener_Wakelock() throws Exception {
         CallerIdentity identity = CallerIdentity.forTest(CURRENT_USER, Process.myPid(), "mypackage",
-                "attribution");
+                "attribution", "listener");
 
         ILocationListener listener = createMockLocationListener();
         mManager.registerLocationRequest(
@@ -1047,7 +1049,7 @@
         private final ArrayList<Runnable> mFlushCallbacks = new ArrayList<>();
 
         TestProvider(ProviderProperties properties, CallerIdentity identity) {
-            super(DIRECT_EXECUTOR, identity, properties);
+            super(DIRECT_EXECUTOR, identity, properties, Collections.emptySet());
         }
 
         public void setProviderAllowed(boolean allowed) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/provider/MockableLocationProviderTest.java b/services/tests/mockingservicestests/src/com/android/server/location/provider/MockableLocationProviderTest.java
index 07170da..cf5db2e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/provider/MockableLocationProviderTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/provider/MockableLocationProviderTest.java
@@ -43,6 +43,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Collections;
+
 @Presubmit
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -71,7 +73,8 @@
                         .setPowerUsage(POWER_USAGE_LOW)
                         .setAccuracy(ACCURACY_FINE)
                         .build(),
-                CallerIdentity.forTest(0, 1, "testpackage", "test"));
+                CallerIdentity.forTest(0, 1, "testpackage", "test"),
+                Collections.emptySet());
 
         mProvider = new MockableLocationProvider(lock);
         mProvider.getController().setListener(mListener);
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/test/FakeProvider.java b/services/tests/mockingservicestests/src/com/android/server/location/test/FakeProvider.java
index 775bdd5..2bc1268 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/test/FakeProvider.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/test/FakeProvider.java
@@ -23,6 +23,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.Collections;
 
 public class FakeProvider extends AbstractLocationProvider {
 
@@ -40,7 +41,7 @@
     private final FakeProviderInterface mFakeInterface;
 
     public FakeProvider(FakeProviderInterface fakeInterface) {
-        super(Runnable::run, null, null);
+        super(Runnable::run, null, null, Collections.emptySet());
         mFakeInterface = fakeInterface;
     }
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS b/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS
index d825dfd..46b797b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS
@@ -1 +1,3 @@
 include /services/core/java/com/android/server/pm/OWNERS
+
+per-file StagingManagerTest.java = dariofreni@google.com, ioffe@google.com, olilan@google.com
diff --git a/services/tests/rescueparty/Android.bp b/services/tests/rescueparty/Android.bp
index 6733af4..ed7de96 100644
--- a/services/tests/rescueparty/Android.bp
+++ b/services/tests/rescueparty/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_test {
     name: "log_rescueparty_reset_event_reported",
     srcs: ["log_rescueparty_reset_event_reported.cpp"],
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 31e2b64..68f5479 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -2,6 +2,15 @@
 // Build FrameworksServicesTests package
 //########################################################################
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworksServicesTests",
 
@@ -172,9 +181,12 @@
         ":FrameworksServicesTests_install_split_feature_a",
         ":FrameworksServicesTests_install_uses_sdk_0",
         ":FrameworksServicesTests_install_uses_sdk_q0",
-        ":FrameworksServicesTests_install_uses_sdk_r",
+        ":FrameworksServicesTests_install_uses_sdk_q0_r0",
+        ":FrameworksServicesTests_install_uses_sdk_r_none",
         ":FrameworksServicesTests_install_uses_sdk_r0",
         ":FrameworksServicesTests_install_uses_sdk_r5",
+        ":FrameworksServicesTests_install_uses_sdk_r0_s0",
+        ":FrameworksServicesTests_install_uses_sdk_r0_s5",
     ],
     out: ["FrameworkServicesTests_apks_as_resources.res.zip"],
     tools: ["soong_zip"],
diff --git a/services/tests/servicestests/aidl/Android.bp b/services/tests/servicestests/aidl/Android.bp
index d4e53dd..6780531 100644
--- a/services/tests/servicestests/aidl/Android.bp
+++ b/services/tests/servicestests/aidl/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library {
     name: "servicestests-aidl",
     sdk_version: "current",
diff --git a/services/tests/servicestests/apks/Android.bp b/services/tests/servicestests/apks/Android.bp
index 3e11604..6c91806 100644
--- a/services/tests/servicestests/apks/Android.bp
+++ b/services/tests/servicestests/apks/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_defaults {
     name: "FrameworksServicesTests_apks_defaults",
     sdk_version: "current",
diff --git a/services/tests/servicestests/apks/install-split-base/Android.bp b/services/tests/servicestests/apks/install-split-base/Android.bp
index 1b62aa2..39992f6 100644
--- a/services/tests/servicestests/apks/install-split-base/Android.bp
+++ b/services/tests/servicestests/apks/install-split-base/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FrameworksServicesTests_install_split_base",
     defaults: ["FrameworksServicesTests_apks_defaults"],
diff --git a/services/tests/servicestests/apks/install-split-feature-a/Android.bp b/services/tests/servicestests/apks/install-split-feature-a/Android.bp
index 45d8917..ca7295e 100644
--- a/services/tests/servicestests/apks/install-split-feature-a/Android.bp
+++ b/services/tests/servicestests/apks/install-split-feature-a/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FrameworksServicesTests_install_split_feature_a",
     defaults: ["FrameworksServicesTests_apks_defaults"],
diff --git a/services/tests/servicestests/apks/install_intent_filters/Android.bp b/services/tests/servicestests/apks/install_intent_filters/Android.bp
index 59c8524..643824d 100644
--- a/services/tests/servicestests/apks/install_intent_filters/Android.bp
+++ b/services/tests/servicestests/apks/install_intent_filters/Android.bp
@@ -1,7 +1,15 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FrameworksServicesTests_install_intent_filters",
     defaults: ["FrameworksServicesTests_apks_defaults"],
 
     srcs: ["**/*.java"],
 }
-
diff --git a/services/tests/servicestests/apks/install_uses_sdk/Android.bp b/services/tests/servicestests/apks/install_uses_sdk/Android.bp
index c24aa2b..a51293d 100644
--- a/services/tests/servicestests/apks/install_uses_sdk/Android.bp
+++ b/services/tests/servicestests/apks/install_uses_sdk/Android.bp
@@ -1,39 +1,56 @@
-android_test_helper_app {
-    name: "FrameworksServicesTests_install_uses_sdk_r0",
-    defaults: ["FrameworksServicesTests_apks_defaults"],
-    manifest: "AndroidManifest-r0.xml",
-
-    srcs: ["**/*.java"],
-}
-
-android_test_helper_app {
-    name: "FrameworksServicesTests_install_uses_sdk_r5",
-    defaults: ["FrameworksServicesTests_apks_defaults"],
-    manifest: "AndroidManifest-r5.xml",
-
-    srcs: ["**/*.java"],
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
 }
 
 android_test_helper_app {
     name: "FrameworksServicesTests_install_uses_sdk_q0",
     defaults: ["FrameworksServicesTests_apks_defaults"],
     manifest: "AndroidManifest-q0.xml",
-
-    srcs: ["**/*.java"],
 }
 
 android_test_helper_app {
-    name: "FrameworksServicesTests_install_uses_sdk_r",
+    name: "FrameworksServicesTests_install_uses_sdk_q0_r0",
     defaults: ["FrameworksServicesTests_apks_defaults"],
-    manifest: "AndroidManifest-r.xml",
+    manifest: "AndroidManifest-q0-r0.xml",
+}
 
-    srcs: ["**/*.java"],
+android_test_helper_app {
+    name: "FrameworksServicesTests_install_uses_sdk_r_none",
+    defaults: ["FrameworksServicesTests_apks_defaults"],
+    manifest: "AndroidManifest-r-none.xml",
+}
+
+android_test_helper_app {
+    name: "FrameworksServicesTests_install_uses_sdk_r0",
+    defaults: ["FrameworksServicesTests_apks_defaults"],
+    manifest: "AndroidManifest-r0.xml",
+}
+
+android_test_helper_app {
+    name: "FrameworksServicesTests_install_uses_sdk_r5",
+    defaults: ["FrameworksServicesTests_apks_defaults"],
+    manifest: "AndroidManifest-r5.xml",
+}
+
+android_test_helper_app {
+    name: "FrameworksServicesTests_install_uses_sdk_r0_s0",
+    defaults: ["FrameworksServicesTests_apks_defaults"],
+    manifest: "AndroidManifest-r0-s0.xml",
+}
+
+android_test_helper_app {
+    name: "FrameworksServicesTests_install_uses_sdk_r0_s5",
+    defaults: ["FrameworksServicesTests_apks_defaults"],
+    manifest: "AndroidManifest-r0-s5.xml",
 }
 
 android_test_helper_app {
     name: "FrameworksServicesTests_install_uses_sdk_0",
     defaults: ["FrameworksServicesTests_apks_defaults"],
     manifest: "AndroidManifest-0.xml",
-
-    srcs: ["**/*.java"],
 }
diff --git a/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-0.xml b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-0.xml
index 215384b..90b13d4 100644
--- a/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-0.xml
+++ b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-0.xml
@@ -18,7 +18,7 @@
 
     <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="29">
         <!-- This is invalid, because there is no sdk version specified -->
-        <extension-sdk android:minExtensionVersion="5" />
+        <extension-sdk android:minExtensionVersion="0" />
     </uses-sdk>
 
     <application>
diff --git a/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r.xml b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-q0-r0.xml
similarity index 80%
copy from services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r.xml
copy to services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-q0-r0.xml
index 5d22577..2a32276 100644
--- a/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r.xml
+++ b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-q0-r0.xml
@@ -17,8 +17,9 @@
         package="com.android.frameworks.servicestests.install_uses_sdk">
 
     <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="29">
-        <!-- This is invalid, because there is no minimum extension version specified -->
-        <extension-sdk android:sdkVersion="10000" />
+        <!-- This fails because 29 doesn't have an extension sdk -->
+        <extension-sdk android:sdkVersion="29" android:minExtensionVersion="0" />
+        <extension-sdk android:sdkVersion="30" android:minExtensionVersion="0" />
     </uses-sdk>
 
     <application>
diff --git a/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r.xml b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r-none.xml
similarity index 94%
rename from services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r.xml
rename to services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r-none.xml
index 5d22577..c79c61c 100644
--- a/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r.xml
+++ b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r-none.xml
@@ -18,7 +18,7 @@
 
     <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="29">
         <!-- This is invalid, because there is no minimum extension version specified -->
-        <extension-sdk android:sdkVersion="10000" />
+        <extension-sdk android:sdkVersion="30" />
     </uses-sdk>
 
     <application>
diff --git a/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r.xml b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r0-s0.xml
similarity index 84%
copy from services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r.xml
copy to services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r0-s0.xml
index 5d22577..af30915 100644
--- a/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r.xml
+++ b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r0-s0.xml
@@ -17,8 +17,8 @@
         package="com.android.frameworks.servicestests.install_uses_sdk">
 
     <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="29">
-        <!-- This is invalid, because there is no minimum extension version specified -->
-        <extension-sdk android:sdkVersion="10000" />
+        <extension-sdk android:sdkVersion="30" android:minExtensionVersion="0" />
+        <extension-sdk android:sdkVersion="31" android:minExtensionVersion="0" />
     </uses-sdk>
 
     <application>
diff --git a/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r.xml b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r0-s5.xml
similarity index 80%
copy from services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r.xml
copy to services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r0-s5.xml
index 5d22577..bafe4c4 100644
--- a/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r.xml
+++ b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r0-s5.xml
@@ -17,8 +17,9 @@
         package="com.android.frameworks.servicestests.install_uses_sdk">
 
     <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="29">
-        <!-- This is invalid, because there is no minimum extension version specified -->
-        <extension-sdk android:sdkVersion="10000" />
+        <!-- This fails because 31 is not version 5 -->
+        <extension-sdk android:sdkVersion="30" android:minExtensionVersion="0" />
+        <extension-sdk android:sdkVersion="31" android:minExtensionVersion="5" />
     </uses-sdk>
 
     <application>
diff --git a/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r0.xml b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r0.xml
index c1244f2..2920b86 100644
--- a/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r0.xml
+++ b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r0.xml
@@ -17,7 +17,7 @@
         package="com.android.frameworks.servicestests.install_uses_sdk">
 
     <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="29">
-        <extension-sdk android:sdkVersion="10000" android:minExtensionVersion="0" />
+        <extension-sdk android:sdkVersion="30" android:minExtensionVersion="0" />
     </uses-sdk>
 
     <application>
diff --git a/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r5.xml b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r5.xml
index 3410938..7723d05 100644
--- a/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r5.xml
+++ b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r5.xml
@@ -18,7 +18,7 @@
 
     <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="29">
         <!-- This will fail to install, because minExtensionVersion is not met -->
-        <extension-sdk android:sdkVersion="10000" android:minExtensionVersion="5" />
+        <extension-sdk android:sdkVersion="30" android:minExtensionVersion="5" />
     </uses-sdk>
 
     <application>
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationGesturesObserverTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationGesturesObserverTest.java
index 895fb17..5dbf837 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationGesturesObserverTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationGesturesObserverTest.java
@@ -69,7 +69,7 @@
         mContext = InstrumentationRegistry.getContext();
         mInstrumentation = InstrumentationRegistry.getInstrumentation();
         mObserver = new MagnificationGesturesObserver(mCallback, new SimpleSwipe(mContext),
-                new TwoFingersDown(mContext));
+                new TwoFingersDownOrSwipe(mContext));
     }
 
     @Test
@@ -77,9 +77,7 @@
         final MotionEvent moveEvent = TouchEventGenerator.moveEvent(Display.DEFAULT_DISPLAY,
                 DEFAULT_X , DEFAULT_Y);
 
-        mInstrumentation.runOnMainSync(() -> {
-            mObserver.onMotionEvent(moveEvent, moveEvent, 0);
-        });
+        mObserver.onMotionEvent(moveEvent, moveEvent, 0);
 
         verify(mCallback).onGestureCancelled(eq(0L),
                 mEventInfoArgumentCaptor.capture(), argThat(new MotionEventMatcher(moveEvent)));
@@ -92,9 +90,7 @@
         final MotionEvent downEvent = TouchEventGenerator.downEvent(Display.DEFAULT_DISPLAY,
                 DEFAULT_X , DEFAULT_Y);
 
-        mInstrumentation.runOnMainSync(() -> {
-            mObserver.onMotionEvent(downEvent, downEvent, 0);
-        });
+        mObserver.onMotionEvent(downEvent, downEvent, 0);
 
         verify(mCallback).onGestureCancelled(eq(0L),
                 mEventInfoArgumentCaptor.capture(), argThat(new MotionEventMatcher(downEvent)));
@@ -108,9 +104,7 @@
         final int timeoutMillis = MagnificationGestureMatcher.getMagnificationMultiTapTimeout(
                 mContext) + 100;
 
-        mInstrumentation.runOnMainSync(() -> {
-            mObserver.onMotionEvent(downEvent, downEvent, 0);
-        });
+        mObserver.onMotionEvent(downEvent, downEvent, 0);
 
         verify(mCallback, timeout(timeoutMillis)).onGestureCancelled(eq(downEvent.getDownTime()),
                 mEventInfoArgumentCaptor.capture(), argThat(new MotionEventMatcher(downEvent)));
@@ -121,14 +115,12 @@
     public void sendEventsOfSwiping_onGestureCompleted() {
         final MotionEvent downEvent = TouchEventGenerator.downEvent(Display.DEFAULT_DISPLAY,
                 DEFAULT_X, DEFAULT_Y);
-        final float swipeDistance = ViewConfiguration.get(mContext).getScaledTouchSlop();
+        final float swipeDistance = ViewConfiguration.get(mContext).getScaledTouchSlop() + 1;
         final MotionEvent moveEvent = TouchEventGenerator.moveEvent(Display.DEFAULT_DISPLAY,
                 DEFAULT_X + swipeDistance, DEFAULT_Y + swipeDistance);
 
-        mInstrumentation.runOnMainSync(() -> {
-            mObserver.onMotionEvent(downEvent, downEvent, 0);
-            mObserver.onMotionEvent(moveEvent, moveEvent, 0);
-        });
+        mObserver.onMotionEvent(downEvent, downEvent, 0);
+        mObserver.onMotionEvent(moveEvent, moveEvent, 0);
 
         verify(mCallback).onGestureCompleted(eq(MagnificationGestureMatcher.GESTURE_SWIPE),
                 eq(downEvent.getDownTime()), mEventInfoArgumentCaptor.capture(),
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/SimpleSwipeTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/SimpleSwipeTest.java
index 01631bf21..0ca631e 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/SimpleSwipeTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/SimpleSwipeTest.java
@@ -78,7 +78,7 @@
 
     @Test
     public void sendSwipeEvent_onGestureCompleted() {
-        final float swipeDistance = ViewConfiguration.get(mContext).getScaledTouchSlop();
+        final float swipeDistance = ViewConfiguration.get(mContext).getScaledTouchSlop() + 1;
         final MotionEvent downEvent = TouchEventGenerator.downEvent(Display.DEFAULT_DISPLAY,
                 DEFAULT_X, DEFAULT_Y);
         final MotionEvent moveEvent = TouchEventGenerator.moveEvent(Display.DEFAULT_DISPLAY,
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/TwoFingersDownOrSwipeTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/TwoFingersDownOrSwipeTest.java
new file mode 100644
index 0000000..162d2a9
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/TwoFingersDownOrSwipeTest.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility.magnification;
+
+import static com.android.server.accessibility.utils.TouchEventGenerator.movePointer;
+import static com.android.server.accessibility.utils.TouchEventGenerator.twoPointersDownEvents;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.after;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.graphics.PointF;
+import android.view.Display;
+import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+
+import androidx.test.InstrumentationRegistry;
+
+import com.android.server.accessibility.utils.TouchEventGenerator;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.List;
+
+/**
+ * Tests for {@link TwoFingersDownOrSwipe}.
+ */
+public class TwoFingersDownOrSwipeTest {
+
+    private static final float DEFAULT_X = 100f;
+    private static final float DEFAULT_Y = 100f;
+
+    private static float sSwipeMinDistance;
+    private static int sTimeoutMillis;
+    private static Context sContext;
+
+    private GesturesObserver mGesturesObserver;
+    @Mock
+    private GesturesObserver.Listener mListener;
+
+    @BeforeClass
+    public static void setupOnce() {
+        sContext = InstrumentationRegistry.getContext();
+        sTimeoutMillis = MagnificationGestureMatcher.getMagnificationMultiTapTimeout(
+                sContext) + 100;
+        sSwipeMinDistance = ViewConfiguration.get(sContext).getScaledTouchSlop() + 1;
+    }
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mGesturesObserver = new GesturesObserver(mListener, new TwoFingersDownOrSwipe(sContext));
+    }
+
+    @Test
+    public void sendSingleDownEvent_GestureCanceledAfterTimeout() {
+        final MotionEvent downEvent = TouchEventGenerator.downEvent(Display.DEFAULT_DISPLAY,
+                DEFAULT_X, DEFAULT_Y);
+
+        mGesturesObserver.onMotionEvent(downEvent, downEvent, 0);
+
+        verify(mListener, timeout(sTimeoutMillis)).onGestureCancelled(any(MotionEvent.class),
+                any(MotionEvent.class), eq(0));
+    }
+
+    @Test
+    public void sendTwoFingerDownEvent_onGestureCompleted() {
+        final List<MotionEvent> downEvents = twoPointersDownEvents(Display.DEFAULT_DISPLAY,
+                new PointF(DEFAULT_X, DEFAULT_Y), new PointF(DEFAULT_X + 10, DEFAULT_Y + 10));
+
+        for (MotionEvent event : downEvents) {
+            mGesturesObserver.onMotionEvent(event, event, 0);
+        }
+
+        verify(mListener, timeout(sTimeoutMillis)).onGestureCompleted(
+                MagnificationGestureMatcher.GESTURE_TWO_FINGERS_DOWN_OR_SWIPE, downEvents.get(1),
+                downEvents.get(1), 0);
+    }
+
+    @Test
+    public void sendSingleTapEvent_onGestureCancelled() {
+        final MotionEvent downEvent = TouchEventGenerator.downEvent(Display.DEFAULT_DISPLAY,
+                DEFAULT_X, DEFAULT_Y);
+        final MotionEvent upEvent = TouchEventGenerator.upEvent(Display.DEFAULT_DISPLAY,
+                DEFAULT_X, DEFAULT_Y);
+
+        mGesturesObserver.onMotionEvent(downEvent, downEvent, 0);
+        mGesturesObserver.onMotionEvent(upEvent, upEvent, 0);
+
+        verify(mListener, after(ViewConfiguration.getDoubleTapTimeout())).onGestureCancelled(
+                any(MotionEvent.class), any(MotionEvent.class), eq(0));
+    }
+
+    @Test
+    public void firstPointerMove_twoPointersDown_onGestureCompleted() {
+        final List<MotionEvent> downEvents = twoPointersDownEvents(Display.DEFAULT_DISPLAY,
+                new PointF(DEFAULT_X, DEFAULT_Y), new PointF(DEFAULT_X + 10, DEFAULT_Y + 10));
+        for (MotionEvent event : downEvents) {
+            mGesturesObserver.onMotionEvent(event, event, 0);
+        }
+        final MotionEvent moveEvent = movePointer(downEvents.get(1), 0, sSwipeMinDistance, 0);
+
+        mGesturesObserver.onMotionEvent(moveEvent, moveEvent, 0);
+
+        verify(mListener).onGestureCompleted(
+                MagnificationGestureMatcher.GESTURE_TWO_FINGERS_DOWN_OR_SWIPE, moveEvent,
+                moveEvent, 0);
+    }
+
+    @Test
+    public void secondPointerMove_twoPointersDown_onGestureCompleted() {
+        final List<MotionEvent> downEvents = twoPointersDownEvents(Display.DEFAULT_DISPLAY,
+                new PointF(DEFAULT_X, DEFAULT_Y), new PointF(DEFAULT_X + 10, DEFAULT_Y + 10));
+        for (MotionEvent event : downEvents) {
+            mGesturesObserver.onMotionEvent(event, event, 0);
+        }
+        final MotionEvent moveEvent = movePointer(downEvents.get(1), 1, sSwipeMinDistance, 0);
+
+        mGesturesObserver.onMotionEvent(moveEvent, moveEvent, 0);
+
+        verify(mListener).onGestureCompleted(
+                MagnificationGestureMatcher.GESTURE_TWO_FINGERS_DOWN_OR_SWIPE, moveEvent,
+                moveEvent, 0);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/TwoFingersDownTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/TwoFingersDownTest.java
deleted file mode 100644
index ed8dc4e..0000000
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/TwoFingersDownTest.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.accessibility.magnification;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.verify;
-
-import android.content.Context;
-import android.view.Display;
-import android.view.MotionEvent;
-
-import androidx.test.InstrumentationRegistry;
-
-import com.android.server.accessibility.utils.TouchEventGenerator;
-
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-/**
- * Tests for {@link TwoFingersDown}.
- */
-public class TwoFingersDownTest {
-
-    private static final float DEFAULT_X = 100f;
-    private static final float DEFAULT_Y = 100f;
-
-    private static Context sContext;
-    private static int sTimeoutMillis;
-
-    private Context mContext;
-    private GesturesObserver mGesturesObserver;
-    @Mock
-    private GesturesObserver.Listener mListener;
-
-    @BeforeClass
-    public static void setupOnce() {
-        sContext = InstrumentationRegistry.getContext();
-        sTimeoutMillis = MagnificationGestureMatcher.getMagnificationMultiTapTimeout(
-                sContext) + 100;
-    }
-
-    @Before
-    public void setUp() {
-        mContext = InstrumentationRegistry.getContext();
-        MockitoAnnotations.initMocks(this);
-        mGesturesObserver = new GesturesObserver(mListener, new TwoFingersDown(mContext));
-    }
-
-    @Test
-    public void sendSingleDownEvent_GestureCanceledAfterTimeout() {
-        final MotionEvent downEvent = TouchEventGenerator.downEvent(Display.DEFAULT_DISPLAY,
-                DEFAULT_X, DEFAULT_Y);
-
-        mGesturesObserver.onMotionEvent(downEvent, downEvent, 0);
-
-        verify(mListener, timeout(sTimeoutMillis)).onGestureCancelled(any(MotionEvent.class),
-                any(MotionEvent.class), eq(0));
-    }
-
-    @Test
-    public void sendTwoFingerDownEvent_onGestureCompleted() {
-        final MotionEvent downEvent = TouchEventGenerator.downEvent(Display.DEFAULT_DISPLAY,
-                DEFAULT_X, DEFAULT_Y);
-        final MotionEvent.PointerCoords defPointerCoords = new MotionEvent.PointerCoords();
-        defPointerCoords.x = DEFAULT_X;
-        defPointerCoords.y = DEFAULT_Y;
-        final MotionEvent.PointerCoords secondPointerCoords = new MotionEvent.PointerCoords();
-        secondPointerCoords.x = DEFAULT_X + 10;
-        secondPointerCoords.y = DEFAULT_Y + 10;
-
-        final MotionEvent twoPointersDownEvent = TouchEventGenerator.twoPointersDownEvent(
-                Display.DEFAULT_DISPLAY, defPointerCoords, secondPointerCoords);
-
-        mGesturesObserver.onMotionEvent(downEvent, downEvent, 0);
-        mGesturesObserver.onMotionEvent(twoPointersDownEvent, twoPointersDownEvent, 0);
-
-        verify(mListener, timeout(sTimeoutMillis)).onGestureCompleted(
-                MagnificationGestureMatcher.GESTURE_TWO_FINGER_DOWN, twoPointersDownEvent,
-                twoPointersDownEvent, 0);
-    }
-
-    @Test
-    public void sendSingleTapEvent_onGestureCancelled() {
-        final MotionEvent downEvent = TouchEventGenerator.downEvent(Display.DEFAULT_DISPLAY,
-                DEFAULT_X, DEFAULT_Y);
-        final MotionEvent upEvent = TouchEventGenerator.upEvent(Display.DEFAULT_DISPLAY,
-                DEFAULT_X, DEFAULT_Y);
-
-        mGesturesObserver.onMotionEvent(downEvent, downEvent, 0);
-        mGesturesObserver.onMotionEvent(upEvent, upEvent, 0);
-
-        verify(mListener, timeout(sTimeoutMillis)).onGestureCancelled(any(MotionEvent.class),
-                any(MotionEvent.class), eq(0));
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
index 4b7ebbc..b9498d6 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
@@ -24,13 +24,15 @@
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
+import android.graphics.PointF;
 import android.graphics.Rect;
 import android.os.RemoteException;
 import android.util.DebugUtils;
 import android.view.InputDevice;
 import android.view.MotionEvent;
+import android.view.ViewConfiguration;
 
-import androidx.test.InstrumentationRegistry;
+import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.accessibility.EventStreamTransformation;
@@ -43,6 +45,7 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.List;
 import java.util.function.IntConsumer;
 
 /**
@@ -75,7 +78,7 @@
     @Before
     public void setUp() throws RemoteException {
         MockitoAnnotations.initMocks(this);
-        mContext = InstrumentationRegistry.getContext();
+        mContext = InstrumentationRegistry.getInstrumentation().getContext();
         mWindowMagnificationManager = new WindowMagnificationManager(mContext, 0,
                 mock(WindowMagnificationManager.Callback.class));
         mMockConnection = new MockWindowMagnificationConnection();
@@ -100,8 +103,8 @@
      * Covers following paths to get to and back between each state and {@link #STATE_IDLE}.
      * <p>
      *     <br> IDLE -> SHOW_MAGNIFIER [label="a11y\nbtn"]
-     *     <br> SHOW_MAGNIFIER -> TWO_FINGER_DOWN [label="2hold"]
-     *     <br> TWO_FINGER_DOWN -> SHOW_MAGNIFIER [label="release"]
+     *     <br> SHOW_MAGNIFIER -> TWO_FINGERS_DOWN [label="2hold"]
+     *     <br> TWO_FINGERS_DOWN -> SHOW_MAGNIFIER [label="release"]
      *     <br> SHOW_MAGNIFIER -> IDLE [label="a11y\nbtn"]
      *     <br> IDLE -> SHOW_MAGNIFIER_TRIPLE_TAP [label="3tap"]
      *     <br> SHOW_MAGNIFIER_TRIPLE_TAP -> IDLE [label="3tap"]
@@ -112,18 +115,16 @@
      */
     @Test
     public void testEachState_isReachableAndRecoverable() {
-        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
-            forEachState(state -> {
-                goFromStateIdleTo(state);
-                assertIn(state);
-                returnToNormalFrom(state);
-                try {
-                    assertIn(STATE_IDLE);
-                } catch (AssertionError e) {
-                    throw new AssertionError("Failed while testing state " + stateToString(state),
-                            e);
-                }
-            });
+        forEachState(state -> {
+            goFromStateIdleTo(state);
+            assertIn(state);
+            returnToNormalFrom(state);
+            try {
+                assertIn(STATE_IDLE);
+            } catch (AssertionError e) {
+                throw new AssertionError("Failed while testing state " + stateToString(state),
+                        e);
+            }
         });
     }
 
@@ -209,10 +210,19 @@
                 case STATE_TWO_FINGERS_DOWN: {
                     goFromStateIdleTo(STATE_SHOW_MAGNIFIER_SHORTCUT);
                     final Rect frame = mMockConnection.getMirrorWindowFrame();
-                    send(downEvent(frame.centerX(), frame.centerY()));
-                    //Second finger is outside the window.
-                    send(twoPointerDownEvent(new float[]{frame.centerX(), frame.centerX() + 10},
-                            new float[]{frame.centerY(), frame.centerY() + 10}));
+                    final PointF firstPointerDown = new PointF(frame.centerX(), frame.centerY());
+                    // The second finger is outside the window.
+                    final PointF secondPointerDown = new PointF(frame.right + 10,
+                            frame.bottom + 10);
+                    final List<MotionEvent> motionEvents =
+                            TouchEventGenerator.twoPointersDownEvents(DISPLAY_0,
+                                    firstPointerDown, secondPointerDown);
+                    for (MotionEvent downEvent: motionEvents) {
+                        send(downEvent);
+                    }
+                    // Wait for two-finger down gesture completed.
+                    Thread.sleep(ViewConfiguration.getDoubleTapTimeout());
+                    InstrumentationRegistry.getInstrumentation().waitForIdleSync();
                 }
                 break;
                 case STATE_SHOW_MAGNIFIER_TRIPLE_TAP: {
@@ -301,16 +311,6 @@
         send(upEvent(DEFAULT_TAP_X, DEFAULT_TAP_Y));
     }
 
-    private MotionEvent twoPointerDownEvent(float[] x, float[] y) {
-        final MotionEvent.PointerCoords defPointerCoords = new MotionEvent.PointerCoords();
-        defPointerCoords.x = x[0];
-        defPointerCoords.y = y[0];
-        final MotionEvent.PointerCoords pointerCoords = new MotionEvent.PointerCoords();
-        pointerCoords.x = x[1];
-        pointerCoords.y = y[1];
-        return TouchEventGenerator.twoPointersDownEvent(DISPLAY_0, defPointerCoords, pointerCoords);
-    }
-
     private String stateDump() {
         return "\nCurrent state dump:\n" + mWindowMagnificationGestureHandler.mCurrentState;
     }
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/utils/TouchEventGenerator.java b/services/tests/servicestests/src/com/android/server/accessibility/utils/TouchEventGenerator.java
index a05881f..fbcde53 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/utils/TouchEventGenerator.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/utils/TouchEventGenerator.java
@@ -19,16 +19,19 @@
 import static android.view.MotionEvent.ACTION_DOWN;
 import static android.view.MotionEvent.ACTION_MOVE;
 import static android.view.MotionEvent.ACTION_POINTER_DOWN;
+import static android.view.MotionEvent.ACTION_POINTER_UP;
 import static android.view.MotionEvent.ACTION_UP;
-import static android.view.MotionEvent.PointerCoords;
 
+import android.graphics.PointF;
 import android.os.SystemClock;
 import android.view.InputDevice;
 import android.view.MotionEvent;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * generates {@link MotionEvent} with source {@link InputDevice#SOURCE_TOUCHSCREEN}
- *
  */
 public class TouchEventGenerator {
 
@@ -39,44 +42,68 @@
     public static MotionEvent moveEvent(int displayId, float x, float y) {
         return generateSingleTouchEvent(displayId, ACTION_MOVE, x, y);
     }
+
     public static MotionEvent upEvent(int displayId, float x, float y) {
         return generateSingleTouchEvent(displayId, ACTION_UP, x, y);
     }
 
-    public static MotionEvent twoPointersDownEvent(int displayId, PointerCoords defPointerCoords,
-            PointerCoords pointerCoords) {
-        return generateTwoPointersEvent(displayId, ACTION_POINTER_DOWN, defPointerCoords,
-                pointerCoords);
-    }
-
     private static MotionEvent generateSingleTouchEvent(int displayId, int action, float x,
             float y) {
-        final long  downTime = SystemClock.uptimeMillis();
-        final MotionEvent ev = MotionEvent.obtain(downTime, downTime,
-                action, x, y, 0);
-        ev.setDisplayId(displayId);
-        ev.setSource(InputDevice.SOURCE_TOUCHSCREEN);
-        return ev;
+        return generateMultiplePointersEvent(displayId, action, new PointF(x, y));
     }
 
-    private static MotionEvent generateTwoPointersEvent(int displayId, int action,
-            PointerCoords defPointerCoords, PointerCoords pointerCoords) {
-        final long  downTime = SystemClock.uptimeMillis();
-        MotionEvent.PointerProperties defPointerProperties = new MotionEvent.PointerProperties();
-        defPointerProperties.id = 0;
-        defPointerProperties.toolType = MotionEvent.TOOL_TYPE_FINGER;
-        MotionEvent.PointerProperties pointerProperties = new MotionEvent.PointerProperties();
-        pointerProperties.id = 1;
-        pointerProperties.toolType = MotionEvent.TOOL_TYPE_FINGER;
+    /**
+     * Creates a list of {@link MotionEvent} with given pointers location.
+     *
+     * @param displayId the display id
+     * @param pointF1   location on the screen of the second pointer.
+     * @param pointF2   location on the screen of the second pointer.
+     * @return a list of {@link MotionEvent} with {@link MotionEvent#ACTION_DOWN} and {@link
+     * MotionEvent#ACTION_POINTER_DOWN}.
+     */
+    public static List<MotionEvent> twoPointersDownEvents(int displayId, PointF pointF1,
+            PointF pointF2) {
+        final List<MotionEvent> downEvents = new ArrayList<>();
+        final MotionEvent downEvent = generateMultiplePointersEvent(displayId,
+                MotionEvent.ACTION_DOWN, pointF1);
+        downEvents.add(downEvent);
 
+        final int actionIndex = 1 << MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+        final int action = ACTION_POINTER_DOWN | actionIndex;
+
+        final MotionEvent twoPointersDownEvent = generateMultiplePointersEvent(displayId, action,
+                pointF1, pointF2);
+        downEvents.add(twoPointersDownEvent);
+        return downEvents;
+    }
+
+    private static MotionEvent generateMultiplePointersEvent(int displayId, int action,
+            PointF... pointFs) {
+        final int length = pointFs.length;
+        final MotionEvent.PointerCoords[] pointerCoordsArray =
+                new MotionEvent.PointerCoords[length];
+        final MotionEvent.PointerProperties[] pointerPropertiesArray =
+                new MotionEvent.PointerProperties[length];
+        for (int i = 0; i < length; i++) {
+            MotionEvent.PointerCoords pointerCoords = new MotionEvent.PointerCoords();
+            pointerCoords.x = pointFs[i].x;
+            pointerCoords.y = pointFs[i].y;
+            pointerCoordsArray[i] = pointerCoords;
+
+            MotionEvent.PointerProperties pointerProperties = new MotionEvent.PointerProperties();
+            pointerProperties.id = i;
+            pointerProperties.toolType = MotionEvent.TOOL_TYPE_FINGER;
+            pointerPropertiesArray[i] = pointerProperties;
+        }
+
+        final long downTime = SystemClock.uptimeMillis();
         final MotionEvent ev = MotionEvent.obtain(
                 /* downTime */ downTime,
                 /* eventTime */ downTime,
                 /* action */ action,
-                /* pointerCount */ 2,
-                /* pointerProperties */ new MotionEvent.PointerProperties[] {
-                        defPointerProperties, pointerProperties},
-                /* pointerCoords */ new PointerCoords[] { defPointerCoords, pointerCoords },
+                /* pointerCount */ length,
+                /* pointerProperties */ pointerPropertiesArray,
+                /* pointerCoords */ pointerCoordsArray,
                 /* metaState */ 0,
                 /* buttonState */ 0,
                 /* xPrecision */ 1.0f,
@@ -88,4 +115,65 @@
         ev.setDisplayId(displayId);
         return ev;
     }
+
+    /**
+     *  Generates a move event that moves the pointer of the original event with given index.
+     *  The original event should not be up event and we don't support
+     *  {@link MotionEvent#ACTION_POINTER_UP} now.
+     *
+     * @param originalEvent the move or down event
+     * @param pointerIndex the index of the pointer we want to move.
+     * @param offsetX the offset in X coordinate.
+     * @param offsetY the offset in Y coordinate.
+     * @return a motion event with move action.
+     */
+    public static MotionEvent movePointer(MotionEvent originalEvent, int pointerIndex,
+            float offsetX, float offsetY) {
+        if (originalEvent.getActionMasked() == ACTION_UP) {
+            throw new IllegalArgumentException("No pointer is on the screen");
+        }
+
+        if (originalEvent.getActionMasked() == ACTION_POINTER_UP) {
+            throw new IllegalArgumentException("unsupported yet,please implement it first");
+        }
+
+        final int pointerCount = originalEvent.getPointerCount();
+        if (pointerIndex >= pointerCount) {
+            throw new IllegalArgumentException(
+                    pointerIndex + "is not available with pointer count" + pointerCount);
+        }
+        final int action = MotionEvent.ACTION_MOVE;
+        final MotionEvent.PointerProperties[] pp = new MotionEvent.PointerProperties[pointerCount];
+        for (int i = 0; i < pointerCount; i++) {
+            MotionEvent.PointerProperties pointerProperty = new MotionEvent.PointerProperties();
+            originalEvent.getPointerProperties(i, pointerProperty);
+            pp[i] = pointerProperty;
+        }
+
+        final MotionEvent.PointerCoords[] pc = new MotionEvent.PointerCoords[pointerCount];
+        for (int i = 0; i < pointerCount; i++) {
+            MotionEvent.PointerCoords pointerCoord = new MotionEvent.PointerCoords();
+            originalEvent.getPointerCoords(i, pointerCoord);
+            pc[i] = pointerCoord;
+        }
+        pc[pointerIndex].x += offsetX;
+        pc[pointerIndex].y += offsetY;
+        final MotionEvent ev = MotionEvent.obtain(
+                /* downTime */ originalEvent.getDownTime(),
+                /* eventTime */ SystemClock.uptimeMillis(),
+                /* action */ action,
+                /* pointerCount */ 2,
+                /* pointerProperties */ pp,
+                /* pointerCoords */ pc,
+                /* metaState */ 0,
+                /* buttonState */ 0,
+                /* xPrecision */ 1.0f,
+                /* yPrecision */ 1.0f,
+                /* deviceId */ 0,
+                /* edgeFlags */ 0,
+                /* source */ originalEvent.getSource(),
+                /* flags */ originalEvent.getFlags());
+        ev.setDisplayId(originalEvent.getDisplayId());
+        return ev;
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/BatteryStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/am/BatteryStatsServiceTest.java
index 488e5cd..1870df9 100644
--- a/services/tests/servicestests/src/com/android/server/am/BatteryStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/BatteryStatsServiceTest.java
@@ -30,6 +30,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -59,6 +60,7 @@
     }
 
     @Test
+    @Ignore("b/180015146")
     public void testAwaitCompletion() throws Exception {
         final CountDownLatch readyLatch = new CountDownLatch(2);
         final CountDownLatch startLatch = new CountDownLatch(1);
diff --git a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
index 1328b91..07f6732 100644
--- a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
@@ -110,6 +110,8 @@
         UserInfo userInfo = addUser(USER_ID_1);
         mAppHibernationService.onUserUnlocking(new SystemService.TargetUser(userInfo));
         doReturn(true).when(mUserManager).isUserUnlockingOrUnlocked(USER_ID_1);
+
+        mAppHibernationService.mIsServiceEnabled = true;
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java
index 41e1563..6630178 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java
@@ -66,11 +66,13 @@
         inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
                 .times(1)).onOpNoted(eq(AppOpsManager.OP_FINE_LOCATION),
                 eq(Process.myUid()), eq(getContext().getPackageName()),
-                eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED));
+                eq(getContext().getAttributionTag()), eq(AppOpsManager.OP_FLAG_SELF),
+                eq(AppOpsManager.MODE_ALLOWED));
         inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
                 .times(1)).onOpNoted(eq(AppOpsManager.OP_CAMERA),
                 eq(Process.myUid()), eq(getContext().getPackageName()),
-                eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED));
+                eq(getContext().getAttributionTag()), eq(AppOpsManager.OP_FLAG_SELF),
+                eq(AppOpsManager.MODE_ALLOWED));
 
         // Stop watching
         appOpsManager.stopWatchingNoted(listener);
@@ -94,7 +96,8 @@
         verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
                 .times(2)).onOpNoted(eq(AppOpsManager.OP_FINE_LOCATION),
                 eq(Process.myUid()), eq(getContext().getPackageName()),
-                eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED));
+                eq(getContext().getAttributionTag()), eq(AppOpsManager.OP_FLAG_SELF),
+                eq(AppOpsManager.MODE_ALLOWED));
 
         // Finish up
         appOpsManager.stopWatchingNoted(listener);
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java
index fec8aa9..c12eb32 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java
@@ -63,11 +63,13 @@
         inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
                 .times(1)).onOpStarted(eq(AppOpsManager.OP_FINE_LOCATION),
                 eq(Process.myUid()), eq(getContext().getPackageName()),
-                eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED));
+                eq(getContext().getAttributionTag()), eq(AppOpsManager.OP_FLAG_SELF),
+                eq(AppOpsManager.MODE_ALLOWED));
         inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
                 .times(1)).onOpStarted(eq(AppOpsManager.OP_CAMERA),
                 eq(Process.myUid()), eq(getContext().getPackageName()),
-                eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED));
+                eq(getContext().getAttributionTag()), eq(AppOpsManager.OP_FLAG_SELF),
+                eq(AppOpsManager.MODE_ALLOWED));
 
         // Stop watching
         appOpsManager.stopWatchingStarted(listener);
@@ -91,7 +93,8 @@
         verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
                 .times(2)).onOpStarted(eq(AppOpsManager.OP_CAMERA),
                 eq(Process.myUid()), eq(getContext().getPackageName()),
-                eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED));
+                eq(getContext().getAttributionTag()), eq(AppOpsManager.OP_FLAG_SELF),
+                eq(AppOpsManager.MODE_ALLOWED));
         verifyNoMoreInteractions(listener);
 
         // Finish up
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
index 73b0105..6890ed1 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
@@ -28,6 +28,7 @@
 import android.app.appsearch.SetSchemaResponse;
 import android.app.appsearch.exceptions.AppSearchException;
 import android.content.Context;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 
 import androidx.test.core.app.ApplicationProvider;
@@ -55,6 +56,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 public class AppSearchImplTest {
@@ -971,21 +973,46 @@
     }
 
     @Test
-    public void testHasSchemaType() throws Exception {
-        // Nothing exists yet
-        assertThat(mAppSearchImpl.hasSchemaTypeLocked("package", "database", "Schema")).isFalse();
+    public void testGetPackageToDatabases() throws Exception {
+        Map<String, Set<String>> existingMapping = mAppSearchImpl.getPackageToDatabases();
+        Map<String, Set<String>> expectedMapping = new ArrayMap<>();
+        expectedMapping.putAll(existingMapping);
 
+        // Has database1
+        expectedMapping.put("package1", ImmutableSet.of("database1"));
         mAppSearchImpl.setSchema(
-                "package",
-                "database",
-                Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
+                "package1",
+                "database1",
+                Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
                 /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                 /*schemasPackageAccessible=*/ Collections.emptyMap(),
                 /*forceOverride=*/ false);
-        assertThat(mAppSearchImpl.hasSchemaTypeLocked("package", "database", "Schema")).isTrue();
+        assertThat(mAppSearchImpl.getPackageToDatabases())
+                .containsExactlyEntriesIn(expectedMapping);
 
-        assertThat(mAppSearchImpl.hasSchemaTypeLocked("package", "database", "UnknownSchema"))
-                .isFalse();
+        // Has both databases
+        expectedMapping.put("package1", ImmutableSet.of("database1", "database2"));
+        mAppSearchImpl.setSchema(
+                "package1",
+                "database2",
+                Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
+                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+                /*schemasPackageAccessible=*/ Collections.emptyMap(),
+                /*forceOverride=*/ false);
+        assertThat(mAppSearchImpl.getPackageToDatabases())
+                .containsExactlyEntriesIn(expectedMapping);
+
+        // Has both packages
+        expectedMapping.put("package2", ImmutableSet.of("database1"));
+        mAppSearchImpl.setSchema(
+                "package2",
+                "database1",
+                Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
+                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+                /*schemasPackageAccessible=*/ Collections.emptyMap(),
+                /*forceOverride=*/ false);
+        assertThat(mAppSearchImpl.getPackageToDatabases())
+                .containsExactlyEntriesIn(expectedMapping);
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java
new file mode 100644
index 0000000..4308885
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appsearch.external.localstorage.stats;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Test;
+
+public class AppSearchStatsTest {
+    static final String TEST_PACKAGE_NAME = "com.google.test";
+    static final String TEST_DATA_BASE = "testDataBase";
+    static final int TEST_STATUS_CODE = 2;
+    static final int TEST_TOTAL_LATENCY_MILLIS = 20;
+
+    @Test
+    public void testAppSearchStats_GeneralStats() {
+        final GeneralStats gStats =
+                new GeneralStats.Builder(TEST_PACKAGE_NAME, TEST_DATA_BASE)
+                        .setStatusCode(TEST_STATUS_CODE)
+                        .setTotalLatencyMillis(TEST_TOTAL_LATENCY_MILLIS)
+                        .build();
+
+        assertThat(gStats.getPackageName()).isEqualTo(TEST_PACKAGE_NAME);
+        assertThat(gStats.getDatabase()).isEqualTo(TEST_DATA_BASE);
+        assertThat(gStats.getStatusCode()).isEqualTo(TEST_STATUS_CODE);
+        assertThat(gStats.getTotalLatencyMillis()).isEqualTo(TEST_TOTAL_LATENCY_MILLIS);
+    }
+
+    @Test
+    public void testAppSearchStats_CallStats() {
+        final int estimatedBinderLatencyMillis = 1;
+        final int numOperationsSucceeded = 2;
+        final int numOperationsFailed = 3;
+
+        final GeneralStats gStats =
+                new GeneralStats.Builder(TEST_PACKAGE_NAME, TEST_DATA_BASE)
+                        .setStatusCode(TEST_STATUS_CODE)
+                        .setTotalLatencyMillis(TEST_TOTAL_LATENCY_MILLIS)
+                        .build();
+        final @CallStats.CallType int callType = CallStats.CALL_TYPE_PUT_DOCUMENTS;
+        final CallStats cStats =
+                new CallStats.Builder(gStats)
+                        .setCallType(callType)
+                        .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
+                        .setNumOperationsSucceeded(numOperationsSucceeded)
+                        .setNumOperationsFailed(numOperationsFailed)
+                        .build();
+
+        assertThat(cStats.getGeneralStats().getPackageName()).isEqualTo(TEST_PACKAGE_NAME);
+        assertThat(cStats.getGeneralStats().getDatabase()).isEqualTo(TEST_DATA_BASE);
+        assertThat(cStats.getGeneralStats().getStatusCode()).isEqualTo(TEST_STATUS_CODE);
+        assertThat(cStats.getGeneralStats().getTotalLatencyMillis())
+                .isEqualTo(TEST_TOTAL_LATENCY_MILLIS);
+        assertThat(cStats.getEstimatedBinderLatencyMillis())
+                .isEqualTo(estimatedBinderLatencyMillis);
+        assertThat(cStats.getCallType()).isEqualTo(callType);
+        assertThat(cStats.getNumOperationsSucceeded()).isEqualTo(numOperationsSucceeded);
+        assertThat(cStats.getNumOperationsFailed()).isEqualTo(numOperationsFailed);
+    }
+
+    @Test
+    public void testAppSearchStats_PutDocumentStats() {
+        final int generateDocumentProtoLatencyMillis = 1;
+        final int rewriteDocumentTypesLatencyMillis = 2;
+        final int nativeLatencyMillis = 3;
+        final int nativeDocumentStoreLatencyMillis = 4;
+        final int nativeIndexLatencyMillis = 5;
+        final int nativeIndexMergeLatencyMillis = 6;
+        final int nativeDocumentSize = 7;
+        final int nativeNumTokensIndexed = 8;
+        final int nativeNumTokensClipped = 9;
+
+        final GeneralStats gStats =
+                new GeneralStats.Builder(TEST_PACKAGE_NAME, TEST_DATA_BASE)
+                        .setStatusCode(TEST_STATUS_CODE)
+                        .setTotalLatencyMillis(TEST_TOTAL_LATENCY_MILLIS)
+                        .build();
+        final PutDocumentStats pStats =
+                new PutDocumentStats.Builder(gStats)
+                        .setGenerateDocumentProtoLatencyMillis(generateDocumentProtoLatencyMillis)
+                        .setRewriteDocumentTypesLatencyMillis(rewriteDocumentTypesLatencyMillis)
+                        .setNativeLatencyMillis(nativeLatencyMillis)
+                        .setNativeDocumentStoreLatencyMillis(nativeDocumentStoreLatencyMillis)
+                        .setNativeIndexLatencyMillis(nativeIndexLatencyMillis)
+                        .setNativeIndexMergeLatencyMillis(nativeIndexMergeLatencyMillis)
+                        .setNativeDocumentSizeBytes(nativeDocumentSize)
+                        .setNativeNumTokensIndexed(nativeNumTokensIndexed)
+                        .setNativeNumTokensClipped(nativeNumTokensClipped)
+                        .build();
+
+        assertThat(pStats.getGeneralStats().getPackageName()).isEqualTo(TEST_PACKAGE_NAME);
+        assertThat(pStats.getGeneralStats().getDatabase()).isEqualTo(TEST_DATA_BASE);
+        assertThat(pStats.getGeneralStats().getStatusCode()).isEqualTo(TEST_STATUS_CODE);
+        assertThat(pStats.getGeneralStats().getTotalLatencyMillis())
+                .isEqualTo(TEST_TOTAL_LATENCY_MILLIS);
+        assertThat(pStats.getGenerateDocumentProtoLatencyMillis())
+                .isEqualTo(generateDocumentProtoLatencyMillis);
+        assertThat(pStats.getRewriteDocumentTypesLatencyMillis())
+                .isEqualTo(rewriteDocumentTypesLatencyMillis);
+        assertThat(pStats.getNativeLatencyMillis()).isEqualTo(nativeLatencyMillis);
+        assertThat(pStats.getNativeDocumentStoreLatencyMillis())
+                .isEqualTo(nativeDocumentStoreLatencyMillis);
+        assertThat(pStats.getNativeIndexLatencyMillis()).isEqualTo(nativeIndexLatencyMillis);
+        assertThat(pStats.getNativeIndexMergeLatencyMillis())
+                .isEqualTo(nativeIndexMergeLatencyMillis);
+        assertThat(pStats.getNativeDocumentSizeBytes()).isEqualTo(nativeDocumentSize);
+        assertThat(pStats.getNativeNumTokensIndexed()).isEqualTo(nativeNumTokensIndexed);
+        assertThat(pStats.getNativeNumTokensClipped()).isEqualTo(nativeNumTokensClipped);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/backup/UserBackupManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/backup/UserBackupManagerServiceTest.java
index b98f025..205ff30 100644
--- a/services/tests/servicestests/src/com/android/server/backup/UserBackupManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/UserBackupManagerServiceTest.java
@@ -23,6 +23,7 @@
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.when;
 
+import android.app.backup.BackupAgent;
 import android.app.backup.BackupManager.OperationType;
 import android.app.backup.IBackupManagerMonitor;
 import android.app.backup.IBackupObserver;
@@ -30,6 +31,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import com.android.internal.backup.IBackupTransport;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.runner.AndroidJUnit4;
@@ -56,6 +58,7 @@
     @Mock IBackupObserver mBackupObserver;
     @Mock PackageManager mPackageManager;
     @Mock TransportClient mTransportClient;
+    @Mock IBackupTransport mBackupTransport;
     @Mock BackupEligibilityRules mBackupEligibilityRules;
 
 
@@ -132,6 +135,33 @@
         assertThat(params.mBackupEligibilityRules).isEqualTo(mBackupEligibilityRules);
     }
 
+    @Test
+    public void testGetOperationTypeFromTransport_returnsBackupByDefault()
+            throws Exception {
+        when(mTransportClient.connectOrThrow(any())).thenReturn(mBackupTransport);
+        when(mBackupTransport.getTransportFlags()).thenReturn(0);
+
+        int operationType = mService.getOperationTypeFromTransport(mTransportClient);
+
+        assertThat(operationType).isEqualTo(OperationType.BACKUP);
+    }
+
+    @Test
+    public void testGetOperationTypeFromTransport_returnsMigrationForMigrationTransport()
+            throws Exception {
+        // This is a temporary flag to control the new behaviour until it's ready to be fully
+        // rolled out.
+        mService.shouldUseNewBackupEligibilityRules = true;
+
+        when(mTransportClient.connectOrThrow(any())).thenReturn(mBackupTransport);
+        when(mBackupTransport.getTransportFlags()).thenReturn(
+                BackupAgent.FLAG_DEVICE_TO_DEVICE_TRANSFER);
+
+        int operationType = mService.getOperationTypeFromTransport(mTransportClient);
+
+        assertThat(operationType).isEqualTo(OperationType.MIGRATION);
+    }
+
     private static PackageInfo getPackageInfo(String packageName) {
         PackageInfo packageInfo = new PackageInfo();
         packageInfo.applicationInfo = new ApplicationInfo();
@@ -141,6 +171,7 @@
 
     private static class TestBackupService extends UserBackupManagerService {
         boolean isEnabledStatePersisted = false;
+        boolean shouldUseNewBackupEligibilityRules = false;
 
         TestBackupService(Context context, PackageManager packageManager) {
             super(context, packageManager);
@@ -158,5 +189,10 @@
 
         @Override
         void updateStateOnBackupEnabled(boolean wasEnabled, boolean enable) {}
+
+        @Override
+        boolean shouldUseNewBackupEligibilityRules() {
+            return shouldUseNewBackupEligibilityRules;
+        }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java b/services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java
index 2cbc3f3..a694d5e 100644
--- a/services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java
+++ b/services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java
@@ -153,4 +153,25 @@
         assertEquals("Period not restored", periodic.periodMillis, oneoff.periodMillis);
         assertEquals("Flex not restored", periodic.flexMillis, oneoff.flexMillis);
     }
+
+    @SmallTest
+    public void testScheduleAsEjIsInExtras() {
+        Account account1 = new Account("account1", "type1");
+        Bundle b1 = new Bundle();
+        b1.putBoolean(ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB, true);
+
+        SyncOperation op1 = new SyncOperation(account1, 0, 1, "foo", 0,
+                SyncOperation.REASON_USER_START, "authority1", b1, false,
+                ContentResolver.SYNC_EXEMPTION_NONE);
+        assertTrue(op1.isScheduledAsExpeditedJob());
+
+        PersistableBundle pb = op1.toJobInfoExtras();
+        assertTrue("EJ extra not found in job extras",
+                ((PersistableBundle) pb.get("syncExtras"))
+                        .containsKey(ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB));
+
+        SyncOperation op2 = SyncOperation.maybeCreateFromJobExtras(pb);
+        assertTrue("EJ extra not found in extras", op2.getClonedExtras()
+                .getBoolean(ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB));
+    }
 }
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 6add8d1..87100a6 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -20,6 +20,8 @@
 import static android.app.admin.DevicePolicyManager.ACTION_CHECK_POLICY_COMPLIANCE;
 import static android.app.admin.DevicePolicyManager.DELEGATION_APP_RESTRICTIONS;
 import static android.app.admin.DevicePolicyManager.DELEGATION_CERT_INSTALL;
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT;
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
 import static android.app.admin.DevicePolicyManager.ID_TYPE_BASE_INFO;
 import static android.app.admin.DevicePolicyManager.ID_TYPE_IMEI;
 import static android.app.admin.DevicePolicyManager.ID_TYPE_MEID;
@@ -826,7 +828,7 @@
      * {@link DevicePolicyManager#forceRemoveActiveAdmin(ComponentName, int)}
      */
     @Test
-    public void testForceRemoveActiveAdmin() throws Exception {
+    public void testForceRemoveActiveAdmin_nonShellCaller() throws Exception {
         mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
 
         // Add admin.
@@ -840,8 +842,53 @@
         // Calling from a non-shell uid should fail with a SecurityException
         mContext.binder.callingUid = 123456;
         assertExpectException(SecurityException.class,
-                /* messageRegex =*/ "Non-shell user attempted to call",
+                /* messageRegex = */ null,
                 () -> dpms.forceRemoveActiveAdmin(admin1, CALLER_USER_HANDLE));
+    }
+
+    /**
+     * Test for:
+     * {@link DevicePolicyManager#forceRemoveActiveAdmin(ComponentName, int)}
+     */
+    @Test
+    public void testForceRemoveActiveAdmin_nonShellCallerWithPermission() throws Exception {
+        mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+
+        // Add admin.
+        setupPackageInPackageManager(admin1.getPackageName(),
+                /* userId= */ CALLER_USER_HANDLE,
+                /* appId= */ 10138,
+                /* flags= */ ApplicationInfo.FLAG_TEST_ONLY);
+        dpm.setActiveAdmin(admin1, /* replace =*/ false);
+        assertThat(dpm.isAdminActive(admin1)).isTrue();
+
+        mContext.binder.callingUid = 123456;
+        mContext.callerPermissions.add(
+                android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+        dpms.forceRemoveActiveAdmin(admin1, CALLER_USER_HANDLE);
+
+        mContext.callerPermissions.add(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
+        // Verify
+        assertThat(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE)).isFalse();
+        verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
+                null, CALLER_USER_HANDLE);
+    }
+
+    /**
+     * Test for:
+     * {@link DevicePolicyManager#forceRemoveActiveAdmin(ComponentName, int)}
+     */
+    @Test
+    public void testForceRemoveActiveAdmin_ShellCaller() throws Exception {
+        mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+
+        // Add admin.
+        setupPackageInPackageManager(admin1.getPackageName(),
+                /* userId= */ CALLER_USER_HANDLE,
+                /* appId= */ 10138,
+                /* flags= */ ApplicationInfo.FLAG_TEST_ONLY);
+        dpm.setActiveAdmin(admin1, /* replace =*/ false);
+        assertThat(dpm.isAdminActive(admin1)).isTrue();
 
         mContext.binder.callingUid = Process.SHELL_UID;
         dpms.forceRemoveActiveAdmin(admin1, CALLER_USER_HANDLE);
@@ -7028,6 +7075,71 @@
     }
 
     @Test
+    public void testSetDeviceOwnerType_throwsExceptionWhenCallerNotAuthorized() {
+        assertThrows(SecurityException.class,
+                () -> dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_DEFAULT));
+    }
+
+    @Test
+    public void testSetDeviceOwnerType_throwsExceptionWhenThereIsNoDeviceOwner() {
+        mContext.binder.clearCallingIdentity();
+        assertThrows(IllegalStateException.class,
+                () -> dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_DEFAULT));
+    }
+
+    @Test
+    public void testSetDeviceOwnerType_throwsExceptionWhenNotAsDeviceOwnerAdmin() throws Exception {
+        setDeviceOwner();
+
+        assertThrows(IllegalStateException.class,
+                () -> dpm.setDeviceOwnerType(admin2, DEVICE_OWNER_TYPE_FINANCED));
+    }
+
+    @Test
+    public void testSetDeviceOwnerType_asDeviceOwner_toFinancedDevice() throws Exception {
+        setDeviceOwner();
+
+        dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+
+        int returnedDeviceOwnerType = dpm.getDeviceOwnerType(admin1);
+        assertThat(dpms.mOwners.hasDeviceOwner()).isTrue();
+        assertThat(returnedDeviceOwnerType).isEqualTo(DEVICE_OWNER_TYPE_FINANCED);
+
+        initializeDpms();
+
+        returnedDeviceOwnerType = dpm.getDeviceOwnerType(admin1);
+        assertThat(dpms.mOwners.hasDeviceOwner()).isTrue();
+        assertThat(returnedDeviceOwnerType).isEqualTo(DEVICE_OWNER_TYPE_FINANCED);
+    }
+
+    @Test
+    public void testSetDeviceOwnerType_asDeviceOwner_throwsExceptionWhenSetDeviceOwnerTypeAgain()
+            throws Exception {
+        setDeviceOwner();
+
+        dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+
+        int returnedDeviceOwnerType = dpm.getDeviceOwnerType(admin1);
+        assertThat(dpms.mOwners.hasDeviceOwner()).isTrue();
+        assertThat(returnedDeviceOwnerType).isEqualTo(DEVICE_OWNER_TYPE_FINANCED);
+
+        assertThrows(IllegalStateException.class,
+                () -> dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_DEFAULT));
+    }
+
+    @Test
+    public void testGetDeviceOwnerType_throwsExceptionWhenThereIsNoDeviceOwner() {
+        assertThrows(IllegalStateException.class, () -> dpm.getDeviceOwnerType(admin1));
+    }
+
+    @Test
+    public void testGetDeviceOwnerType_throwsExceptionWhenNotAsDeviceOwnerAdmin() throws Exception {
+        setDeviceOwner();
+
+        assertThrows(IllegalStateException.class, () -> dpm.getDeviceOwnerType(admin2));
+    }
+
+    @Test
     public void testSetUsbDataSignalingEnabled_noDeviceOwnerOrPoOfOrgOwnedDevice() {
         assertThrows(SecurityException.class,
                 () -> dpm.setUsbDataSignalingEnabled(true));
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
index bfe183c..39ca925d 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
@@ -16,6 +16,9 @@
 
 package com.android.server.devicepolicy;
 
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT;
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.ComponentName;
@@ -35,7 +38,6 @@
  * <p>Run this test with:
  *
  * {@code atest FrameworksServicesTests:com.android.server.devicepolicy.OwnersTest}
- *
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -67,6 +69,8 @@
 
             assertThat(owners.hasDeviceOwner()).isFalse();
             assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+            assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+                    DEVICE_OWNER_TYPE_DEFAULT);
             assertThat(owners.getSystemUpdatePolicy()).isNull();
             assertThat(owners.getProfileOwnerKeys()).isEmpty();
 
@@ -75,6 +79,12 @@
             assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
             assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
             assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
+
+            owners.setDeviceOwnerType(owners.getDeviceOwnerPackageName(),
+                    DEVICE_OWNER_TYPE_FINANCED);
+            // There is no device owner, so the default owner type should be returned.
+            assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+                    DEVICE_OWNER_TYPE_DEFAULT);
         }
 
         // Then re-read and check.
@@ -84,6 +94,8 @@
 
             assertThat(owners.hasDeviceOwner()).isFalse();
             assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+            assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+                    DEVICE_OWNER_TYPE_DEFAULT);
             assertThat(owners.getSystemUpdatePolicy()).isNull();
             assertThat(owners.getProfileOwnerKeys()).isEmpty();
 
@@ -122,6 +134,8 @@
             assertThat(owners.getDeviceOwnerName()).isEqualTo(null);
             assertThat(owners.getDeviceOwnerPackageName()).isEqualTo("com.google.android.testdpc");
             assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
+            assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+                    DEVICE_OWNER_TYPE_DEFAULT);
 
             assertThat(owners.getSystemUpdatePolicy()).isNull();
             assertThat(owners.getProfileOwnerKeys()).isEmpty();
@@ -142,6 +156,8 @@
             assertThat(owners.getDeviceOwnerName()).isEqualTo(null);
             assertThat(owners.getDeviceOwnerPackageName()).isEqualTo("com.google.android.testdpc");
             assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
+            assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+                    DEVICE_OWNER_TYPE_DEFAULT);
 
             assertThat(owners.getSystemUpdatePolicy()).isNull();
             assertThat(owners.getProfileOwnerKeys()).isEmpty();
@@ -180,6 +196,8 @@
             assertThat(owners.hasDeviceOwner()).isFalse();
             assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
             assertThat(owners.getSystemUpdatePolicy()).isNull();
+            assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+                    DEVICE_OWNER_TYPE_DEFAULT);
 
             assertThat(owners.getProfileOwnerKeys()).hasSize(2);
             assertThat(owners.getProfileOwnerComponent(10))
@@ -208,6 +226,8 @@
             assertThat(owners.hasDeviceOwner()).isFalse();
             assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
             assertThat(owners.getSystemUpdatePolicy()).isNull();
+            assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+                    DEVICE_OWNER_TYPE_DEFAULT);
 
             assertThat(owners.getProfileOwnerKeys()).hasSize(2);
             assertThat(owners.getProfileOwnerComponent(10))
@@ -260,6 +280,8 @@
             assertThat(owners.getDeviceOwnerName()).isEqualTo(null);
             assertThat(owners.getDeviceOwnerPackageName()).isEqualTo("com.google.android.testdpc");
             assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
+            assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+                    DEVICE_OWNER_TYPE_DEFAULT);
 
             assertThat(owners.getSystemUpdatePolicy()).isNotNull();
             assertThat(owners.getSystemUpdatePolicy().getPolicyType()).isEqualTo(5);
@@ -292,6 +314,8 @@
             assertThat(owners.getDeviceOwnerName()).isEqualTo(null);
             assertThat(owners.getDeviceOwnerPackageName()).isEqualTo("com.google.android.testdpc");
             assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
+            assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+                    DEVICE_OWNER_TYPE_DEFAULT);
 
             assertThat(owners.getSystemUpdatePolicy()).isNotNull();
             assertThat(owners.getSystemUpdatePolicy().getPolicyType()).isEqualTo(5);
@@ -315,12 +339,21 @@
             assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
 
             owners.setDeviceOwnerUserRestrictionsMigrated();
+
+            owners.setDeviceOwnerType(owners.getDeviceOwnerPackageName(),
+                    DEVICE_OWNER_TYPE_FINANCED);
+            assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+                    DEVICE_OWNER_TYPE_FINANCED);
         }
 
         {
             final OwnersTestable owners = new OwnersTestable(getServices());
             owners.load();
 
+            assertThat(owners.hasDeviceOwner()).isTrue();
+            assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+                    DEVICE_OWNER_TYPE_FINANCED);
+
             assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
             assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue();
             assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isTrue();
@@ -328,12 +361,22 @@
             assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
 
             owners.setProfileOwnerUserRestrictionsMigrated(11);
+
+            owners.setDeviceOwnerType(owners.getDeviceOwnerPackageName(),
+                    DEVICE_OWNER_TYPE_DEFAULT);
+            // The previous device owner type should persist.
+            assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+                    DEVICE_OWNER_TYPE_FINANCED);
         }
 
         {
             final OwnersTestable owners = new OwnersTestable(getServices());
             owners.load();
 
+            assertThat(owners.hasDeviceOwner()).isTrue();
+            assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+                    DEVICE_OWNER_TYPE_FINANCED);
+
             assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
             assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue();
             assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
@@ -369,6 +412,8 @@
 
             assertThat(owners.hasDeviceOwner()).isFalse();
             assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+            assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+                    DEVICE_OWNER_TYPE_DEFAULT);
 
 
             assertThat(owners.getSystemUpdatePolicy()).isNull();
@@ -388,6 +433,8 @@
 
             assertThat(owners.hasDeviceOwner()).isFalse();
             assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+            assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+                    DEVICE_OWNER_TYPE_DEFAULT);
 
 
             assertThat(owners.getSystemUpdatePolicy()).isNull();
@@ -425,6 +472,8 @@
 
             assertThat(owners.hasDeviceOwner()).isFalse();
             assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+            assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+                    DEVICE_OWNER_TYPE_DEFAULT);
             assertThat(owners.getProfileOwnerKeys()).isEmpty();
 
             assertThat(owners.getSystemUpdatePolicy()).isNotNull();
@@ -444,6 +493,8 @@
 
             assertThat(owners.hasDeviceOwner()).isFalse();
             assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+            assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+                    DEVICE_OWNER_TYPE_DEFAULT);
             assertThat(owners.getProfileOwnerKeys()).isEmpty();
 
             assertThat(owners.getSystemUpdatePolicy()).isNotNull();
@@ -472,9 +523,16 @@
         assertThat(owners.getLegacyConfigFile().exists()).isFalse();
 
         assertThat(owners.getDeviceOwnerFile().exists()).isTrue();
+        assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+                DEVICE_OWNER_TYPE_DEFAULT);
         assertThat(owners.getProfileOwnerFile(10).exists()).isTrue();
         assertThat(owners.getProfileOwnerFile(11).exists()).isTrue();
 
+        String previousDeviceOwnerPackageName = owners.getDeviceOwnerPackageName();
+        owners.setDeviceOwnerType(previousDeviceOwnerPackageName, DEVICE_OWNER_TYPE_FINANCED);
+        assertThat(owners.getDeviceOwnerType(previousDeviceOwnerPackageName)).isEqualTo(
+                DEVICE_OWNER_TYPE_FINANCED);
+
         // Then clear all information and save.
         owners.clearDeviceOwner();
         owners.clearSystemUpdatePolicy();
@@ -491,5 +549,8 @@
         assertThat(owners.getDeviceOwnerFile().exists()).isFalse();
         assertThat(owners.getProfileOwnerFile(10).exists()).isFalse();
         assertThat(owners.getProfileOwnerFile(11).exists()).isFalse();
+
+        assertThat(owners.getDeviceOwnerType(previousDeviceOwnerPackageName)).isEqualTo(
+                DEVICE_OWNER_TYPE_DEFAULT);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
index a078a77..26a549d 100644
--- a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
@@ -21,8 +21,10 @@
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertThrows;
 
+import android.hardware.devicestate.DeviceStateInfo;
 import android.hardware.devicestate.DeviceStateRequest;
 import android.hardware.devicestate.IDeviceStateManagerCallback;
 import android.os.Binder;
@@ -33,10 +35,13 @@
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import junit.framework.Assert;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Optional;
 
@@ -70,14 +75,14 @@
     public void baseStateChanged() {
         assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
         assertEquals(mService.getPendingState(), Optional.empty());
-        assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
+        assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
         assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
                 DEFAULT_DEVICE_STATE.getIdentifier());
 
         mProvider.setState(OTHER_DEVICE_STATE.getIdentifier());
         assertEquals(mService.getCommittedState(), OTHER_DEVICE_STATE);
         assertEquals(mService.getPendingState(), Optional.empty());
-        assertEquals(mService.getBaseState().get(), OTHER_DEVICE_STATE);
+        assertEquals(mService.getBaseState(), OTHER_DEVICE_STATE);
         assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
                 OTHER_DEVICE_STATE.getIdentifier());
     }
@@ -89,21 +94,21 @@
         mProvider.setState(OTHER_DEVICE_STATE.getIdentifier());
         assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
         assertEquals(mService.getPendingState().get(), OTHER_DEVICE_STATE);
-        assertEquals(mService.getBaseState().get(), OTHER_DEVICE_STATE);
+        assertEquals(mService.getBaseState(), OTHER_DEVICE_STATE);
         assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
                 OTHER_DEVICE_STATE.getIdentifier());
 
         mProvider.setState(DEFAULT_DEVICE_STATE.getIdentifier());
         assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
         assertEquals(mService.getPendingState().get(), OTHER_DEVICE_STATE);
-        assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
+        assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
         assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
                 OTHER_DEVICE_STATE.getIdentifier());
 
         mPolicy.resumeConfigure();
         assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
         assertEquals(mService.getPendingState(), Optional.empty());
-        assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
+        assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
         assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
                 DEFAULT_DEVICE_STATE.getIdentifier());
     }
@@ -116,7 +121,7 @@
 
         assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
         assertEquals(mService.getPendingState(), Optional.empty());
-        assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
+        assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
         assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
                 DEFAULT_DEVICE_STATE.getIdentifier());
     }
@@ -129,16 +134,19 @@
 
         assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
         assertEquals(mService.getPendingState(), Optional.empty());
-        assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
+        assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
         assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
                 DEFAULT_DEVICE_STATE.getIdentifier());
     }
 
     @Test
-    public void supportedStatesChanged() {
+    public void supportedStatesChanged() throws RemoteException {
+        TestDeviceStateManagerCallback callback = new TestDeviceStateManagerCallback();
+        mService.getBinderService().registerCallback(callback);
+
         assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
         assertEquals(mService.getPendingState(), Optional.empty());
-        assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
+        assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
 
         mProvider.notifySupportedDeviceStates(new DeviceState[]{ DEFAULT_DEVICE_STATE });
 
@@ -146,27 +154,44 @@
         // supported.
         assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
         assertEquals(mService.getPendingState(), Optional.empty());
-        assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
+        assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
+
+        assertArrayEquals(callback.getLastNotifiedInfo().supportedStates,
+                new int[] { DEFAULT_DEVICE_STATE.getIdentifier() });
     }
 
     @Test
-    public void supportedStatesChanged_unsupportedBaseState() {
+    public void supportedStatesChanged_statesRemainSame() throws RemoteException {
+        TestDeviceStateManagerCallback callback = new TestDeviceStateManagerCallback();
+        mService.getBinderService().registerCallback(callback);
+
         assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
         assertEquals(mService.getPendingState(), Optional.empty());
-        assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
+        assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
 
-        mProvider.notifySupportedDeviceStates(new DeviceState[]{ OTHER_DEVICE_STATE });
+        mProvider.notifySupportedDeviceStates(new DeviceState[]{ DEFAULT_DEVICE_STATE,
+                OTHER_DEVICE_STATE });
 
-        // The current requested state is cleared because it is no longer supported.
+        // The current committed and requests states do not change because the current state remains
+        // supported.
         assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
         assertEquals(mService.getPendingState(), Optional.empty());
-        assertEquals(mService.getBaseState(), Optional.empty());
+        assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
 
-        mProvider.setState(OTHER_DEVICE_STATE.getIdentifier());
+        // The callback wasn't notified about a change in supported states as the states have not
+        // changed.
+        assertNull(callback.getLastNotifiedInfo());
+    }
 
-        assertEquals(mService.getCommittedState(), OTHER_DEVICE_STATE);
-        assertEquals(mService.getPendingState(), Optional.empty());
-        assertEquals(mService.getBaseState().get(), OTHER_DEVICE_STATE);
+    @Test
+    public void getDeviceStateInfo() throws RemoteException {
+        DeviceStateInfo info = mService.getBinderService().getDeviceStateInfo();
+        assertNotNull(info);
+        assertArrayEquals(info.supportedStates,
+                new int[] { DEFAULT_DEVICE_STATE.getIdentifier(),
+                        OTHER_DEVICE_STATE.getIdentifier() });
+        assertEquals(info.baseState, DEFAULT_DEVICE_STATE.getIdentifier());
+        assertEquals(info.currentState, DEFAULT_DEVICE_STATE.getIdentifier());
     }
 
     @Test
@@ -175,41 +200,33 @@
         mService.getBinderService().registerCallback(callback);
 
         mProvider.setState(OTHER_DEVICE_STATE.getIdentifier());
-        assertNotNull(callback.getLastNotifiedValue());
-        assertEquals(callback.getLastNotifiedValue().intValue(),
+        assertEquals(callback.getLastNotifiedInfo().baseState,
+                OTHER_DEVICE_STATE.getIdentifier());
+        assertEquals(callback.getLastNotifiedInfo().currentState,
                 OTHER_DEVICE_STATE.getIdentifier());
 
         mProvider.setState(DEFAULT_DEVICE_STATE.getIdentifier());
-        assertEquals(callback.getLastNotifiedValue().intValue(),
+        assertEquals(callback.getLastNotifiedInfo().baseState,
+                DEFAULT_DEVICE_STATE.getIdentifier());
+        assertEquals(callback.getLastNotifiedInfo().currentState,
                 DEFAULT_DEVICE_STATE.getIdentifier());
 
         mPolicy.blockConfigure();
         mProvider.setState(OTHER_DEVICE_STATE.getIdentifier());
         // The callback should not have been notified of the state change as the policy is still
         // pending callback.
-        assertEquals(callback.getLastNotifiedValue().intValue(),
+        assertEquals(callback.getLastNotifiedInfo().baseState,
+                DEFAULT_DEVICE_STATE.getIdentifier());
+        assertEquals(callback.getLastNotifiedInfo().currentState,
                 DEFAULT_DEVICE_STATE.getIdentifier());
 
         mPolicy.resumeConfigure();
         // Now that the policy is finished processing the callback should be notified of the state
         // change.
-        assertEquals(callback.getLastNotifiedValue().intValue(),
+        assertEquals(callback.getLastNotifiedInfo().baseState,
                 OTHER_DEVICE_STATE.getIdentifier());
-    }
-
-    @Test
-    public void registerCallback_emitsInitialValue() throws RemoteException {
-        TestDeviceStateManagerCallback callback = new TestDeviceStateManagerCallback();
-        mService.getBinderService().registerCallback(callback);
-        assertNotNull(callback.getLastNotifiedValue());
-        assertEquals(callback.getLastNotifiedValue().intValue(),
-                DEFAULT_DEVICE_STATE.getIdentifier());
-    }
-
-    @Test
-    public void getSupportedDeviceStates() throws RemoteException {
-        final int[] expectedStates = new int[] { 0, 1 };
-        assertEquals(mService.getBinderService().getSupportedDeviceStates(), expectedStates);
+        assertEquals(callback.getLastNotifiedInfo().currentState,
+                OTHER_DEVICE_STATE.getIdentifier());
     }
 
     @Test
@@ -228,11 +245,16 @@
                 TestDeviceStateManagerCallback.STATUS_ACTIVE);
         // Committed state changes as there is a requested override.
         assertEquals(mService.getCommittedState(), OTHER_DEVICE_STATE);
-        assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
+        assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
         assertEquals(mService.getOverrideState().get(), OTHER_DEVICE_STATE);
         assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
                 OTHER_DEVICE_STATE.getIdentifier());
 
+        assertNotNull(callback.getLastNotifiedInfo());
+        assertEquals(callback.getLastNotifiedInfo().baseState,
+                DEFAULT_DEVICE_STATE.getIdentifier());
+        assertEquals(callback.getLastNotifiedInfo().currentState,
+                OTHER_DEVICE_STATE.getIdentifier());
 
         mService.getBinderService().cancelRequest(token);
 
@@ -240,10 +262,15 @@
                 TestDeviceStateManagerCallback.STATUS_CANCELED);
         // Committed state is set back to the requested state once the override is cleared.
         assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
-        assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
+        assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
         assertFalse(mService.getOverrideState().isPresent());
         assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
                 DEFAULT_DEVICE_STATE.getIdentifier());
+
+        assertEquals(callback.getLastNotifiedInfo().baseState,
+                DEFAULT_DEVICE_STATE.getIdentifier());
+        assertEquals(callback.getLastNotifiedInfo().currentState,
+                DEFAULT_DEVICE_STATE.getIdentifier());
     }
 
     @Test
@@ -263,7 +290,7 @@
 
         // Committed state changes as there is a requested override.
         assertEquals(mService.getCommittedState(), OTHER_DEVICE_STATE);
-        assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
+        assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
         assertEquals(mService.getOverrideState().get(), OTHER_DEVICE_STATE);
         assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
                 OTHER_DEVICE_STATE.getIdentifier());
@@ -275,7 +302,7 @@
                 TestDeviceStateManagerCallback.STATUS_CANCELED);
         // Committed state is set back to the requested state once the override is cleared.
         assertEquals(mService.getCommittedState(), OTHER_DEVICE_STATE);
-        assertEquals(mService.getBaseState().get(), OTHER_DEVICE_STATE);
+        assertEquals(mService.getBaseState(), OTHER_DEVICE_STATE);
         assertFalse(mService.getOverrideState().isPresent());
         assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
                 OTHER_DEVICE_STATE.getIdentifier());
@@ -297,7 +324,7 @@
                 TestDeviceStateManagerCallback.STATUS_ACTIVE);
         // Committed state changes as there is a requested override.
         assertEquals(mService.getCommittedState(), OTHER_DEVICE_STATE);
-        assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
+        assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
         assertEquals(mService.getOverrideState().get(), OTHER_DEVICE_STATE);
         assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
                 OTHER_DEVICE_STATE.getIdentifier());
@@ -310,7 +337,7 @@
         // Committed state is set back to the requested state as the override state is no longer
         // supported.
         assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
-        assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
+        assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
         assertFalse(mService.getOverrideState().isPresent());
         assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
                 DEFAULT_DEVICE_STATE.getIdentifier());
@@ -348,6 +375,10 @@
         });
     }
 
+    private static void assertArrayEquals(int[] expected, int[] actual) {
+        Assert.assertTrue(Arrays.equals(expected, actual));
+    }
+
     private static final class TestDeviceStatePolicy implements DeviceStatePolicy {
         private final DeviceStateProvider mProvider;
         private int mLastDeviceStateRequestedToConfigure = INVALID_DEVICE_STATE;
@@ -429,12 +460,14 @@
         public static final int STATUS_SUSPENDED = 2;
         public static final int STATUS_CANCELED = 3;
 
-        private Integer mLastNotifiedValue;
+        @Nullable
+        private DeviceStateInfo mLastNotifiedInfo;
+        private boolean mNotifiedOfChangeInSupportedStates;
         private final HashMap<IBinder, Integer> mLastNotifiedStatus = new HashMap<>();
 
         @Override
-        public void onDeviceStateChanged(int deviceState) {
-            mLastNotifiedValue = deviceState;
+        public void onDeviceStateInfoChanged(DeviceStateInfo info) {
+            mLastNotifiedInfo = info;
         }
 
         @Override
@@ -453,8 +486,8 @@
         }
 
         @Nullable
-        Integer getLastNotifiedValue() {
-            return mLastNotifiedValue;
+        DeviceStateInfo getLastNotifiedInfo() {
+            return mLastNotifiedInfo;
         }
 
         int getLastNotifiedStatus(IBinder requestToken) {
diff --git a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
index 732c08c..54825ee 100644
--- a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
@@ -30,7 +30,6 @@
 import android.hardware.SensorManager;
 import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
 import android.os.Handler;
-import android.platform.test.annotations.Presubmit;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -44,7 +43,6 @@
 import org.mockito.MockitoAnnotations;
 
 @SmallTest
-@Presubmit
 @RunWith(AndroidJUnit4.class)
 public class AutomaticBrightnessControllerTest {
     private static final float BRIGHTNESS_MIN_FLOAT = 0.0f;
@@ -66,7 +64,6 @@
     @Mock HysteresisLevels mAmbientBrightnessThresholds;
     @Mock HysteresisLevels mScreenBrightnessThresholds;
     @Mock Handler mNoOpHandler;
-    @Mock DisplayDeviceConfig mDisplayDeviceConfig;
     @Mock DisplayDevice mDisplayDevice;
 
     private static final int LIGHT_SENSOR_WARMUP_TIME = 0;
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
index 9396ed2..285806b 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
@@ -30,7 +30,6 @@
 import android.content.res.TypedArray;
 import android.hardware.display.BrightnessConfiguration;
 import android.os.PowerManager;
-import android.platform.test.annotations.Presubmit;
 import android.util.MathUtils;
 import android.util.Spline;
 
@@ -43,7 +42,6 @@
 import java.util.Arrays;
 
 @SmallTest
-@Presubmit
 @RunWith(AndroidJUnit4.class)
 public class BrightnessMappingStrategyTest {
 
@@ -90,7 +88,9 @@
     };
 
     private static final float[] DISPLAY_RANGE_NITS = { 2.685f, 478.5f };
-    private static final int[] BACKLIGHT_RANGE = { 1, 255 };
+    private static final float[] DISPLAY_LEVELS_RANGE_NITS = { 13.25f, 478.5f };
+    private static final float[] BACKLIGHT_RANGE_ZERO_TO_ONE = { 0.0f, 1.0f };
+    private static final float[] DISPLAY_LEVELS_RANGE_BACKLIGHT_FLOAT = { 0.03149606299f, 1.0f };
 
     private static final float[] EMPTY_FLOAT_ARRAY = new float[0];
     private static final int[] EMPTY_INT_ARRAY = new int[0];
@@ -116,25 +116,28 @@
     };
     private static final Spline GAMMA_CORRECTION_SPLINE = Spline.createSpline(
             new float[] { 0.0f, 100.0f, 1000.0f, 2500.0f, 4000.0f, 4900.0f, 5000.0f },
-            new float[] { 0.035f, 0.035f, 0.221f, 0.523f, 0.797f, 0.980f, 1.0f });
+            new float[] { 0.0475f, 0.0475f, 0.2225f, 0.5140f, 0.8056f, 0.9805f, 1.0f });
 
     @Test
     public void testSimpleStrategyMappingAtControlPoints() {
         Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT);
-        BrightnessMappingStrategy simple = BrightnessMappingStrategy.create(res);
+        DisplayDeviceConfig ddc = createDdc();
+        BrightnessMappingStrategy simple = BrightnessMappingStrategy.create(res, ddc);
         assertNotNull("BrightnessMappingStrategy should not be null", simple);
         for (int i = 0; i < LUX_LEVELS.length; i++) {
-            final float expectedLevel =
-                    (float) DISPLAY_LEVELS_BACKLIGHT[i] / PowerManager.BRIGHTNESS_ON;
+            final float expectedLevel = MathUtils.map(PowerManager.BRIGHTNESS_OFF + 1,
+                    PowerManager.BRIGHTNESS_ON, PowerManager.BRIGHTNESS_MIN,
+                    PowerManager.BRIGHTNESS_MAX, DISPLAY_LEVELS_BACKLIGHT[i]);
             assertEquals(expectedLevel,
-                    simple.getBrightness(LUX_LEVELS[i]), 0.01f /*tolerance*/);
+                    simple.getBrightness(LUX_LEVELS[i]), 0.0001f /*tolerance*/);
         }
     }
 
     @Test
     public void testSimpleStrategyMappingBetweenControlPoints() {
         Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT);
-        BrightnessMappingStrategy simple = BrightnessMappingStrategy.create(res);
+        DisplayDeviceConfig ddc = createDdc();
+        BrightnessMappingStrategy simple = BrightnessMappingStrategy.create(res, ddc);
         assertNotNull("BrightnessMappingStrategy should not be null", simple);
         for (int i = 1; i < LUX_LEVELS.length; i++) {
             final float lux = (LUX_LEVELS[i - 1] + LUX_LEVELS[i]) / 2;
@@ -148,66 +151,71 @@
     @Test
     public void testSimpleStrategyIgnoresNewConfiguration() {
         Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT);
-        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res);
+        DisplayDeviceConfig ddc = createDdc();
+        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc);
 
-        final int N = LUX_LEVELS.length;
         final float[] lux = { 0f, 1f };
         final float[] nits = { 0, PowerManager.BRIGHTNESS_ON };
 
         BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits)
                 .build();
         strategy.setBrightnessConfiguration(config);
-        assertNotEquals(1.0f, strategy.getBrightness(1f), 0.01 /*tolerance*/);
+        assertNotEquals(1.0f, strategy.getBrightness(1f), 0.0001f /*tolerance*/);
     }
 
     @Test
     public void testSimpleStrategyIgnoresNullConfiguration() {
         Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT);
-        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res);
+        DisplayDeviceConfig ddc = createDdc();
+        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc);
 
         strategy.setBrightnessConfiguration(null);
         final int N = DISPLAY_LEVELS_BACKLIGHT.length;
         final float expectedBrightness =
                 (float) DISPLAY_LEVELS_BACKLIGHT[N - 1] / PowerManager.BRIGHTNESS_ON;
         assertEquals(expectedBrightness,
-                strategy.getBrightness(LUX_LEVELS[N - 1]), 0.01 /*tolerance*/);
+                strategy.getBrightness(LUX_LEVELS[N - 1]), 0.0001f /*tolerance*/);
     }
 
     @Test
     public void testPhysicalStrategyMappingAtControlPoints() {
-        Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS,
-                DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
-        BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res);
+        Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS);
+        DisplayDeviceConfig ddc = createDdc();
+        BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res, ddc);
         assertNotNull("BrightnessMappingStrategy should not be null", physical);
         for (int i = 0; i < LUX_LEVELS.length; i++) {
-            final float expectedLevel = DISPLAY_LEVELS_NITS[i] / DISPLAY_RANGE_NITS[1];
+            final float expectedLevel = MathUtils.map(DISPLAY_RANGE_NITS[0], DISPLAY_RANGE_NITS[1],
+                    DISPLAY_LEVELS_RANGE_BACKLIGHT_FLOAT[0],
+                    DISPLAY_LEVELS_RANGE_BACKLIGHT_FLOAT[1],
+                    DISPLAY_LEVELS_NITS[i]);
             assertEquals(expectedLevel,
-                    physical.getBrightness(LUX_LEVELS[i]), 0.01f /*tolerance*/);
+                    physical.getBrightness(LUX_LEVELS[i]),
+                    0.0001f /*tolerance*/);
         }
     }
 
     @Test
     public void testPhysicalStrategyMappingBetweenControlPoints() {
-        Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS,
-                DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
-        BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res);
+        Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS);
+        DisplayDeviceConfig ddc = createDdc(DISPLAY_RANGE_NITS, BACKLIGHT_RANGE_ZERO_TO_ONE);
+        BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res, ddc);
         assertNotNull("BrightnessMappingStrategy should not be null", physical);
-        Spline backlightToBrightness =
-                Spline.createSpline(toFloatArray(BACKLIGHT_RANGE), DISPLAY_RANGE_NITS);
+        Spline brightnessToNits =
+                Spline.createSpline(BACKLIGHT_RANGE_ZERO_TO_ONE, DISPLAY_RANGE_NITS);
         for (int i = 1; i < LUX_LEVELS.length; i++) {
-            final float lux = (LUX_LEVELS[i - 1] + LUX_LEVELS[i]) / 2;
-            final float backlight = physical.getBrightness(lux) * PowerManager.BRIGHTNESS_ON;
-            final float nits = backlightToBrightness.interpolate(backlight);
-            assertTrue("Desired brightness should be between adjacent control points.",
+            final float lux = (LUX_LEVELS[i - 1] + LUX_LEVELS[i]) / 2.0f;
+            final float brightness = physical.getBrightness(lux);
+            final float nits = brightnessToNits.interpolate(brightness);
+            assertTrue("Desired brightness should be between adjacent control points: " + nits,
                     nits > DISPLAY_LEVELS_NITS[i - 1] && nits < DISPLAY_LEVELS_NITS[i]);
         }
     }
 
     @Test
     public void testPhysicalStrategyUsesNewConfigurations() {
-        Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS,
-                DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
-        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res);
+        Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS);
+        DisplayDeviceConfig ddc = createDdc();
+        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc);
 
         final float[] lux = { 0f, 1f };
         final float[] nits = {
@@ -218,46 +226,53 @@
         BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits)
                 .build();
         strategy.setBrightnessConfiguration(config);
-        assertEquals(1.0f, strategy.getBrightness(1f), 0.01 /*tolerance*/);
+        assertEquals(1.0f, strategy.getBrightness(1f), 0.0001f /*tolerance*/);
 
         // Check that null returns us to the default configuration.
         strategy.setBrightnessConfiguration(null);
         final int N = DISPLAY_LEVELS_NITS.length;
         final float expectedBrightness = DISPLAY_LEVELS_NITS[N - 1] / DISPLAY_RANGE_NITS[1];
         assertEquals(expectedBrightness,
-                strategy.getBrightness(LUX_LEVELS[N - 1]), 0.01f /*tolerance*/);
+                strategy.getBrightness(LUX_LEVELS[N - 1]), 0.0001f /*tolerance*/);
     }
 
     @Test
     public void testPhysicalStrategyRecalculateSplines() {
-        Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS,
-                BACKLIGHT_RANGE);
-        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res);
+        Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS);
+        DisplayDeviceConfig ddc = createDdc(DISPLAY_RANGE_NITS);
+        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc);
         float[] adjustedNits50p = new float[DISPLAY_RANGE_NITS.length];
         for (int i = 0; i < DISPLAY_RANGE_NITS.length; i++) {
             adjustedNits50p[i] = DISPLAY_RANGE_NITS[i] * 0.5f;
         }
 
         // Default is unadjusted
-        assertEquals(2.685f, strategy.convertToNits(BACKLIGHT_RANGE[0]), 0.01f /* tolerance */);
-        assertEquals(478.5f, strategy.convertToNits(BACKLIGHT_RANGE[1]), 0.01f /* tolerance */);
+        assertEquals(DISPLAY_RANGE_NITS[0], strategy.convertToNits(BACKLIGHT_RANGE_ZERO_TO_ONE[0]),
+                0.0001f /* tolerance */);
+        assertEquals(DISPLAY_RANGE_NITS[1], strategy.convertToNits(BACKLIGHT_RANGE_ZERO_TO_ONE[1]),
+                0.0001f /* tolerance */);
 
         // When adjustment is turned on, adjustment array is used
         strategy.recalculateSplines(true, adjustedNits50p);
-        assertEquals(1.3425f, strategy.convertToNits(BACKLIGHT_RANGE[0]), 0.01f /* tolerance */);
-        assertEquals(239.25f, strategy.convertToNits(BACKLIGHT_RANGE[1]), 0.01f /* tolerance */);
+        assertEquals(DISPLAY_RANGE_NITS[0] / 2,
+                strategy.convertToNits(BACKLIGHT_RANGE_ZERO_TO_ONE[0]), 0.0001f /* tolerance */);
+        assertEquals(DISPLAY_RANGE_NITS[1] / 2,
+                strategy.convertToNits(BACKLIGHT_RANGE_ZERO_TO_ONE[1]), 0.0001f /* tolerance */);
 
         // When adjustment is turned off, adjustment array is ignored
         strategy.recalculateSplines(false, adjustedNits50p);
-        assertEquals(2.685f, strategy.convertToNits(BACKLIGHT_RANGE[0]), 0.01f /* tolerance */);
-        assertEquals(478.5f, strategy.convertToNits(BACKLIGHT_RANGE[1]), 0.01f /* tolerance */);
+        assertEquals(DISPLAY_RANGE_NITS[0], strategy.convertToNits(BACKLIGHT_RANGE_ZERO_TO_ONE[0]),
+                0.0001f /* tolerance */);
+        assertEquals(DISPLAY_RANGE_NITS[1], strategy.convertToNits(BACKLIGHT_RANGE_ZERO_TO_ONE[1]),
+                0.0001f /* tolerance */);
     }
 
     @Test
     public void testDefaultStrategyIsPhysical() {
         Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT,
-                DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
-        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res);
+                DISPLAY_LEVELS_NITS);
+        DisplayDeviceConfig ddc = createDdc();
+        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc);
         assertTrue(strategy instanceof BrightnessMappingStrategy.PhysicalMappingStrategy);
     }
 
@@ -268,15 +283,15 @@
         int tmp = lux[idx];
         lux[idx] = lux[idx+1];
         lux[idx+1] = tmp;
-        Resources res = createResources(lux, DISPLAY_LEVELS_NITS,
-                DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
-        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res);
+        Resources res = createResources(lux, DISPLAY_LEVELS_NITS);
+        DisplayDeviceConfig ddc = createDdc();
+        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc);
         assertNull(strategy);
 
         // And make sure we get the same result even if it's monotone but not increasing.
         lux[idx] = lux[idx+1];
-        res = createResources(lux, DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
-        strategy = BrightnessMappingStrategy.create(res);
+        res = createResources(lux, DISPLAY_LEVELS_NITS);
+        strategy = BrightnessMappingStrategy.create(res, ddc);
         assertNull(strategy);
     }
 
@@ -287,13 +302,13 @@
         // Make sure it's strictly increasing so that the only failure is the differing array
         // lengths
         lux[lux.length - 1] = lux[lux.length - 2] + 1;
-        Resources res = createResources(lux, DISPLAY_LEVELS_NITS,
-                DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
-        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res);
+        Resources res = createResources(lux, DISPLAY_LEVELS_NITS);
+        DisplayDeviceConfig ddc = createDdc();
+        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc);
         assertNull(strategy);
 
         res = createResources(lux, DISPLAY_LEVELS_BACKLIGHT);
-        strategy = BrightnessMappingStrategy.create(res);
+        strategy = BrightnessMappingStrategy.create(res, ddc);
         assertNull(strategy);
 
         // Extra backlight level
@@ -301,43 +316,45 @@
                 DISPLAY_LEVELS_BACKLIGHT, DISPLAY_LEVELS_BACKLIGHT.length+1);
         backlight[backlight.length - 1] = backlight[backlight.length - 2] + 1;
         res = createResources(LUX_LEVELS, backlight);
-        strategy = BrightnessMappingStrategy.create(res);
+        strategy = BrightnessMappingStrategy.create(res, ddc);
         assertNull(strategy);
 
         // Extra nits level
         final float[] nits = Arrays.copyOf(DISPLAY_RANGE_NITS, DISPLAY_LEVELS_NITS.length+1);
         nits[nits.length - 1] = nits[nits.length - 2] + 1;
-        res = createResources(LUX_LEVELS, nits, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
-        strategy = BrightnessMappingStrategy.create(res);
+        res = createResources(LUX_LEVELS, nits);
+        strategy = BrightnessMappingStrategy.create(res, ddc);
         assertNull(strategy);
     }
 
     @Test
     public void testPhysicalStrategyRequiresNitsMapping() {
         Resources res = createResources(LUX_LEVELS, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/,
-                DISPLAY_LEVELS_NITS, EMPTY_FLOAT_ARRAY /*nitsRange*/, BACKLIGHT_RANGE);
-        BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res);
+                DISPLAY_LEVELS_NITS);
+        DisplayDeviceConfig ddc = createDdc(EMPTY_FLOAT_ARRAY /*nitsRange*/);
+        BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res, ddc);
         assertNull(physical);
 
         res = createResources(LUX_LEVELS, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/,
-                DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, EMPTY_INT_ARRAY /*backlightRange*/);
-        physical = BrightnessMappingStrategy.create(res);
+                DISPLAY_LEVELS_NITS);
+        physical = BrightnessMappingStrategy.create(res, ddc);
         assertNull(physical);
 
         res = createResources(LUX_LEVELS, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/,
-                DISPLAY_LEVELS_NITS, EMPTY_FLOAT_ARRAY /*nitsRange*/,
-                EMPTY_INT_ARRAY /*backlightRange*/);
-        physical = BrightnessMappingStrategy.create(res);
+                DISPLAY_LEVELS_NITS);
+        physical = BrightnessMappingStrategy.create(res, ddc);
         assertNull(physical);
     }
 
     @Test
     public void testStrategiesAdaptToUserDataPoint() {
-        Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS,
-                DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
-        assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy.create(res));
+        Resources res = createResources(LUX_LEVELS, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/,
+                DISPLAY_LEVELS_NITS);
+        DisplayDeviceConfig ddc = createDdc(DISPLAY_RANGE_NITS, BACKLIGHT_RANGE_ZERO_TO_ONE);
+        assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy.create(res, ddc));
+        ddc = createDdc(DISPLAY_RANGE_NITS, BACKLIGHT_RANGE_ZERO_TO_ONE);
         res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT);
-        assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy.create(res));
+        assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy.create(res, ddc));
     }
 
     private static void assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy strategy) {
@@ -353,7 +370,7 @@
 
         // Then make sure that all control points after the middle lux level are also set to max...
         for (int i = idx; i < LUX_LEVELS.length; i++) {
-            assertEquals(strategy.getBrightness(LUX_LEVELS[idx]), 1.0, 0.01 /*tolerance*/);
+            assertEquals(strategy.getBrightness(LUX_LEVELS[idx]), 1.0, 0.0001f /*tolerance*/);
         }
 
         // ...and that all control points before the middle lux level are strictly less than the
@@ -371,12 +388,12 @@
         strategy.clearUserDataPoints();
         for (int i = 0; i < LUX_LEVELS.length; i++) {
             assertEquals(initialBrightnessLevels[i], strategy.getBrightness(LUX_LEVELS[i]),
-                    0.01 /*tolerance*/);
+                    0.0001f /*tolerance*/);
         }
 
         // Now set the middle of the lux range to something just above the minimum.
         float minBrightness = strategy.getBrightness(LUX_LEVELS[0]);
-        strategy.addUserDataPoint(LUX_LEVELS[idx], minBrightness + 0.01f);
+        strategy.addUserDataPoint(LUX_LEVELS[idx], minBrightness + 0.0001f);
 
         // Then make sure the curve is still monotonic.
         prevBrightness = 0f;
@@ -391,31 +408,21 @@
         // be true assuming that there are more than two lux levels in the curve since we picked a
         // brightness just barely above the minimum for the middle of the curve.
         minBrightness = (float) MathUtils.pow(minBrightness, MAXIMUM_GAMMA); // Gamma correction.
-        assertEquals(minBrightness, strategy.getBrightness(LUX_LEVELS[0]), 0.01 /*tolerance*/);
-    }
-
-    private static float[] toFloatArray(int[] vals) {
-        float[] newVals = new float[vals.length];
-        for (int i = 0; i < vals.length; i++) {
-            newVals[i] = (float) vals[i];
-        }
-        return newVals;
+        assertEquals(minBrightness, strategy.getBrightness(LUX_LEVELS[0]), 0.0001f /*tolerance*/);
     }
 
     private Resources createResources(int[] luxLevels, int[] brightnessLevelsBacklight) {
         return createResources(luxLevels, brightnessLevelsBacklight,
-                EMPTY_FLOAT_ARRAY /*brightnessLevelsNits*/, EMPTY_FLOAT_ARRAY /*nitsRange*/,
-                EMPTY_INT_ARRAY /*backlightRange*/);
+                EMPTY_FLOAT_ARRAY /*brightnessLevelsNits*/);
     }
 
-    private Resources createResources(int[] luxLevels, float[] brightnessLevelsNits,
-            float[] nitsRange, int[] backlightRange) {
+    private Resources createResources(int[] luxLevels, float[] brightnessLevelsNits) {
         return createResources(luxLevels, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/,
-                brightnessLevelsNits, nitsRange, backlightRange);
+                brightnessLevelsNits);
     }
 
     private Resources createResources(int[] luxLevels, int[] brightnessLevelsBacklight,
-            float[] brightnessLevelsNits, float[] nitsRange, int[] backlightRange) {
+            float[] brightnessLevelsNits) {
         Resources mockResources = mock(Resources.class);
         // For historical reasons, the lux levels resource implicitly defines the first point as 0,
         // so we need to chop it off of the array the mock resource object returns.
@@ -432,15 +439,6 @@
                 com.android.internal.R.array.config_autoBrightnessDisplayValuesNits))
                 .thenReturn(mockBrightnessLevelNits);
 
-        TypedArray mockNitsRange = createFloatTypedArray(nitsRange);
-        when(mockResources.obtainTypedArray(
-                com.android.internal.R.array.config_screenBrightnessNits))
-                .thenReturn(mockNitsRange);
-
-        when(mockResources.getIntArray(
-                com.android.internal.R.array.config_screenBrightnessBacklight))
-                .thenReturn(backlightRange);
-
         when(mockResources.getInteger(
                 com.android.internal.R.integer.config_screenBrightnessSettingMinimum))
                 .thenReturn(1);
@@ -453,6 +451,21 @@
         return mockResources;
     }
 
+    private DisplayDeviceConfig createDdc() {
+        return createDdc(DISPLAY_RANGE_NITS);
+    }
+
+    private DisplayDeviceConfig createDdc(float[] nitsArray) {
+        return createDdc(nitsArray, DISPLAY_LEVELS_RANGE_BACKLIGHT_FLOAT);
+    }
+
+    private DisplayDeviceConfig createDdc(float[] nitsArray, float[] backlightArray) {
+        DisplayDeviceConfig mockDdc = mock(DisplayDeviceConfig.class);
+        when(mockDdc.getNits()).thenReturn(nitsArray);
+        when(mockDdc.getBrightness()).thenReturn(backlightArray);
+        return mockDdc;
+    }
+
     private TypedArray createFloatTypedArray(float[] vals) {
         TypedArray mockArray = mock(TypedArray.class);
         when(mockArray.length()).thenAnswer(invocation -> {
@@ -490,21 +503,22 @@
         final float y1 = GAMMA_CORRECTION_SPLINE.interpolate(x1);
         final float y2 = GAMMA_CORRECTION_SPLINE.interpolate(x2);
         final float y3 = GAMMA_CORRECTION_SPLINE.interpolate(x3);
-        Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS,
-                DISPLAY_LEVELS_NITS, DISPLAY_LEVELS_BACKLIGHT);
-        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources);
+
+        Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS);
+        DisplayDeviceConfig ddc = createDdc();
+        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources, ddc);
         // Let's start with a validity check:
-        assertEquals(y1, strategy.getBrightness(x1), 0.01f /* tolerance */);
-        assertEquals(y2, strategy.getBrightness(x2), 0.01f /* tolerance */);
-        assertEquals(y3, strategy.getBrightness(x3), 0.01f /* tolerance */);
+        assertEquals(y1, strategy.getBrightness(x1), 0.0001f /* tolerance */);
+        assertEquals(y2, strategy.getBrightness(x2), 0.0001f /* tolerance */);
+        assertEquals(y3, strategy.getBrightness(x3), 0.0001f /* tolerance */);
         // OK, let's roll:
         float gamma = 0.5f;
         strategy.addUserDataPoint(x2, (float) MathUtils.pow(y2, gamma));
-        assertEquals(MathUtils.pow(y1, gamma), strategy.getBrightness(x1), 0.01f /* tolerance */);
-        assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.01f /* tolerance */);
-        assertEquals(MathUtils.pow(y3, gamma), strategy.getBrightness(x3), 0.01f /* tolerance */);
-        // The adjustment should be +0.63 (manual calculation).
-        assertEquals(+0.63f, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */);
+        assertEquals(MathUtils.pow(y1, gamma), strategy.getBrightness(x1), 0.0001f /* tolerance */);
+        assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.0001f /* tolerance */);
+        assertEquals(MathUtils.pow(y3, gamma), strategy.getBrightness(x3), 0.0001f /* tolerance */);
+        // The adjustment should be +0.6308 (manual calculation).
+        assertEquals(+0.6308f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
     }
 
     @Test
@@ -518,39 +532,39 @@
         final float y1 = GAMMA_CORRECTION_SPLINE.interpolate(x1);
         final float y2 = GAMMA_CORRECTION_SPLINE.interpolate(x2);
         final float y3 = GAMMA_CORRECTION_SPLINE.interpolate(x3);
-        Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS,
-                DISPLAY_LEVELS_NITS, DISPLAY_LEVELS_BACKLIGHT);
-        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources);
+        Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS);
+        DisplayDeviceConfig ddc = createDdc();
+        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources, ddc);
         // Validity check:
-        assertEquals(y1, strategy.getBrightness(x1), 0.01f /* tolerance */);
-        assertEquals(y2, strategy.getBrightness(x2), 0.01f /* tolerance */);
-        assertEquals(y3, strategy.getBrightness(x3), 0.01f /* tolerance */);
+        assertEquals(y1, strategy.getBrightness(x1), 0.0001f /* tolerance */);
+        assertEquals(y2, strategy.getBrightness(x2), 0.0001f /* tolerance */);
+        assertEquals(y3, strategy.getBrightness(x3), 0.0001f /* tolerance */);
         // Let's roll:
         float gamma = 0.25f;
         final float minGamma = 1.0f / MAXIMUM_GAMMA;
         strategy.addUserDataPoint(x2, (float) MathUtils.pow(y2, gamma));
-        assertEquals(MathUtils.pow(y1, minGamma), strategy.getBrightness(x1),
-                0.01f /* tolerance */);
-        assertEquals(MathUtils.pow(y2, gamma),    strategy.getBrightness(x2),
-                0.01f /* tolerance */);
-        assertEquals(MathUtils.pow(y3, minGamma), strategy.getBrightness(x3),
-                0.01f /* tolerance */);
+        assertEquals(MathUtils.pow(y1, minGamma),
+                strategy.getBrightness(x1), 0.0001f /* tolerance */);
+        assertEquals(MathUtils.pow(y2, gamma),
+                strategy.getBrightness(x2), 0.0001f /* tolerance */);
+        assertEquals(MathUtils.pow(y3, minGamma),
+                strategy.getBrightness(x3), 0.0001f /* tolerance */);
         // The adjustment should be +1.0 (maximum adjustment).
-        assertEquals(+1.0f, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */);
+        assertEquals(+1.0f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
     }
 
     @Test
     public void testGammaCorrectionExtremeChangeAtCenter() {
         // Extreme changes (e.g. setting brightness to 0.0 or 1.0) can't be gamma corrected, so we
         // just make sure the adjustment reflects the change.
-        Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS,
-                DISPLAY_LEVELS_NITS, DISPLAY_LEVELS_BACKLIGHT);
-        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources);
-        assertEquals(0.0f, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */);
+        Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS);
+        DisplayDeviceConfig ddc = createDdc();
+        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources, ddc);
+        assertEquals(0.0f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
         strategy.addUserDataPoint(2500, 1.0f);
-        assertEquals(+1.0f, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */);
+        assertEquals(+1.0f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
         strategy.addUserDataPoint(2500, 0.0f);
-        assertEquals(-1.0f, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */);
+        assertEquals(-1.0f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
     }
 
     @Test
@@ -564,28 +578,28 @@
         final float y0 = GAMMA_CORRECTION_SPLINE.interpolate(x0);
         final float y2 = GAMMA_CORRECTION_SPLINE.interpolate(x2);
         final float y4 = GAMMA_CORRECTION_SPLINE.interpolate(x4);
-        Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS,
-                DISPLAY_LEVELS_NITS, DISPLAY_LEVELS_BACKLIGHT);
-        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources);
+        Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS);
+        DisplayDeviceConfig ddc = createDdc();
+        BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources, ddc);
         // Validity, as per tradition:
-        assertEquals(y0, strategy.getBrightness(x0), 0.01f /* tolerance */);
-        assertEquals(y2, strategy.getBrightness(x2), 0.01f /* tolerance */);
-        assertEquals(y4, strategy.getBrightness(x4), 0.01f /* tolerance */);
+        assertEquals(y0, strategy.getBrightness(x0), 0.0001f /* tolerance */);
+        assertEquals(y2, strategy.getBrightness(x2), 0.0001f /* tolerance */);
+        assertEquals(y4, strategy.getBrightness(x4), 0.0001f /* tolerance */);
         // Rollin':
         float adjustment = 0.3f;
         float gamma = (float) MathUtils.pow(MAXIMUM_GAMMA, -adjustment);
         strategy.addUserDataPoint(x0, y0 + adjustment);
-        assertEquals(y0 + adjustment, strategy.getBrightness(x0), 0.01f /* tolerance */);
-        assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.01f /* tolerance */);
-        assertEquals(MathUtils.pow(y4, gamma), strategy.getBrightness(x4), 0.01f /* tolerance */);
-        assertEquals(adjustment, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */);
+        assertEquals(y0 + adjustment, strategy.getBrightness(x0), 0.0001f /* tolerance */);
+        assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.0001f /* tolerance */);
+        assertEquals(MathUtils.pow(y4, gamma), strategy.getBrightness(x4), 0.0001f /* tolerance */);
+        assertEquals(adjustment, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
         // Similarly, if we set a user data point at (x4, 1.0), the adjustment should be 1 - y4.
         adjustment = 1.0f - y4;
         gamma = (float) MathUtils.pow(MAXIMUM_GAMMA, -adjustment);
         strategy.addUserDataPoint(x4, 1.0f);
-        assertEquals(MathUtils.pow(y0, gamma), strategy.getBrightness(x0), 0.01f /* tolerance */);
-        assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.01f /* tolerance */);
-        assertEquals(1.0f, strategy.getBrightness(x4), 0.01f /* tolerance */);
-        assertEquals(adjustment, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */);
+        assertEquals(MathUtils.pow(y0, gamma), strategy.getBrightness(x0), 0.0001f /* tolerance */);
+        assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.0001f /* tolerance */);
+        assertEquals(1.0f, strategy.getBrightness(x4), 0.0001f /* tolerance */);
+        assertEquals(adjustment, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index 1c55072..bc86d1d 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -993,7 +993,7 @@
         private DisplayDeviceInfo mDisplayDeviceInfo;
 
         FakeDisplayDevice() {
-            super(null, null, "");
+            super(null, null, "", mContext);
         }
 
         public void setDisplayDeviceInfo(DisplayDeviceInfo displayDeviceInfo) {
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
index ee0f2e8..81b2381 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -47,7 +47,6 @@
 import android.hardware.display.DisplayManager;
 import android.os.Handler;
 import android.os.Looper;
-import android.platform.test.annotations.Presubmit;
 import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.test.mock.MockContentResolver;
@@ -83,7 +82,6 @@
 import java.util.stream.Collectors;
 
 @SmallTest
-@Presubmit
 @RunWith(AndroidJUnit4.class)
 public class DisplayModeDirectorTest {
     // The tolerance within which we consider something approximately equals.
diff --git a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
index d72606a..196454b 100644
--- a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
@@ -22,7 +22,6 @@
 import static org.junit.Assert.assertTrue;
 
 import android.hardware.display.BrightnessConfiguration;
-import android.platform.test.annotations.Presubmit;
 import android.util.Pair;
 
 import androidx.test.filters.SmallTest;
@@ -41,7 +40,6 @@
 import java.nio.charset.StandardCharsets;
 
 @SmallTest
-@Presubmit
 @RunWith(AndroidJUnit4.class)
 public class PersistentDataStoreTest {
     private PersistentDataStore mDataStore;
diff --git a/services/tests/servicestests/src/com/android/server/graphics/fonts/PersistentSystemFontConfigTest.java b/services/tests/servicestests/src/com/android/server/graphics/fonts/PersistentSystemFontConfigTest.java
index 27fce3c..912da94 100644
--- a/services/tests/servicestests/src/com/android/server/graphics/fonts/PersistentSystemFontConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/graphics/fonts/PersistentSystemFontConfigTest.java
@@ -45,7 +45,7 @@
     public void testWriteRead() throws Exception {
         long expectedModifiedDate = 1234567890;
         PersistentSystemFontConfig.Config config = new PersistentSystemFontConfig.Config();
-        config.lastModifiedDate = expectedModifiedDate;
+        config.lastModifiedMillis = expectedModifiedDate;
         config.updatedFontDirs.add("~~abc");
         config.updatedFontDirs.add("~~def");
 
@@ -65,7 +65,7 @@
                 PersistentSystemFontConfig.Config another = new PersistentSystemFontConfig.Config();
                 PersistentSystemFontConfig.loadFromXml(bais, another);
 
-                assertThat(another.lastModifiedDate).isEqualTo(expectedModifiedDate);
+                assertThat(another.lastModifiedMillis).isEqualTo(expectedModifiedDate);
                 assertThat(another.updatedFontDirs).containsExactly("~~abc", "~~def");
                 assertThat(another.fontFamilies).containsExactly(fontFamily);
             }
@@ -82,7 +82,7 @@
                      new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))) {
             PersistentSystemFontConfig.Config config = new PersistentSystemFontConfig.Config();
             PersistentSystemFontConfig.loadFromXml(bais, config);
-            assertThat(config.lastModifiedDate).isEqualTo(0);
+            assertThat(config.lastModifiedMillis).isEqualTo(0);
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
index 7771afc..843296e 100644
--- a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
+++ b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
@@ -151,7 +151,7 @@
         FakeFontFileParser parser = new FakeFontFileParser();
         FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
         PersistentSystemFontConfig.Config config = new PersistentSystemFontConfig.Config();
-        config.lastModifiedDate = expectedModifiedDate;
+        config.lastModifiedMillis = expectedModifiedDate;
         writeConfig(config, mConfigFile);
         UpdatableFontDir dirForPreparation = new UpdatableFontDir(
                 mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil,
@@ -507,7 +507,7 @@
         File readonlyFile = new File(readonlyDir, "readonly_config.xml");
 
         PersistentSystemFontConfig.Config config = new PersistentSystemFontConfig.Config();
-        config.lastModifiedDate = expectedModifiedDate;
+        config.lastModifiedMillis = expectedModifiedDate;
         writeConfig(config, readonlyFile);
 
         assertThat(readonlyDir.setWritable(false, false)).isTrue();
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java
index f2254a9..c08857c 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java
@@ -74,8 +74,6 @@
         when(mContextSpy.getSystemService(PowerManager.class)).thenReturn(powerManager);
         when(mIPowerManagerMock.isInteractive()).thenReturn(true);
 
-        HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(mContextSpy);
-
         mHdmiControlService = new HdmiControlService(mContextSpy) {
             @Override
             AudioManager getAudioManager() {
@@ -106,15 +104,11 @@
             protected void writeStringSystemProperty(String key, String value) {
                 // do nothing
             }
-
-            @Override
-            protected HdmiCecConfig getHdmiCecConfig() {
-                return hdmiCecConfig;
-            }
         };
 
         Looper looper = mTestLooper.getLooper();
         mHdmiControlService.setIoLooper(looper);
+        mHdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(mContextSpy));
         mNativeWrapper = new FakeNativeWrapper();
         HdmiCecController hdmiCecController = HdmiCecController.createWithNativeWrapper(
                 this.mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java b/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java
index 44418ce..50ba761 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java
@@ -76,8 +76,6 @@
         when(mContextSpy.getSystemService(PowerManager.class)).thenReturn(powerManager);
         when(mIPowerManagerMock.isInteractive()).thenReturn(true);
 
-        HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(mContextSpy);
-
         HdmiControlService hdmiControlService =
                 new HdmiControlService(mContextSpy) {
                     @Override
@@ -112,11 +110,6 @@
                     Looper getServiceLooper() {
                         return mTestLooper.getLooper();
                     }
-
-                    @Override
-                    protected HdmiCecConfig getHdmiCecConfig() {
-                        return hdmiCecConfig;
-                    }
                 };
 
         mHdmiCecLocalDeviceAudioSystem = new HdmiCecLocalDeviceAudioSystem(hdmiControlService) {
@@ -128,6 +121,7 @@
         mHdmiCecLocalDeviceAudioSystem.init();
         Looper looper = mTestLooper.getLooper();
         hdmiControlService.setIoLooper(looper);
+        hdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(mContextSpy));
         mNativeWrapper = new FakeNativeWrapper();
         HdmiCecController hdmiCecController = HdmiCecController.createWithNativeWrapper(
                 hdmiControlService, mNativeWrapper, hdmiControlService.getAtomWriter());
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 d454d87..aa5bc93 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java
@@ -77,8 +77,6 @@
         when(mContextSpy.getSystemService(PowerManager.class)).thenReturn(powerManager);
         when(mIPowerManagerMock.isInteractive()).thenReturn(true);
 
-        HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(mContextSpy);
-
         HdmiControlService hdmiControlService =
                 new HdmiControlService(mContextSpy) {
                     @Override
@@ -113,15 +111,11 @@
                     Looper getServiceLooper() {
                         return mTestLooper.getLooper();
                     }
-
-                    @Override
-                    protected HdmiCecConfig getHdmiCecConfig() {
-                        return hdmiCecConfig;
-                    }
                 };
 
         Looper looper = mTestLooper.getLooper();
         hdmiControlService.setIoLooper(looper);
+        hdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(mContextSpy));
         mNativeWrapper = new FakeNativeWrapper();
         HdmiCecController hdmiCecController = HdmiCecController.createWithNativeWrapper(
                 hdmiControlService, mNativeWrapper, hdmiControlService.getAtomWriter());
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/DevicePowerStatusActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/DevicePowerStatusActionTest.java
index 7cb72c4..ef7b274 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/DevicePowerStatusActionTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/DevicePowerStatusActionTest.java
@@ -86,8 +86,6 @@
         when(mContextSpy.getSystemService(PowerManager.class)).thenReturn(powerManager);
         when(mIPowerManagerMock.isInteractive()).thenReturn(true);
 
-        HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(mContextSpy);
-
         mHdmiControlService = new HdmiControlService(mContextSpy) {
             @Override
             AudioManager getAudioManager() {
@@ -118,15 +116,11 @@
             protected void writeStringSystemProperty(String key, String value) {
                 // do nothing
             }
-
-            @Override
-            protected HdmiCecConfig getHdmiCecConfig() {
-                return hdmiCecConfig;
-            }
         };
 
         Looper looper = mTestLooper.getLooper();
         mHdmiControlService.setIoLooper(looper);
+        mHdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(mContextSpy));
         mNativeWrapper = new FakeNativeWrapper();
         HdmiCecController hdmiCecController = HdmiCecController.createWithNativeWrapper(
                 this.mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/DeviceSelectActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/DeviceSelectActionTest.java
index f49cbca..678f8b2 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/DeviceSelectActionTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/DeviceSelectActionTest.java
@@ -106,8 +106,6 @@
         PowerManager powerManager = new PowerManager(context, mIPowerManagerMock,
                 mIThermalServiceMock, new Handler(mMyLooper));
 
-        HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(context);
-
         mHdmiControlService =
                 new HdmiControlService(InstrumentationRegistry.getTargetContext()) {
                     @Override
@@ -133,16 +131,12 @@
                     protected PowerManager getPowerManager() {
                         return powerManager;
                     }
-
-                    @Override
-                    protected HdmiCecConfig getHdmiCecConfig() {
-                        return hdmiCecConfig;
-                    }
                 };
 
         mHdmiCecLocalDeviceTv = new HdmiCecLocalDeviceTv(mHdmiControlService);
         mHdmiCecLocalDeviceTv.init();
         mHdmiControlService.setIoLooper(mMyLooper);
+        mHdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(context));
         mNativeWrapper = new FakeNativeWrapper();
         mHdmiCecController = HdmiCecController.createWithNativeWrapper(
                 mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
@@ -221,7 +215,8 @@
                                                  "testDeviceSelect");
         action.start();
         mTestLooper.dispatchAll();
-        assertThat(mNativeWrapper.getResultMessages()).doesNotContain(SET_STREAM_PATH);
+        assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
+        mNativeWrapper.clearResultMessages();
         assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
         action.processCommand(REPORT_POWER_STATUS_ON);
         mTestLooper.dispatchAll();
@@ -238,12 +233,15 @@
         DeviceSelectAction action = createDeviceSelectAction(actionTimer, callback,
                                         /*isCec20=*/false);
         action.start();
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
         assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
         action.processCommand(REPORT_POWER_STATUS_STANDBY);
         mTestLooper.dispatchAll();
         HdmiCecMessage userControlPressed = HdmiCecMessageBuilder.buildUserControlPressed(
                         ADDR_TV, ADDR_PLAYBACK_1, HdmiCecKeycode.CEC_KEYCODE_POWER);
         assertThat(mNativeWrapper.getResultMessages()).contains(userControlPressed);
+        mNativeWrapper.clearResultMessages();
         assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_DEVICE_POWER_ON);
         action.handleTimerEvent(STATE_WAIT_FOR_DEVICE_POWER_ON);
         action.processCommand(REPORT_POWER_STATUS_ON);
@@ -261,6 +259,9 @@
         DeviceSelectAction action = createDeviceSelectAction(actionTimer, callback,
                                         /*isCec20=*/false);
         action.start();
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
+        mNativeWrapper.clearResultMessages();
         assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
         action.processCommand(REPORT_POWER_STATUS_STANDBY);
         assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_DEVICE_POWER_ON);
@@ -285,6 +286,9 @@
         DeviceSelectAction action = createDeviceSelectAction(actionTimer, callback,
                                         /*isCec20=*/false);
         action.start();
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
+        mNativeWrapper.clearResultMessages();
         assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
         action.processCommand(REPORT_POWER_STATUS_STANDBY);
         assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_DEVICE_POWER_ON);
@@ -330,8 +334,11 @@
         action.start();
         mTestLooper.dispatchAll();
         assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
+        mNativeWrapper.clearResultMessages();
         assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
         action.processCommand(REPORT_POWER_STATUS_ON);
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).doesNotContain(SET_STREAM_PATH);
         assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
     }
 
@@ -354,9 +361,12 @@
         HdmiCecMessage userControlPressed = HdmiCecMessageBuilder.buildUserControlPressed(
                         ADDR_TV, ADDR_PLAYBACK_1, HdmiCecKeycode.CEC_KEYCODE_POWER);
         assertThat(mNativeWrapper.getResultMessages()).doesNotContain(userControlPressed);
+        mNativeWrapper.clearResultMessages();
         assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_DEVICE_POWER_ON);
         action.handleTimerEvent(STATE_WAIT_FOR_DEVICE_POWER_ON);
         action.processCommand(REPORT_POWER_STATUS_ON);
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).doesNotContain(SET_STREAM_PATH);
         assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/FakeNativeWrapper.java b/services/tests/servicestests/src/com/android/server/hdmi/FakeNativeWrapper.java
index fcbd897..1958cb0 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/FakeNativeWrapper.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/FakeNativeWrapper.java
@@ -58,6 +58,7 @@
     private int mMyPhysicalAddress = 0;
     private HdmiPortInfo[] mHdmiPortInfo = null;
     private HdmiCecController.HdmiCecCallback mCallback = null;
+    private int mCecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0;
 
     @Override
     public String nativeInit() {
@@ -96,7 +97,7 @@
 
     @Override
     public int nativeGetVersion() {
-        return HdmiControlManager.HDMI_CEC_VERSION_2_0;
+        return mCecVersion;
     }
 
     @Override
@@ -132,6 +133,10 @@
         mPortConnectionStatus.put(port, connected);
     }
 
+    public void setCecVersion(@HdmiControlManager.HdmiCecVersion int cecVersion) {
+        mCecVersion = cecVersion;
+    }
+
     public void onCecMessage(HdmiCecMessage hdmiCecMessage) {
         if (mCallback == null) {
             return;
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 eedbc95..6bb148d 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
@@ -98,8 +98,6 @@
         PowerManager powerManager = new PowerManager(context, mIPowerManagerMock,
                 mIThermalServiceMock, new Handler(mMyLooper));
 
-        HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(context);
-
         mHdmiControlService =
             new HdmiControlService(InstrumentationRegistry.getTargetContext()) {
                 @Override
@@ -188,17 +186,13 @@
                 protected PowerManager getPowerManager() {
                     return powerManager;
                 }
-
-                @Override
-                protected HdmiCecConfig getHdmiCecConfig() {
-                    return hdmiCecConfig;
-                }
             };
 
         mHdmiControlService.getHdmiCecConfig().setIntValue(
                 HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE,
                 HdmiControlManager.VOLUME_CONTROL_ENABLED);
         mMyLooper = mTestLooper.getLooper();
+        mHdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(context));
         mHdmiCecLocalDeviceAudioSystem = new HdmiCecLocalDeviceAudioSystem(mHdmiControlService);
         mHdmiCecLocalDevicePlayback = new HdmiCecLocalDevicePlayback(mHdmiControlService) {
             @Override
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 b11ac24..915392e 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
@@ -87,7 +87,6 @@
         mMyLooper = mTestLooper.getLooper();
         PowerManager powerManager = new PowerManager(context, mIPowerManagerMock,
                 mIThermalServiceMock, new Handler(mMyLooper));
-        HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(context);
 
         mHdmiControlService =
                 new HdmiControlService(InstrumentationRegistry.getTargetContext()) {
@@ -136,15 +135,11 @@
                     protected PowerManager getPowerManager() {
                         return powerManager;
                     }
-
-                    @Override
-                    protected HdmiCecConfig getHdmiCecConfig() {
-                        return hdmiCecConfig;
-                    }
                 };
 
         mHdmiCecLocalDevicePlayback = new HdmiCecLocalDevicePlayback(mHdmiControlService);
         mHdmiCecLocalDevicePlayback.init();
+        mHdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(context));
         mHdmiControlService.setIoLooper(mMyLooper);
         mNativeWrapper = new FakeNativeWrapper();
         mHdmiCecController = HdmiCecController.createWithNativeWrapper(
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
index 0717112..b3f0085 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
@@ -128,8 +128,6 @@
 
         Context context = InstrumentationRegistry.getTargetContext();
 
-        HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(context);
-
         mHdmiControlService =
                 new HdmiControlService(context) {
                     @Override
@@ -163,13 +161,9 @@
                     void wakeUp() {
                         mWakeupMessageReceived = true;
                     }
-
-                    @Override
-                    protected HdmiCecConfig getHdmiCecConfig() {
-                        return hdmiCecConfig;
-                    }
                 };
         mHdmiControlService.setIoLooper(mTestLooper.getLooper());
+        mHdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(context));
         mNativeWrapper = new FakeNativeWrapper();
         mHdmiCecController = HdmiCecController.createWithNativeWrapper(
                 mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
index 4623eb5..4b3ef2f 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
@@ -81,8 +81,6 @@
         PowerManager powerManager = new PowerManager(context, mIPowerManagerMock,
                 mIThermalServiceMock, new Handler(mMyLooper));
 
-        HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(context);
-
         mHdmiControlService =
                 new HdmiControlService(InstrumentationRegistry.getTargetContext()) {
                     @Override
@@ -119,16 +117,12 @@
                     AudioManager getAudioManager() {
                         return mAudioManager;
                     }
-
-                    @Override
-                    protected HdmiCecConfig getHdmiCecConfig() {
-                        return hdmiCecConfig;
-                    }
                 };
 
         mHdmiCecLocalDeviceTv = new HdmiCecLocalDeviceTv(mHdmiControlService);
         mHdmiCecLocalDeviceTv.init();
         mHdmiControlService.setIoLooper(mMyLooper);
+        mHdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(context));
         mNativeWrapper = new FakeNativeWrapper();
         mHdmiCecController = HdmiCecController.createWithNativeWrapper(
                 mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecPowerStatusControllerTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecPowerStatusControllerTest.java
index 06373c2..1c7ff42 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecPowerStatusControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecPowerStatusControllerTest.java
@@ -62,12 +62,12 @@
     private FakeNativeWrapper mNativeWrapper;
     private TestLooper mTestLooper = new TestLooper();
     private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
-    private int mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
     @Mock
     private IPowerManager mIPowerManagerMock;
     @Mock
     private IThermalService mIThermalServiceMock;
     private HdmiControlService mHdmiControlService;
+    private HdmiCecLocalDevicePlayback mHdmiCecLocalDevicePlayback;
 
     @Before
     public void setUp() throws Exception {
@@ -81,8 +81,6 @@
         when(contextSpy.getSystemService(PowerManager.class)).thenReturn(powerManager);
         when(mIPowerManagerMock.isInteractive()).thenReturn(true);
 
-        HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(contextSpy);
-
         mHdmiControlService = new HdmiControlService(contextSpy) {
             @Override
             boolean isControlEnabled() {
@@ -100,33 +98,24 @@
             }
 
             @Override
-            int getCecVersion() {
-                return mHdmiCecVersion;
-            }
-
-            @Override
             boolean isPowerStandby() {
                 return false;
             }
-
-            @Override
-            protected HdmiCecConfig getHdmiCecConfig() {
-                return hdmiCecConfig;
-            }
         };
         mHdmiControlService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
 
-        HdmiCecLocalDevicePlayback hdmiCecLocalDevicePlayback = new HdmiCecLocalDevicePlayback(
+        mHdmiCecLocalDevicePlayback = new HdmiCecLocalDevicePlayback(
                 mHdmiControlService);
-        hdmiCecLocalDevicePlayback.init();
+        mHdmiCecLocalDevicePlayback.init();
         mHdmiControlService.setIoLooper(myLooper);
+        mHdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(contextSpy));
         mNativeWrapper = new FakeNativeWrapper();
         HdmiCecController hdmiCecController = HdmiCecController.createWithNativeWrapper(
                 mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
         mHdmiControlService.setCecController(hdmiCecController);
         mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
         mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
-        mLocalDevices.add(hdmiCecLocalDevicePlayback);
+        mLocalDevices.add(mHdmiCecLocalDevicePlayback);
         HdmiPortInfo[] hdmiPortInfos = new HdmiPortInfo[1];
         hdmiPortInfos[0] =
                 new HdmiPortInfo(1, HdmiPortInfo.PORT_OUTPUT, 0x0000, true, false, false);
@@ -188,77 +177,84 @@
 
     @Test
     public void setPowerStatus_doesntSendBroadcast_1_4() {
+        setCecVersion(HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
         mHdmiCecPowerStatusController.setPowerStatus(HdmiControlManager.POWER_STATUS_ON);
         mTestLooper.dispatchAll();
 
         HdmiCecMessage reportPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus(
-                Constants.ADDR_PLAYBACK_1, Constants.ADDR_BROADCAST,
+                mHdmiCecLocalDevicePlayback.mAddress, Constants.ADDR_BROADCAST,
                 HdmiControlManager.POWER_STATUS_ON);
         assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportPowerStatus);
     }
 
     @Test
     public void setPowerStatus_transient_doesntSendBroadcast_1_4() {
+        setCecVersion(HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
         mHdmiCecPowerStatusController.setPowerStatus(
                 HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON);
         mTestLooper.dispatchAll();
 
         HdmiCecMessage reportPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus(
-                Constants.ADDR_PLAYBACK_1, Constants.ADDR_BROADCAST,
+                mHdmiCecLocalDevicePlayback.mAddress, Constants.ADDR_BROADCAST,
                 HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON);
         assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportPowerStatus);
     }
 
     @Test
     public void setPowerStatus_fast_transient_doesntSendBroadcast_1_4() {
+        setCecVersion(HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
         mHdmiCecPowerStatusController.setPowerStatus(
                 HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON, false);
         mTestLooper.dispatchAll();
 
         HdmiCecMessage reportPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus(
-                Constants.ADDR_PLAYBACK_1, Constants.ADDR_BROADCAST,
+                mHdmiCecLocalDevicePlayback.mAddress, Constants.ADDR_BROADCAST,
                 HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON);
         assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportPowerStatus);
     }
 
     @Test
     public void setPowerStatus_sendsBroadcast_2_0() {
-        mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0;
-
+        setCecVersion(HdmiControlManager.HDMI_CEC_VERSION_2_0);
         mHdmiCecPowerStatusController.setPowerStatus(HdmiControlManager.POWER_STATUS_ON);
         mTestLooper.dispatchAll();
 
         HdmiCecMessage reportPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus(
-                Constants.ADDR_PLAYBACK_1, Constants.ADDR_BROADCAST,
+                mHdmiCecLocalDevicePlayback.mAddress, Constants.ADDR_BROADCAST,
                 HdmiControlManager.POWER_STATUS_ON);
         assertThat(mNativeWrapper.getResultMessages()).contains(reportPowerStatus);
     }
 
     @Test
     public void setPowerStatus_transient_sendsBroadcast_2_0() {
-        mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0;
-
+        setCecVersion(HdmiControlManager.HDMI_CEC_VERSION_2_0);
         mHdmiCecPowerStatusController.setPowerStatus(
                 HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON);
         mTestLooper.dispatchAll();
 
         HdmiCecMessage reportPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus(
-                Constants.ADDR_PLAYBACK_1, Constants.ADDR_BROADCAST,
+                mHdmiCecLocalDevicePlayback.mAddress, Constants.ADDR_BROADCAST,
                 HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON);
         assertThat(mNativeWrapper.getResultMessages()).contains(reportPowerStatus);
     }
 
     @Test
     public void setPowerStatus_fast_transient_doesntSendBroadcast_2_0() {
-        mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0;
-
+        setCecVersion(HdmiControlManager.HDMI_CEC_VERSION_2_0);
         mHdmiCecPowerStatusController.setPowerStatus(
                 HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON, false);
         mTestLooper.dispatchAll();
 
         HdmiCecMessage reportPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus(
-                Constants.ADDR_PLAYBACK_1, Constants.ADDR_BROADCAST,
+                mHdmiCecLocalDevicePlayback.mAddress, Constants.ADDR_BROADCAST,
                 HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON);
         assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportPowerStatus);
     }
+
+    private void setCecVersion(int version) {
+        mHdmiControlService.getHdmiCecConfig().setIntValue(
+                HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION, version);
+        mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
+        mTestLooper.dispatchAll();
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
index be584d7..47f3bf9 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -19,6 +19,7 @@
 import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_PLAYBACK;
 
 import static com.android.server.SystemService.PHASE_BOOT_COMPLETED;
+import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
 import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -44,6 +45,7 @@
 import android.os.test.TestLooper;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
+import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -67,14 +69,64 @@
 @RunWith(JUnit4.class)
 public class HdmiControlServiceTest {
 
-    private class HdmiCecLocalDeviceMyDevice extends HdmiCecLocalDeviceSource {
+    private class MockPlaybackDevice extends HdmiCecLocalDevicePlayback {
 
         private boolean mCanGoToStandby;
         private boolean mIsStandby;
         private boolean mIsDisabled;
 
-        protected HdmiCecLocalDeviceMyDevice(HdmiControlService service, int deviceType) {
-            super(service, deviceType);
+        MockPlaybackDevice(HdmiControlService service) {
+            super(service);
+        }
+
+        @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 class MockAudioSystemDevice extends HdmiCecLocalDeviceAudioSystem {
+
+        private boolean mCanGoToStandby;
+        private boolean mIsStandby;
+        private boolean mIsDisabled;
+
+        MockAudioSystemDevice(HdmiControlService service) {
+            super(service);
         }
 
         @Override
@@ -122,8 +174,8 @@
     private Context mContextSpy;
     private HdmiControlService mHdmiControlService;
     private HdmiCecController mHdmiCecController;
-    private HdmiCecLocalDeviceMyDevice mMyAudioSystemDevice;
-    private HdmiCecLocalDeviceMyDevice mMyPlaybackDevice;
+    private MockAudioSystemDevice mAudioSystemDevice;
+    private MockPlaybackDevice mPlaybackDevice;
     private FakeNativeWrapper mNativeWrapper;
     private Looper mMyLooper;
     private TestLooper mTestLooper = new TestLooper();
@@ -143,6 +195,7 @@
         PowerManager powerManager = new PowerManager(mContextSpy, mIPowerManagerMock,
                 mIThermalServiceMock, null);
         when(mContextSpy.getSystemService(Context.POWER_SERVICE)).thenReturn(powerManager);
+        when(mContextSpy.getSystemService(PowerManager.class)).thenReturn(powerManager);
         when(mIPowerManagerMock.isInteractive()).thenReturn(true);
 
         HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(mContextSpy);
@@ -156,21 +209,17 @@
             @Override
             protected void writeStringSystemProperty(String key, String value) {
             }
-
-            @Override
-            protected HdmiCecConfig getHdmiCecConfig() {
-                return hdmiCecConfig;
-            }
         };
         mMyLooper = mTestLooper.getLooper();
 
-        mMyAudioSystemDevice =
-                new HdmiCecLocalDeviceMyDevice(mHdmiControlService, DEVICE_AUDIO_SYSTEM);
-        mMyPlaybackDevice = new HdmiCecLocalDeviceMyDevice(mHdmiControlService, DEVICE_PLAYBACK);
-        mMyAudioSystemDevice.init();
-        mMyPlaybackDevice.init();
+        mAudioSystemDevice = new MockAudioSystemDevice(mHdmiControlService);
+        mPlaybackDevice = new MockPlaybackDevice(mHdmiControlService);
+        mAudioSystemDevice.init();
+        mPlaybackDevice.init();
 
         mHdmiControlService.setIoLooper(mMyLooper);
+        mHdmiControlService.setHdmiCecConfig(hdmiCecConfig);
+        mHdmiControlService.onBootPhase(PHASE_SYSTEM_SERVICES_READY);
 
         mNativeWrapper = new FakeNativeWrapper();
         mHdmiCecController = HdmiCecController.createWithNativeWrapper(
@@ -179,8 +228,8 @@
         mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
         mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
 
-        mLocalDevices.add(mMyAudioSystemDevice);
-        mLocalDevices.add(mMyPlaybackDevice);
+        mLocalDevices.add(mAudioSystemDevice);
+        mLocalDevices.add(mPlaybackDevice);
         mHdmiPortInfo = new HdmiPortInfo[4];
         mHdmiPortInfo[0] =
             new HdmiPortInfo(1, HdmiPortInfo.PORT_INPUT, 0x2100, true, false, false);
@@ -191,6 +240,9 @@
         mHdmiPortInfo[3] =
             new HdmiPortInfo(4, HdmiPortInfo.PORT_INPUT, 0x3000, true, false, false);
         mNativeWrapper.setPortInfo(mHdmiPortInfo);
+        mHdmiControlService.getHdmiCecConfig().setIntValue(
+                HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
+                HdmiControlManager.HDMI_CEC_CONTROL_ENABLED);
         mHdmiControlService.initService();
         mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
 
@@ -200,13 +252,13 @@
     @Test
     public void onStandby_notByCec_cannotGoToStandby() {
         mStandbyMessageReceived = false;
-        mMyPlaybackDevice.setCanGoToStandby(false);
+        mPlaybackDevice.setCanGoToStandby(false);
 
         mHdmiControlService.onStandby(HdmiControlService.STANDBY_SCREEN_OFF);
-        assertTrue(mMyPlaybackDevice.isStandby());
-        assertTrue(mMyAudioSystemDevice.isStandby());
-        assertFalse(mMyPlaybackDevice.isDisabled());
-        assertFalse(mMyAudioSystemDevice.isDisabled());
+        assertTrue(mPlaybackDevice.isStandby());
+        assertTrue(mAudioSystemDevice.isStandby());
+        assertFalse(mPlaybackDevice.isDisabled());
+        assertFalse(mAudioSystemDevice.isDisabled());
     }
 
     @Test
@@ -214,10 +266,10 @@
         mStandbyMessageReceived = true;
 
         mHdmiControlService.onStandby(HdmiControlService.STANDBY_SCREEN_OFF);
-        assertTrue(mMyPlaybackDevice.isStandby());
-        assertTrue(mMyAudioSystemDevice.isStandby());
-        assertTrue(mMyPlaybackDevice.isDisabled());
-        assertTrue(mMyAudioSystemDevice.isDisabled());
+        assertTrue(mPlaybackDevice.isStandby());
+        assertTrue(mAudioSystemDevice.isStandby());
+        assertTrue(mPlaybackDevice.isDisabled());
+        assertTrue(mAudioSystemDevice.isDisabled());
     }
 
     @Test
@@ -274,6 +326,7 @@
         mHdmiControlService.getHdmiCecConfig().setIntValue(
                 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
                 HdmiControlManager.HDMI_CEC_VERSION_2_0);
+        mTestLooper.dispatchAll();
 
         mHdmiControlService.setControlEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED);
         mNativeWrapper.clearResultMessages();
@@ -484,17 +537,6 @@
     }
 
     @Test
-    public void getCecVersion_default() {
-        // Set the Settings value to "null" to emulate it being empty and force the default value.
-        Settings.Global.putString(mContextSpy.getContentResolver(),
-                Settings.Global.HDMI_CEC_VERSION,
-                null);
-        mHdmiControlService.setControlEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED);
-        assertThat(mHdmiControlService.getCecVersion()).isEqualTo(
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
-    }
-
-    @Test
     public void getCecVersion_1_4() {
         mHdmiControlService.getHdmiCecConfig().setIntValue(
                 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
@@ -565,8 +607,8 @@
         HdmiCecMessage reportFeatures = HdmiCecMessageBuilder.buildReportFeatures(
                 Constants.ADDR_PLAYBACK_1, HdmiControlManager.HDMI_CEC_VERSION_2_0,
                 Arrays.asList(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM),
-                mMyPlaybackDevice.getRcProfile(), mMyPlaybackDevice.getRcFeatures(),
-                mMyPlaybackDevice.getDeviceFeatures());
+                mPlaybackDevice.getRcProfile(), mPlaybackDevice.getRcFeatures(),
+                mPlaybackDevice.getDeviceFeatures());
         assertThat(mNativeWrapper.getResultMessages()).contains(reportFeatures);
     }
 
@@ -583,8 +625,8 @@
         HdmiCecMessage reportFeatures = HdmiCecMessageBuilder.buildReportFeatures(
                 Constants.ADDR_PLAYBACK_1, HdmiControlManager.HDMI_CEC_VERSION_2_0,
                 Arrays.asList(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM),
-                mMyPlaybackDevice.getRcProfile(), mMyPlaybackDevice.getRcFeatures(),
-                mMyPlaybackDevice.getDeviceFeatures());
+                mPlaybackDevice.getRcProfile(), mPlaybackDevice.getRcFeatures(),
+                mPlaybackDevice.getDeviceFeatures());
         assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportFeatures);
     }
 
@@ -600,8 +642,8 @@
         HdmiCecMessage reportFeatures = HdmiCecMessageBuilder.buildReportFeatures(
                 Constants.ADDR_PLAYBACK_1, HdmiControlManager.HDMI_CEC_VERSION_2_0,
                 Arrays.asList(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM),
-                mMyPlaybackDevice.getRcProfile(), mMyPlaybackDevice.getRcFeatures(),
-                mMyPlaybackDevice.getDeviceFeatures());
+                mPlaybackDevice.getRcProfile(), mPlaybackDevice.getRcFeatures(),
+                mPlaybackDevice.getDeviceFeatures());
         assertThat(mNativeWrapper.getResultMessages()).contains(reportFeatures);
     }
 
@@ -622,6 +664,46 @@
         assertEquals(runnerUid, Binder.getCallingWorkSourceUid());
     }
 
+    @Test
+    public void initCecVersion_limitToMinimumSupportedVersion() {
+        mNativeWrapper.setCecVersion(HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
+        Log.e("MARVIN", "set setting CEC");
+        mHdmiControlService.getHdmiCecConfig().setIntValue(
+                HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
+                HdmiControlManager.HDMI_CEC_VERSION_2_0);
+
+        mTestLooper.dispatchAll();
+        assertThat(mHdmiControlService.getCecVersion()).isEqualTo(
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
+    }
+
+    @Test
+    public void initCecVersion_limitToAtLeast1_4() {
+        Log.e("MARVIN", "set HAL CEC to 0");
+        mNativeWrapper.setCecVersion(0x0);
+        Log.e("MARVIN", "set setting CEC to 2");
+        mHdmiControlService.getHdmiCecConfig().setIntValue(
+                HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
+                HdmiControlManager.HDMI_CEC_VERSION_2_0);
+
+        mTestLooper.dispatchAll();
+        assertThat(mHdmiControlService.getCecVersion()).isEqualTo(
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
+    }
+
+    @Test
+    public void initCecVersion_useHighestMatchingVersion() {
+        mNativeWrapper.setCecVersion(HdmiControlManager.HDMI_CEC_VERSION_2_0);
+        Log.e("MARVIN", "set setting CEC");
+        mHdmiControlService.getHdmiCecConfig().setIntValue(
+                HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
+                HdmiControlManager.HDMI_CEC_VERSION_2_0);
+
+        mTestLooper.dispatchAll();
+        assertThat(mHdmiControlService.getCecVersion()).isEqualTo(
+                HdmiControlManager.HDMI_CEC_VERSION_2_0);
+    }
+
     private static class VolumeControlFeatureCallback extends
             IHdmiCecVolumeControlFeatureListener.Stub {
         boolean mCallbackReceived = false;
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/PowerStatusMonitorActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/PowerStatusMonitorActionTest.java
index b8dfd56..605f781 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/PowerStatusMonitorActionTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/PowerStatusMonitorActionTest.java
@@ -84,8 +84,6 @@
         when(mContextSpy.getSystemService(PowerManager.class)).thenReturn(powerManager);
         when(mIPowerManagerMock.isInteractive()).thenReturn(true);
 
-        HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(mContextSpy);
-
         mHdmiControlService = new HdmiControlService(mContextSpy) {
             @Override
             AudioManager getAudioManager() {
@@ -116,15 +114,11 @@
             protected void writeStringSystemProperty(String key, String value) {
                 // do nothing
             }
-
-            @Override
-            protected HdmiCecConfig getHdmiCecConfig() {
-                return hdmiCecConfig;
-            }
         };
 
         Looper looper = mTestLooper.getLooper();
         mHdmiControlService.setIoLooper(looper);
+        mHdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(mContextSpy));
         mNativeWrapper = new FakeNativeWrapper();
         HdmiCecController hdmiCecController = HdmiCecController.createWithNativeWrapper(
                 this.mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
@@ -185,6 +179,7 @@
         mHdmiControlService.getHdmiCecConfig().setIntValue(
                 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
                 HdmiControlManager.HDMI_CEC_VERSION_2_0);
+        mTestLooper.dispatchAll();
         sendMessageFromPlaybackDevice(ADDR_PLAYBACK_1, 0x1000);
         reportPowerStatus(ADDR_PLAYBACK_1, true, HdmiControlManager.POWER_STATUS_ON);
         mTestLooper.dispatchAll();
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 f9160ab..e82c788 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java
@@ -65,8 +65,6 @@
 
         Context context = InstrumentationRegistry.getTargetContext();
 
-        HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(context);
-
         HdmiControlService hdmiControlService = new HdmiControlService(context) {
                     @Override
                     void sendCecCommand(
@@ -164,15 +162,11 @@
                     int pathToPortId(int path) {
                         return -1;
                     }
-
-                    @Override
-                    protected HdmiCecConfig getHdmiCecConfig() {
-                        return hdmiCecConfig;
-                    }
                 };
 
         Looper looper = mTestLooper.getLooper();
         hdmiControlService.setIoLooper(looper);
+        hdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(context));
         HdmiCecController.NativeWrapper nativeWrapper = new FakeNativeWrapper();
         HdmiCecController hdmiCecController = HdmiCecController.createWithNativeWrapper(
                 hdmiControlService, nativeWrapper, hdmiControlService.getAtomWriter());
diff --git a/services/tests/servicestests/src/com/android/server/lights/LightsServiceTest.java b/services/tests/servicestests/src/com/android/server/lights/LightsServiceTest.java
index 3e9709d..f0a9a00 100644
--- a/services/tests/servicestests/src/com/android/server/lights/LightsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/lights/LightsServiceTest.java
@@ -31,6 +31,7 @@
 import android.hardware.lights.Light;
 import android.hardware.lights.LightState;
 import android.hardware.lights.LightsManager;
+import android.hardware.lights.SystemLightsManager;
 import android.os.Looper;
 
 import androidx.test.filters.SmallTest;
@@ -93,7 +94,7 @@
     @Test
     public void testGetLights_filtersSystemLights() {
         LightsService service = new LightsService(mContext, () -> mHal, Looper.getMainLooper());
-        LightsManager manager = new LightsManager(mContext, service.mManagerService);
+        LightsManager manager = new SystemLightsManager(mContext, service.mManagerService);
 
         // When lights are listed, only the 4 MICROPHONE lights should be visible.
         assertThat(manager.getLights().size()).isEqualTo(4);
@@ -102,14 +103,14 @@
     @Test
     public void testControlMultipleLights() {
         LightsService service = new LightsService(mContext, () -> mHal, Looper.getMainLooper());
-        LightsManager manager = new LightsManager(mContext, service.mManagerService);
+        LightsManager manager = new SystemLightsManager(mContext, service.mManagerService);
 
         // When the session requests to turn 3/4 lights on:
         LightsManager.LightsSession session = manager.openSession();
         session.requestLights(new Builder()
-                .setLight(manager.getLights().get(0), new LightState(0xf1))
-                .setLight(manager.getLights().get(1), new LightState(0xf2))
-                .setLight(manager.getLights().get(2), new LightState(0xf3))
+                .addLight(manager.getLights().get(0), new LightState(0xf1))
+                .addLight(manager.getLights().get(1), new LightState(0xf2))
+                .addLight(manager.getLights().get(2), new LightState(0xf3))
                 .build());
 
         // Then all 3 should turn on.
@@ -122,9 +123,9 @@
     }
 
     @Test
-    public void testControlLights_onlyEffectiveForLifetimeOfClient() {
+    public void testControlLights_onlyEffectiveForLifetimeOfClient() throws Exception {
         LightsService service = new LightsService(mContext, () -> mHal, Looper.getMainLooper());
-        LightsManager manager = new LightsManager(mContext, service.mManagerService);
+        LightsManager manager = new SystemLightsManager(mContext, service.mManagerService);
         Light micLight = manager.getLights().get(0);
 
         // The light should begin by being off.
@@ -132,38 +133,41 @@
 
         // When a session commits changes:
         LightsManager.LightsSession session = manager.openSession();
-        session.requestLights(new Builder().setLight(micLight, new LightState(GREEN)).build());
+        session.requestLights(new Builder().addLight(micLight, new LightState(GREEN)).build());
         // Then the light should turn on.
         assertThat(manager.getLightState(micLight).getColor()).isEqualTo(GREEN);
 
         // When the session goes away:
         session.close();
+
         // Then the light should turn off.
         assertThat(manager.getLightState(micLight).getColor()).isEqualTo(TRANSPARENT);
     }
 
     @Test
-    public void testControlLights_firstCallerWinsContention() {
+    public void testControlLights_firstCallerWinsContention() throws Exception {
         LightsService service = new LightsService(mContext, () -> mHal, Looper.getMainLooper());
-        LightsManager manager = new LightsManager(mContext, service.mManagerService);
+        LightsManager manager = new SystemLightsManager(mContext, service.mManagerService);
         Light micLight = manager.getLights().get(0);
 
         LightsManager.LightsSession session1 = manager.openSession();
         LightsManager.LightsSession session2 = manager.openSession();
 
         // When session1 and session2 both request the same light:
-        session1.requestLights(new Builder().setLight(micLight, new LightState(BLUE)).build());
-        session2.requestLights(new Builder().setLight(micLight, new LightState(WHITE)).build());
+        session1.requestLights(new Builder().addLight(micLight, new LightState(BLUE)).build());
+        session2.requestLights(new Builder().addLight(micLight, new LightState(WHITE)).build());
         // Then session1 should win because it was created first.
         assertThat(manager.getLightState(micLight).getColor()).isEqualTo(BLUE);
 
         // When session1 goes away:
         session1.close();
+
         // Then session2 should have its request go into effect.
         assertThat(manager.getLightState(micLight).getColor()).isEqualTo(WHITE);
 
         // When session2 goes away:
         session2.close();
+
         // Then the light should turn off because there are no more sessions.
         assertThat(manager.getLightState(micLight).getColor()).isEqualTo(0);
     }
@@ -171,12 +175,12 @@
     @Test
     public void testClearLight() {
         LightsService service = new LightsService(mContext, () -> mHal, Looper.getMainLooper());
-        LightsManager manager = new LightsManager(mContext, service.mManagerService);
+        LightsManager manager = new SystemLightsManager(mContext, service.mManagerService);
         Light micLight = manager.getLights().get(0);
 
         // When the session turns a light on:
         LightsManager.LightsSession session = manager.openSession();
-        session.requestLights(new Builder().setLight(micLight, new LightState(WHITE)).build());
+        session.requestLights(new Builder().addLight(micLight, new LightState(WHITE)).build());
 
         // And then the session clears it again:
         session.requestLights(new Builder().clearLight(micLight).build());
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 73191dc..4a42940 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
@@ -150,7 +150,7 @@
         }
 
         @Override
-        public RecoverableKeyStoreManager getRecoverableKeyStoreManager(KeyStore keyStore) {
+        public RecoverableKeyStoreManager getRecoverableKeyStoreManager() {
             return mRecoverableKeyStoreManager;
         }
 
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 3ebe4ef..74bf4f5 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -115,7 +115,6 @@
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkPolicy;
-import android.net.NetworkPolicyManager;
 import android.net.NetworkState;
 import android.net.NetworkStats;
 import android.net.NetworkStatsHistory;
@@ -386,8 +385,7 @@
                 Log.d(TAG, "set mUidObserver to " + mUidObserver);
                 return null;
             }
-        }).when(mActivityManager).registerUidObserver(any(), anyInt(),
-                eq(NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE), any(String.class));
+        }).when(mActivityManager).registerUidObserver(any(), anyInt(), anyInt(), any(String.class));
 
         mFutureIntent = newRestrictBackgroundChangedFuture();
         mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager,
@@ -2043,7 +2041,7 @@
         final NetworkCapabilities networkCapabilities = new NetworkCapabilities();
         networkCapabilities.addTransportType(TRANSPORT_WIFI);
         networkCapabilities.setSSID(TEST_SSID);
-        return new NetworkState(TYPE_WIFI, prop, networkCapabilities, null, null, TEST_SSID);
+        return new NetworkState(TYPE_WIFI, prop, networkCapabilities, null, null);
     }
 
     private void expectHasInternetPermission(int uid, boolean hasIt) throws Exception {
@@ -2067,7 +2065,7 @@
                 new NetworkState(TYPE_MOBILE,
                         buildLinkProperties(TEST_IFACE),
                         buildNetworkCapabilities(TEST_SUB_ID, roaming),
-                        new Network(TEST_NET_ID), TEST_IMSI, null)
+                        new Network(TEST_NET_ID), TEST_IMSI)
         });
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index e46ab6b..029e9a3 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -45,6 +45,13 @@
 import android.app.IUidObserver;
 import android.app.Person;
 import android.app.admin.DevicePolicyManager;
+import android.app.appsearch.AppSearchBatchResult;
+import android.app.appsearch.AppSearchManager;
+import android.app.appsearch.AppSearchResult;
+import android.app.appsearch.IAppSearchBatchResultCallback;
+import android.app.appsearch.IAppSearchManager;
+import android.app.appsearch.IAppSearchResultCallback;
+import android.app.appsearch.PackageIdentifier;
 import android.app.role.OnRoleHoldersChangedListener;
 import android.app.usage.UsageStatsManagerInternal;
 import android.content.ActivityNotFoundException;
@@ -78,6 +85,7 @@
 import android.os.Bundle;
 import android.os.FileUtils;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Looper;
 import android.os.PersistableBundle;
 import android.os.Process;
@@ -150,6 +158,8 @@
                     return mMockUserManager;
                 case Context.DEVICE_POLICY_SERVICE:
                     return mMockDevicePolicyManager;
+                case Context.APP_SEARCH_SERVICE:
+                    return new AppSearchManager(getTestContext(), mMockAppSearchManager);
                 case Context.ROLE_SERVICE:
                     // RoleManager is final and cannot be mocked, so we only override the inject
                     // accessor methods in ShortcutService.
@@ -159,6 +169,11 @@
         }
 
         @Override
+        public String getOpPackageName() {
+            return getTestContext().getOpPackageName();
+        }
+
+        @Override
         public String getSystemServiceName(Class<?> serviceClass) {
             return getTestContext().getSystemServiceName(serviceClass);
         }
@@ -601,6 +616,123 @@
         }
     }
 
+    protected class MockAppSearchManager implements IAppSearchManager {
+
+        protected Map<String, List<PackageIdentifier>> mSchemasPackageAccessible =
+                new ArrayMap<>(1);
+
+        @Override
+        public void setSchema(String packageName, String databaseName, List<Bundle> schemaBundles,
+                List<String> schemasNotPlatformSurfaceable,
+                Map<String, List<Bundle>> schemasPackageAccessibleBundles, boolean forceOverride,
+                int userId, IAppSearchResultCallback callback) throws RemoteException {
+            for (Map.Entry<String, List<Bundle>> entry :
+                    schemasPackageAccessibleBundles.entrySet()) {
+                final String key = entry.getKey();
+                final List<PackageIdentifier> packageIdentifiers;
+                if (!mSchemasPackageAccessible.containsKey(key)) {
+                    packageIdentifiers = new ArrayList<>(entry.getValue().size());
+                    mSchemasPackageAccessible.put(key, packageIdentifiers);
+                } else {
+                    packageIdentifiers = mSchemasPackageAccessible.get(key);
+                }
+                for (int i = 0; i < entry.getValue().size(); i++) {
+                    packageIdentifiers.add(new PackageIdentifier(entry.getValue().get(i)));
+                }
+            }
+            callback.onResult(AppSearchResult.newSuccessfulResult(null));
+        }
+
+        @Override
+        public void getSchema(String packageName, String databaseName, int userId,
+                IAppSearchResultCallback callback) throws RemoteException {
+            ignore(callback);
+        }
+
+        @Override
+        public void putDocuments(String packageName, String databaseName,
+                List<Bundle> documentBundles, int userId, IAppSearchBatchResultCallback callback)
+                throws RemoteException {
+            ignore(callback);
+        }
+
+        @Override
+        public void getDocuments(String packageName, String databaseName, String namespace,
+                List<String> uris, Map<String, List<String>> typePropertyPaths, int userId,
+                IAppSearchBatchResultCallback callback) throws RemoteException {
+            ignore(callback);
+        }
+
+        @Override
+        public void query(String packageName, String databaseName, String queryExpression,
+                Bundle searchSpecBundle, int userId, IAppSearchResultCallback callback)
+                throws RemoteException {
+            ignore(callback);
+        }
+
+        @Override
+        public void globalQuery(String packageName, String queryExpression, Bundle searchSpecBundle,
+                int userId, IAppSearchResultCallback callback) throws RemoteException {
+            ignore(callback);
+        }
+
+        @Override
+        public void getNextPage(long nextPageToken, int userId, IAppSearchResultCallback callback)
+                throws RemoteException {
+            ignore(callback);
+        }
+
+        @Override
+        public void invalidateNextPageToken(long nextPageToken, int userId) throws RemoteException {
+
+        }
+
+        @Override
+        public void reportUsage(String packageName, String databaseName, String namespace,
+                String uri, long usageTimeMillis, int userId, IAppSearchResultCallback callback)
+                throws RemoteException {
+            ignore(callback);
+        }
+
+        @Override
+        public void removeByUri(String packageName, String databaseName, String namespace,
+                List<String> uris, int userId, IAppSearchBatchResultCallback callback)
+                throws RemoteException {
+            ignore(callback);
+        }
+
+        @Override
+        public void removeByQuery(String packageName, String databaseName, String queryExpression,
+                Bundle searchSpecBundle, int userId, IAppSearchResultCallback callback)
+                throws RemoteException {
+            ignore(callback);
+        }
+
+        @Override
+        public void persistToDisk(int userId) throws RemoteException {
+
+        }
+
+        @Override
+        public void initialize(int userId, IAppSearchResultCallback callback)
+                throws RemoteException {
+            ignore(callback);
+        }
+
+        @Override
+        public IBinder asBinder() {
+            return null;
+        }
+
+        private void ignore(IAppSearchResultCallback callback) throws RemoteException {
+            callback.onResult(AppSearchResult.newSuccessfulResult(null));
+        }
+
+        private void ignore(IAppSearchBatchResultCallback callback) throws RemoteException {
+            callback.onResult(new AppSearchBatchResult.Builder().build());
+        }
+    }
+
     public static class ShortcutActivity extends Activity {
     }
 
@@ -652,6 +784,7 @@
     protected PackageManagerInternal mMockPackageManagerInternal;
     protected UserManager mMockUserManager;
     protected DevicePolicyManager mMockDevicePolicyManager;
+    protected MockAppSearchManager mMockAppSearchManager;
     protected UserManagerInternal mMockUserManagerInternal;
     protected UsageStatsManagerInternal mMockUsageStatsManagerInternal;
     protected ActivityManagerInternal mMockActivityManagerInternal;
@@ -801,6 +934,7 @@
         mMockPackageManagerInternal = mock(PackageManagerInternal.class);
         mMockUserManager = mock(UserManager.class);
         mMockDevicePolicyManager = mock(DevicePolicyManager.class);
+        mMockAppSearchManager = new MockAppSearchManager();
         mMockUserManagerInternal = mock(UserManagerInternal.class);
         mMockUsageStatsManagerInternal = mock(UsageStatsManagerInternal.class);
         mMockActivityManagerInternal = mock(ActivityManagerInternal.class);
diff --git a/services/tests/servicestests/src/com/android/server/pm/OWNERS b/services/tests/servicestests/src/com/android/server/pm/OWNERS
index d825dfd..e15b5f5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/pm/OWNERS
@@ -1 +1,3 @@
 include /services/core/java/com/android/server/pm/OWNERS
+
+per-file *Shortcut* = file:/core/java/android/content/pm/SHORTCUT_OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest12.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest12.java
new file mode 100644
index 0000000..b17085e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest12.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.pm;
+
+import android.app.appsearch.PackageIdentifier;
+import android.content.pm.AppSearchShortcutInfo;
+
+import java.util.Random;
+
+/**
+ * Tests for {@link android.app.appsearch.AppSearchManager} and relevant APIs in ShortcutManager.
+ *
+ atest -c com.android.server.pm.ShortcutManagerTest12
+ */
+public class ShortcutManagerTest12 extends BaseShortcutManagerTest {
+
+    public void testUpdateShortcutVisibility_updatesShortcutSchema() {
+
+        final byte[] cert = new byte[20];
+        new Random().nextBytes(cert);
+
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            mManager.updateShortcutVisibility(CALLING_PACKAGE_2, cert, true);
+            assertTrue(mMockAppSearchManager.mSchemasPackageAccessible.containsKey(
+                    AppSearchShortcutInfo.SCHEMA_TYPE));
+            assertTrue(mMockAppSearchManager.mSchemasPackageAccessible.get(
+                    AppSearchShortcutInfo.SCHEMA_TYPE).get(0).equals(
+                            new PackageIdentifier(CALLING_PACKAGE_2, cert)));
+        });
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
index ff43da6..ee0a16a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
@@ -86,6 +86,7 @@
     private TestData mBarUser0DelegateLastClassLoader;
 
     private TestData mSystemServerJar;
+    private TestData mSystemServerJarUpdatedContext;
     private TestData mSystemServerJarInvalid;
 
     private int mUser0;
@@ -113,6 +114,8 @@
 
         mSystemServerJar = new TestData("android", isa, mUser0, PATH_CLASS_LOADER_NAME);
         mSystemServerJarInvalid = new TestData("android", isa, mUser0, PATH_CLASS_LOADER_NAME);
+        mSystemServerJarUpdatedContext = new TestData("android", isa, mUser0,
+                DELEGATE_LAST_CLASS_LOADER_NAME);
 
         mDexManager = new DexManager(/*Context*/ null, mPM, /*PackageDexOptimizer*/ null,
                 mInstaller, mInstallLock);
@@ -522,6 +525,24 @@
     }
 
     @Test
+    public void testSystemServerOverwritesContext() {
+        // Record bar secondaries with the default PathClassLoader.
+        List<String> secondaries = mSystemServerJar.getSecondaryDexPaths();
+
+        notifyDexLoad(mSystemServerJar, secondaries, mUser0);
+        PackageUseInfo pui = getPackageUseInfo(mSystemServerJar);
+        assertSecondaryUse(mSystemServerJar, pui, secondaries, /*isUsedByOtherApps*/false, mUser0);
+
+        // Record bar secondaries again with a different class loader. This will change the context.
+        notifyDexLoad(mSystemServerJarUpdatedContext, secondaries, mUser0);
+
+        pui = getPackageUseInfo(mSystemServerJar);
+        // We expect that all the contexts to be updated according to the last notify.
+        assertSecondaryUse(mSystemServerJarUpdatedContext, pui, secondaries,
+                /*isUsedByOtherApps*/false, mUser0);
+    }
+
+    @Test
     public void testNotifyUnsupportedClassLoaderDoesNotChangeExisting() {
         List<String> secondaries = mBarUser0.getSecondaryDexPaths();
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/OWNERS b/services/tests/servicestests/src/com/android/server/pm/dex/OWNERS
new file mode 100644
index 0000000..66ef75d
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/dex/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
index adf4551..3450710 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
@@ -451,7 +451,7 @@
                 "PCL[new_context.dex]");
         assertTrue(record(fooSecondary1User0NewContext));
 
-        // Not check that the context was switch to variable.
+        // Now check that the context was switch to variable.
         TestData expectedContext = mFooSecondary1User0.updateClassLoaderContext(
                 PackageDexUsage.VARIABLE_CLASS_LOADER_CONTEXT);
 
@@ -461,6 +461,22 @@
     }
 
     @Test
+    public void testRecordClassLoaderContextOverwritten() {
+        // Record a secondary dex file.
+        assertTrue(record(mFooSecondary1User0));
+        // Now update its context.
+        TestData fooSecondary1User0NewContext = mFooSecondary1User0.updateClassLoaderContext(
+                "PCL[new_context.dex]", true);
+        assertTrue(record(fooSecondary1User0NewContext));
+
+        // Now check that the context was overwritten.
+        TestData expectedContext = mFooSecondary1User0.updateClassLoaderContext(
+                "PCL[new_context.dex]", true);
+
+        assertPackageDexUsage(null, expectedContext);
+    }
+
+    @Test
     public void testDexUsageClassLoaderContext() {
         final boolean isUsedByOtherApps = false;
         final int userId = 0;
@@ -642,8 +658,9 @@
 
     private boolean record(TestData testData) {
         return mPackageDexUsage.record(testData.mPackageName, testData.mDexFile,
-               testData.mOwnerUserId, testData.mLoaderIsa,
-               testData.mPrimaryOrSplit, testData.mUsedBy, testData.mClassLoaderContext);
+                testData.mOwnerUserId, testData.mLoaderIsa,
+                testData.mPrimaryOrSplit, testData.mUsedBy, testData.mClassLoaderContext,
+                testData.mOverwriteCLC);
     }
 
     private boolean record(PackageDexUsage packageDexUsage, TestData testData, Set<String> users) {
@@ -651,7 +668,8 @@
         for (String user : users) {
             result = result && packageDexUsage.record(testData.mPackageName, testData.mDexFile,
                     testData.mOwnerUserId, testData.mLoaderIsa,
-                    testData.mPrimaryOrSplit, user, testData.mClassLoaderContext);
+                    testData.mPrimaryOrSplit, user, testData.mClassLoaderContext,
+                    testData.mOverwriteCLC);
         }
         return result;
     }
@@ -682,15 +700,16 @@
         private final boolean mPrimaryOrSplit;
         private final String mUsedBy;
         private final String mClassLoaderContext;
+        private final boolean mOverwriteCLC;
 
         private TestData(String packageName, String dexFile, int ownerUserId,
                 String loaderIsa, boolean primaryOrSplit, String usedBy) {
             this(packageName, dexFile, ownerUserId, loaderIsa, primaryOrSplit,
-                    usedBy, "PCL[" + dexFile + "]");
+                    usedBy, "PCL[" + dexFile + "]", false);
         }
         private TestData(String packageName, String dexFile, int ownerUserId,
                 String loaderIsa, boolean primaryOrSplit, String usedBy,
-                String classLoaderContext) {
+                String classLoaderContext, boolean overwriteCLC) {
             mPackageName = packageName;
             mDexFile = dexFile;
             mOwnerUserId = ownerUserId;
@@ -698,16 +717,21 @@
             mPrimaryOrSplit = primaryOrSplit;
             mUsedBy = usedBy;
             mClassLoaderContext = classLoaderContext;
+            mOverwriteCLC = overwriteCLC;
         }
 
         private TestData updateClassLoaderContext(String newContext) {
+            return updateClassLoaderContext(newContext, mOverwriteCLC);
+        }
+
+        private TestData updateClassLoaderContext(String newContext, boolean overwriteCLC) {
             return new TestData(mPackageName, mDexFile, mOwnerUserId, mLoaderIsa,
-                    mPrimaryOrSplit, mUsedBy, newContext);
+                    mPrimaryOrSplit, mUsedBy, newContext, overwriteCLC);
         }
 
         private TestData updateUsedBy(String newUsedBy) {
             return new TestData(mPackageName, mDexFile, mOwnerUserId, mLoaderIsa,
-                mPrimaryOrSplit, newUsedBy, mClassLoaderContext);
+                mPrimaryOrSplit, newUsedBy, mClassLoaderContext, mOverwriteCLC);
         }
 
         private boolean isUsedByOtherApps() {
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java
index fb13d87..c2b3858 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java
@@ -17,10 +17,10 @@
 package com.android.server.pm.parsing;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 import android.apex.ApexInfo;
 import android.content.Context;
@@ -39,6 +39,7 @@
 import android.os.Bundle;
 import android.os.FileUtils;
 import android.platform.test.annotations.Presubmit;
+import android.util.Pair;
 import android.util.SparseIntArray;
 
 import androidx.test.InstrumentationRegistry;
@@ -50,12 +51,17 @@
 import com.android.server.pm.parsing.pkg.AndroidPackage;
 import com.android.server.pm.parsing.pkg.ParsedPackage;
 
+import com.google.common.truth.Expect;
+
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import java.io.File;
 import java.io.InputStream;
 import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.function.Function;
 
 /**
@@ -89,6 +95,8 @@
     private static final int PLATFORM_VERSION = 20;
     private static final int NEWER_VERSION = 30;
 
+    @Rule public final Expect expect = Expect.create();
+
     private void verifyComputeMinSdkVersion(int minSdkVersion, String minSdkCodename,
             boolean isPlatformReleased, int expectedMinSdk) {
         final String[] outError = new String[1];
@@ -553,36 +561,44 @@
 
     @Test
     public void testUsesSdk() throws Exception {
-        ParsedPackage pkg =
-                parsePackage("install_uses_sdk.apk_r0", R.raw.install_uses_sdk_r0, x -> x);
-        SparseIntArray minExtVers = pkg.getMinExtensionVersions();
+        ParsedPackage pkg;
+        SparseIntArray minExtVers;
+        pkg = parsePackage("install_uses_sdk.apk_r0", R.raw.install_uses_sdk_r0, x -> x);
+        minExtVers = pkg.getMinExtensionVersions();
         assertEquals(1, minExtVers.size());
-        assertEquals(0, minExtVers.get(10000, -1));
+        assertEquals(0, minExtVers.get(30, -1));
 
-        try {
-            parsePackage("install_uses_sdk.apk_r5", R.raw.install_uses_sdk_r5, x -> x);
-            fail("Expected parsing exception due to incompatible extension SDK version");
-        } catch (PackageParser.PackageParserException expected) {
-            assertEquals(PackageManager.INSTALL_FAILED_OLDER_SDK, expected.error);
-        }
-        try {
-            parsePackage("install_uses_sdk.apk_q0", R.raw.install_uses_sdk_q0, x -> x);
-            fail("Expected parsing exception due to non-existent extension SDK");
-        } catch (PackageParser.PackageParserException expected) {
-            assertEquals(PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, expected.error);
-        }
-        try {
-            parsePackage("install_uses_sdk.apk_r", R.raw.install_uses_sdk_r, x -> x);
-            fail("Expected parsing exception due to unspecified extension SDK version");
-        } catch (PackageParser.PackageParserException expected) {
-            assertEquals(PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, expected.error);
-        }
-        try {
-            parsePackage("install_uses_sdk.apk_0", R.raw.install_uses_sdk_0, x -> x);
-            fail("Expected parsing exception due to unspecified extension SDK");
-        } catch (PackageParser.PackageParserException expected) {
-            assertEquals(PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, expected.error);
-        }
+        pkg = parsePackage("install_uses_sdk.apk_r0_s0", R.raw.install_uses_sdk_r0_s0, x -> x);
+        minExtVers = pkg.getMinExtensionVersions();
+        assertEquals(2, minExtVers.size());
+        assertEquals(0, minExtVers.get(30, -1));
+        assertEquals(0, minExtVers.get(31, -1));
 
+        Map<Pair<String, Integer>, Integer> appToError = new HashMap<>();
+        appToError.put(Pair.create("install_uses_sdk.apk_r5", R.raw.install_uses_sdk_r5),
+                       PackageManager.INSTALL_FAILED_OLDER_SDK);
+        appToError.put(Pair.create("install_uses_sdk.apk_r0_s5", R.raw.install_uses_sdk_r0_s5),
+                       PackageManager.INSTALL_FAILED_OLDER_SDK);
+
+        appToError.put(Pair.create("install_uses_sdk.apk_q0", R.raw.install_uses_sdk_q0),
+                       PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED);
+        appToError.put(Pair.create("install_uses_sdk.apk_q0_r0", R.raw.install_uses_sdk_q0_r0),
+                       PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED);
+        appToError.put(Pair.create("install_uses_sdk.apk_r_none", R.raw.install_uses_sdk_r_none),
+                       PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED);
+        appToError.put(Pair.create("install_uses_sdk.apk_0", R.raw.install_uses_sdk_0),
+                       PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED);
+
+        for (Map.Entry<Pair<String, Integer>, Integer> entry : appToError.entrySet()) {
+            String filename = entry.getKey().first;
+            int resId = entry.getKey().second;
+            int result = entry.getValue();
+            try {
+                parsePackage(filename, resId, x -> x);
+                expect.withMessage("Expected parsing error %d from %s", result, filename).fail();
+            } catch (PackageParser.PackageParserException expected) {
+                expect.that(expected.error).isEqualTo(result);
+            }
+        }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/power/FaceDownDetectorTest.java b/services/tests/servicestests/src/com/android/server/power/FaceDownDetectorTest.java
new file mode 100644
index 0000000..ef20ee7
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/power/FaceDownDetectorTest.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorManager;
+import android.testing.TestableContext;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.server.display.TestUtils;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.lang.reflect.Constructor;
+import java.time.Duration;
+
+public class FaceDownDetectorTest {
+    @ClassRule
+    public static final TestableContext sContext = new TestableContext(
+            InstrumentationRegistry.getInstrumentation().getTargetContext(), null);
+
+    private final FaceDownDetector mFaceDownDetector =
+            new FaceDownDetector(this::onFlip);
+
+    @Mock private SensorManager mSensorManager;
+
+    private long mCurrentTime;
+    private int mOnFaceDownCalls = 0;
+    private int mOnFaceDownExitCalls = 0;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        sContext.addMockSystemService(SensorManager.class, mSensorManager);
+        mCurrentTime = 0;
+    }
+
+    @Test
+    public void faceDownFor2Seconds_triggersFaceDown() throws Exception {
+        mFaceDownDetector.systemReady(sContext);
+
+        // Face up
+        // Using 0.5 on x to simulate constant acceleration, such as a sloped surface.
+        mFaceDownDetector.onSensorChanged(createTestEvent(0.5f, 0.0f, 10.0f));
+
+        for (int i = 0; i < 200; i++) {
+            advanceTime(Duration.ofMillis(20));
+            mFaceDownDetector.onSensorChanged(createTestEvent(0.5f, 0.0f, -10.0f));
+        }
+
+        assertThat(mOnFaceDownCalls).isEqualTo(1);
+        assertThat(mOnFaceDownExitCalls).isEqualTo(0);
+    }
+
+    @Test
+    public void faceDownFor2Seconds_withMotion_DoesNotTriggerFaceDown() throws Exception {
+        mFaceDownDetector.systemReady(sContext);
+
+        // Face up
+        mFaceDownDetector.onSensorChanged(createTestEvent(0.5f, 0.0f, 10.0f));
+
+        for (int i = 0; i < 100; i++) {
+            advanceTime(Duration.ofMillis(20));
+            //Move along x direction
+            mFaceDownDetector.onSensorChanged(createTestEvent(0.5f * i, 0.0f, -10.0f));
+        }
+
+        assertThat(mOnFaceDownCalls).isEqualTo(0);
+        assertThat(mOnFaceDownExitCalls).isEqualTo(0);
+    }
+
+    @Test
+    public void faceDownForHalfSecond_DoesNotTriggerFaceDown() throws Exception {
+        mFaceDownDetector.systemReady(sContext);
+
+        // Face up
+        mFaceDownDetector.onSensorChanged(createTestEvent(0.5f, 0.0f, 10.0f));
+
+        for (int i = 0; i < 100; i++) {
+            advanceTime(Duration.ofMillis(5));
+            mFaceDownDetector.onSensorChanged(createTestEvent(0.5f, 0.0f, -10.0f));
+        }
+
+        assertThat(mOnFaceDownCalls).isEqualTo(0);
+        assertThat(mOnFaceDownExitCalls).isEqualTo(0);
+    }
+
+    @Test
+    public void faceDownFor2Seconds_followedByFaceUp_triggersFaceDownExit() throws Exception {
+        mFaceDownDetector.systemReady(sContext);
+
+        // Face up
+        // Using 0.5 on x to simulate constant acceleration, such as a sloped surface.
+        mFaceDownDetector.onSensorChanged(createTestEvent(0.5f, 0.0f, 10.0f));
+
+        // Trigger face down
+        for (int i = 0; i < 100; i++) {
+            advanceTime(Duration.ofMillis(20));
+            mFaceDownDetector.onSensorChanged(createTestEvent(0.5f, 0.0f, -10.0f));
+        }
+
+        // Phone flips
+        for (int i = 0; i < 10; i++) {
+            advanceTime(Duration.ofMillis(5));
+            mFaceDownDetector.onSensorChanged(createTestEvent(0.5f, 1.0f, 0.0f));
+        }
+
+        assertThat(mOnFaceDownCalls).isEqualTo(1);
+        assertThat(mOnFaceDownExitCalls).isEqualTo(1);
+    }
+
+    private void advanceTime(Duration duration) {
+        mCurrentTime += duration.toNanos();
+    }
+
+    /**
+     * Create a test event to replicate an accelerometer sensor event.
+     * @param x Acceleration along the x dimension.
+     * @param y Acceleration along the y dimension.
+     * @param gravity Acceleration along the Z dimension. Relates to
+     */
+    private SensorEvent createTestEvent(float x, float y, float gravity) throws Exception {
+        final Constructor<SensorEvent> constructor =
+                SensorEvent.class.getDeclaredConstructor(int.class);
+        constructor.setAccessible(true);
+        final SensorEvent event = constructor.newInstance(3);
+        event.sensor =
+                TestUtils.createSensor(Sensor.TYPE_ACCELEROMETER, Sensor.STRING_TYPE_ACCELEROMETER);
+        event.values[0] = x;
+        event.values[1] = y;
+        event.values[2] = gravity;
+        event.timestamp = mCurrentTime;
+        return event;
+    }
+
+    private void onFlip(boolean isFaceDown) {
+        if (isFaceDown) {
+            mOnFaceDownCalls++;
+        } else {
+            mOnFaceDownExitCalls++;
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/power/NotifierTest.java b/services/tests/servicestests/src/com/android/server/power/NotifierTest.java
index 1c2d8e8..5012ca9 100644
--- a/services/tests/servicestests/src/com/android/server/power/NotifierTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/NotifierTest.java
@@ -209,7 +209,8 @@
     private final PowerManagerService.Injector mInjector = new PowerManagerService.Injector() {
         @Override
         Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
-                SuspendBlocker suspendBlocker, WindowManagerPolicy policy) {
+                SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
+                FaceDownDetector faceDownDetector) {
             return mNotifierMock;
         }
 
@@ -296,6 +297,7 @@
                 IBatteryStats.Stub.asInterface(ServiceManager.getService(
                         BatteryStats.SERVICE_NAME)),
                 mInjector.createSuspendBlocker(mService, "testBlocker"),
+                null,
                 null);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index 592eea1..ea27331 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -98,9 +98,11 @@
 import org.mockito.ArgumentMatcher;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * Tests for {@link com.android.server.power.PowerManagerService}.
@@ -211,7 +213,8 @@
         mService = new PowerManagerService(mContextSpy, new Injector() {
             @Override
             Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
-                    SuspendBlocker suspendBlocker, WindowManagerPolicy policy) {
+                    SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
+                    FaceDownDetector faceDownDetector) {
                 return mNotifierMock;
             }
 
@@ -401,30 +404,33 @@
     @Test
     public void testGetDesiredScreenPolicy_WithVR() throws Exception {
         createService();
+        mService.systemReady(null);
         // Brighten up the screen
-        mService.setWakefulnessLocked(WAKEFULNESS_AWAKE, PowerManager.WAKE_REASON_UNKNOWN, 0);
-        assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
+        mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_AWAKE, 0, 0, 0, 0,
+                null, null);
+        assertThat(mService.getDesiredScreenPolicyLocked(Display.DEFAULT_DISPLAY)).isEqualTo(
                 DisplayPowerRequest.POLICY_BRIGHT);
 
         // Move to VR
         mService.setVrModeEnabled(true);
-        assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
+        assertThat(mService.getDesiredScreenPolicyLocked(Display.DEFAULT_DISPLAY)).isEqualTo(
                 DisplayPowerRequest.POLICY_VR);
 
         // Then take a nap
-        mService.setWakefulnessLocked(WAKEFULNESS_ASLEEP, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,
-                0);
-        assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
+        mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_ASLEEP, 0, 0, 0, 0,
+                null, null);
+        assertThat(mService.getDesiredScreenPolicyLocked(Display.DEFAULT_DISPLAY)).isEqualTo(
                 DisplayPowerRequest.POLICY_OFF);
 
         // Wake up to VR
-        mService.setWakefulnessLocked(WAKEFULNESS_AWAKE, PowerManager.WAKE_REASON_UNKNOWN, 0);
-        assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
+        mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_AWAKE, 0, 0, 0, 0,
+                null, null);
+        assertThat(mService.getDesiredScreenPolicyLocked(Display.DEFAULT_DISPLAY)).isEqualTo(
                 DisplayPowerRequest.POLICY_VR);
 
         // And back to normal
         mService.setVrModeEnabled(false);
-        assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
+        assertThat(mService.getDesiredScreenPolicyLocked(Display.DEFAULT_DISPLAY)).isEqualTo(
                 DisplayPowerRequest.POLICY_BRIGHT);
     }
 
@@ -675,8 +681,9 @@
     }
 
     @Test
-    public void testForceSuspend_forceSuspendFailurePropogated() {
+    public void testForceSuspend_forceSuspendFailurePropagated() throws Exception {
         createService();
+        startSystem();
         when(mNativeWrapperMock.nativeForceSuspend()).thenReturn(false);
         assertThat(mService.getBinderServiceInstance().forceSuspend()).isFalse();
     }
@@ -840,7 +847,7 @@
         createService();
         startSystem();
 
-        assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
+        assertThat(mService.getDesiredScreenPolicyLocked(Display.DEFAULT_DISPLAY)).isEqualTo(
                 DisplayPowerRequest.POLICY_BRIGHT);
     }
 
@@ -859,11 +866,8 @@
     public void testQuiescentBoot_DesiredScreenPolicyShouldBeOff() throws Exception {
         when(mSystemPropertiesMock.get(eq(SYSTEM_PROPERTY_QUIESCENT), any())).thenReturn("1");
         createService();
-        assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
-                DisplayPowerRequest.POLICY_OFF);
-
         startSystem();
-        assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
+        assertThat(mService.getDesiredScreenPolicyLocked(Display.DEFAULT_DISPLAY)).isEqualTo(
                 DisplayPowerRequest.POLICY_OFF);
     }
 
@@ -873,7 +877,7 @@
         createService();
         startSystem();
         forceAwake();
-        assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
+        assertThat(mService.getDesiredScreenPolicyLocked(Display.DEFAULT_DISPLAY)).isEqualTo(
                 DisplayPowerRequest.POLICY_BRIGHT);
     }
 
@@ -889,7 +893,7 @@
 
         mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
         assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
-        assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
+        assertThat(mService.getDesiredScreenPolicyLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
                 DisplayPowerRequest.POLICY_BRIGHT);
     }
 
@@ -1163,6 +1167,87 @@
     }
 
     @Test
+    public void testMultiDisplay_wakefulnessUpdates() throws Exception {
+        final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1;
+        final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener =
+                new AtomicReference<>();
+        doAnswer((Answer<Void>) invocation -> {
+            listener.set(invocation.getArgument(0));
+            return null;
+        }).when(mDisplayManagerInternalMock).registerDisplayGroupListener(any());
+
+        createService();
+        startSystem();
+        listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId);
+
+        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+
+        mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_ASLEEP, 0, 0, 0, 0,
+                null, null);
+        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+
+        mService.setWakefulnessLocked(nonDefaultDisplayGroupId, WAKEFULNESS_ASLEEP, 0, 0, 0, 0,
+                null, null);
+        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+
+        mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_AWAKE, 0, 0, 0, 0,
+                null, null);
+        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+    }
+
+    @Test
+    public void testMultiDisplay_addDisplayGroup_preservesWakefulness() throws Exception {
+        final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1;
+        final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener =
+                new AtomicReference<>();
+        doAnswer((Answer<Void>) invocation -> {
+            listener.set(invocation.getArgument(0));
+            return null;
+        }).when(mDisplayManagerInternalMock).registerDisplayGroupListener(any());
+
+        createService();
+        startSystem();
+
+        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+
+        mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_ASLEEP, 0, 0, 0, 0,
+                null, null);
+        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+
+        listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId);
+
+        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+    }
+
+    @Test
+    public void testMultiDisplay_removeDisplayGroup_updatesWakefulness() throws Exception {
+        final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1;
+        final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener =
+                new AtomicReference<>();
+        doAnswer((Answer<Void>) invocation -> {
+            listener.set(invocation.getArgument(0));
+            return null;
+        }).when(mDisplayManagerInternalMock).registerDisplayGroupListener(any());
+
+        createService();
+        startSystem();
+        listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId);
+
+        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+
+        mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_ASLEEP, 0, 0, 0, 0,
+                null, null);
+        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+
+        listener.get().onDisplayGroupRemoved(nonDefaultDisplayGroupId);
+        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+
+        mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_AWAKE, 0, 0, 0, 0,
+                null, null);
+        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+    }
+
+    @Test
     public void testGetFullPowerSavePolicy_returnsStateMachineResult() {
         createService();
         mService.systemReady(null);
diff --git a/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java
index ddbe81c..26b34fd 100644
--- a/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java
@@ -318,7 +318,8 @@
         assertTrue(pssProto.energyMeasurement.length == ENERGY_METER_COUNT);
         for (int i = 0; i < pssProto.energyMeasurement.length; i++) {
             assertTrue(pssProto.energyMeasurement[i].id == i);
-            assertTrue(pssProto.energyMeasurement[i].timestampMs == i);
+            assertTrue(pssProto.energyMeasurement[i].timestampMs ==
+                    i + mPowerStatsLogger.getStartWallTime());
             assertTrue(pssProto.energyMeasurement[i].durationMs == i);
             assertTrue(pssProto.energyMeasurement[i].energyUws == i);
         }
@@ -359,7 +360,8 @@
         assertTrue(pssProto.energyConsumerResult.length == ENERGY_CONSUMER_COUNT);
         for (int i = 0; i < pssProto.energyConsumerResult.length; i++) {
             assertTrue(pssProto.energyConsumerResult[i].id == i);
-            assertTrue(pssProto.energyConsumerResult[i].timestampMs == i);
+            assertTrue(pssProto.energyConsumerResult[i].timestampMs ==
+                    i + mPowerStatsLogger.getStartWallTime());
             assertTrue(pssProto.energyConsumerResult[i].energyUws == i);
             assertTrue(pssProto.energyConsumerResult[i].attribution.length
                     == ENERGY_CONSUMER_ATTRIBUTION_COUNT);
@@ -420,7 +422,8 @@
                 assertTrue(stateResidency.id == j);
                 assertTrue(stateResidency.totalTimeInStateMs == j);
                 assertTrue(stateResidency.totalStateEntryCount == j);
-                assertTrue(stateResidency.lastEntryTimestampMs == j);
+                assertTrue(stateResidency.lastEntryTimestampMs ==
+                        j + mPowerStatsLogger.getStartWallTime());
             }
         }
     }
diff --git a/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS
index 816bc6b..33385af 100644
--- a/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS
@@ -1 +1 @@
-include /core/java/android/media/soundtrigger/OWNERS
+include /media/aidl/android/media/soundtrigger_middleware/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
index 5574836..5f86d28 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -287,8 +287,7 @@
     }
 
     private static ExternalTimeSuggestion createExternalTimeSuggestion() {
-        TimestampedValue<Long> timeValue = new TimestampedValue<>(100L, 1_000_000L);
-        return new ExternalTimeSuggestion(timeValue);
+        return new ExternalTimeSuggestion(100L, 1_000_000L);
     }
 
     private static class StubbedTimeDetectorStrategy implements TimeDetectorStrategy {
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
index daa1b25..f7a498b 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -1483,11 +1483,8 @@
          * reference time.
          */
         ExternalTimeSuggestion generateExternalTimeSuggestion(Instant suggestedTime) {
-            TimestampedValue<Long> utcTime =
-                    new TimestampedValue<>(
-                            mFakeEnvironment.peekElapsedRealtimeMillis(),
+            return new ExternalTimeSuggestion(mFakeEnvironment.peekElapsedRealtimeMillis(),
                             suggestedTime.toEpochMilli());
-            return new ExternalTimeSuggestion(utcTime);
         }
 
         /**
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java
index 682a80c..5d27552 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java
@@ -46,8 +46,8 @@
     public void test_unrestricted() {
         ConfigurationInternal baseConfig = new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
                 .setUserConfigAllowed(true)
-                .setAutoDetectionSupported(true)
-                .setGeoDetectionSupported(true)
+                .setAutoDetectionFeatureSupported(true)
+                .setGeoDetectionFeatureSupported(true)
                 .setAutoDetectionEnabled(true)
                 .setLocationEnabled(true)
                 .setGeoDetectionEnabled(true)
@@ -108,8 +108,8 @@
     public void test_restricted() {
         ConfigurationInternal baseConfig = new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
                 .setUserConfigAllowed(false)
-                .setAutoDetectionSupported(true)
-                .setGeoDetectionSupported(true)
+                .setAutoDetectionFeatureSupported(true)
+                .setGeoDetectionFeatureSupported(true)
                 .setAutoDetectionEnabled(true)
                 .setLocationEnabled(true)
                 .setGeoDetectionEnabled(true)
@@ -170,8 +170,8 @@
     public void test_autoDetectNotSupported() {
         ConfigurationInternal baseConfig = new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
                 .setUserConfigAllowed(true)
-                .setAutoDetectionSupported(false)
-                .setGeoDetectionSupported(false)
+                .setAutoDetectionFeatureSupported(false)
+                .setGeoDetectionFeatureSupported(false)
                 .setAutoDetectionEnabled(true)
                 .setLocationEnabled(true)
                 .setGeoDetectionEnabled(true)
@@ -232,8 +232,8 @@
     public void test_geoDetectNotSupported() {
         ConfigurationInternal baseConfig = new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
                 .setUserConfigAllowed(true)
-                .setAutoDetectionSupported(true)
-                .setGeoDetectionSupported(false)
+                .setAutoDetectionFeatureSupported(true)
+                .setGeoDetectionFeatureSupported(false)
                 .setAutoDetectionEnabled(true)
                 .setLocationEnabled(true)
                 .setGeoDetectionEnabled(true)
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
index d2452ea..14e0bbd 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
@@ -364,8 +364,8 @@
         // the tests.
         final boolean geoDetectionEnabled = autoDetectionEnabled;
         return new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
-                .setAutoDetectionSupported(true)
-                .setGeoDetectionSupported(true)
+                .setAutoDetectionFeatureSupported(true)
+                .setGeoDetectionFeatureSupported(true)
                 .setUserConfigAllowed(true)
                 .setAutoDetectionEnabled(autoDetectionEnabled)
                 .setLocationEnabled(geoDetectionEnabled)
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
index c8dba5f..f1f8b2f 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
@@ -90,8 +90,8 @@
     private static final ConfigurationInternal CONFIG_INT_USER_RESTRICTED_AUTO_DISABLED =
             new ConfigurationInternal.Builder(USER_ID)
                     .setUserConfigAllowed(false)
-                    .setAutoDetectionSupported(true)
-                    .setGeoDetectionSupported(true)
+                    .setAutoDetectionFeatureSupported(true)
+                    .setGeoDetectionFeatureSupported(true)
                     .setAutoDetectionEnabled(false)
                     .setLocationEnabled(true)
                     .setGeoDetectionEnabled(false)
@@ -100,8 +100,8 @@
     private static final ConfigurationInternal CONFIG_INT_USER_RESTRICTED_AUTO_ENABLED =
             new ConfigurationInternal.Builder(USER_ID)
                     .setUserConfigAllowed(false)
-                    .setAutoDetectionSupported(true)
-                    .setGeoDetectionSupported(true)
+                    .setAutoDetectionFeatureSupported(true)
+                    .setGeoDetectionFeatureSupported(true)
                     .setAutoDetectionEnabled(true)
                     .setLocationEnabled(true)
                     .setGeoDetectionEnabled(true)
@@ -110,8 +110,8 @@
     private static final ConfigurationInternal CONFIG_INT_AUTO_DETECT_NOT_SUPPORTED =
             new ConfigurationInternal.Builder(USER_ID)
                     .setUserConfigAllowed(true)
-                    .setAutoDetectionSupported(false)
-                    .setGeoDetectionSupported(false)
+                    .setAutoDetectionFeatureSupported(false)
+                    .setGeoDetectionFeatureSupported(false)
                     .setAutoDetectionEnabled(false)
                     .setLocationEnabled(true)
                     .setGeoDetectionEnabled(false)
@@ -120,8 +120,8 @@
     private static final ConfigurationInternal CONFIG_INT_AUTO_SUPPORTED_GEO_NOT_SUPPORTED =
             new ConfigurationInternal.Builder(USER_ID)
                     .setUserConfigAllowed(true)
-                    .setAutoDetectionSupported(true)
-                    .setGeoDetectionSupported(false)
+                    .setAutoDetectionFeatureSupported(true)
+                    .setGeoDetectionFeatureSupported(false)
                     .setAutoDetectionEnabled(true)
                     .setLocationEnabled(true)
                     .setGeoDetectionEnabled(true)
@@ -130,8 +130,8 @@
     private static final ConfigurationInternal CONFIG_INT_AUTO_DISABLED_GEO_DISABLED =
             new ConfigurationInternal.Builder(USER_ID)
                     .setUserConfigAllowed(true)
-                    .setAutoDetectionSupported(true)
-                    .setGeoDetectionSupported(true)
+                    .setAutoDetectionFeatureSupported(true)
+                    .setGeoDetectionFeatureSupported(true)
                     .setAutoDetectionEnabled(false)
                     .setLocationEnabled(true)
                     .setGeoDetectionEnabled(false)
@@ -139,8 +139,8 @@
 
     private static final ConfigurationInternal CONFIG_INT_AUTO_ENABLED_GEO_DISABLED =
             new ConfigurationInternal.Builder(USER_ID)
-                    .setAutoDetectionSupported(true)
-                    .setGeoDetectionSupported(true)
+                    .setAutoDetectionFeatureSupported(true)
+                    .setGeoDetectionFeatureSupported(true)
                     .setUserConfigAllowed(true)
                     .setAutoDetectionEnabled(true)
                     .setLocationEnabled(true)
@@ -149,8 +149,8 @@
 
     private static final ConfigurationInternal CONFIG_INT_AUTO_ENABLED_GEO_ENABLED =
             new ConfigurationInternal.Builder(USER_ID)
-                    .setAutoDetectionSupported(true)
-                    .setGeoDetectionSupported(true)
+                    .setAutoDetectionFeatureSupported(true)
+                    .setGeoDetectionFeatureSupported(true)
                     .setUserConfigAllowed(true)
                     .setAutoDetectionEnabled(true)
                     .setLocationEnabled(true)
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestSupport.java b/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestSupport.java
index d319488..8280cdc 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestSupport.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestSupport.java
@@ -44,8 +44,8 @@
             @UserIdInt int userId, boolean geoDetectionEnabled) {
         return new ConfigurationInternal.Builder(userId)
                 .setUserConfigAllowed(true)
-                .setAutoDetectionSupported(true)
-                .setGeoDetectionSupported(true)
+                .setAutoDetectionFeatureSupported(true)
+                .setGeoDetectionFeatureSupported(true)
                 .setAutoDetectionEnabled(true)
                 .setLocationEnabled(true)
                 .setGeoDetectionEnabled(geoDetectionEnabled)
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 11fb002..624c3de 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -144,6 +144,9 @@
     private static final long RARE_THRESHOLD = 48 * HOUR_MS;
     private static final long RESTRICTED_THRESHOLD = 96 * HOUR_MS;
 
+    private static final int ASSERT_RETRY_ATTEMPTS = 20;
+    private static final int ASSERT_RETRY_DELAY_MILLISECONDS = 500;
+
     /** Mock variable used in {@link MyInjector#isPackageInstalled(String, int, int)} */
     private static boolean isPackageInstalled = true;
 
@@ -589,16 +592,37 @@
                 mInjector.mElapsedRealtime);
     }
 
-    private void assertBucket(int bucket) {
+    private void assertBucket(int bucket) throws InterruptedException {
         assertBucket(bucket, PACKAGE_1);
     }
 
-    private void assertBucket(int bucket, String pkg) {
+    private void assertBucket(int bucket, String pkg) throws InterruptedException {
+        int retries = 0;
+        do {
+            if (bucket == getStandbyBucket(mController, pkg)) {
+                // Success
+                return;
+            }
+            Thread.sleep(ASSERT_RETRY_DELAY_MILLISECONDS);
+            retries++;
+        } while(retries < ASSERT_RETRY_ATTEMPTS);
+        // try one last time
         assertEquals(bucket, getStandbyBucket(mController, pkg));
     }
 
-    private void assertNotBucket(int bucket) {
-        assertNotEquals(bucket, getStandbyBucket(mController, PACKAGE_1));
+    private void assertNotBucket(int bucket) throws InterruptedException {
+        final String pkg = PACKAGE_1;
+        int retries = 0;
+        do {
+            if (bucket != getStandbyBucket(mController, pkg)) {
+                // Success
+                return;
+            }
+            Thread.sleep(ASSERT_RETRY_DELAY_MILLISECONDS);
+            retries++;
+        } while(retries < ASSERT_RETRY_ATTEMPTS);
+        // try one last time
+        assertNotEquals(bucket, getStandbyBucket(mController, pkg));
     }
 
     @Test
@@ -996,7 +1020,7 @@
      * a low bucket after the RESTRICTED timeout.
      */
     @Test
-    public void testRestrictedTimeoutOverridesRestoredLowBucketPrediction() {
+    public void testRestrictedTimeoutOverridesRestoredLowBucketPrediction() throws Exception {
         reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
         assertBucket(STANDBY_BUCKET_ACTIVE);
 
@@ -1032,7 +1056,7 @@
      * a low bucket after the RESTRICTED timeout.
      */
     @Test
-    public void testRestrictedTimeoutOverridesPredictionLowBucket() {
+    public void testRestrictedTimeoutOverridesPredictionLowBucket() throws Exception {
         reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
 
         // Not long enough to time out into RESTRICTED.
@@ -1055,7 +1079,7 @@
     }
 
     @Test
-    public void testRestrictedBucketDisabled() {
+    public void testRestrictedBucketDisabled() throws Exception {
         mInjector.mIsRestrictedBucketEnabled = false;
         // Get the controller to read the new value. Capturing the ContentObserver isn't possible
         // at the moment.
@@ -1080,7 +1104,7 @@
     }
 
     @Test
-    public void testRestrictedBucket_EnabledToDisabled() {
+    public void testRestrictedBucket_EnabledToDisabled() throws Exception {
         reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
         mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD;
         mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
@@ -1097,7 +1121,7 @@
     }
 
     @Test
-    public void testPredictionRaiseFromRestrictedTimeout_highBucket() {
+    public void testPredictionRaiseFromRestrictedTimeout_highBucket() throws Exception {
         reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
 
         // Way past all timeouts. App times out into RESTRICTED bucket.
@@ -1114,7 +1138,7 @@
     }
 
     @Test
-    public void testPredictionRaiseFromRestrictedTimeout_lowBucket() {
+    public void testPredictionRaiseFromRestrictedTimeout_lowBucket() throws Exception {
         reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
 
         // Way past all timeouts. App times out into RESTRICTED bucket.
@@ -1366,7 +1390,7 @@
     }
 
     @Test
-    public void testAddActiveDeviceAdmin() {
+    public void testAddActiveDeviceAdmin() throws Exception {
         assertActiveAdmins(USER_ID, (String[]) null);
         assertActiveAdmins(USER_ID2, (String[]) null);
 
@@ -1402,7 +1426,7 @@
     }
 
     @Test
-    public void isActiveDeviceAdmin() {
+    public void isActiveDeviceAdmin() throws Exception {
         assertActiveAdmins(USER_ID, (String[]) null);
         assertActiveAdmins(USER_ID2, (String[]) null);
 
@@ -1488,7 +1512,7 @@
     }
 
     @Test
-    public void testAppUpdateOnRestrictedBucketStatus() {
+    public void testAppUpdateOnRestrictedBucketStatus() throws Exception {
         // Updates shouldn't change bucket if the app timed out.
         // Way past all timeouts. App times out into RESTRICTED bucket.
         reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
@@ -1563,7 +1587,7 @@
     }
 
     @Test
-    public void testSystemHeadlessAppElevated() {
+    public void testSystemHeadlessAppElevated() throws Exception {
         reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
         reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime,
                 PACKAGE_SYSTEM_HEADFULL);
@@ -1589,7 +1613,7 @@
     }
 
     @Test
-    public void testWellbeingAppElevated() {
+    public void testWellbeingAppElevated() throws Exception {
         reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_WELLBEING);
         assertBucket(STANDBY_BUCKET_ACTIVE, PACKAGE_WELLBEING);
         reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
diff --git a/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java b/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java
index b40d59c..57e95d7 100644
--- a/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java
@@ -22,6 +22,7 @@
 
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.LongSparseArray;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
@@ -619,6 +620,129 @@
     }
 
     @Test
+    public void testWatchedLongSparseArray() {
+        final String name = "WatchedLongSparseArray";
+        WatchableTester tester;
+
+        // Create a few leaves
+        Leaf leafA = new Leaf();
+        Leaf leafB = new Leaf();
+        Leaf leafC = new Leaf();
+        Leaf leafD = new Leaf();
+
+        // Test WatchedLongSparseArray
+        WatchedLongSparseArray<Leaf> array = new WatchedLongSparseArray<>();
+        array.put(INDEX_A, leafA);
+        array.put(INDEX_B, leafB);
+        tester = new WatchableTester(array, name);
+        tester.verify(0, "Initial array - no registration");
+        leafA.tick();
+        tester.verify(0, "Updates with no registration");
+        tester.register();
+        tester.verify(0, "Updates with no registration");
+        leafA.tick();
+        tester.verify(1, "Updates with registration");
+        leafB.tick();
+        tester.verify(2, "Updates with registration");
+        array.remove(INDEX_B);
+        tester.verify(3, "Removed b");
+        leafB.tick();
+        tester.verify(3, "Updates with b not watched");
+        array.put(INDEX_B, leafB);
+        array.put(INDEX_C, leafB);
+        tester.verify(5, "Added b twice");
+        leafB.tick();
+        tester.verify(6, "Changed b - single notification");
+        array.remove(INDEX_C);
+        tester.verify(7, "Removed first b");
+        leafB.tick();
+        tester.verify(8, "Changed b - single notification");
+        array.remove(INDEX_B);
+        tester.verify(9, "Removed second b");
+        leafB.tick();
+        tester.verify(9, "Updated leafB - no change");
+        array.clear();
+        tester.verify(10, "Cleared array");
+        leafB.tick();
+        tester.verify(10, "Change to b not in array");
+
+        // Special methods
+        array.put(INDEX_A, leafA);
+        array.put(INDEX_B, leafB);
+        array.put(INDEX_C, leafC);
+        tester.verify(13, "Added c");
+        leafC.tick();
+        tester.verify(14, "Ticked c");
+        array.setValueAt(array.indexOfKey(INDEX_C), leafD);
+        tester.verify(15, "Replaced c with d");
+        leafC.tick();
+        tester.verify(15, "Ticked c (c not registered)");
+        leafD.tick();
+        tester.verify(16, "Ticked d and c (c not registered)");
+        array.append(INDEX_D, leafC);
+        tester.verify(17, "Append c");
+        leafC.tick();
+        leafD.tick();
+        tester.verify(19, "Ticked d and c");
+        assertEquals("Verify four elements", 4, array.size());
+        // Figure out which elements are at which indices.
+        Leaf[] x = new Leaf[4];
+        for (int i = 0; i < 4; i++) {
+            x[i] = array.valueAt(i);
+        }
+        array.removeAt(1);
+        tester.verify(20, "Removed one element");
+        x[1].tick();
+        tester.verify(20, "Ticked one removed element");
+        x[2].tick();
+        tester.verify(21, "Ticked one remaining element");
+
+        // Snapshot
+        {
+            final WatchedLongSparseArray<Leaf> arraySnap = array.snapshot();
+            tester.verify(21, "Generate snapshot (no changes)");
+            // Verify that the snapshot is a proper copy of the source.
+            assertEquals(name + " snap same size",
+                         array.size(), arraySnap.size());
+            for (int i = 0; i < array.size(); i++) {
+                for (int j = 0; j < arraySnap.size(); j++) {
+                    assertTrue(name + " elements differ",
+                               array.valueAt(i) != arraySnap.valueAt(j));
+                }
+                assertTrue(name + " element copy",
+                           array.valueAt(i).equals(arraySnap.valueAt(i)));
+            }
+            leafD.tick();
+            tester.verify(22, "Tick after snapshot");
+            // Verify that the array snapshot is sealed
+            verifySealed(name, ()->arraySnap.put(INDEX_A, leafB));
+            assertTrue(!array.isSealed());
+            assertTrue(arraySnap.isSealed());
+        }
+        // Recreate the snapshot since the test corrupted it.
+        {
+            final WatchedLongSparseArray<Leaf> arraySnap = array.snapshot();
+            // Verify that elements are also snapshots
+            final Leaf arraySnapElement = arraySnap.valueAt(0);
+            verifySealed("ArraySnapshotElement", ()->arraySnapElement.tick());
+        }
+        // Verify copy-in/out
+        {
+            final String msg = name + " copy-in/out";
+            LongSparseArray<Leaf> base = new LongSparseArray<>();
+            array.copyTo(base);
+            WatchedLongSparseArray<Leaf> copy = new WatchedLongSparseArray<>();
+            copy.copyFrom(base);
+            final int end = array.size();
+            assertTrue(msg + " size mismatch " + end + " " + copy.size(), end == copy.size());
+            for (int i = 0; i < end; i++) {
+                final long key = array.keyAt(i);
+                assertTrue(msg, array.get(i) == copy.get(i));
+            }
+        }
+    }
+
+    @Test
     public void testWatchedSparseBooleanArray() {
         final String name = "WatchedSparseBooleanArray";
         WatchableTester tester;
@@ -733,4 +857,43 @@
             }
         }
     }
+
+    @Test
+    public void testNestedArrays() {
+        final String name = "NestedArrays";
+        WatchableTester tester;
+
+        // Create a few leaves
+        Leaf leafA = new Leaf();
+        Leaf leafB = new Leaf();
+        Leaf leafC = new Leaf();
+        Leaf leafD = new Leaf();
+
+        // Test nested arrays.
+        WatchedLongSparseArray<Leaf> lsaA = new WatchedLongSparseArray<>();
+        lsaA.put(2, leafA);
+        WatchedLongSparseArray<Leaf> lsaB = new WatchedLongSparseArray<>();
+        lsaB.put(4, leafB);
+        WatchedLongSparseArray<Leaf> lsaC = new WatchedLongSparseArray<>();
+        lsaC.put(6, leafC);
+
+        WatchedArrayMap<String, WatchedLongSparseArray<Leaf>> array =
+                new WatchedArrayMap<>();
+        array.put("A", lsaA);
+        array.put("B", lsaB);
+
+        // Test WatchedSparseIntArray
+        tester = new WatchableTester(array, name);
+        tester.verify(0, "Initial array - no registration");
+        tester.register();
+        tester.verify(0, "Initial array - post registration");
+        leafA.tick();
+        tester.verify(1, "tick grand-leaf");
+        lsaA.put(2, leafD);
+        tester.verify(2, "replace leafA");
+        leafA.tick();
+        tester.verify(2, "tick unregistered leafA");
+        leafD.tick();
+        tester.verify(3, "tick leafD");
+    }
 }
diff --git a/services/tests/servicestests/test-apps/ConnTestApp/Android.bp b/services/tests/servicestests/test-apps/ConnTestApp/Android.bp
index 13e6644..0731e2c 100644
--- a/services/tests/servicestests/test-apps/ConnTestApp/Android.bp
+++ b/services/tests/servicestests/test-apps/ConnTestApp/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "ConnTestApp",
 
diff --git a/services/tests/servicestests/test-apps/JobTestApp/Android.bp b/services/tests/servicestests/test-apps/JobTestApp/Android.bp
index b29e187..6458bcd 100644
--- a/services/tests/servicestests/test-apps/JobTestApp/Android.bp
+++ b/services/tests/servicestests/test-apps/JobTestApp/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "JobTestApp",
 
diff --git a/services/tests/servicestests/test-apps/PackageParserApp/Android.bp b/services/tests/servicestests/test-apps/PackageParserApp/Android.bp
index f69dfe9..b11c85c0 100644
--- a/services/tests/servicestests/test-apps/PackageParserApp/Android.bp
+++ b/services/tests/servicestests/test-apps/PackageParserApp/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "PackageParserTestApp1",
     sdk_version: "current",
diff --git a/services/tests/servicestests/test-apps/SimpleServiceTestApp/Android.bp b/services/tests/servicestests/test-apps/SimpleServiceTestApp/Android.bp
index 5cbd39c..50b89d4 100644
--- a/services/tests/servicestests/test-apps/SimpleServiceTestApp/Android.bp
+++ b/services/tests/servicestests/test-apps/SimpleServiceTestApp/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "SimpleServiceTestApp",
 
diff --git a/services/tests/servicestests/test-apps/SuspendTestApp/Android.bp b/services/tests/servicestests/test-apps/SuspendTestApp/Android.bp
index 7257275..5e77498 100644
--- a/services/tests/servicestests/test-apps/SuspendTestApp/Android.bp
+++ b/services/tests/servicestests/test-apps/SuspendTestApp/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "SuspendTestApp",
 
diff --git a/services/tests/shortcutmanagerutils/Android.bp b/services/tests/shortcutmanagerutils/Android.bp
index 35ca354..deabb6c 100644
--- a/services/tests/shortcutmanagerutils/Android.bp
+++ b/services/tests/shortcutmanagerutils/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library {
     name: "ShortcutManagerTestUtils",
 
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 1dd4212..1ba414e 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -2,6 +2,15 @@
 // Build FrameworksUiServicesTests package
 //########################################################################
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworksUiServicesTests",
 
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
index 80a046a..9ac755f 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
@@ -17,6 +17,8 @@
 
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ALERTING;
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_CONVERSATIONS;
+import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ONGOING;
+import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_SILENT;
 
 import static com.android.server.notification.NotificationManagerService.NotificationListeners.TAG_REQUESTED_LISTENERS;
 
@@ -205,6 +207,52 @@
     }
 
     @Test
+    public void testEnsureFilters_newServiceWithMetadata_onlyOneListed() {
+        ServiceInfo si = new ServiceInfo();
+        si.packageName = "new";
+        si.name = "comp";
+        si.metaData = new Bundle();
+        si.metaData.putInt(NotificationListenerService.META_DATA_DEFAULT_FILTER_TYPES, 2);
+
+        mListeners.ensureFilters(si, 0);
+
+        assertThat(mListeners.getNotificationListenerFilter(
+                Pair.create(si.getComponentName(), 0)).getTypes())
+                .isEqualTo(FLAG_FILTER_TYPE_ALERTING);
+    }
+
+    @Test
+    public void testEnsureFilters_newServiceWithMetadata_disabledTypes() {
+        ServiceInfo si = new ServiceInfo();
+        si.packageName = "new";
+        si.name = "comp";
+        si.metaData = new Bundle();
+        si.metaData.putString(NotificationListenerService.META_DATA_DISABLED_FILTER_TYPES, "1,2");
+
+        mListeners.ensureFilters(si, 0);
+
+        assertThat(mListeners.getNotificationListenerFilter(
+                Pair.create(si.getComponentName(), 0)).getTypes())
+                .isEqualTo(FLAG_FILTER_TYPE_SILENT | FLAG_FILTER_TYPE_ONGOING);
+    }
+
+    @Test
+    public void testEnsureFilters_newServiceWithMetadata_metaDataDisagrees() {
+        ServiceInfo si = new ServiceInfo();
+        si.packageName = "new";
+        si.name = "comp";
+        si.metaData = new Bundle();
+        si.metaData.putString(NotificationListenerService.META_DATA_DEFAULT_FILTER_TYPES, "1,2");
+        si.metaData.putInt(NotificationListenerService.META_DATA_DISABLED_FILTER_TYPES, 1);
+
+        mListeners.ensureFilters(si, 0);
+
+        assertThat(mListeners.getNotificationListenerFilter(
+                Pair.create(si.getComponentName(), 0)).getTypes())
+                .isEqualTo(FLAG_FILTER_TYPE_ALERTING);
+    }
+
+    @Test
     public void testEnsureFilters_newServiceWithEmptyMetadata() {
         ServiceInfo si = new ServiceInfo();
         si.packageName = "new";
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index a640509..cebdbbe 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -3671,8 +3671,8 @@
         mService.addNotification(r);
 
         final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
-        mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getSbn().getTag(),
-                r.getSbn().getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
+        mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getUserId(),
+                r.getKey(), NotificationStats.DISMISSAL_AOD,
                 NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv);
         waitForIdle();
 
@@ -3694,8 +3694,8 @@
         mService.addNotification(r);
 
         final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
-        mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getSbn().getTag(),
-                r.getSbn().getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
+        mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getUserId(),
+                r.getKey(), NotificationStats.DISMISSAL_AOD,
                 NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv);
         waitForIdle();
 
@@ -6693,8 +6693,7 @@
         final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
                 true);
         mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG,
-                nrSummary.getSbn().getTag(),
-                nrSummary.getSbn().getId(), nrSummary.getUserId(), nrSummary.getKey(),
+                nrSummary.getUserId(), nrSummary.getKey(),
                 NotificationStats.DISMISSAL_SHADE,
                 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, nv);
         waitForIdle();
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
index 35b224a..2ae2ef7 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
@@ -51,6 +51,7 @@
 
 import com.android.internal.util.FastXmlSerializer;
 import com.android.server.UiServiceTestCase;
+import com.android.server.pm.PackageManagerService;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -259,6 +260,17 @@
     }
 
     @Test
+    public void testSnoozeSentToAndroid() throws Exception {
+        NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
+        mSnoozeHelper.snooze(r, 1000);
+        ArgumentCaptor<PendingIntent> captor = ArgumentCaptor.forClass(PendingIntent.class);
+        verify(mAm, times(1)).setExactAndAllowWhileIdle(
+                anyInt(), anyLong(), captor.capture());
+        assertEquals(PackageManagerService.PLATFORM_PACKAGE_NAME,
+                captor.getValue().getIntent().getPackage());
+    }
+
+    @Test
     public void testSnooze() throws Exception {
         NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
         mSnoozeHelper.snooze(r, (String) null);
diff --git a/services/tests/wmtests/Android.bp b/services/tests/wmtests/Android.bp
index ddf284401..90dac47 100644
--- a/services/tests/wmtests/Android.bp
+++ b/services/tests/wmtests/Android.bp
@@ -2,6 +2,15 @@
 // Build WmTests package
 //########################################################################
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 // Include all test java files.
 filegroup {
     name: "wmtests-sources",
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 aa1110c..d8e7582 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -555,9 +555,10 @@
         activity.setRequestedOrientation(
                 isScreenPortrait ? SCREEN_ORIENTATION_PORTRAIT : SCREEN_ORIENTATION_LANDSCAPE);
 
-        // Asserts it has orientation derived from bounds.
-        assertEquals(isScreenPortrait ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT,
+        // Asserts it has orientation derived requested orientation (fixed orientation letterbox).
+        assertEquals(isScreenPortrait ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE,
                 activity.getConfiguration().orientation);
+        assertTrue(activity.isLetterboxedForFixedOrientationAndAspectRatio());
     }
 
     @Test
@@ -1964,17 +1965,17 @@
 
         // Non-resizable
         mAtm.mForceResizableActivities = false;
-        mAtm.mSizeCompatFreeform = false;
+        mAtm.mSupportsNonResizableMultiWindow = false;
         assertFalse(activity.supportsFreeform());
 
         // Force resizable
         mAtm.mForceResizableActivities = true;
-        mAtm.mSizeCompatFreeform = false;
+        mAtm.mSupportsNonResizableMultiWindow = false;
         assertTrue(activity.supportsFreeform());
 
         // Allow non-resizable
         mAtm.mForceResizableActivities = false;
-        mAtm.mSizeCompatFreeform = true;
+        mAtm.mSupportsNonResizableMultiWindow = true;
         assertTrue(activity.supportsFreeform());
     }
 
@@ -2288,7 +2289,7 @@
                 IWindowManager.FIXED_TO_USER_ROTATION_ENABLED);
         reset(task);
         activity.reportDescendantOrientationChangeIfNeeded();
-        verify(task).onConfigurationChanged(any(Configuration.class));
+        verify(task, atLeast(1)).onConfigurationChanged(any(Configuration.class));
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
index d13e4dc..7df17fd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
@@ -38,6 +38,7 @@
 
 import static com.android.server.wm.DisplayArea.Type.ABOVE_TASKS;
 import static com.android.server.wm.DisplayAreaPolicyBuilder.Feature;
+import static com.android.server.wm.DisplayAreaPolicyBuilder.KEY_ROOT_DISPLAY_AREA_ID;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -595,6 +596,17 @@
         assertThat(token.isDescendantOf(mRoot)).isTrue();
         assertThat(token.isDescendantOf(mGroupRoot1)).isFalse();
         assertThat(token.isDescendantOf(mGroupRoot2)).isFalse();
+
+        // When the window has options for target root id, attach it to the target root.
+        final Bundle options = new Bundle();
+        options.putInt(KEY_ROOT_DISPLAY_AREA_ID, mGroupRoot2.mFeatureId);
+        final WindowToken token2 = new WindowToken(mWms, mock(IBinder.class),
+                TYPE_STATUS_BAR, true /* persistOnEmpty */, mDisplayContent,
+                true /* ownerCanManageAppTokens */, false /* roundedCornerOverlay */,
+                false /* fromClientToken */, options);
+        policy.addWindow(token2);
+
+        assertThat(token2.isDescendantOf(mGroupRoot2)).isTrue();
     }
 
     @Test
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 781cfec..137cf65 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -32,6 +32,8 @@
 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
 import static android.view.InsetsState.ITYPE_STATUS_BAR;
 import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_180;
+import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
 import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
@@ -121,6 +123,7 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
+import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.wm.utils.WmDisplayCutout;
 
 import org.junit.Test;
@@ -955,16 +958,14 @@
                 IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
         final int newOrientation = getRotatedOrientation(dc);
 
-        final Task stack = new TaskBuilder(mSupervisor)
+        final Task task = new TaskBuilder(mSupervisor)
                 .setDisplay(dc).setCreateActivity(true).build();
-        final ActivityRecord activity = stack.getTopMostTask().getTopNonFinishingActivity();
+        final ActivityRecord activity = task.getTopMostTask().getTopNonFinishingActivity();
+        dc.setFocusedApp(activity);
 
         activity.setRequestedOrientation(newOrientation);
 
-        final int expectedOrientation = newOrientation == SCREEN_ORIENTATION_PORTRAIT
-                ? Configuration.ORIENTATION_PORTRAIT
-                : Configuration.ORIENTATION_LANDSCAPE;
-        assertEquals(expectedOrientation, dc.getConfiguration().orientation);
+        assertTrue("The display should be rotated.", dc.getRotation() % 2 == 1);
     }
 
     @Test
@@ -972,17 +973,42 @@
         final DisplayContent dc = createNewDisplay();
         dc.getDisplayRotation().setFixedToUserRotation(
                 IWindowManager.FIXED_TO_USER_ROTATION_ENABLED);
+        dc.getDisplayRotation().setUserRotation(
+                WindowManagerPolicy.USER_ROTATION_LOCKED, ROTATION_180);
         final int newOrientation = getRotatedOrientation(dc);
 
-        final Task stack = new TaskBuilder(mSupervisor)
+        final Task task = new TaskBuilder(mSupervisor)
                 .setDisplay(dc).setCreateActivity(true).build();
-        final ActivityRecord activity = stack.getTopMostTask().getTopNonFinishingActivity();
+        final ActivityRecord activity = task.getTopMostTask().getTopNonFinishingActivity();
+        dc.setFocusedApp(activity);
 
         activity.setRequestedOrientation(newOrientation);
 
         verify(dc, never()).updateDisplayOverrideConfigurationLocked(any(), eq(activity),
                 anyBoolean(), same(null));
-        assertEquals(dc.getDisplayRotation().getUserRotation(), dc.getRotation());
+        assertEquals(ROTATION_180, dc.getRotation());
+    }
+
+    @Test
+    public void testFixedToUserRotationChanged() {
+        final DisplayContent dc = createNewDisplay();
+        dc.getDisplayRotation().setFixedToUserRotation(
+                IWindowManager.FIXED_TO_USER_ROTATION_ENABLED);
+        dc.getDisplayRotation().setUserRotation(
+                WindowManagerPolicy.USER_ROTATION_LOCKED, ROTATION_0);
+        final int newOrientation = getRotatedOrientation(dc);
+
+        final Task task = new TaskBuilder(mSupervisor)
+                .setDisplay(dc).setCreateActivity(true).build();
+        final ActivityRecord activity = task.getTopMostTask().getTopNonFinishingActivity();
+        dc.setFocusedApp(activity);
+
+        activity.setRequestedOrientation(newOrientation);
+
+        dc.getDisplayRotation().setFixedToUserRotation(
+                IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
+
+        assertTrue("The display should be rotated.", dc.getRotation() % 2 == 1);
     }
 
     @Test
@@ -1418,7 +1444,7 @@
         // Assume the animation of PipTaskOrganizer is done and then commit fullscreen to task.
         pinnedTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         displayContent.continueUpdateOrientationForDiffOrienLaunchingApp();
-        assertFalse(displayContent.getPinnedStackController().isPipActiveOrWindowingModeChanging());
+        assertFalse(displayContent.getPinnedTaskController().isPipActiveOrWindowingModeChanging());
         assertEquals(pinnedConfigOrientation, displayConfig.orientation);
 
         clearInvocations(mWm);
@@ -1429,7 +1455,7 @@
         assertFalse(displayContent.hasTopFixedRotationLaunchingApp());
         verify(mWm, atLeastOnce()).startFreezingDisplay(anyInt(), anyInt(), any(), anyInt());
         assertEquals(homeConfigOrientation, displayConfig.orientation);
-        assertTrue(displayContent.getPinnedStackController().isPipActiveOrWindowingModeChanging());
+        assertTrue(displayContent.getPinnedTaskController().isPipActiveOrWindowingModeChanging());
     }
 
     @Test
@@ -1489,7 +1515,7 @@
     }
 
     @Test
-    public void testClearIntermediateFixedRotation() throws RemoteException {
+    public void testClearIntermediateFixedRotationAdjustments() throws RemoteException {
         final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
         mDisplayContent.setFixedRotationLaunchingApp(activity,
                 (mDisplayContent.getRotation() + 1) % 4);
@@ -1508,7 +1534,8 @@
                 ArgumentCaptor.forClass(FixedRotationAdjustmentsItem.class);
         verify(mAtm.getLifecycleManager(), atLeastOnce()).scheduleTransaction(
                 eq(activity.app.getThread()), adjustmentsCaptor.capture());
-        assertFalse(activity.hasFixedRotationTransform());
+        // The transformation is kept for animation in real case.
+        assertTrue(activity.hasFixedRotationTransform());
         final FixedRotationAdjustmentsItem clearAdjustments = FixedRotationAdjustmentsItem.obtain(
                 activity.token, null /* fixedRotationAdjustments */);
         // The captor may match other items. The first one must be the item to clear adjustments.
@@ -1819,6 +1846,37 @@
         verify(t).show(mDisplayContent.mImeScreenshot);
     }
 
+    @Test
+    public void testRotateBounds_keepSamePhysicalPosition() {
+        final DisplayContent dc =
+                new TestDisplayContent.Builder(mAtm, 1000, 2000).build();
+        final Rect initBounds = new Rect(0, 0, 700, 1500);
+        final Rect rotateBounds = new Rect(initBounds);
+
+        // Rotate from 0 to 0
+        dc.rotateBounds(ROTATION_0, ROTATION_0, rotateBounds);
+
+        assertEquals(new Rect(0, 0, 700, 1500), rotateBounds);
+
+        // Rotate from 0 to 90
+        rotateBounds.set(initBounds);
+        dc.rotateBounds(ROTATION_0, ROTATION_90, rotateBounds);
+
+        assertEquals(new Rect(0, 300, 1500, 1000), rotateBounds);
+
+        // Rotate from 0 to 180
+        rotateBounds.set(initBounds);
+        dc.rotateBounds(ROTATION_0, ROTATION_180, rotateBounds);
+
+        assertEquals(new Rect(300, 500, 1000, 2000), rotateBounds);
+
+        // Rotate from 0 to 270
+        rotateBounds.set(initBounds);
+        dc.rotateBounds(ROTATION_0, ROTATION_270, rotateBounds);
+
+        assertEquals(new Rect(500, 0, 2000, 700), rotateBounds);
+    }
+
     private boolean isOptionsPanelAtRight(int displayId) {
         return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index b1ea4a5..5a0466a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -130,7 +130,7 @@
         // insets state with the global one.
         final InsetsState insetsState =
                 win.getDisplayContent().getInsetsStateController().getRawInsetsState();
-        win.mAboveInsetsState = insetsState;
+        win.mAboveInsetsState.set(insetsState);
     }
 
     public void setRotation(int rotation, boolean includingWindows) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index 2163661..074ef36 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -18,6 +18,7 @@
 
 import static android.view.InsetsState.ITYPE_IME;
 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
+import static android.view.RoundedCorners.NO_ROUNDED_CORNERS;
 import static android.view.Surface.ROTATION_0;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
@@ -37,6 +38,7 @@
 
 import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM;
 import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_RIGHT;
+import static com.android.server.wm.utils.WmDisplayCutout.NO_CUTOUT;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -300,9 +302,9 @@
         displayPolicy.addWindowLw(mNavBarWindow, mNavBarWindow.mAttrs);
         mNavBarWindow.getControllableInsetProvider().setServerVisible(true);
         final InsetsState state = mDisplayContent.getInsetsStateController().getRawInsetsState();
-        mImeWindow.mAboveInsetsState = state;
+        mImeWindow.mAboveInsetsState.set(state);
         mDisplayContent.mDisplayFrames = new DisplayFrames(mDisplayContent.getDisplayId(),
-                state, displayInfo, null /* displayCutout */, null /* roundedCorners*/);
+                state, displayInfo, NO_CUTOUT, NO_ROUNDED_CORNERS);
 
         mDisplayContent.setInputMethodWindowLocked(mImeWindow);
         mImeWindow.mAttrs.setFitInsetsSides(Side.all() & ~Side.BOTTOM);
@@ -321,4 +323,16 @@
         assertFalse(navBarSource.getFrame().isEmpty());
         assertTrue(imeSource.getFrame().contains(navBarSource.getFrame()));
     }
+
+    @UseTestDisplay
+    @Test
+    public void testDisplayPolicyNotCrash() {
+        final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
+
+        // Verify if modules initialized after DisplayContent ctr throws NPE.
+        displayPolicy.onDisplayInfoChanged(mDisplayInfo);
+        displayPolicy.onConfigurationChanged();
+        displayPolicy.onOverlayChangedLw();
+        displayPolicy.release();
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
index 20775e8..683ed88 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
@@ -117,7 +117,7 @@
     static Pair<DisplayInfo, WmDisplayCutout> displayInfoAndCutoutForRotation(int rotation,
             boolean withDisplayCutout, boolean isLongEdgeCutout) {
         final DisplayInfo info = new DisplayInfo();
-        WmDisplayCutout cutout = null;
+        WmDisplayCutout cutout = WmDisplayCutout.NO_CUTOUT;
 
         final boolean flippedDimensions = rotation == ROTATION_90 || rotation == ROTATION_270;
         info.logicalWidth = flippedDimensions ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
diff --git a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
index f91c9d0..e9c356d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
@@ -171,7 +171,7 @@
         final Rect activityBounds = new Rect(mFirstActivity.getBounds());
 
         // DAG is portrait (860x1200), so Task and Activity fill DAG.
-        assertThat(mFirstTask.isTaskLetterboxed()).isFalse();
+        assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
         assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
         assertThat(taskBounds).isEqualTo(dagBounds);
         assertThat(activityBounds).isEqualTo(taskBounds);
@@ -194,8 +194,8 @@
         final Rect activityConfigBounds =
                 new Rect(mFirstActivity.getConfiguration().windowConfiguration.getBounds());
 
-        // DAG is landscape (1200x860), Task fills parent
-        assertThat(mFirstTask.isTaskLetterboxed()).isFalse();
+        // DAG is landscape (1200x860), no fixed orientation letterbox
+        assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
         assertThat(mFirstActivity.inSizeCompatMode()).isTrue();
         assertThat(newDagBounds.width()).isEqualTo(dagBounds.height());
         assertThat(newDagBounds.height()).isEqualTo(dagBounds.width());
@@ -211,7 +211,7 @@
     }
 
     @Test
-    public void testLaunchLandscapeApp_taskIsLetterboxInDisplayAreaGroup() {
+    public void testLaunchLandscapeApp_activityIsLetterboxForFixedOrientationInDisplayAreaGroup() {
         mFirstRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
         mSecondRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
         mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);
@@ -221,17 +221,18 @@
         final Rect taskBounds = new Rect(mFirstTask.getBounds());
         final Rect activityBounds = new Rect(mFirstActivity.getBounds());
 
-        // DAG is portrait (860x1200), so Task is letterbox (860x[860x860/1200=616])
-        assertThat(mFirstTask.isTaskLetterboxed()).isTrue();
+        // DAG is portrait (860x1200), and activity is letterboxed for fixed orientation
+        // (860x[860x860/1200=616]). Task fills DAG.
+        assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isTrue();
         assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
-        assertThat(taskBounds.width()).isEqualTo(dagBounds.width());
-        assertThat(taskBounds.height())
+        assertThat(taskBounds).isEqualTo(dagBounds);
+        assertThat(activityBounds.width()).isEqualTo(dagBounds.width());
+        assertThat(activityBounds.height())
                 .isEqualTo(dagBounds.width() * dagBounds.width() / dagBounds.height());
-        assertThat(activityBounds).isEqualTo(taskBounds);
     }
 
     @Test
-    public void testLaunchLandscapeApp_taskLetterboxBecomesActivityLetterboxAfterRotation() {
+    public void testLaunchLandscapeApp_fixedOrientationLetterboxBecomesSizeCompatAfterRotation() {
         mFirstRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
         mSecondRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
         mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);
@@ -245,9 +246,8 @@
         final Rect newTaskBounds = new Rect(mFirstTask.getBounds());
         final Rect newActivityBounds = new Rect(mFirstActivity.getBounds());
 
-        // DAG is landscape (1200x860), Task fills parent
-        // Task letterbox size
-        assertThat(mFirstTask.isTaskLetterboxed()).isFalse();
+        // DAG is landscape (1200x860), no fixed orientation letterbox
+        assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
         assertThat(mFirstActivity.inSizeCompatMode()).isTrue();
         assertThat(newDagBounds.width()).isEqualTo(dagBounds.height());
         assertThat(newDagBounds.height()).isEqualTo(dagBounds.width());
@@ -311,7 +311,7 @@
     }
 
     @Test
-    public void testResizableFixedOrientationApp_taskLevelLetterboxing() {
+    public void testResizableFixedOrientationApp_fixedOrientationLetterboxing() {
         mFirstRoot.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
         mSecondRoot.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
 
@@ -324,7 +324,7 @@
         assertThat(mDisplay.getLastOrientation()).isEqualTo(SCREEN_ORIENTATION_LANDSCAPE);
         assertThat(mFirstRoot.getConfiguration().orientation).isEqualTo(ORIENTATION_PORTRAIT);
         assertThat(mFirstActivity.getConfiguration().orientation).isEqualTo(ORIENTATION_PORTRAIT);
-        assertThat(mFirstTask.isTaskLetterboxed()).isFalse();
+        assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
         assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
 
         // Launch portrait on second DAG
@@ -336,13 +336,13 @@
         assertThat(mDisplay.getLastOrientation()).isEqualTo(SCREEN_ORIENTATION_PORTRAIT);
         assertThat(mSecondRoot.getConfiguration().orientation).isEqualTo(ORIENTATION_LANDSCAPE);
         assertThat(mSecondActivity.getConfiguration().orientation).isEqualTo(ORIENTATION_LANDSCAPE);
-        assertThat(mSecondTask.isTaskLetterboxed()).isFalse();
+        assertThat(mSecondActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
         assertThat(mSecondActivity.inSizeCompatMode()).isFalse();
 
         // First activity is letterboxed in portrait as requested.
         assertThat(mFirstRoot.getConfiguration().orientation).isEqualTo(ORIENTATION_LANDSCAPE);
         assertThat(mFirstActivity.getConfiguration().orientation).isEqualTo(ORIENTATION_PORTRAIT);
-        assertThat(mFirstTask.isTaskLetterboxed()).isTrue();
+        assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isTrue();
         assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
 
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index ee293fc..be03603 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -32,13 +32,14 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.server.wm.DisplayContent.IME_TARGET_INPUT;
+import static com.android.server.wm.WindowContainer.POSITION_TOP;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -208,7 +209,7 @@
         app.mAboveInsetsState.getSource(ITYPE_IME).setFrame(mImeWindow.getFrame());
 
         // Make sure app got notified.
-        verify(app, atLeast(1)).notifyInsetsChanged();
+        verify(app, atLeastOnce()).notifyInsetsChanged();
 
         // app will get visible IME insets while below IME.
         assertTrue(getController().getInsetsForWindow(app).getSource(ITYPE_IME).isVisible());
@@ -336,6 +337,92 @@
         assertFalse(app.getInsetsState().getSource(ITYPE_STATUS_BAR).isVisible());
     }
 
+    @Test
+    public void testUpdateAboveInsetsState_provideInsets() {
+        final WindowState app = createTestWindow("app");
+        final WindowState statusBar = createTestWindow("statusBar");
+        final WindowState navBar = createTestWindow("navBar");
+
+        getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
+
+        assertNull(app.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+        assertNull(statusBar.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+        assertNull(navBar.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+
+        getController().updateAboveInsetsState(statusBar, true /* notifyInsetsChange */);
+
+        assertNotNull(app.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+        assertNull(statusBar.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+        assertNull(navBar.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+
+        verify(app, atLeastOnce()).notifyInsetsChanged();
+    }
+
+    @Test
+    public void testUpdateAboveInsetsState_receiveInsets() {
+        final WindowState app = createTestWindow("app");
+        final WindowState statusBar = createTestWindow("statusBar");
+        final WindowState navBar = createTestWindow("navBar");
+
+        getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
+        getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null, null);
+
+        assertNull(app.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+        assertNull(app.mAboveInsetsState.peekSource(ITYPE_NAVIGATION_BAR));
+
+        getController().updateAboveInsetsState(app, true /* notifyInsetsChange */);
+
+        assertNotNull(app.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+        assertNotNull(app.mAboveInsetsState.peekSource(ITYPE_NAVIGATION_BAR));
+
+        verify(app, atLeastOnce()).notifyInsetsChanged();
+    }
+
+    @Test
+    public void testUpdateAboveInsetsState_zOrderChanged() {
+        final WindowState ime = createTestWindow("ime");
+        final WindowState app = createTestWindow("app");
+        final WindowState statusBar = createTestWindow("statusBar");
+        final WindowState navBar = createTestWindow("navBar");
+
+        getController().getSourceProvider(ITYPE_IME).setWindow(ime, null, null);
+        getController().getSourceProvider(ITYPE_IME).setClientVisible(true);
+        getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
+        getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null, null);
+        getController().updateAboveInsetsState(ime, false /* notifyInsetsChange */);
+        getController().updateAboveInsetsState(statusBar, false /* notifyInsetsChange */);
+        getController().updateAboveInsetsState(navBar, false /* notifyInsetsChange */);
+
+        // ime is below others.
+        assertNull(app.mAboveInsetsState.peekSource(ITYPE_IME));
+        assertNull(statusBar.mAboveInsetsState.peekSource(ITYPE_IME));
+        assertNull(navBar.mAboveInsetsState.peekSource(ITYPE_IME));
+        assertNotNull(ime.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+        assertNotNull(ime.mAboveInsetsState.peekSource(ITYPE_NAVIGATION_BAR));
+
+        ime.getParent().positionChildAt(POSITION_TOP, ime, true /* includingParents */);
+        getController().updateAboveInsetsState(ime, true /* notifyInsetsChange */);
+
+        // ime is above others.
+        assertNotNull(app.mAboveInsetsState.peekSource(ITYPE_IME));
+        assertNotNull(statusBar.mAboveInsetsState.peekSource(ITYPE_IME));
+        assertNotNull(navBar.mAboveInsetsState.peekSource(ITYPE_IME));
+        assertNull(ime.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+        assertNull(ime.mAboveInsetsState.peekSource(ITYPE_NAVIGATION_BAR));
+
+        verify(ime, atLeastOnce()).notifyInsetsChanged();
+        verify(app, atLeastOnce()).notifyInsetsChanged();
+        verify(statusBar, atLeastOnce()).notifyInsetsChanged();
+        verify(navBar, atLeastOnce()).notifyInsetsChanged();
+    }
+
+    private WindowState createTestWindow(String name) {
+        final WindowState win = createWindow(null, TYPE_APPLICATION, name);
+        win.setHasSurface(true);
+        spyOn(win);
+        return win;
+    }
+
     private InsetsStateController getController() {
         return mDisplayContent.getInsetsStateController();
     }
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 f935bfc..d663b64 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
@@ -122,6 +122,7 @@
     @Mock private StatusBarManagerInternal mStatusBarManagerInternal;
     @Mock private TelecomManager mTelecomManager;
     @Mock private RecentTasks mRecentTasks;
+    @Mock private TaskChangeNotificationController mTaskChangeNotificationController;
 
     private LockTaskController mLockTaskController;
     private Context mContext;
@@ -145,7 +146,7 @@
         mSupervisor.mRootWindowContainer = mRootWindowContainer;
 
         mLockTaskController = new LockTaskController(mContext, mSupervisor,
-                new ImmediatelyExecuteHandler());
+                new ImmediatelyExecuteHandler(), mTaskChangeNotificationController);
         mLockTaskController.setWindowManager(mWindowManager);
         mLockTaskController.mStatusBarService = mStatusBarService;
         mLockTaskController.mDevicePolicyManager = mDevicePolicyManager;
diff --git a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index 15e045c..2fdd63e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -16,8 +16,11 @@
 
 package com.android.server.wm;
 
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY;
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
 import static android.view.WindowManager.TRANSIT_OLD_NONE;
 import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
 
@@ -94,10 +97,19 @@
         mController = new RemoteAnimationController(mWm, mAdapter, mHandler);
     }
 
+    private WindowState createAppOverlayWindow() {
+        final WindowState win = createWindow(null /* parent */, TYPE_APPLICATION_OVERLAY,
+                "testOverlayWindow");
+        win.mActivityRecord = null;
+        win.mHasSurface = true;
+        return win;
+    }
+
     @Test
     public void testRun() throws Exception {
         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
         mDisplayContent.mOpeningApps.add(win.mActivityRecord);
+        final WindowState overlayWin = createAppOverlayWindow();
         try {
             final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
                     new Point(50, 100), null, new Rect(50, 100, 150, 150), null).mAdapter;
@@ -109,12 +121,12 @@
                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
             final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
-            final ArgumentCaptor<RemoteAnimationTarget[]> nonApsCaptor =
+            final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
             final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
                     ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
             verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_ACTIVITY_OPEN),
-                    appsCaptor.capture(), wallpapersCaptor.capture(), nonApsCaptor.capture(),
+                    appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
                     finishedCaptor.capture());
             assertEquals(1, appsCaptor.getValue().length);
             final RemoteAnimationTarget app = appsCaptor.getValue()[0];
@@ -130,6 +142,7 @@
             finishedCaptor.getValue().onAnimationFinished();
             verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
                     eq(adapter));
+            assertEquals(0, nonAppsCaptor.getValue().length);
         } finally {
             mDisplayContent.mOpeningApps.clear();
         }
@@ -424,6 +437,89 @@
         }
     }
 
+    @Test
+    public void testNonAppIncluded_keygaurdGoingAway() throws Exception {
+        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
+        mDisplayContent.mOpeningApps.add(win.mActivityRecord);
+        // Add overlay window hidden by the keyguard.
+        final WindowState overlayWin = createAppOverlayWindow();
+        overlayWin.hide(false /* doAnimation */, false /* requestAnim */);
+        try {
+            final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
+                    win.mActivityRecord, new Point(50, 100), null,
+                    new Rect(50, 100, 150, 150), null).mAdapter;
+            adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
+                    mFinishedCallback);
+            mController.goodToGo(TRANSIT_OLD_KEYGUARD_GOING_AWAY);
+            mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+            final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
+                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
+            final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
+                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
+            final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
+                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
+            final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
+                    ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
+            verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_KEYGUARD_GOING_AWAY),
+                    appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
+                    finishedCaptor.capture());
+            assertEquals(1, appsCaptor.getValue().length);
+            final RemoteAnimationTarget app = appsCaptor.getValue()[0];
+            assertEquals(new Point(50, 100), app.position);
+            assertEquals(new Rect(50, 100, 150, 150), app.sourceContainerBounds);
+            assertEquals(win.mActivityRecord.getPrefixOrderIndex(), app.prefixOrderIndex);
+            assertEquals(win.mActivityRecord.getTask().mTaskId, app.taskId);
+            assertEquals(mMockLeash, app.leash);
+            assertEquals(false, app.isTranslucent);
+            verify(mMockTransaction).setPosition(mMockLeash, app.position.x, app.position.y);
+            verify(mMockTransaction).setWindowCrop(mMockLeash, 100, 50);
+
+            finishedCaptor.getValue().onAnimationFinished();
+            verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
+                    eq(adapter));
+            assertEquals(1, nonAppsCaptor.getValue().length);
+        } finally {
+            mDisplayContent.mOpeningApps.clear();
+        }
+    }
+
+    @Test
+    public void testNonAppIncluded_keygaurdGoingAwayToWallpaper() throws Exception {
+        final WindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm, mock(IBinder.class),
+                true, mDisplayContent, true /* ownerCanManageAppTokens */);
+        spyOn(mDisplayContent.mWallpaperController);
+        doReturn(true).when(mDisplayContent.mWallpaperController).isWallpaperVisible();
+        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
+        mDisplayContent.mOpeningApps.add(win.mActivityRecord);
+        // Add overlay window hidden by the keyguard.
+        final WindowState overlayWin = createAppOverlayWindow();
+        overlayWin.hide(false /* doAnimation */, false /* requestAnim */);
+        try {
+            final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
+                    win.mActivityRecord, new Point(50, 100), null,
+                    new Rect(50, 100, 150, 150), null).mAdapter;
+            adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
+                    mFinishedCallback);
+            mController.goodToGo(TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER);
+            mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+            final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
+                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
+            final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
+                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
+            final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
+                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
+            final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
+                    ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
+            verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER),
+                    appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
+                    finishedCaptor.capture());
+            assertEquals(1, wallpapersCaptor.getValue().length);
+            assertEquals(1, nonAppsCaptor.getValue().length);
+        } finally {
+            mDisplayContent.mOpeningApps.clear();
+        }
+    }
+
     private static void verifyNoMoreInteractionsExceptAsBinder(IInterface binder) {
         verify(binder, atLeast(0)).asBinder();
         verifyNoMoreInteractions(binder);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index e843dd7..b73c664 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -23,6 +23,7 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.view.Surface.ROTATION_180;
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
@@ -43,7 +44,6 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.same;
@@ -126,6 +126,7 @@
         // Put app window into freeform and then make it a compat app.
         final Rect bounds = new Rect(100, 100, 400, 600);
         mTask.setBounds(bounds);
+
         prepareUnresizable(mActivity, -1.f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);
         assertEquals(bounds, mActivity.getBounds());
 
@@ -194,12 +195,7 @@
                 new TestDisplayContent.Builder(mAtm, 1000, 2000)
                         .setDensityDpi(200).build();
 
-        mActivity = new ActivityBuilder(mAtm)
-                .setTask(mTask)
-                .setResizeMode(RESIZE_MODE_UNRESIZEABLE)
-                .setMaxAspectRatio(1.5f)
-                .build();
-        mActivity.mVisibleRequested = true;
+        prepareUnresizable(mActivity, 1.5f /* maxAspect */, SCREEN_ORIENTATION_UNSPECIFIED);
 
         final Rect originalBounds = new Rect(mActivity.getBounds());
         final int originalDpi = mActivity.getConfiguration().densityDpi;
@@ -566,18 +562,18 @@
                 .setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE)
                 .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
                 .build();
-        assertTrue(activity.shouldUseSizeCompatMode());
+        assertTrue(activity.shouldCreateCompatDisplayInsets());
 
         // The non-resizable activity should not be size compat because it is on a resizable task
         // in multi-window mode.
         mTask.setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM);
-        assertFalse(activity.shouldUseSizeCompatMode());
+        assertFalse(activity.shouldCreateCompatDisplayInsets());
 
         // The non-resizable activity should not be size compat because the display support
         // changing windowing mode from fullscreen to freeform.
         mTask.mDisplayContent.setDisplayWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM);
         mTask.setWindowingMode(WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
-        assertFalse(activity.shouldUseSizeCompatMode());
+        assertFalse(activity.shouldCreateCompatDisplayInsets());
     }
 
     @Test
@@ -597,7 +593,7 @@
                         SizeCompatTests.class.getName()))
                 .setUid(android.os.Process.myUid())
                 .build();
-        assertFalse(activity.shouldUseSizeCompatMode());
+        assertFalse(activity.shouldCreateCompatDisplayInsets());
     }
 
     @Test
@@ -653,7 +649,7 @@
     }
 
     @Test
-    public void testDisplayIgnoreOrientationRequest_fixedOrientationAppLaunchedInTaskLetterbox() {
+    public void testDisplayIgnoreOrientationRequest_fixedOrientationAppLaunchedLetterbox() {
         // Set up a display in landscape and ignoring orientation request.
         setUpDisplaySizeWithApp(2800, 1400);
         mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
@@ -662,7 +658,6 @@
         prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);
 
         final Rect displayBounds = new Rect(mActivity.mDisplayContent.getBounds());
-        final Rect taskBounds = new Rect(mTask.getBounds());
         final Rect activityBounds = new Rect(mActivity.getBounds());
 
         // Display shouldn't be rotated.
@@ -670,19 +665,19 @@
                 mActivity.mDisplayContent.getLastOrientation());
         assertTrue(displayBounds.width() > displayBounds.height());
 
-        // App should launch in task level letterboxing.
-        assertTrue(mTask.isTaskLetterboxed());
+        // App should launch in fixed orientation letterbox.
+        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
         assertFalse(mActivity.inSizeCompatMode());
-        assertEquals(taskBounds, activityBounds);
 
-        // Task bounds should be 700x1400 with the ratio as the display.
-        assertEquals(displayBounds.height(), taskBounds.height());
+        // Activity bounds should be 700x1400 with the ratio as the display.
+        assertEquals(displayBounds.height(), activityBounds.height());
         assertEquals(displayBounds.height() * displayBounds.height() / displayBounds.width(),
-                taskBounds.width());
+                activityBounds.width());
     }
 
     @Test
-    public void testDisplayIgnoreOrientationRequest_taskLetterboxBecameSizeCompatAfterRotate() {
+    public void
+            testDisplayIgnoreOrientationRequest_orientationLetterboxBecameSizeCompatAfterRotate() {
         // Set up a display in landscape and ignoring orientation request.
         setUpDisplaySizeWithApp(2800, 1400);
         mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
@@ -700,7 +695,7 @@
         assertTrue(displayBounds.width() < displayBounds.height());
 
         // App should be in size compat.
-        assertFalse(mTask.isTaskLetterboxed());
+        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
         assertScaled();
         assertEquals(activityBounds.width(), newActivityBounds.width());
         assertEquals(activityBounds.height(), newActivityBounds.height());
@@ -719,7 +714,7 @@
         Rect activityBounds = new Rect(mActivity.getBounds());
 
         // App should launch in fullscreen.
-        assertFalse(mTask.isTaskLetterboxed());
+        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
         assertFalse(mActivity.inSizeCompatMode());
         assertEquals(displayBounds, activityBounds);
 
@@ -731,7 +726,7 @@
         assertTrue(displayBounds.width() > displayBounds.height());
 
         // App should be in size compat.
-        assertFalse(mTask.isTaskLetterboxed());
+        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
         assertScaled();
 
         // App bounds should be 700x1400 with the ratio as the display.
@@ -741,7 +736,7 @@
     }
 
     @Test
-    public void testDisplayIgnoreOrientationRequest_newLaunchedOrientationAppInTaskLetterbox() {
+    public void testDisplayIgnoreOrientationRequest_newLaunchedOrientationAppInLetterbox() {
         // Set up a display in landscape and ignoring orientation request.
         setUpDisplaySizeWithApp(2800, 1400);
         final DisplayContent display = mActivity.mDisplayContent;
@@ -750,7 +745,7 @@
         // Portrait fixed app without max aspect.
         prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);
 
-        assertTrue(mTask.isTaskLetterboxed());
+        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
         assertFalse(mActivity.inSizeCompatMode());
 
         // Launch another portrait fixed app.
@@ -765,19 +760,19 @@
         // Update with new activity requested orientation and recompute bounds with no previous
         // size compat cache.
         verify(mTask).onDescendantOrientationChanged(same(newActivity));
-        verify(mTask).computeFullscreenBounds(any(), any());
 
         final Rect displayBounds = new Rect(display.getBounds());
         final Rect taskBounds = new Rect(mTask.getBounds());
         final Rect newActivityBounds = new Rect(newActivity.getBounds());
 
-        // Task and app bounds should be 700x1400 with the ratio as the display.
-        assertTrue(mTask.isTaskLetterboxed());
+        // Task and display bounds should be equal while activity should be letterboxed and
+        // has 700x1400 bounds with the ratio as the display.
+        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
         assertFalse(newActivity.inSizeCompatMode());
-        assertEquals(taskBounds, newActivityBounds);
-        assertEquals(displayBounds.height(), taskBounds.height());
+        assertEquals(taskBounds, displayBounds);
+        assertEquals(displayBounds.height(), newActivityBounds.height());
         assertEquals(displayBounds.height() * displayBounds.height() / displayBounds.width(),
-                taskBounds.width());
+                newActivityBounds.width());
     }
 
     @Test
@@ -790,7 +785,7 @@
         // Portrait fixed app without max aspect.
         prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);
 
-        assertTrue(mTask.isTaskLetterboxed());
+        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
         assertFalse(mActivity.inSizeCompatMode());
 
         // Launch another portrait fixed app with max aspect ratio as 1.3.
@@ -806,21 +801,20 @@
         // Update with new activity requested orientation and recompute bounds with no previous
         // size compat cache.
         verify(mTask).onDescendantOrientationChanged(same(newActivity));
-        verify(mTask).computeFullscreenBounds(any(), any());
 
         final Rect displayBounds = new Rect(display.getBounds());
         final Rect taskBounds = new Rect(mTask.getBounds());
         final Rect newActivityBounds = new Rect(newActivity.getBounds());
 
-        // Task bounds should be (1400 / 1.3 = 1076)x1400 with the app requested ratio.
-        assertTrue(mTask.isTaskLetterboxed());
-        assertEquals(displayBounds.height(), taskBounds.height());
-        assertEquals((long) Math.rint(taskBounds.height() / newActivity.info.maxAspectRatio),
-                taskBounds.width());
+        // Task bounds should fill parent bounds.
+        assertEquals(displayBounds, taskBounds);
 
-        // App bounds should be fullscreen in Task bounds.
+        // Activity bounds should be (1400 / 1.3 = 1076)x1400 with the app requested ratio.
+        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
         assertFalse(newActivity.inSizeCompatMode());
-        assertEquals(taskBounds, newActivityBounds);
+        assertEquals(displayBounds.height(), newActivityBounds.height());
+        assertEquals((long) Math.rint(newActivityBounds.height() / newActivity.info.maxAspectRatio),
+                newActivityBounds.width());
     }
 
     @Test
@@ -834,26 +828,23 @@
         prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);
         clearInvocations(mActivity);
 
-        assertTrue(mTask.isTaskLetterboxed());
+        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
         assertFalse(mActivity.inSizeCompatMode());
-        assertEquals(mTask.getLastTaskBoundsComputeActivity(), mActivity);
 
         // Rotate display to portrait.
         rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
 
         // App should be in size compat.
-        assertFalse(mTask.isTaskLetterboxed());
+        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
         assertScaled();
-        assertEquals(mTask.getLastTaskBoundsComputeActivity(), mActivity);
 
         final Rect activityBounds = new Rect(mActivity.getBounds());
         mTask.resumeTopActivityUncheckedLocked(null /* prev */, null /* options */);
 
         // App still in size compat, and the bounds don't change.
         verify(mActivity, never()).clearSizeCompatMode();
-        assertFalse(mTask.isTaskLetterboxed());
+        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
         assertScaled();
-        assertEquals(mTask.getLastTaskBoundsComputeActivity(), mActivity);
         assertEquals(activityBounds, mActivity.getBounds());
     }
 
@@ -867,22 +858,22 @@
         // Portrait fixed app.
         prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);
 
-        // In Task letterbox
-        assertTrue(mTask.isTaskLetterboxed());
+        // In fixed orientation letterbox
+        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
         assertFalse(mActivity.inSizeCompatMode());
 
         // Rotate display to portrait.
         rotateDisplay(display, ROTATION_90);
 
         // App should be in size compat.
-        assertFalse(mTask.isTaskLetterboxed());
+        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
         assertScaled();
 
         // Rotate display to landscape.
         rotateDisplay(display, ROTATION_180);
 
         // In Task letterbox
-        assertTrue(mTask.isTaskLetterboxed());
+        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
         assertFalse(mActivity.inSizeCompatMode());
     }
 
@@ -898,22 +889,22 @@
         // Landscape fixed app.
         prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_LANDSCAPE);
 
-        // In Task letterbox
-        assertTrue(mTask.isTaskLetterboxed());
+        // In fixed orientation letterbox
+        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
         assertFalse(mActivity.inSizeCompatMode());
 
         // Rotate display to portrait.
         rotateDisplay(display, ROTATION_90);
 
         // App should be in size compat.
-        assertFalse(mTask.isTaskLetterboxed());
+        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
         assertScaled();
 
         // Rotate display to landscape.
         rotateDisplay(display, ROTATION_180);
 
-        // In Task letterbox
-        assertTrue(mTask.isTaskLetterboxed());
+        // In fixed orientation letterbox
+        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
         assertFalse(mActivity.inSizeCompatMode());
     }
 
@@ -972,21 +963,21 @@
         addWindowToActivity(mActivity);
         mActivity.mRootWindowContainer.performSurfacePlacement();
 
-        // Split screen is also in portrait [1000,1400], so Task should be in letterbox, and
-        // activity fills task.
-        assertEquals(ORIENTATION_LANDSCAPE, mTask.getConfiguration().orientation);
+        // Split screen is also in portrait [1000,1400], so activty should be in fixed orientation
+        // letterbox.
+        assertEquals(ORIENTATION_PORTRAIT, mTask.getConfiguration().orientation);
         assertEquals(ORIENTATION_LANDSCAPE, mActivity.getConfiguration().orientation);
         assertFitted();
-        assertTrue(mTask.isTaskLetterboxed());
+        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
 
-        // Letterbox should fill the gap between the split screen and the letterboxed task.
+        // Letterbox should fill the gap between the split screen and the letterboxed activity.
         final Rect primarySplitBounds = new Rect(organizer.mPrimary.getBounds());
-        final Rect letterboxedTaskBounds = new Rect(mTask.getBounds());
-        assertTrue(primarySplitBounds.contains(letterboxedTaskBounds));
-        assertEquals(new Rect(letterboxedTaskBounds.left - primarySplitBounds.left,
-                letterboxedTaskBounds.top - primarySplitBounds.top,
-                primarySplitBounds.right - letterboxedTaskBounds.right,
-                primarySplitBounds.bottom - letterboxedTaskBounds.bottom),
+        final Rect letterboxedBounds = new Rect(mActivity.getBounds());
+        assertTrue(primarySplitBounds.contains(letterboxedBounds));
+        assertEquals(new Rect(letterboxedBounds.left - primarySplitBounds.left,
+                letterboxedBounds.top - primarySplitBounds.top,
+                primarySplitBounds.right - letterboxedBounds.right,
+                primarySplitBounds.bottom - letterboxedBounds.bottom),
                 mActivity.getLetterboxInsets());
     }
 
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 4984799..a1e5afb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -661,7 +661,7 @@
 
     @Test
     public void testForceMaximizesUnresizeableApp() {
-        mAtm.mSizeCompatFreeform = false;
+        mAtm.mSupportsNonResizableMultiWindow = false;
         final TestDisplayContent freeformDisplay = createNewDisplayContent(
                 WINDOWING_MODE_FREEFORM);
 
@@ -683,12 +683,12 @@
     }
 
     @Test
-    public void testLaunchesAppInWindowOnFreeformDisplay() {
-        mAtm.mSizeCompatFreeform = true;
+    public void testLaunchesPortraitSizeCompatOnFreeformLandscapeDisplayWithFreeformSizeCompat() {
+        mAtm.mSupportsNonResizableMultiWindow = true;
         final TestDisplayContent freeformDisplay = createNewDisplayContent(
                 WINDOWING_MODE_FREEFORM);
 
-        Rect expectedLaunchBounds = new Rect(0, 0, 200, 100);
+        Rect expectedLaunchBounds = new Rect(0, 0, 100, 200);
 
         final ActivityOptions options = ActivityOptions.makeBasic();
         options.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);
@@ -699,6 +699,7 @@
         mCurrent.mBounds.set(expectedLaunchBounds);
 
         mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
+        mActivity.info.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
 
         assertEquals(RESULT_CONTINUE,
                 new CalculateRequestBuilder().setOptions(options).calculate());
@@ -710,6 +711,38 @@
     }
 
     @Test
+    public void testLaunchesLandscapeSizeCompatOnFreeformLandscapeDisplayWithFreeformSizeCompat() {
+        mAtm.mSupportsNonResizableMultiWindow = true;
+        final TestDisplayContent freeformDisplay = createNewDisplayContent(
+                WINDOWING_MODE_FREEFORM);
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
+        mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
+        mActivity.info.screenOrientation = SCREEN_ORIENTATION_LANDSCAPE;
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
+
+        assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
+                WINDOWING_MODE_FREEFORM);
+    }
+
+    @Test
+    public void testLaunchesPortraitUnresizableOnFreeformDisplayWithFreeformSizeCompat() {
+        mAtm.mSupportsNonResizableMultiWindow = true;
+        final TestDisplayContent freeformDisplay = createNewDisplayContent(
+                WINDOWING_MODE_FREEFORM);
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
+        mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
+        mActivity.info.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
+
+        assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
+                WINDOWING_MODE_FREEFORM);
+    }
+
+    @Test
     public void testSkipsForceMaximizingAppsOnNonFreeformDisplay() {
         final ActivityOptions options = ActivityOptions.makeBasic();
         options.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);
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 0eb8c8d..d853b93 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -266,8 +266,9 @@
         root.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
         assertEquals(root, task.getRootActivity());
         assertEquals(SCREEN_ORIENTATION_PORTRAIT, task.getRootActivity().getOrientation());
-        assertThat(task.getBounds().width()).isLessThan(task.getBounds().height());
-        assertEquals(fullScreenBounds.height(), task.getBounds().height());
+        // Portrait orientation is enforced on activity level. Task should fill fullscreen bounds.
+        assertThat(task.getBounds().height()).isLessThan(task.getBounds().width());
+        assertEquals(fullScreenBounds, task.getBounds());
 
         // Top activity gets used
         final ActivityRecord top = new ActivityBuilder(mAtm).setTask(task).setParentTask(stack)
@@ -286,8 +287,11 @@
         // Fix the display orientation to portrait which is 90 degrees for the test display.
         dr.setUserRotation(USER_ROTATION_FREE, ROTATION_90);
 
-        assertThat(task.getBounds().width()).isGreaterThan(task.getBounds().height());
-        assertEquals(fullScreenBoundsPort.width(), task.getBounds().width());
+        // Fixed orientation request should be resolved on activity level. Task fills display
+        // bounds.
+        assertThat(task.getBounds().height()).isGreaterThan(task.getBounds().width());
+        assertThat(top.getBounds().width()).isGreaterThan(top.getBounds().height());
+        assertEquals(fullScreenBoundsPort, task.getBounds());
 
         // in FREEFORM, no constraint
         final Rect freeformBounds = new Rect(display.getBounds());
@@ -297,10 +301,11 @@
         task.setBounds(freeformBounds);
         assertEquals(freeformBounds, task.getBounds());
 
-        // FULLSCREEN letterboxes bounds
+        // FULLSCREEN letterboxes bounds on activity level, no constraint on task level.
         stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
-        assertThat(task.getBounds().width()).isGreaterThan(task.getBounds().height());
-        assertEquals(fullScreenBoundsPort.width(), task.getBounds().width());
+        assertThat(task.getBounds().height()).isGreaterThan(task.getBounds().width());
+        assertThat(top.getBounds().width()).isGreaterThan(top.getBounds().height());
+        assertEquals(fullScreenBoundsPort, task.getBounds());
 
         // FREEFORM restores bounds as before
         stack.setWindowingMode(WINDOWING_MODE_FREEFORM);
@@ -327,9 +332,10 @@
 
         assertEquals(fullScreenBounds, task.getBounds());
 
-        // Setting app to fixed portrait fits within parent
+        // Setting app to fixed portrait fits within parent on activity level. Task fills parent.
         root.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
-        assertThat(task.getBounds().width()).isLessThan(task.getBounds().height());
+        assertThat(root.getBounds().width()).isLessThan(root.getBounds().height());
+        assertEquals(task.getBounds(), fullScreenBounds);
 
         assertEquals(SCREEN_ORIENTATION_PORTRAIT, task.getOrientation());
     }
@@ -424,7 +430,8 @@
         // to the input bounds.
         final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task).build();
         final ActivityRecord.CompatDisplayInsets compatIntsets =
-                new ActivityRecord.CompatDisplayInsets(display, activity);
+                new ActivityRecord.CompatDisplayInsets(
+                        display, activity, /* fixedOrientationBounds= */ null);
         task.computeConfigResourceOverrides(inOutConfig, parentConfig, compatIntsets);
 
         assertEquals(largerLandscapeBounds, inOutConfig.windowConfiguration.getAppBounds());
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 1c0f640..c3eb5c4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -257,24 +257,4 @@
         task.resolveOverrideConfiguration(parentConfig);
         assertThat(resolvedOverride.getWindowingMode()).isEqualTo(WINDOWING_MODE_UNDEFINED);
     }
-
-    @Test
-    public void testCleanUpActivityReferences_clearLastTaskBoundsComputeActivity() {
-        final Task rootTask = createTaskStackOnDisplay(mDisplayContent);
-        final Task leafTask = createTaskInStack(rootTask, 0 /* userId */);
-        final ActivityRecord activity2 = createActivityRecord(mDisplayContent, leafTask);
-        final ActivityRecord activity1 = createActivityRecord(mDisplayContent, leafTask);
-        activity1.finishing = false;
-        leafTask.resolveOverrideConfiguration(rootTask.getConfiguration());
-
-        assertEquals(activity1, leafTask.getLastTaskBoundsComputeActivity());
-
-        leafTask.cleanUpActivityReferences(activity2);
-
-        assertNotNull(leafTask.getLastTaskBoundsComputeActivity());
-
-        leafTask.cleanUpActivityReferences(activity1);
-
-        assertNull(leafTask.getLastTaskBoundsComputeActivity());
-    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
index e4b865f..86d8eee 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -91,11 +91,6 @@
         return attrs.type == TYPE_NOTIFICATION_SHADE;
     }
 
-    @Override
-    public boolean canBeHiddenByKeyguardLw(WindowState win) {
-        return false;
-    }
-
     /**
      * Sets a runnable to run when adding a splash screen which gets executed after the window has
      * been added but before returning the surface.
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java
index 0dd8d23..18c8cf5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java
@@ -18,7 +18,6 @@
 
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW;
-import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
 import static android.provider.Settings.Global.DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH;
@@ -119,20 +118,6 @@
     }
 
     @Test
-    public void testEnableSizeCompatFreeform() {
-        try (BoolSettingsSession enableSizeCompatFreeformSession = new
-                BoolSettingsSession(DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM)) {
-            final boolean enableSizeCompatFreeform =
-                    !enableSizeCompatFreeformSession.getSetting();
-            final Uri enableSizeCompatFreeformUri =
-                    enableSizeCompatFreeformSession.setSetting(enableSizeCompatFreeform);
-            mWm.mSettingsObserver.onChange(false, enableSizeCompatFreeformUri);
-
-            assertEquals(mWm.mAtmService.mSizeCompatFreeform, enableSizeCompatFreeform);
-        }
-    }
-
-    @Test
     public void testSupportsNonResizableMultiWindow() {
         try (BoolSettingsSession supportsNonResizableMultiWindowSession = new
                 BoolSettingsSession(DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW)) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index 9c16143..2c2c09a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -61,6 +61,7 @@
 import android.app.ActivityManager;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityTaskManager.RootTaskInfo;
+import android.app.IRequestFinishCallback;
 import android.app.PictureInPictureParams;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ParceledListSlice;
@@ -976,7 +977,8 @@
         assertTrue(stack2.isOrganized());
 
         // Verify a back pressed does not call the organizer
-        mWm.mAtmService.mActivityClientController.onBackPressedOnTaskRoot(activity.token);
+        mWm.mAtmService.mActivityClientController.onBackPressedOnTaskRoot(activity.token,
+                new IRequestFinishCallback.Default());
         // Ensure events dispatch to organizer.
         mWm.mAtmService.mTaskOrganizerController.dispatchPendingEvents();
         verify(organizer, never()).onBackPressedOnTaskRoot(any());
@@ -986,7 +988,8 @@
                 stack.mRemoteToken.toWindowContainerToken(), true);
 
         // Verify now that the back press does call the organizer
-        mWm.mAtmService.mActivityClientController.onBackPressedOnTaskRoot(activity.token);
+        mWm.mAtmService.mActivityClientController.onBackPressedOnTaskRoot(activity.token,
+                new IRequestFinishCallback.Default());
         // Ensure events dispatch to organizer.
         mWm.mAtmService.mTaskOrganizerController.dispatchPendingEvents();
         verify(organizer, times(1)).onBackPressedOnTaskRoot(any());
@@ -996,7 +999,8 @@
                 stack.mRemoteToken.toWindowContainerToken(), false);
 
         // Verify now that the back press no longer calls the organizer
-        mWm.mAtmService.mActivityClientController.onBackPressedOnTaskRoot(activity.token);
+        mWm.mAtmService.mActivityClientController.onBackPressedOnTaskRoot(activity.token,
+                new IRequestFinishCallback.Default());
         // Ensure events dispatch to organizer.
         mWm.mAtmService.mTaskOrganizerController.dispatchPendingEvents();
         verify(organizer, times(1)).onBackPressedOnTaskRoot(any());
@@ -1201,7 +1205,8 @@
         mWm.mWindowPlacerLocked.deferLayout();
 
         stack.removeImmediately();
-        mWm.mAtmService.mActivityClientController.onBackPressedOnTaskRoot(record.token);
+        mWm.mAtmService.mActivityClientController.onBackPressedOnTaskRoot(record.token,
+                new IRequestFinishCallback.Default());
         waitUntilHandlersIdle();
 
         ArrayList<PendingTaskEvent> pendingEvents = getTaskPendingEvent(stack);
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 8969695..51aec65 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -251,7 +251,7 @@
 
         // Simulate the window is in split screen primary stack and the current state is
         // minimized and home stack is resizable, so that we should ignore input for the stack.
-        final DockedStackDividerController controller =
+        final DockedTaskDividerController controller =
                 mDisplayContent.getDockedDividerController();
         final Task stack = createTaskStackOnDisplay(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
                 ACTIVITY_TYPE_STANDARD, mDisplayContent);
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 c13d6b1..ebc5c4f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -538,9 +538,8 @@
 
     /** Creates a {@link DisplayContent} and adds it to the system. */
     private DisplayContent createNewDisplay(DisplayInfo info, @DisplayImePolicy int imePolicy) {
-        final DisplayContent display =
+        final DisplayContent dc =
                 new TestDisplayContent.Builder(mAtm, info).build();
-        final DisplayContent dc = display.mDisplayContent;
         // this display can show IME.
         dc.mWmService.mDisplayWindowSettings.setDisplayImePolicy(dc, imePolicy);
         return dc;
diff --git a/services/texttospeech/Android.bp b/services/texttospeech/Android.bp
index bacc932..391ab89 100644
--- a/services/texttospeech/Android.bp
+++ b/services/texttospeech/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.texttospeech-sources",
     srcs: ["java/**/*.java"],
@@ -10,4 +19,4 @@
     defaults: ["platform_service_defaults"],
     srcs: [":services.texttospeech-sources"],
     libs: ["services.core"],
-}
\ No newline at end of file
+}
diff --git a/services/translation/Android.bp b/services/translation/Android.bp
index 804a617..f257f1b 100644
--- a/services/translation/Android.bp
+++ b/services/translation/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.translation-sources",
     srcs: ["java/**/*.java"],
@@ -10,4 +19,4 @@
     defaults: ["platform_service_defaults"],
     srcs: [":services.translation-sources"],
     libs: ["services.core"],
-}
\ No newline at end of file
+}
diff --git a/services/usage/Android.bp b/services/usage/Android.bp
index 80f040b..867773d 100644
--- a/services/usage/Android.bp
+++ b/services/usage/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.usage-sources",
     srcs: ["java/**/*.java"],
diff --git a/services/usb/Android.bp b/services/usb/Android.bp
index 89e5d5f..01feacd 100644
--- a/services/usb/Android.bp
+++ b/services/usb/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.usb-sources",
     srcs: ["java/**/*.java"],
diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java
index 6bf6715..c53c95c 100644
--- a/services/usb/java/com/android/server/usb/UsbPortManager.java
+++ b/services/usb/java/com/android/server/usb/UsbPortManager.java
@@ -42,13 +42,13 @@
 import android.hardware.usb.UsbManager;
 import android.hardware.usb.UsbPort;
 import android.hardware.usb.UsbPortStatus;
+import android.hardware.usb.V1_0.IUsb;
 import android.hardware.usb.V1_0.PortRole;
 import android.hardware.usb.V1_0.PortRoleType;
 import android.hardware.usb.V1_0.Status;
 import android.hardware.usb.V1_1.PortStatus_1_1;
 import android.hardware.usb.V1_2.IUsbCallback;
 import android.hardware.usb.V1_2.PortStatus;
-import android.hardware.usb.V1_3.IUsb;
 import android.hidl.manager.V1_0.IServiceManager;
 import android.hidl.manager.V1_0.IServiceNotification;
 import android.os.Bundle;
diff --git a/services/voiceinteraction/Android.bp b/services/voiceinteraction/Android.bp
index 02061be..702ddb1 100644
--- a/services/voiceinteraction/Android.bp
+++ b/services/voiceinteraction/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.voiceinteraction-sources",
     srcs: ["java/**/*.java"],
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index 35e65c1..ed71d17 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -22,25 +22,49 @@
 import android.content.Intent;
 import android.hardware.soundtrigger.IRecognitionStatusCallback;
 import android.hardware.soundtrigger.SoundTrigger;
+import android.media.AudioAttributes;
+import android.media.AudioRecord;
+import android.media.MediaRecorder;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.service.voice.AlwaysOnHotwordDetector;
 import android.service.voice.HotwordDetectionService;
 import android.service.voice.IDspHotwordDetectionCallback;
 import android.service.voice.IHotwordDetectionService;
+import android.util.Pair;
 import android.util.Slog;
 
 import com.android.internal.app.IHotwordRecognitionStatusCallback;
 import com.android.internal.infra.ServiceConnector;
 
+import java.io.IOException;
+import java.io.OutputStream;
 import java.io.PrintWriter;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
 
 /**
  * A class that provides the communication with the HotwordDetectionService.
  */
 final class HotwordDetectionConnection {
-    static final String TAG = "HotwordDetectionConnection";
+    private static final String TAG = "HotwordDetectionConnection";
     // TODO (b/177502877): Set the Debug flag to false before shipping.
-    static final boolean DEBUG = true;
+    private static final boolean DEBUG = true;
+
+    // Number of bytes per sample of audio (which is a short).
+    private static final int BYTES_PER_SAMPLE = 2;
+    // TODO: These constants need to be refined.
+    private static final long VALIDATION_TIMEOUT_MILLIS = 3000;
+    private static final long VOICE_INTERACTION_TIMEOUT_TO_OPEN_MIC_MILLIS = 2000;
+    private static final int MAX_STREAMING_SECONDS = 10;
+
+    private final Executor mAudioCopyExecutor = Executors.newCachedThreadPool();
+    // TODO: This may need to be a Handler(looper)
+    private final ScheduledExecutorService mScheduledExecutorService =
+            Executors.newSingleThreadScheduledExecutor();
 
     final Object mLock;
     final ComponentName mDetectionComponentName;
@@ -93,42 +117,106 @@
         }
     }
 
-    private void detectFromDspSource(int sessionId, IDspHotwordDetectionCallback callback) {
+    private void detectFromDspSource(SoundTrigger.KeyphraseRecognitionEvent recognitionEvent,
+            IHotwordRecognitionStatusCallback externalCallback) {
         if (DEBUG) {
             Slog.d(TAG, "detectFromDspSource");
         }
+
+        AudioRecord record = createAudioRecord(recognitionEvent);
+
+        Pair<ParcelFileDescriptor, ParcelFileDescriptor> clientPipe = createPipe();
+
+        if (clientPipe == null) {
+            // Error.
+            // Need to propagate as unknown error or something?
+            return;
+        }
+        ParcelFileDescriptor audioSink = clientPipe.second;
+        ParcelFileDescriptor clientRead = clientPipe.first;
+
+        record.startRecording();
+
+        mAudioCopyExecutor.execute(() -> {
+            try (OutputStream fos =
+                         new ParcelFileDescriptor.AutoCloseOutputStream(audioSink)) {
+                byte[] buffer = new byte[1024];
+
+                while (true) {
+                    int bytesRead = record.read(buffer, 0, 1024);
+
+                    if (bytesRead < 0) {
+                        break;
+                    }
+
+                    fos.write(buffer, 0, bytesRead);
+                }
+            } catch (IOException e) {
+                Slog.w(TAG, "Failed supplying audio data to validator", e);
+            }
+        });
+
+        Runnable cancellingJob = () -> {
+            record.stop();
+            bestEffortCloseFileDescriptor(audioSink);
+            // TODO: consider calling externalCallback.onRejected(ERROR_TIMEOUT).
+        };
+
+        ScheduledFuture<?> cancelingFuture =
+                mScheduledExecutorService.schedule(
+                        cancellingJob, VALIDATION_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+
+        // TODO: consider making this a non-anonymous class.
+        IDspHotwordDetectionCallback internalCallback = new IDspHotwordDetectionCallback.Stub() {
+            @Override
+            public void onDetected() throws RemoteException {
+                if (DEBUG) {
+                    Slog.d(TAG, "onDetected");
+                }
+                bestEffortCloseFileDescriptor(audioSink);
+                cancelingFuture.cancel(true);
+
+                // Give 2 more seconds for the interactor to start consuming the mic. If it fails to
+                // do so under the given time, we'll force-close the mic to make sure resources are
+                // freed up.
+                // TODO: consider modelling these 2 seconds in the API.
+                mScheduledExecutorService.schedule(
+                        cancellingJob,
+                        VOICE_INTERACTION_TIMEOUT_TO_OPEN_MIC_MILLIS,
+                        TimeUnit.MILLISECONDS);
+
+                externalCallback.onKeyphraseDetected(recognitionEvent);
+            }
+
+            @Override
+            public void onRejected() throws RemoteException {
+                if (DEBUG) {
+                    Slog.d(TAG, "onRejected");
+                }
+                cancelingFuture.cancel(true);
+                externalCallback.onRejected(
+                        AlwaysOnHotwordDetector.HOTWORD_DETECTION_FALSE_ALERT);
+            }
+        };
+
         mRemoteHotwordDetectionService.run(
-                service -> service.detectFromDspSource(sessionId, callback));
+                service -> service.detectFromDspSource(
+                        clientRead,
+                        recognitionEvent.getCaptureFormat(),
+                        VALIDATION_TIMEOUT_MILLIS,
+                        internalCallback));
+        bestEffortCloseFileDescriptor(clientRead);
     }
 
     static final class SoundTriggerCallback extends IRecognitionStatusCallback.Stub {
         private SoundTrigger.KeyphraseRecognitionEvent mRecognitionEvent;
         private final HotwordDetectionConnection mHotwordDetectionConnection;
         private final IHotwordRecognitionStatusCallback mExternalCallback;
-        private final IDspHotwordDetectionCallback mInternalCallback;
 
         SoundTriggerCallback(IHotwordRecognitionStatusCallback callback,
                 HotwordDetectionConnection connection) {
             mHotwordDetectionConnection = connection;
             mExternalCallback = callback;
-            mInternalCallback = new IDspHotwordDetectionCallback.Stub() {
-                @Override
-                public void onDetected() throws RemoteException {
-                    if (DEBUG) {
-                        Slog.d(TAG, "onDetected");
-                    }
-                    mExternalCallback.onKeyphraseDetected(mRecognitionEvent);
-                }
-
-                @Override
-                public void onRejected() throws RemoteException {
-                    if (DEBUG) {
-                        Slog.d(TAG, "onRejected");
-                    }
-                    mExternalCallback.onRejected(
-                            AlwaysOnHotwordDetector.HOTWORD_DETECTION_FALSE_ALERT);
-                }
-            };
         }
 
         @Override
@@ -142,7 +230,7 @@
             if (useHotwordDetectionService) {
                 mRecognitionEvent = recognitionEvent;
                 mHotwordDetectionConnection.detectFromDspSource(
-                        recognitionEvent.getCaptureSession(), mInternalCallback);
+                        recognitionEvent, mExternalCallback);
             } else {
                 mExternalCallback.onKeyphraseDetected(recognitionEvent);
             }
@@ -171,6 +259,48 @@
         }
     }
 
+    // TODO: figure out if we need to let the client configure some of the parameters.
+    private static AudioRecord createAudioRecord(
+            @NonNull SoundTrigger.KeyphraseRecognitionEvent recognitionEvent) {
+        int sampleRate = recognitionEvent.getCaptureFormat().getSampleRate();
+        return new AudioRecord(
+                new AudioAttributes.Builder()
+                        .setInternalCapturePreset(MediaRecorder.AudioSource.HOTWORD).build(),
+                recognitionEvent.getCaptureFormat(),
+                getBufferSizeInBytes(sampleRate, MAX_STREAMING_SECONDS),
+                recognitionEvent.getCaptureSession());
+    }
+
+    /**
+     * Returns the number of bytes required to store {@code bufferLengthSeconds} of audio sampled at
+     * {@code sampleRate} Hz, using the format returned by DSP audio capture.
+     */
+    private static int getBufferSizeInBytes(int sampleRate, int bufferLengthSeconds) {
+        return BYTES_PER_SAMPLE * sampleRate * bufferLengthSeconds;
+    }
+
+    private static Pair<ParcelFileDescriptor, ParcelFileDescriptor> createPipe() {
+        ParcelFileDescriptor[] fileDescriptors;
+        try {
+            fileDescriptors = ParcelFileDescriptor.createPipe();
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed to create audio stream pipe", e);
+            return null;
+        }
+
+        return Pair.create(fileDescriptors[0], fileDescriptors[1]);
+    }
+
+    private static void bestEffortCloseFileDescriptor(ParcelFileDescriptor fd) {
+        try {
+            fd.close();
+        } catch (IOException e) {
+            if (DEBUG) {
+                Slog.w(TAG, "Failed closing file descriptor", e);
+            }
+        }
+    }
+
     public void dump(String prefix, PrintWriter pw) {
         pw.print(prefix); pw.print("mBound="); pw.println(mBound);
     }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index f687e4b..dce63eb 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -76,6 +76,7 @@
 import android.util.Log;
 import android.util.Slog;
 
+import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.IHotwordRecognitionStatusCallback;
 import com.android.internal.app.IVoiceActionCheckCallback;
@@ -430,25 +431,17 @@
                 // Eventually it will be an error to not specify this.
                 setCurInteractor(new ComponentName(curInteractorInfo.getServiceInfo().packageName,
                         curInteractorInfo.getServiceInfo().name), userHandle);
-                if (curInteractorInfo.getRecognitionService() != null) {
-                    setCurRecognizer(
-                            new ComponentName(curInteractorInfo.getServiceInfo().packageName,
-                                    curInteractorInfo.getRecognitionService()), userHandle);
-                    return;
-                }
+            } else {
+                // No voice interactor, so clear the setting.
+                setCurInteractor(null, userHandle);
             }
 
-            // No voice interactor, we'll just set up a simple recognizer.
-            initSimpleRecognizer(curInteractorInfo, userHandle);
+            initRecognizer(userHandle);
         }
 
-        public void initSimpleRecognizer(VoiceInteractionServiceInfo curInteractorInfo,
-                int userHandle) {
+        public void initRecognizer(int userHandle) {
             ComponentName curRecognizer = findAvailRecognizer(null, userHandle);
             if (curRecognizer != null) {
-                if (curInteractorInfo == null) {
-                    setCurInteractor(null, userHandle);
-                }
                 setCurRecognizer(curRecognizer, userHandle);
             }
         }
@@ -651,6 +644,10 @@
         }
 
         ComponentName findAvailRecognizer(String prefPackage, int userHandle) {
+            if (prefPackage == null) {
+                prefPackage = getDefaultRecognizer();
+            }
+
             List<ResolveInfo> available =
                     mContext.getPackageManager().queryIntentServicesAsUser(
                             new Intent(RecognitionService.SERVICE_INTERFACE),
@@ -678,6 +675,12 @@
             }
         }
 
+        @Nullable
+        public String getDefaultRecognizer() {
+            String recognizer = mContext.getString(R.string.config_systemSpeechRecognizer);
+            return TextUtils.isEmpty(recognizer) ? null : recognizer;
+        }
+
         ComponentName getCurRecognizer(int userHandle) {
             String curRecognizer = Settings.Secure.getStringForUser(
                     mContext.getContentResolver(),
@@ -1607,20 +1610,6 @@
                 }
             }
 
-            private @NonNull String getDefaultRecognizer(@NonNull UserHandle user) {
-                ResolveInfo resolveInfo = mPm.resolveServiceAsUser(
-                        new Intent(RecognitionService.SERVICE_INTERFACE),
-                        PackageManager.GET_META_DATA, user.getIdentifier());
-
-                if (resolveInfo == null || resolveInfo.serviceInfo == null) {
-                    Log.w(TAG, "Unable to resolve default voice recognition service.");
-                    return "";
-                }
-
-                return new ComponentName(resolveInfo.serviceInfo.packageName,
-                        resolveInfo.serviceInfo.name).flattenToShortString();
-            }
-
             /**
              * Convert the assistant-role holder into settings. The rest of the system uses the
              * settings.
@@ -1642,9 +1631,6 @@
                             Settings.Secure.ASSISTANT, "", userId);
                     Settings.Secure.putStringForUser(getContext().getContentResolver(),
                             Settings.Secure.VOICE_INTERACTION_SERVICE, "", userId);
-                    Settings.Secure.putStringForUser(getContext().getContentResolver(),
-                            Settings.Secure.VOICE_RECOGNITION_SERVICE, getDefaultRecognizer(user),
-                            userId);
                 } else {
                     // Assistant is singleton role
                     String pkg = roleHolders.get(0);
@@ -1671,9 +1657,6 @@
                         Settings.Secure.putStringForUser(getContext().getContentResolver(),
                                 Settings.Secure.VOICE_INTERACTION_SERVICE, serviceComponentName,
                                 userId);
-                        Settings.Secure.putStringForUser(getContext().getContentResolver(),
-                                Settings.Secure.VOICE_RECOGNITION_SERVICE, serviceRecognizerName,
-                                userId);
 
                         return;
                     }
@@ -1693,9 +1676,6 @@
                                 activityInfo.getComponentName().flattenToShortString(), userId);
                         Settings.Secure.putStringForUser(getContext().getContentResolver(),
                                 Settings.Secure.VOICE_INTERACTION_SERVICE, "", userId);
-                        Settings.Secure.putStringForUser(getContext().getContentResolver(),
-                                Settings.Secure.VOICE_RECOGNITION_SERVICE,
-                                getDefaultRecognizer(user), userId);
                         return;
                     }
                 }
@@ -1772,7 +1752,9 @@
                     synchronized (VoiceInteractionManagerServiceStub.this) {
                         Slog.i(TAG, "Force stopping current voice recognizer: "
                                 + getCurRecognizer(userHandle));
-                        initSimpleRecognizer(null, userHandle);
+                        // TODO: Figure out why the interactor was being cleared and document it.
+                        setCurInteractor(null, userHandle);
+                        initRecognizer(userHandle);
                     }
                 }
                 return hitInt || hitRec;
@@ -1793,6 +1775,9 @@
                 if (isPackageAppearing(pkgName) != PACKAGE_UNCHANGED) {
                     return;
                 }
+                if (getCurRecognizer(mCurUser) == null) {
+                    initRecognizer(mCurUser);
+                }
                 final String curInteractorStr = Settings.Secure.getStringForUser(
                         mContext.getContentResolver(),
                         Settings.Secure.VOICE_INTERACTION_SERVICE, mCurUser);
@@ -1807,12 +1792,6 @@
                                 availInteractorInfo.getServiceInfo().packageName,
                                 availInteractorInfo.getServiceInfo().name);
                         setCurInteractor(availInteractor, mCurUser);
-                        if (getCurRecognizer(mCurUser) == null &&
-                                availInteractorInfo.getRecognitionService() != null) {
-                            setCurRecognizer(new ComponentName(
-                                    availInteractorInfo.getServiceInfo().packageName,
-                                    availInteractorInfo.getRecognitionService()), mCurUser);
-                        }
                     }
                 } else {
                     if (didSomePackagesChange()) {
@@ -1843,10 +1822,7 @@
                     if (curRecognizer == null) {
                         // Could a new recognizer appear when we don't have one pre-installed?
                         if (anyPackagesAppearing()) {
-                            curRecognizer = findAvailRecognizer(null, userHandle);
-                            if (curRecognizer != null) {
-                                setCurRecognizer(curRecognizer, userHandle);
-                            }
+                            initRecognizer(userHandle);
                         }
                         return;
                     }
diff --git a/services/wifi/Android.bp b/services/wifi/Android.bp
index fcfcbeb..7f22bd8b 100644
--- a/services/wifi/Android.bp
+++ b/services/wifi/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "services.wifi-sources",
     srcs: ["java/**/*.java"],
diff --git a/startop/apps/test/Android.bp b/startop/apps/test/Android.bp
index f42c755..98b9b64e 100644
--- a/startop/apps/test/Android.bp
+++ b/startop/apps/test/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "startop_test_app",
     srcs: [
diff --git a/startop/iorap/Android.bp b/startop/iorap/Android.bp
index 993d1e1..4fdf34c 100644
--- a/startop/iorap/Android.bp
+++ b/startop/iorap/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
   name: "services.startop.iorap-javasources",
   srcs: ["src/**/*.java"],
diff --git a/startop/iorap/functional_tests/Android.bp b/startop/iorap/functional_tests/Android.bp
index 8a5bd34..43c6155 100644
--- a/startop/iorap/functional_tests/Android.bp
+++ b/startop/iorap/functional_tests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "iorap-functional-tests",
     srcs: ["src/**/*.java"],
@@ -39,4 +48,3 @@
     certificate: "platform",
     platform_apis: true,
 }
-
diff --git a/startop/iorap/stress/Android.bp b/startop/iorap/stress/Android.bp
index f9f251bd..6e8725d 100644
--- a/startop/iorap/stress/Android.bp
+++ b/startop/iorap/stress/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_binary {
   name: "iorap.stress.memory",
   srcs: ["main_memory.cc"],
diff --git a/startop/iorap/tests/Android.bp b/startop/iorap/tests/Android.bp
index 3e60ad4..ad3d001 100644
--- a/startop/iorap/tests/Android.bp
+++ b/startop/iorap/tests/Android.bp
@@ -13,6 +13,15 @@
 // limitations under the License.
 
 // TODO: once b/80095087 is fixed, rewrite this back to android_test
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library {
     name: "libiorap-java-test-lib",
     srcs: ["src/**/*.kt"],
diff --git a/startop/view_compiler/Android.bp b/startop/view_compiler/Android.bp
index cac7b82..9023921 100644
--- a/startop/view_compiler/Android.bp
+++ b/startop/view_compiler/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_defaults {
     name: "viewcompiler_defaults",
     header_libs: [
diff --git a/startop/view_compiler/dex_builder_test/Android.bp b/startop/view_compiler/dex_builder_test/Android.bp
index f783aa6..2048964 100644
--- a/startop/view_compiler/dex_builder_test/Android.bp
+++ b/startop/view_compiler/dex_builder_test/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 genrule {
     name: "generate_compiled_layout1",
     tools: [":viewcompiler"],
diff --git a/core/java/android/service/screenshot/ScreenshotHash.aidl b/telecomm/java/android/telecom/Connection.aidl
similarity index 73%
copy from core/java/android/service/screenshot/ScreenshotHash.aidl
copy to telecomm/java/android/telecom/Connection.aidl
index a7c50db..5b40036 100644
--- a/core/java/android/service/screenshot/ScreenshotHash.aidl
+++ b/telecomm/java/android/telecom/Connection.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -11,9 +11,12 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License.
+ * limitations under the License
  */
 
-package android.service.screenshot;
+package android.telecom;
 
-parcelable ScreenshotHash;
+/**
+ * {@hide}
+ */
+parcelable Connection.CallFilteringCompletionInfo;
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 942a54e..7c6253ce 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -29,6 +29,7 @@
 import android.app.Notification;
 import android.bluetooth.BluetoothDevice;
 import android.compat.annotation.UnsupportedAppUsage;
+import android.content.ComponentName;
 import android.content.Intent;
 import android.hardware.camera2.CameraManager;
 import android.net.Uri;
@@ -38,7 +39,9 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.telephony.ims.ImsStreamMediaProfile;
@@ -3379,6 +3382,121 @@
     public void handleRttUpgradeResponse(@Nullable RttTextStream rttTextStream) {}
 
     /**
+     * Information provided to a {@link Connection} upon completion of call filtering in Telecom.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final class CallFilteringCompletionInfo implements Parcelable {
+        private final boolean mIsBlocked;
+        private final boolean mIsInContacts;
+        private final CallScreeningService.CallResponse mCallResponse;
+        private final ComponentName mCallScreeningComponent;
+
+        /**
+         * Constructor for {@link CallFilteringCompletionInfo}
+         *
+         * @param isBlocked Whether any part of the call filtering process indicated that this call
+         *                  should be blocked.
+         * @param isInContacts Whether the caller is in the user's contacts.
+         * @param callResponse The instance of {@link CallScreeningService.CallResponse} provided
+         *                     by the {@link CallScreeningService} that processed this call, or
+         *                     {@code null} if no call screening service ran.
+         * @param callScreeningComponent The component of the {@link CallScreeningService}
+         *                                 that processed this call, or {@link null} if no
+         *                                 call screening service ran.
+         */
+        public CallFilteringCompletionInfo(boolean isBlocked, boolean isInContacts,
+                @Nullable CallScreeningService.CallResponse callResponse,
+                @Nullable ComponentName callScreeningComponent) {
+            mIsBlocked = isBlocked;
+            mIsInContacts = isInContacts;
+            mCallResponse = callResponse;
+            mCallScreeningComponent = callScreeningComponent;
+        }
+
+        /** @hide */
+        protected CallFilteringCompletionInfo(Parcel in) {
+            mIsBlocked = in.readByte() != 0;
+            mIsInContacts = in.readByte() != 0;
+            CallScreeningService.ParcelableCallResponse response
+                    = in.readParcelable(CallScreeningService.class.getClassLoader());
+            mCallResponse = response == null ? null : response.toCallResponse();
+            mCallScreeningComponent = in.readParcelable(ComponentName.class.getClassLoader());
+        }
+
+        @NonNull
+        public static final Creator<CallFilteringCompletionInfo> CREATOR =
+                new Creator<CallFilteringCompletionInfo>() {
+                    @Override
+                    public CallFilteringCompletionInfo createFromParcel(Parcel in) {
+                        return new CallFilteringCompletionInfo(in);
+                    }
+
+                    @Override
+                    public CallFilteringCompletionInfo[] newArray(int size) {
+                        return new CallFilteringCompletionInfo[size];
+                    }
+                };
+
+        /**
+         * @return Whether any part of the call filtering process indicated that this call should be
+         *         blocked.
+         */
+        public boolean isBlocked() {
+            return mIsBlocked;
+        }
+
+        /**
+         * @return Whether the caller is in the user's contacts.
+         */
+        public boolean isInContacts() {
+            return mIsInContacts;
+        }
+
+        /**
+         * @return The instance of {@link CallScreeningService.CallResponse} provided
+         *         by the {@link CallScreeningService} that processed this
+         *         call, or {@code null} if no call screening service ran.
+         */
+        public @Nullable CallScreeningService.CallResponse getCallResponse() {
+            return mCallResponse;
+        }
+
+        /**
+         * @return The component of the {@link CallScreeningService}
+         *         that processed this call, or {@code null} if no call screening service ran.
+         */
+        public @Nullable ComponentName getCallScreeningComponent() {
+            return mCallScreeningComponent;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public String toString() {
+            return "CallFilteringCompletionInfo{" +
+                    "mIsBlocked=" + mIsBlocked +
+                    ", mIsInContacts=" + mIsInContacts +
+                    ", mCallResponse=" + mCallResponse +
+                    ", mCallScreeningPackageName='" + mCallScreeningComponent + '\'' +
+                    '}';
+        }
+
+        /** @hide */
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeByte((byte) (mIsBlocked ? 1 : 0));
+            dest.writeByte((byte) (mIsInContacts ? 1 : 0));
+            dest.writeParcelable(mCallResponse == null ? null : mCallResponse.toParcelable(), 0);
+            dest.writeParcelable(mCallScreeningComponent, 0);
+        }
+    }
+
+    /**
      * Indicates that call filtering in Telecom is complete
      *
      * This method is called for a connection created via
@@ -3386,24 +3504,13 @@
      * Telecom, including checking the blocked number db, per-contact settings, and custom call
      * filtering apps.
      *
-     * @param isBlocked {@code true} if the call was blocked, {@code false} otherwise. If this is
-     *                  {@code true}, {@link #onDisconnect()} will be called soon after
-     *                  this is called.
-     * @param isInContacts Indicates whether the caller is in the user's contacts list.
-     * @param callScreeningResponse The response that was returned from the
-     *                              {@link CallScreeningService} that handled this call. If no
-     *                              response was received from a call screening service,
-     *                              this will be {@code null}.
-     * @param isResponseFromSystemDialer Whether {@code callScreeningResponse} was sent from the
-     *                                  system dialer. If {@code callScreeningResponse} is
-     *                                  {@code null}, this will be {@code false}.
+     * @param callFilteringCompletionInfo Info provided by Telecom on the results of call filtering.
      * @hide
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.READ_CONTACTS)
-    public void onCallFilteringCompleted(boolean isBlocked, boolean isInContacts,
-            @Nullable CallScreeningService.CallResponse callScreeningResponse,
-            boolean isResponseFromSystemDialer) { }
+    public void onCallFilteringCompleted(
+            @NonNull CallFilteringCompletionInfo callFilteringCompletionInfo) { }
 
     static String toLogSafePhoneNumber(String number) {
         // For unknown number, log empty string.
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 966ece3..c189b19 100755
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -758,19 +758,15 @@
         }
 
         @Override
-        public void onCallFilteringCompleted(String callId, boolean isBlocked, boolean isInContacts,
-                CallScreeningService.ParcelableCallResponse callScreeningResponse,
-                boolean isResponseFromSystemDialer,
+        public void onCallFilteringCompleted(String callId,
+                Connection.CallFilteringCompletionInfo completionInfo,
                 Session.Info sessionInfo) {
             Log.startSession(sessionInfo, SESSION_CALL_FILTERING_COMPLETED);
             try {
                 SomeArgs args = SomeArgs.obtain();
                 args.arg1 = callId;
-                args.arg2 = isBlocked;
-                args.arg3 = isInContacts;
-                args.arg4 = callScreeningResponse;
-                args.arg5 = isResponseFromSystemDialer;
-                args.arg6 = Log.createSubsession();
+                args.arg2 = completionInfo;
+                args.arg3 = Log.createSubsession();
                 mHandler.obtainMessage(MSG_ON_CALL_FILTERING_COMPLETED, args).sendToTarget();
             } finally {
                 Log.endSession();
@@ -1441,16 +1437,12 @@
                 case MSG_ON_CALL_FILTERING_COMPLETED: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        Log.continueSession((Session) args.arg6,
+                        Log.continueSession((Session) args.arg3,
                                 SESSION_HANDLER + SESSION_CALL_FILTERING_COMPLETED);
                         String callId = (String) args.arg1;
-                        boolean isBlocked = (boolean) args.arg2;
-                        boolean isInContacts = (boolean) args.arg3;
-                        CallScreeningService.ParcelableCallResponse callScreeningResponse =
-                                (CallScreeningService.ParcelableCallResponse) args.arg4;
-                        boolean isResponseFromSystemDialer = (boolean) args.arg5;
-                        onCallFilteringCompleted(callId, isBlocked, isInContacts,
-                                callScreeningResponse, isResponseFromSystemDialer);
+                        Connection.CallFilteringCompletionInfo completionInfo =
+                                (Connection.CallFilteringCompletionInfo) args.arg2;
+                        onCallFilteringCompleted(callId, completionInfo);
                     } finally {
                         args.recycle();
                         Log.endSession();
@@ -2466,16 +2458,12 @@
         }
     }
 
-    private void onCallFilteringCompleted(String callId, boolean isBlocked, boolean isInContacts,
-            CallScreeningService.ParcelableCallResponse callScreeningResponse,
-            boolean isResponseFromSystemDialer) {
-        Log.i(this, "onCallFilteringCompleted(%s, %b, %b, %s, %b)", callId,
-                isBlocked, isInContacts, callScreeningResponse, isResponseFromSystemDialer);
+    private void onCallFilteringCompleted(String callId, Connection.CallFilteringCompletionInfo
+            callFilteringCompletionInfo) {
+        Log.i(this, "onCallFilteringCompleted(%s, %s)", callId, callFilteringCompletionInfo);
         Connection connection = findConnectionForAction(callId, "onCallFilteringCompleted");
         if (connection != null) {
-            connection.onCallFilteringCompleted(isBlocked, isInContacts,
-                    callScreeningResponse == null ? null : callScreeningResponse.toCallResponse(),
-                    isResponseFromSystemDialer);
+            connection.onCallFilteringCompleted(callFilteringCompletionInfo);
         }
     }
 
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index 5cf8de8..f20ee7e 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -138,6 +138,24 @@
  *     }
  * }
  * }
+ *
+ * </pre>
+ * <p id="companionInCallService">
+ * <h3>Access to InCallService for Wearable Devices</h3>
+ * <ol>
+ * If your app is a third-party companion app and wants to access InCallService APIs, what your
+ * app could do are:
+ * <p>
+ *   <ol>
+ *     <li> Declare MANAGE_ONGOING_CALLS permission in your manifest
+ *     <li> Associate with a physical wearable device via the
+ *          {@link android.companion.CompanionDeviceManager} API as a companion app. See:
+ *          https://developer.android.com/guide/topics/connectivity/companion-device-pairing
+ *     <li> Implement this InCallService with BIND_INCALL_SERVICE permission
+ *   </ol>
+ * </ol>
+ * <p>
+ *
  * </pre>
  * <p id="incomingCallNotification">
  * <h3>Showing the Incoming Call Notification</h3>
diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java
index 6c6097a..7a6fddb 100644
--- a/telecomm/java/android/telecom/RemoteConnection.java
+++ b/telecomm/java/android/telecom/RemoteConnection.java
@@ -1202,27 +1202,18 @@
     /**
      * Notifies this {@link RemoteConnection} that call filtering has completed, as well as
      * the results of a contacts lookup for the remote party.
-     * @param isBlocked Whether call filtering indicates that the call should be blocked
-     * @param isInContacts Whether the remote party is in the user's contacts
-     * @param callScreeningResponse The response that was returned from the
-     *                              {@link CallScreeningService} that handled this call. If no
-     *                              response was received from a call screening service,
-     *                              this will be {@code null}.
-     * @param isResponseFromSystemDialer Whether {@code callScreeningResponse} was sent from the
-     *                                  system dialer. If {@code callScreeningResponse} is
-     *                                  {@code null}, this will be {@code false}.
+     *
+     * @param completionInfo Info provided by Telecom on the results of call filtering.
      * @hide
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.READ_CONTACTS)
-    public void onCallFilteringCompleted(boolean isBlocked, boolean isInContacts,
-            @Nullable CallScreeningService.CallResponse callScreeningResponse,
-            boolean isResponseFromSystemDialer) {
+    public void onCallFilteringCompleted(
+            @NonNull Connection.CallFilteringCompletionInfo completionInfo) {
         Log.startSession("RC.oCFC", getActiveOwnerInfo());
         try {
             if (mConnected) {
-                mConnectionService.onCallFilteringCompleted(mConnectionId, isBlocked, isInContacts,
-                        callScreeningResponse.toParcelable(), isResponseFromSystemDialer,
+                mConnectionService.onCallFilteringCompleted(mConnectionId, completionInfo,
                         null /*Session.Info*/);
             }
         } catch (RemoteException ignored) {
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 472d639..17749e8 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1702,22 +1702,22 @@
     }
 
     /**
-     * Returns whether the caller has {@link InCallService} access for companion apps.
-     *
-     * A companion app is an app associated with a physical wearable device via the
-     * {@link android.companion.CompanionDeviceManager} API.
+     * Returns whether the caller has {@link android.Manifest.permission#MANAGE_ONGOING_CALLS}
+     * permission. The permission can be obtained by associating with a physical wearable device
+     * via the {@link android.companion.CompanionDeviceManager} API as a companion app. If the
+     * caller app has the permission, it has {@link InCallService} access to manage ongoing calls.
      *
      * @return {@code true} if the caller has {@link InCallService} access for
      *      companion app; {@code false} otherwise.
      */
-    public boolean hasCompanionInCallServiceAccess() {
+    public boolean hasManageOngoingCallsPermission() {
         ITelecomService service = getTelecomService();
         if (service != null) {
             try {
-                return service.hasCompanionInCallServiceAccess(
+                return service.hasManageOngoingCallsPermission(
                         mContext.getOpPackageName());
             } catch (RemoteException e) {
-                Log.e(TAG, "RemoteException calling hasCompanionInCallServiceAccess().", e);
+                Log.e(TAG, "RemoteException calling hasManageOngoingCallsPermission().", e);
                 if (!isSystemProcess()) {
                     e.rethrowAsRuntimeException();
                 }
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
index 7599e18..d72f8aa 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -20,7 +20,7 @@
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 import android.telecom.CallAudioState;
-import android.telecom.CallScreeningService;
+import android.telecom.Connection;
 import android.telecom.ConnectionRequest;
 import android.telecom.Logging.Session;
 import android.telecom.PhoneAccountHandle;
@@ -119,9 +119,9 @@
 
     void sendCallEvent(String callId, String event, in Bundle extras, in Session.Info sessionInfo);
 
-    void onCallFilteringCompleted(String callId, boolean isBlocked, boolean isInContacts,
-            in CallScreeningService.ParcelableCallResponse callScreeningResponse,
-            boolean isResponseFromSystemDialer, in Session.Info sessionInfo);
+    void onCallFilteringCompleted(String callId,
+            in Connection.CallFilteringCompletionInfo completionInfo,
+            in Session.Info sessionInfo);
 
     void onExtrasChanged(String callId, in Bundle extras, in Session.Info sessionInfo);
 
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 88ef1b0..eb106b5 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -179,9 +179,9 @@
     boolean isInCall(String callingPackage, String callingFeatureId);
 
     /**
-     * @see TelecomServiceImpl#hasCompanionInCallServiceAccess
+     * @see TelecomServiceImpl#hasManageOngoingCallsPermission
      */
-    boolean hasCompanionInCallServiceAccess(String callingPackage);
+    boolean hasManageOngoingCallsPermission(String callingPackage);
 
     /**
      * @see TelecomServiceImpl#isInManagedCall
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index 48a5ab6..5e50bea 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -686,6 +686,67 @@
     }
 
     /**
+     * Given a list of permissions, check to see if the caller has at least one of them. If the
+     * caller has none of these permissions, throw a SecurityException.
+     */
+    public static void enforceAnyPermissionGranted(Context context, int uid, String message,
+            String... permissions) {
+        if (permissions.length == 0) return;
+        boolean isGranted = false;
+        for (String perm : permissions) {
+            if (context.checkCallingOrSelfPermission(perm) == PERMISSION_GRANTED) {
+                isGranted = true;
+                break;
+            }
+        }
+
+        if (isGranted) return;
+
+        StringBuilder b = new StringBuilder(message);
+        b.append(": Neither user ");
+        b.append(uid);
+        b.append(" nor current process has ");
+        b.append(permissions[0]);
+        for (int i = 1; i < permissions.length; i++) {
+            b.append(" or ");
+            b.append(permissions[i]);
+        }
+        throw new SecurityException(b.toString());
+    }
+
+    /**
+     * Given a list of permissions, check to see if the caller has at least one of them granted. If
+     * not, check to see if the caller has carrier privileges. If the caller does not have any  of
+     * these permissions, throw a SecurityException.
+     */
+    public static void enforceAnyPermissionGrantedOrCarrierPrivileges(Context context, int subId,
+            int uid, String message, String... permissions) {
+        if (permissions.length == 0) return;
+        boolean isGranted = false;
+        for (String perm : permissions) {
+            if (context.checkCallingOrSelfPermission(perm) == PERMISSION_GRANTED) {
+                isGranted = true;
+                break;
+            }
+        }
+
+        if (isGranted) return;
+        if (checkCarrierPrivilegeForSubId(context, subId)) return;
+
+        StringBuilder b = new StringBuilder(message);
+        b.append(": Neither user ");
+        b.append(uid);
+        b.append(" nor current process has ");
+        b.append(permissions[0]);
+        for (int i = 1; i < permissions.length; i++) {
+            b.append(" or ");
+            b.append(permissions[i]);
+        }
+        b.append(" or carrier privileges");
+        throw new SecurityException(b.toString());
+    }
+
+    /**
      * Throws if the caller is not of a shell (or root) UID.
      *
      * @param callingUid pass Binder.callingUid().
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index c6757fb..4ae11b8 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -111,6 +111,7 @@
     public @interface NetworkType {
     }
 
+    // TODO(b/180542000): remove and replace references with @ApnSetting.ApnType
     @IntDef(flag = true, prefix = {"TYPE_"}, value = {
             ApnSetting.TYPE_DEFAULT,
             ApnSetting.TYPE_MMS,
@@ -124,6 +125,7 @@
             ApnSetting.TYPE_EMERGENCY,
             ApnSetting.TYPE_MCX,
             ApnSetting.TYPE_XCAP,
+            // ApnSetting.TYPE_ENTERPRISE
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ApnType {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 6d3fa81..b52f4919 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -33,7 +33,11 @@
 import android.service.carrier.CarrierService;
 import android.telecom.TelecomManager;
 import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsRegistrationAttributes;
 import android.telephony.ims.ImsSsData;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.feature.MmTelFeature;
+import android.telephony.ims.feature.RcsFeature;
 
 import com.android.internal.telephony.ICarrierConfigLoader;
 import com.android.telephony.Rlog;
@@ -1717,8 +1721,14 @@
      * Configs used for APN setup.
      */
     public static final class Apn {
-        /** Prefix of all Apn.KEY_* constants. */
-        private static final String KEY_PREFIX = "apn.";
+        /**
+         * Prefix of all Apn.KEY_* constants.
+         *
+         * @deprecated Since KEY_PREFIX is unnecessary to public, it will modify to private
+         * next android generation.
+         */
+        @Deprecated
+        public static final String KEY_PREFIX = "apn.";
 
         /** IPv4 internet protocol */
         public static final String PROTOCOL_IPV4 = "IP";
@@ -3666,14 +3676,13 @@
         /** Prefix of all ImsServiceEntitlement.KEY_* constants. */
         public static final String KEY_PREFIX = "imsserviceentitlement.";
 
-
         /** The address of the entitlement configuration server. */
-        public static final String KEY_AES_URL_STRING = KEY_PREFIX + "aes_url_string";
-
+        public static final String KEY_ENTITLEMENT_SERVER_URL_STRING =
+                KEY_PREFIX + "entitlement_server_url_string";
 
         private static PersistableBundle getDefaults() {
             PersistableBundle defaults = new PersistableBundle();
-            defaults.putString(KEY_AES_URL_STRING, "");
+            defaults.putString(KEY_ENTITLEMENT_SERVER_URL_STRING, "");
             return defaults;
         }
     }
@@ -4001,6 +4010,43 @@
                 KEY_PREFIX + "enable_presence_publish_bool";
 
         /**
+         * Each string in this array contains a mapping between the service-id and version portion
+         * of the service-description element and the associated IMS feature tag(s) that are
+         * associated with each element (see RCC.07 Table 7).
+         * <p>
+         * Each string contains 3 parts, which define the mapping between service-description and
+         * feature tag(s) that must be present in the IMS REGISTER for the RCS service to be
+         * published as part of the RCS PUBLISH procedure:
+         * [service-id]|[version]|[desc]|[feature_tag];[feature_tag];...
+         * <ul>
+         *   <li>[service-id]: the service-id element associated with the RCS capability.</li>
+         *   <li>[version]: The version element associated with that service-id</li>
+         *   <li>[desc]: The optional desecription element associated with that service-id</li>
+         *   <li>[feature_tag];[feature_tag]: The list of all feature tags associated with this
+         *       capability that MUST ALL be present in the IMS registration for this this
+         *       capability to be published to the network.</li>
+         * </ul>
+         * <p>
+         * Features managed by the framework will be considered capable when the ImsService reports
+         * that those services are capable via the
+         * {@link MmTelFeature#notifyCapabilitiesStatusChanged(MmTelFeature.MmTelCapabilities)} or
+         * {@link RcsFeature#notifyCapabilitiesStatusChanged(RcsFeature.RcsImsCapabilities)} APIs.
+         * For RCS services not managed by the framework, the capability of these services are
+         * determined by looking at the feature tags associated with the IMS registration using the
+         * {@link ImsRegistrationAttributes} API and mapping them to the service-description map.
+         * <p>
+         * The framework contains a default value of this key, which is based off of RCC.07
+         * specification. Capabilities based of carrier extensions may be added to this list on a
+         * carrier-by-carrier basis as required in order to support additional services in the
+         * PUBLISH. If this list contains a service-id and version that overlaps with the default,
+         * it will override the framework default.
+         * @hide
+         */
+        @SystemApi
+        public static final String KEY_PUBLISH_SERVICE_DESC_FEATURE_TAG_MAP_OVERRIDE_STRING_ARRAY =
+                KEY_PREFIX + "publish_service_desc_feature_tag_map_override_string_array";
+
+        /**
          * Flag indicating whether or not this carrier supports the exchange of phone numbers with
          * the carrier's RCS presence server in order to retrieve the RCS capabilities of requested
          * contacts used in the RCS User Capability Exchange (UCE) procedure. See RCC.71, section 3
@@ -4059,6 +4105,8 @@
             defaults.putInt(KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT, 4000);
             defaults.putBoolean(KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, false);
             defaults.putBoolean(KEY_ENABLE_PRESENCE_PUBLISH_BOOL, false);
+            defaults.putStringArray(KEY_PUBLISH_SERVICE_DESC_FEATURE_TAG_MAP_OVERRIDE_STRING_ARRAY,
+                    new String[] {});
             defaults.putBoolean(KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL, false);
             defaults.putBoolean(KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL, false);
             defaults.putBoolean(KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL, true);
@@ -4230,10 +4278,6 @@
         public static final String KEY_RETRANSMIT_TIMER_MSEC_INT_ARRAY =
                 KEY_PREFIX + "retransmit_timer_sec_int_array";
 
-        /** Controls if wifi mac Id should be added to network access identifier(NAI) */
-        public static final String KEY_ADD_WIFI_MAC_ADDR_TO_NAI_BOOL =
-                KEY_PREFIX + "add_wifi_mac_addr_to_nai_bool";
-
         /**
          * Specifies the local identity type for IKE negotiations. Possible values are {@link
          * #ID_TYPE_FQDN}, {@link #ID_TYPE_RFC822_ADDR}, {@link #ID_TYPE_KEY_ID}
@@ -4557,7 +4601,6 @@
                     KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY,
                     new int[] {EPDG_ADDRESS_PLMN, EPDG_ADDRESS_STATIC});
             defaults.putStringArray(KEY_MCC_MNCS_STRING_ARRAY, new String[] {});
-            defaults.putBoolean(KEY_ADD_WIFI_MAC_ADDR_TO_NAI_BOOL, false);
             defaults.putInt(KEY_IKE_LOCAL_ID_TYPE_INT, ID_TYPE_RFC822_ADDR);
             defaults.putInt(KEY_IKE_REMOTE_ID_TYPE_INT, ID_TYPE_FQDN);
             defaults.putBoolean(KEY_ADD_KE_TO_CHILD_SESSION_REKEY_BOOL, false);
@@ -4749,7 +4792,7 @@
     public static final String KEY_NETWORK_TEMP_NOT_METERED_SUPPORTED_BOOL =
             "network_temp_not_metered_supported_bool";
 
-    /*
+    /**
      * Boolean indicating whether the SIM PIN can be stored and verified
      * seamlessly after an unattended reboot.
      *
@@ -4764,7 +4807,7 @@
     public static final String KEY_STORE_SIM_PIN_FOR_UNATTENDED_REBOOT_BOOL =
             "store_sim_pin_for_unattended_reboot_bool";
 
-     /**
+    /**
      * Determine whether "Enable 2G" toggle can be shown.
      *
      * Used to trade privacy/security against potentially reduced carrier coverage for some
@@ -4772,6 +4815,16 @@
      */
     public static final String KEY_HIDE_ENABLE_2G = "hide_enable_2g_bool";
 
+    /**
+     * Indicates the allowed APN types that can be used for LTE initial attach. The order of APN
+     * types in the configuration is the order of APN types that will be used for initial attach.
+     * Empty list indicates that no APN types are allowed for initial attach.
+     *
+     * @hide
+     */
+    public static final String KEY_ALLOWED_INITIAL_ATTACH_APN_TYPES_STRING_ARRAY =
+            "allowed_initial_attach_apn_types_string_array";
+
     /** The default value for every variable. */
     private final static PersistableBundle sDefaults;
 
@@ -5316,7 +5369,7 @@
         sDefaults.putStringArray(KEY_MISSED_INCOMING_CALL_SMS_ORIGINATOR_STRING_ARRAY,
                 new String[0]);
         sDefaults.putStringArray(KEY_APN_PRIORITY_STRING_ARRAY, new String[] {
-                "default:0", "mms:2", "supl:2", "dun:2", "hipri:3", "fota:2",
+                "default:0", "enterprise:1", "mms:2", "supl:2", "dun:2", "hipri:3", "fota:2",
                 "ims:2", "cbs:2", "ia:2", "emergency:2", "mcx:3", "xcap:3"
         });
         sDefaults.putStringArray(KEY_MISSED_INCOMING_CALL_SMS_PATTERN_STRING_ARRAY, new String[0]);
@@ -5330,6 +5383,8 @@
         sDefaults.putInt(KEY_DEFAULT_RTT_MODE_INT, 0);
         sDefaults.putBoolean(KEY_STORE_SIM_PIN_FOR_UNATTENDED_REBOOT_BOOL, true);
         sDefaults.putBoolean(KEY_HIDE_ENABLE_2G, false);
+        sDefaults.putStringArray(KEY_ALLOWED_INITIAL_ATTACH_APN_TYPES_STRING_ARRAY,
+                new String[]{"ia", "default", "ims", "mms", "dun", "emergency"});
     }
 
     /**
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index 99a77ae5..c8ed82c 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -917,6 +917,10 @@
     public static final int HANDOFF_PREFERENCE_CHANGED = 0x8CB;
     /** Data call fail due to the slice not being allowed for the data call. */
     public static final int SLICE_REJECTED = 0x8CC;
+    /** No matching rule available for the request, and match-all rule is not allowed for it. */
+    public static final int MATCH_ALL_RULE_NOT_ALLOWED = 0x8CD;
+    /** If connection failed for all matching URSP rules. */
+    public static final int ALL_MATCHING_RULES_FAILED = 0x8CE;
 
     //IKE error notifications message as specified in 3GPP TS 24.302 (Section 8.1.2.2).
 
diff --git a/telephony/java/android/telephony/SignalStrengthUpdateRequest.java b/telephony/java/android/telephony/SignalStrengthUpdateRequest.java
index af67ed2..fe7e5976 100644
--- a/telephony/java/android/telephony/SignalStrengthUpdateRequest.java
+++ b/telephony/java/android/telephony/SignalStrengthUpdateRequest.java
@@ -187,7 +187,7 @@
         return mIsSystemThresholdReportingRequestedWhileIdle;
     }
 
-    /*
+    /**
      * @return the live token of the request
      *
      * @hide
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 6c013df..4926687 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -2649,6 +2649,37 @@
      */
     public void sendMultimediaMessage(Context context, Uri contentUri, String locationUrl,
             Bundle configOverrides, PendingIntent sentIntent) {
+        sendMultimediaMessage(context, contentUri, locationUrl, configOverrides, sentIntent,
+                0L /* messageId */);
+    }
+
+    /**
+     * Send an MMS message
+     *
+     * Same as {@link #sendMultimediaMessage(Context context, Uri contentUri, String locationUrl,
+     *           Bundle configOverrides, PendingIntent sentIntent)}, but adds an optional messageId.
+     * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this
+     * manager on a multi-SIM device, this operation may fail sending the MMS message because no
+     * suitable default subscription could be found. In this case, if {@code sentIntent} is
+     * non-null, then the {@link PendingIntent} will be sent with an error code
+     * {@code RESULT_NO_DEFAULT_SMS_APP}. See {@link #getDefault()} for more information on the
+     * conditions where this operation may fail.
+     * </p>
+     *
+     * @param context application context
+     * @param contentUri the content Uri from which the message pdu will be read
+     * @param locationUrl the optional location url where message should be sent to
+     * @param configOverrides the carrier-specific messaging configuration values to override for
+     *  sending the message.
+     * @param sentIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is successfully sent, or failed
+     * @param messageId an id that uniquely identifies the message requested to be sent.
+     * Used for logging and diagnostics purposes. The id may be 0.
+     * @throws IllegalArgumentException if contentUri is empty
+     */
+    public void sendMultimediaMessage(@NonNull Context context, @NonNull Uri contentUri,
+            @Nullable String locationUrl, @Nullable Bundle configOverrides,
+            @Nullable PendingIntent sentIntent, long messageId) {
         if (contentUri == null) {
             throw new IllegalArgumentException("Uri contentUri null");
         }
@@ -2658,7 +2689,7 @@
                 @Override
                 public void onSuccess(int subId) {
                     m.sendMultimediaMessage(subId, contentUri, locationUrl, configOverrides,
-                            sentIntent, 0L /* messageId */);
+                            sentIntent, messageId);
                 }
 
                 @Override
@@ -2692,6 +2723,39 @@
      */
     public void downloadMultimediaMessage(Context context, String locationUrl, Uri contentUri,
             Bundle configOverrides, PendingIntent downloadedIntent) {
+        downloadMultimediaMessage(context, locationUrl, contentUri, configOverrides,
+                downloadedIntent, 0L /* messageId */);
+    }
+
+    /**
+     * Download an MMS message from carrier by a given location URL
+     *
+     * Same as {@link #downloadMultimediaMessage(Context context, String locationUrl,
+     *      Uri contentUri, Bundle configOverrides, PendingIntent downloadedIntent)},
+     *      but adds an optional messageId.
+     * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this
+     * manager on a multi-SIM device, this operation may fail downloading the MMS message because no
+     * suitable default subscription could be found. In this case, if {@code downloadedIntent} is
+     * non-null, then the {@link PendingIntent} will be sent with an error code
+     * {@code RESULT_NO_DEFAULT_SMS_APP}. See {@link #getDefault()} for more information on the
+     * conditions where this operation may fail.
+     * </p>
+     *
+     * @param context application context
+     * @param locationUrl the location URL of the MMS message to be downloaded, usually obtained
+     *  from the MMS WAP push notification
+     * @param contentUri the content uri to which the downloaded pdu will be written
+     * @param configOverrides the carrier-specific messaging configuration values to override for
+     *  downloading the message.
+     * @param downloadedIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is downloaded, or the download is failed
+     * @param messageId an id that uniquely identifies the message requested to be downloaded.
+     * Used for logging and diagnostics purposes. The id may be 0.
+     * @throws IllegalArgumentException if locationUrl or contentUri is empty
+     */
+    public void downloadMultimediaMessage(@NonNull Context context, @NonNull String locationUrl,
+            @NonNull Uri contentUri, @Nullable Bundle configOverrides,
+            @Nullable PendingIntent downloadedIntent, long messageId) {
         if (TextUtils.isEmpty(locationUrl)) {
             throw new IllegalArgumentException("Empty MMS location URL");
         }
@@ -2704,7 +2768,7 @@
                 @Override
                 public void onSuccess(int subId) {
                     m.downloadMultimediaMessage(subId, locationUrl, contentUri, configOverrides,
-                            downloadedIntent, 0L /* messageId */);
+                            downloadedIntent, messageId);
                 }
 
                 @Override
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 6a9b71d..61e809b 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -29,6 +29,7 @@
 import android.annotation.LongDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
@@ -8579,6 +8580,9 @@
      */
     @Deprecated
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    @RequiresFeature(
+            enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported",
+            value = TelephonyManager.CAPABILITY_ALLOWED_NETWORK_TYPES_USED)
     @SystemApi
     public boolean setAllowedNetworkTypes(@NetworkTypeBitMask long allowedNetworkTypes) {
         try {
@@ -8670,6 +8674,9 @@
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    @RequiresFeature(
+            enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported",
+            value = TelephonyManager.CAPABILITY_ALLOWED_NETWORK_TYPES_USED)
     public void setAllowedNetworkTypesForReason(@AllowedNetworkTypesReason int reason,
             @NetworkTypeBitMask long allowedNetworkTypes) {
         if (!isValidAllowedNetworkTypesReason(reason)) {
@@ -8708,6 +8715,9 @@
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @RequiresFeature(
+            enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported",
+            value = TelephonyManager.CAPABILITY_ALLOWED_NETWORK_TYPES_USED)
     public @NetworkTypeBitMask long getAllowedNetworkTypesForReason(
             @AllowedNetworkTypesReason int reason) {
         if (!isValidAllowedNetworkTypesReason(reason)) {
@@ -11293,21 +11303,16 @@
      *
      * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges})
-     * Additionally, depending on the level of location permissions the caller holds (i.e. no
-     * location permissions, {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}, or
-     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}), location-sensitive fields will
-     * be cleared from the return value.
-     *
-     * <p>Note also that if the caller holds any sort of location permission, a usage event for the
-     * {@link android.app.AppOpsManager#OPSTR_FINE_LOCATION} or
-     * {@link android.app.AppOpsManager#OPSTR_FINE_LOCATION}
-     * will be logged against the caller when calling this method.
+     * and {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}.
      *
      * May return {@code null} when the subscription is inactive or when there was an error
      * communicating with the phone process.
      */
     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
-    @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
+    @RequiresPermission(allOf = {
+            Manifest.permission.READ_PHONE_STATE,
+            Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     public @Nullable ServiceState getServiceState() {
         return getServiceStateForSubscriber(getSubId());
     }
@@ -15216,8 +15221,13 @@
      *     <li>Generate the ks_NAF/ ks_Ext_NAF to be returned via the callback.</li>
      * </ol>
      *
-     * <p> Requires Permission: MODIFY_PHONE_STATE or that the calling app has carrier
-     * privileges (see {@link #hasCarrierPrivileges}).
+     * <p> Requires Permission:
+     * <ul>
+     *     <li>{@link android.Manifest.permission#MODIFY_PHONE_STATE},</li>
+     *     <li>{@link android.Manifest.permission#PERFORM_IMS_SINGLE_REGISTRATION},</li>
+     *     <li>or that the caller has carrier privileges (see
+     *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+     * </ul>
      * @param appType icc application type, like {@link #APPTYPE_USIM} or {@link
      * #APPTYPE_ISIM} or {@link#APPTYPE_UNKNOWN}
      * @param nafId Network Application Function(NAF) fully qualified domain name and
@@ -15244,7 +15254,8 @@
      */
     @SystemApi
     @WorkerThread
-    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    @RequiresPermission(anyOf = {android.Manifest.permission.MODIFY_PHONE_STATE,
+            Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION})
     public void bootstrapAuthenticationRequest(
             @UiccAppTypeExt int appType, @NonNull Uri nafId,
             @NonNull UaSecurityProtocolIdentifier securityProtocol,
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index d58fa912..b503733 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -28,8 +28,6 @@
 import android.os.Parcelable;
 import android.provider.Telephony;
 import android.provider.Telephony.Carriers;
-import android.telephony.Annotation;
-import android.telephony.Annotation.ApnType;
 import android.telephony.Annotation.NetworkType;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
@@ -116,6 +114,31 @@
     public static final int TYPE_MCX = ApnTypes.MCX;
     /** APN type for XCAP. */
     public static final int TYPE_XCAP = ApnTypes.XCAP;
+    /**
+     * APN type for ENTERPRISE.
+     * @hide
+     */
+    public static final int TYPE_ENTERPRISE = TYPE_XCAP << 1;
+
+    /** @hide */
+    @IntDef(flag = true, prefix = {"TYPE_"}, value = {
+            TYPE_DEFAULT,
+            TYPE_MMS,
+            TYPE_SUPL,
+            TYPE_DUN,
+            TYPE_HIPRI,
+            TYPE_FOTA,
+            TYPE_IMS,
+            TYPE_CBS,
+            TYPE_IA,
+            TYPE_EMERGENCY,
+            TYPE_MCX,
+            TYPE_XCAP,
+            TYPE_ENTERPRISE,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ApnType {
+    }
 
     // Possible values for authentication types.
     /** No authentication type. */
@@ -151,6 +174,7 @@
             TYPE_MMS_STRING,
             TYPE_SUPL_STRING,
             TYPE_XCAP_STRING,
+            TYPE_ENTERPRISE_STRING,
     }, prefix = "TYPE_", suffix = "_STRING")
     @Retention(RetentionPolicy.SOURCE)
     public @interface ApnTypeString {}
@@ -291,6 +315,12 @@
     @SystemApi
     public static final String TYPE_XCAP_STRING = "xcap";
 
+    /**
+     * APN type for ENTERPRISE traffic.
+     * @hide
+     */
+    public static final String TYPE_ENTERPRISE_STRING = "enterprise";
+
 
     /** @hide */
     @IntDef(prefix = { "AUTH_TYPE_" }, value = {
@@ -370,6 +400,7 @@
         APN_TYPE_STRING_MAP.put(TYPE_EMERGENCY_STRING, TYPE_EMERGENCY);
         APN_TYPE_STRING_MAP.put(TYPE_MCX_STRING, TYPE_MCX);
         APN_TYPE_STRING_MAP.put(TYPE_XCAP_STRING, TYPE_XCAP);
+        APN_TYPE_STRING_MAP.put(TYPE_ENTERPRISE_STRING, TYPE_ENTERPRISE);
 
         APN_TYPE_INT_MAP = new ArrayMap<>();
         APN_TYPE_INT_MAP.put(TYPE_DEFAULT, TYPE_DEFAULT_STRING);
@@ -384,6 +415,7 @@
         APN_TYPE_INT_MAP.put(TYPE_EMERGENCY, TYPE_EMERGENCY_STRING);
         APN_TYPE_INT_MAP.put(TYPE_MCX, TYPE_MCX_STRING);
         APN_TYPE_INT_MAP.put(TYPE_XCAP, TYPE_XCAP_STRING);
+        APN_TYPE_INT_MAP.put(TYPE_ENTERPRISE, TYPE_ENTERPRISE_STRING);
 
         PROTOCOL_STRING_MAP = new ArrayMap<>();
         PROTOCOL_STRING_MAP.put("IP", PROTOCOL_IP);
@@ -1490,7 +1522,7 @@
      * @hide
      */
     @SystemApi
-    public static @NonNull @ApnTypeString String getApnTypeString(@Annotation.ApnType int apnType) {
+    public static @NonNull @ApnTypeString String getApnTypeString(@ApnType int apnType) {
         if (apnType == TYPE_ALL) {
             return "*";
         }
@@ -1503,7 +1535,7 @@
      * when provided with an invalid int for compatibility purposes.
      * @hide
      */
-    public static @NonNull String getApnTypeStringInternal(@Annotation.ApnType int apnType) {
+    public static @NonNull String getApnTypeStringInternal(@ApnType int apnType) {
         String result = getApnTypeString(apnType);
         return TextUtils.isEmpty(result) ? "Unknown" : result;
     }
@@ -1517,7 +1549,7 @@
      * @hide
      */
     @SystemApi
-    public static @Annotation.ApnType int getApnTypeInt(@NonNull @ApnTypeString String apnType) {
+    public static @ApnType int getApnTypeInt(@NonNull @ApnTypeString String apnType) {
         return APN_TYPE_STRING_MAP.getOrDefault(apnType.toLowerCase(), 0);
     }
 
@@ -2162,7 +2194,7 @@
         public ApnSetting build() {
             if ((mApnTypeBitmask & (TYPE_DEFAULT | TYPE_MMS | TYPE_SUPL | TYPE_DUN | TYPE_HIPRI
                     | TYPE_FOTA | TYPE_IMS | TYPE_CBS | TYPE_IA | TYPE_EMERGENCY | TYPE_MCX
-                    | TYPE_XCAP)) == 0
+                    | TYPE_XCAP | TYPE_ENTERPRISE)) == 0
                 || TextUtils.isEmpty(mApnName) || TextUtils.isEmpty(mEntryName)) {
                 return null;
             }
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index bd4bf07..a764229 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -138,6 +138,7 @@
     private final Qos mDefaultQos;
     private final List<QosBearerSession> mQosBearerSessions;
     private final SliceInfo mSliceInfo;
+    private final List<TrafficDescriptor> mTrafficDescriptors;
 
     /**
      * @param cause Data call fail cause. {@link DataFailCause#NONE} indicates no error.
@@ -189,6 +190,7 @@
         mDefaultQos = null;
         mQosBearerSessions = new ArrayList<>();
         mSliceInfo = null;
+        mTrafficDescriptors = new ArrayList<>();
     }
 
     private DataCallResponse(@DataFailureCause int cause, long suggestedRetryTime, int id,
@@ -198,7 +200,7 @@
             @Nullable List<InetAddress> pcscfAddresses, int mtu, int mtuV4, int mtuV6,
             @HandoverFailureMode int handoverFailureMode, int pduSessionId,
             @Nullable Qos defaultQos, @Nullable List<QosBearerSession> qosBearerSessions,
-            @Nullable SliceInfo sliceInfo) {
+            @Nullable SliceInfo sliceInfo, @Nullable List<TrafficDescriptor> trafficDescriptors) {
         mCause = cause;
         mSuggestedRetryTime = suggestedRetryTime;
         mId = id;
@@ -219,8 +221,11 @@
         mHandoverFailureMode = handoverFailureMode;
         mPduSessionId = pduSessionId;
         mDefaultQos = defaultQos;
-        mQosBearerSessions = qosBearerSessions;
+        mQosBearerSessions = (qosBearerSessions == null)
+                ? new ArrayList<>() : new ArrayList<>(qosBearerSessions);
         mSliceInfo = sliceInfo;
+        mTrafficDescriptors = (trafficDescriptors == null)
+                ? new ArrayList<>() : new ArrayList<>(trafficDescriptors);
     }
 
     /** @hide */
@@ -249,6 +254,8 @@
         mQosBearerSessions = new ArrayList<>();
         source.readList(mQosBearerSessions, QosBearerSession.class.getClassLoader());
         mSliceInfo = source.readParcelable(SliceInfo.class.getClassLoader());
+        mTrafficDescriptors = new ArrayList<>();
+        source.readList(mTrafficDescriptors, TrafficDescriptor.class.getClassLoader());
     }
 
     /**
@@ -381,7 +388,6 @@
      *
      * @hide
      */
-
     @Nullable
     public Qos getDefaultQos() {
         return mDefaultQos;
@@ -406,6 +412,14 @@
         return mSliceInfo;
     }
 
+    /**
+     * @return The traffic descriptors related to this data connection.
+     */
+    @NonNull
+    public List<TrafficDescriptor> getTrafficDescriptors() {
+        return mTrafficDescriptors;
+    }
+
     @NonNull
     @Override
     public String toString() {
@@ -429,6 +443,7 @@
            .append(" defaultQos=").append(mDefaultQos)
            .append(" qosBearerSessions=").append(mQosBearerSessions)
            .append(" sliceInfo=").append(mSliceInfo)
+           .append(" trafficDescriptors=").append(mTrafficDescriptors)
            .append("}");
         return sb.toString();
     }
@@ -443,15 +458,22 @@
 
         DataCallResponse other = (DataCallResponse) o;
 
-        final boolean isQosSame = (mDefaultQos == null || other.mDefaultQos == null) ?
-                mDefaultQos == other.mDefaultQos :
-                mDefaultQos.equals(other.mDefaultQos);
+        final boolean isQosSame = (mDefaultQos == null || other.mDefaultQos == null)
+                ? mDefaultQos == other.mDefaultQos
+                : mDefaultQos.equals(other.mDefaultQos);
 
-        final boolean isQosBearerSessionsSame = (mQosBearerSessions == null || mQosBearerSessions == null) ?
-                mQosBearerSessions == other.mQosBearerSessions :
-                mQosBearerSessions.size() == other.mQosBearerSessions.size()
+        final boolean isQosBearerSessionsSame =
+                (mQosBearerSessions == null || other.mQosBearerSessions == null)
+                ? mQosBearerSessions == other.mQosBearerSessions
+                : mQosBearerSessions.size() == other.mQosBearerSessions.size()
                 && mQosBearerSessions.containsAll(other.mQosBearerSessions);
 
+        final boolean isTrafficDescriptorsSame =
+                (mTrafficDescriptors == null || other.mTrafficDescriptors == null)
+                ? mTrafficDescriptors == other.mTrafficDescriptors
+                : mTrafficDescriptors.size() == other.mTrafficDescriptors.size()
+                && mTrafficDescriptors.containsAll(other.mTrafficDescriptors);
+
         return mCause == other.mCause
                 && mSuggestedRetryTime == other.mSuggestedRetryTime
                 && mId == other.mId
@@ -473,7 +495,8 @@
                 && mPduSessionId == other.mPduSessionId
                 && isQosSame
                 && isQosBearerSessionsSame
-                && Objects.equals(mSliceInfo, other.mSliceInfo);
+                && Objects.equals(mSliceInfo, other.mSliceInfo)
+                && isTrafficDescriptorsSame;
     }
 
     @Override
@@ -481,7 +504,7 @@
         return Objects.hash(mCause, mSuggestedRetryTime, mId, mLinkStatus, mProtocolType,
                 mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses, mPcscfAddresses,
                 mMtu, mMtuV4, mMtuV6, mHandoverFailureMode, mPduSessionId, mDefaultQos,
-                mQosBearerSessions, mSliceInfo);
+                mQosBearerSessions, mSliceInfo, mTrafficDescriptors);
     }
 
     @Override
@@ -517,6 +540,7 @@
         }
         dest.writeList(mQosBearerSessions);
         dest.writeParcelable(mSliceInfo, flags);
+        dest.writeList(mTrafficDescriptors);
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<DataCallResponse> CREATOR =
@@ -602,6 +626,8 @@
 
         private SliceInfo mSliceInfo;
 
+        private List<TrafficDescriptor> mTrafficDescriptors = new ArrayList<>();
+
         /**
          * Default constructor for Builder.
          */
@@ -841,6 +867,24 @@
         }
 
         /**
+         * The traffic descriptors for this data connection, as defined in 3GPP TS 24.526
+         * Section 5.2. They are used for URSP traffic matching as described in 3GPP TS 24.526
+         * Section 4.2.2. They includes an optional DNN, which, if present, must be used for traffic
+         * matching; it does not specify the end point to be used for the data call. The end point
+         * is specified by {@link DataProfile}, which must be used as the end point if one is not
+         * specified through URSP rules.
+         *
+         * @param trafficDescriptors the traffic descriptors for the data call.
+         *
+         * @return The same instance of the builder.
+         */
+        public @NonNull Builder setTrafficDescriptors(
+                @NonNull List<TrafficDescriptor> trafficDescriptors) {
+            mTrafficDescriptors = trafficDescriptors;
+            return this;
+        }
+
+        /**
          * Build the DataCallResponse.
          *
          * @return the DataCallResponse object.
@@ -849,7 +893,7 @@
             return new DataCallResponse(mCause, mSuggestedRetryTime, mId, mLinkStatus,
                     mProtocolType, mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses,
                     mPcscfAddresses, mMtu, mMtuV4, mMtuV6, mHandoverFailureMode, mPduSessionId,
-                    mDefaultQos, mQosBearerSessions, mSliceInfo);
+                    mDefaultQos, mQosBearerSessions, mSliceInfo, mTrafficDescriptors);
         }
     }
 }
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index 484c318..f5f29c6 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -200,6 +200,17 @@
          *        handover is occurring from EPDG to 5G.  If the slice passed is rejected, then
          *        {@link DataCallResponse#getCause()} is
          *        {@link android.telephony.DataFailCause#SLICE_REJECTED}.
+         * @param trafficDescriptor {@link TrafficDescriptor} for which data connection needs to be
+         *        established. It is used for URSP traffic matching as described in 3GPP TS 24.526
+         *        Section 4.2.2. It includes an optional DNN which, if present, must be used for
+         *        traffic matching; it does not specify the end point to be used for the data call.
+         * @param matchAllRuleAllowed Indicates if using default match-all URSP rule for this
+         *        request is allowed. If false, this request must not use the match-all URSP rule
+         *        and if a non-match-all rule is not found (or if URSP rules are not available) then
+         *        {@link DataCallResponse#getCause()} is
+         *        {@link android.telephony.DataFailCause#MATCH_ALL_RULE_NOT_ALLOWED}. This is needed
+         *        as some requests need to have a hard failure if the intention cannot be met,
+         *        for example, a zero-rating slice.
          * @param callback The result callback for this request.
          */
         public void setupDataCall(int accessNetworkType, @NonNull DataProfile dataProfile,
@@ -207,6 +218,7 @@
                 @SetupDataReason int reason,
                 @Nullable LinkProperties linkProperties,
                 @IntRange(from = 0, to = 15) int pduSessionId, @Nullable SliceInfo sliceInfo,
+                @Nullable TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed,
                 @NonNull DataServiceCallback callback) {
             /* Call the old version since the new version isn't supported */
             setupDataCall(accessNetworkType, dataProfile, isRoaming, allowRoaming, reason,
@@ -403,10 +415,13 @@
         public final LinkProperties linkProperties;
         public final int pduSessionId;
         public final SliceInfo sliceInfo;
+        public final TrafficDescriptor trafficDescriptor;
+        public final boolean matchAllRuleAllowed;
         public final IDataServiceCallback callback;
         SetupDataCallRequest(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
-                             boolean allowRoaming, int reason, LinkProperties linkProperties,
-                             int pduSessionId, SliceInfo sliceInfo, IDataServiceCallback callback) {
+                boolean allowRoaming, int reason, LinkProperties linkProperties, int pduSessionId,
+                SliceInfo sliceInfo, TrafficDescriptor trafficDescriptor,
+                boolean matchAllRuleAllowed, IDataServiceCallback callback) {
             this.accessNetworkType = accessNetworkType;
             this.dataProfile = dataProfile;
             this.isRoaming = isRoaming;
@@ -415,6 +430,8 @@
             this.reason = reason;
             this.pduSessionId = pduSessionId;
             this.sliceInfo = sliceInfo;
+            this.trafficDescriptor = trafficDescriptor;
+            this.matchAllRuleAllowed = matchAllRuleAllowed;
             this.callback = callback;
         }
     }
@@ -525,7 +542,8 @@
                             setupDataCallRequest.dataProfile, setupDataCallRequest.isRoaming,
                             setupDataCallRequest.allowRoaming, setupDataCallRequest.reason,
                             setupDataCallRequest.linkProperties, setupDataCallRequest.pduSessionId,
-                            setupDataCallRequest.sliceInfo,
+                            setupDataCallRequest.sliceInfo, setupDataCallRequest.trafficDescriptor,
+                            setupDataCallRequest.matchAllRuleAllowed,
                             (setupDataCallRequest.callback != null)
                                     ? new DataServiceCallback(setupDataCallRequest.callback)
                                     : null);
@@ -690,11 +708,12 @@
         public void setupDataCall(int slotIndex, int accessNetworkType, DataProfile dataProfile,
                 boolean isRoaming, boolean allowRoaming, int reason,
                 LinkProperties linkProperties, int pduSessionId, SliceInfo sliceInfo,
+                TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed,
                 IDataServiceCallback callback) {
             mHandler.obtainMessage(DATA_SERVICE_REQUEST_SETUP_DATA_CALL, slotIndex, 0,
                     new SetupDataCallRequest(accessNetworkType, dataProfile, isRoaming,
                             allowRoaming, reason, linkProperties, pduSessionId, sliceInfo,
-                            callback))
+                            trafficDescriptor, matchAllRuleAllowed, callback))
                     .sendToTarget();
         }
 
diff --git a/telephony/java/android/telephony/data/IDataService.aidl b/telephony/java/android/telephony/data/IDataService.aidl
index e0b9a1a..81f5fd3 100644
--- a/telephony/java/android/telephony/data/IDataService.aidl
+++ b/telephony/java/android/telephony/data/IDataService.aidl
@@ -20,6 +20,7 @@
 import android.telephony.data.DataProfile;
 import android.telephony.data.IDataServiceCallback;
 import android.telephony.data.SliceInfo;
+import android.telephony.data.TrafficDescriptor;
 
 /**
  * {@hide}
@@ -30,7 +31,9 @@
     void removeDataServiceProvider(int slotId);
     void setupDataCall(int slotId, int accessNetwork, in DataProfile dataProfile, boolean isRoaming,
                        boolean allowRoaming, int reason, in LinkProperties linkProperties,
-                       int pduSessionId, in SliceInfo sliceInfo, IDataServiceCallback callback);
+                       int pduSessionId, in SliceInfo sliceInfo,
+                       in TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed,
+                       IDataServiceCallback callback);
     void deactivateDataCall(int slotId, int cid, int reason, IDataServiceCallback callback);
     void setInitialAttachApn(int slotId, in DataProfile dataProfile, boolean isRoaming,
                              IDataServiceCallback callback);
diff --git a/core/java/android/service/screenshot/ScreenshotHash.aidl b/telephony/java/android/telephony/data/TrafficDescriptor.aidl
similarity index 80%
copy from core/java/android/service/screenshot/ScreenshotHash.aidl
copy to telephony/java/android/telephony/data/TrafficDescriptor.aidl
index a7c50db..a9c7604 100644
--- a/core/java/android/service/screenshot/ScreenshotHash.aidl
+++ b/telephony/java/android/telephony/data/TrafficDescriptor.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
-package android.service.screenshot;
+/** @hide */
+package android.telephony.data;
 
-parcelable ScreenshotHash;
+parcelable TrafficDescriptor;
diff --git a/telephony/java/android/telephony/data/TrafficDescriptor.java b/telephony/java/android/telephony/data/TrafficDescriptor.java
new file mode 100644
index 0000000..480379d
--- /dev/null
+++ b/telephony/java/android/telephony/data/TrafficDescriptor.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.data;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * A traffic descriptor, as defined in 3GPP TS 24.526 Section 5.2. It is used for URSP traffic
+ * matching as described in 3GPP TS 24.526 Section 4.2.2. It includes an optional DNN, which,
+ * if present, must be used for traffic matching; it does not specify the end point to be used for
+ * the data call.
+ * @hide
+ */
+@SystemApi
+public final class TrafficDescriptor implements Parcelable {
+    private final String mDnn;
+    private final String mOsAppId;
+
+    private TrafficDescriptor(@NonNull Parcel in) {
+        mDnn = in.readString();
+        mOsAppId = in.readString();
+    }
+
+    /**
+     * Create a traffic descriptor, as defined in 3GPP TS 24.526 Section 5.2
+     * @param dnn optional DNN, which must be used for traffic matching, if present
+     * @param osAppId OsId + osAppId of the traffic descriptor
+     */
+    public TrafficDescriptor(@Nullable String dnn, @Nullable String osAppId) {
+        mDnn = dnn;
+        mOsAppId = osAppId;
+    }
+
+    /**
+     * DNN stands for Data Network Name and represents an APN as defined in 3GPP TS 23.003.
+     * @return the DNN of this traffic descriptor.
+     */
+    public @Nullable String getDnn() {
+        return mDnn;
+    }
+
+    /**
+     * OsAppId represents the OsId + OsAppId as defined in 3GPP TS 24.526 Section 5.2.
+     * @return the OS App ID of this traffic descriptor.
+     */
+    public @Nullable String getOsAppId() {
+        return mOsAppId;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @NonNull @Override
+    public String toString() {
+        return "TrafficDescriptor={mDnn=" + mDnn + ", mOsAppId=" + mOsAppId + "}";
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString(mDnn);
+        dest.writeString(mOsAppId);
+    }
+
+    public static final @NonNull Parcelable.Creator<TrafficDescriptor> CREATOR =
+            new Parcelable.Creator<TrafficDescriptor>() {
+                @Override
+                public @NonNull TrafficDescriptor createFromParcel(@NonNull Parcel source) {
+                    return new TrafficDescriptor(source);
+                }
+
+                @Override
+                public @NonNull TrafficDescriptor[] newArray(int size) {
+                    return new TrafficDescriptor[size];
+                }
+            };
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        TrafficDescriptor that = (TrafficDescriptor) o;
+        return Objects.equals(mDnn, that.mDnn) && Objects.equals(mOsAppId, that.mOsAppId);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mDnn, mOsAppId);
+    }
+}
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index a9dae89..9bb4db8 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -282,6 +282,15 @@
     public static final String EXTRA_PICTURE_URL = "android.telephony.ims.extra.PICTURE_URL";
 
     /**
+     * Boolean extra indicating whether the call is a business call.
+     *
+     * This extra will be set to {@code true} if and only if the SIP INVITE headers contain the
+     * "Organization" header.
+     */
+    public static final String EXTRA_IS_BUSINESS_CALL =
+            "android.telephony.ims.extra.IS_BUSINESS_CALL";
+
+    /**
      * Values for EXTRA_OIR / EXTRA_CNAP
      */
     /**
@@ -791,7 +800,9 @@
                 + ", emergencyCallTesting=" + mEmergencyCallTesting
                 + ", hasKnownUserIntentEmergency=" + mHasKnownUserIntentEmergency
                 + ", mRestrictCause=" + mRestrictCause
-                + ", mCallerNumberVerstat= " + mCallerNumberVerificationStatus + " }";
+                + ", mCallerNumberVerstat= " + mCallerNumberVerificationStatus
+                + ", mAcceptedRtpHeaderExtensions= " + mAcceptedRtpHeaderExtensionTypes
+                + " }";
     }
 
     @Override
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index 31ba853..6fda2e1 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -32,6 +32,7 @@
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyFrameworkInitializer;
+import android.telephony.TelephonyManager;
 import android.telephony.ims.aidl.IImsConfigCallback;
 import android.telephony.ims.aidl.IRcsConfigCallback;
 import android.telephony.ims.feature.MmTelFeature;
@@ -1300,7 +1301,7 @@
      * provisioning.
      * <p>
      * Requires Permission: Manifest.permission.MODIFY_PHONE_STATE or that the calling app has
-     * carrier privileges (see {@link #hasCarrierPrivileges}).
+     * carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
      * @param config The XML file to be read. ASCII/UTF8 encoded text if not compressed.
      * @param isCompressed The XML file is compressed in gzip format and must be decompressed
      *         before being read.
@@ -1330,7 +1331,7 @@
      * the intent is valid. and {@link #EXTRA_STATUS} to specify RCS VoLTE single registration
      * status.
      */
-    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION)
     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE =
             "android.telephony.ims.action.RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE";
@@ -1375,7 +1376,7 @@
      * provisioning status events {@link #registerRcsProvisioningChangedCallback}
      * @param rcc RCS client configuration {@link RcsClientConfiguration}
      */
-    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION)
     public void setRcsClientConfiguration(
             @NonNull RcsClientConfiguration rcc) throws ImsException {
         try {
@@ -1390,6 +1391,14 @@
     /**
      * Returns a flag to indicate whether or not the device supports IMS single registration for
      * MMTEL and RCS features as well as if the carrier has provisioned the feature.
+     *
+     * <p> Requires Permission:
+     * <ul>
+     *     <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li>
+     *     <li>{@link android.Manifest.permission#PERFORM_IMS_SINGLE_REGISTRATION},</li>
+     *     <li>or that the caller has carrier privileges (see
+     *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+     * </ul>
      * @return true if IMS single registration is capable at this time, or false otherwise
      * @throws ImsException If the remote ImsService is not available for
      * any reason or the subscription associated with this instance is no
@@ -1398,7 +1407,8 @@
      * @see PackageManager#FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION for whether or not this
      * device supports IMS single registration.
      */
-    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION})
     public boolean isRcsVolteSingleRegistrationCapable() throws ImsException {
         try {
             return getITelephony().isRcsVolteSingleRegistrationCapable(mSubId);
@@ -1408,36 +1418,44 @@
     }
 
    /**
-     * Registers a new {@link RcsProvisioningCallback} to listen to changes to
-     * RCS provisioning xml.
-     *
-     * <p>RCS application must be the default messaging application and must
-     * have already registered its {@link RcsClientConfiguration} by using
-     * {@link #setRcsClientConfiguration} before it registers the provisioning
-     * callback. If ProvisioningManager has a valid RCS configuration at the
-     * time of callback registration and a reconfiguration is not required
-     * due to RCS client parameters change, then the callback shall be invoked
-     * immediately with the xml.
-     * When the subscription associated with this callback is removed (SIM removed,
-     * ESIM swap,etc...), this callback will automatically be removed.
-     *
-     * @param executor The {@link Executor} to call the callback methods on
-     * @param callback The rcs provisioning callback to be registered.
-     * @see #unregisterRcsProvisioningChangedCallback(RcsProvisioningCallback)
-     * @see SubscriptionManager.OnSubscriptionsChangedListener
-     * @throws IllegalArgumentException if the subscription associated with this
-     * callback is not active (SIM is not inserted, ESIM inactive) or the
-     * subscription is invalid.
-     * @throws ImsException if the subscription associated with this callback is
-     * valid, but the {@link ImsService} associated with the subscription is not
-     * available. This can happen if the service crashed, for example.
-     * It shall also throw this exception when the RCS client parameters for the
-     * application are not valid. In that case application must set the client
-     * params (See {@link #setRcsClientConfiguration}) and re register the
-     * callback.
-     * See {@link ImsException#getCode()} for a more detailed reason.
-     */
-    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    * Registers a new {@link RcsProvisioningCallback} to listen to changes to
+    * RCS provisioning xml.
+    *
+    * <p>RCS application must be the default messaging application and must
+    * have already registered its {@link RcsClientConfiguration} by using
+    * {@link #setRcsClientConfiguration} before it registers the provisioning
+    * callback. If ProvisioningManager has a valid RCS configuration at the
+    * time of callback registration and a reconfiguration is not required
+    * due to RCS client parameters change, then the callback shall be invoked
+    * immediately with the xml.
+    * When the subscription associated with this callback is removed (SIM removed,
+    * ESIM swap,etc...), this callback will automatically be removed.
+    * <p> Requires Permission:
+    * <ul>
+    *     <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li>
+    *     <li>{@link android.Manifest.permission#PERFORM_IMS_SINGLE_REGISTRATION},</li>
+    *     <li>or that the caller has carrier privileges (see
+    *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+    * </ul>
+    *
+    * @param executor The {@link Executor} to call the callback methods on
+    * @param callback The rcs provisioning callback to be registered.
+    * @see #unregisterRcsProvisioningChangedCallback(RcsProvisioningCallback)
+    * @see SubscriptionManager.OnSubscriptionsChangedListener
+    * @throws IllegalArgumentException if the subscription associated with this
+    * callback is not active (SIM is not inserted, ESIM inactive) or the
+    * subscription is invalid.
+    * @throws ImsException if the subscription associated with this callback is
+    * valid, but the {@link ImsService} associated with the subscription is not
+    * available. This can happen if the service crashed, for example.
+    * It shall also throw this exception when the RCS client parameters for the
+    * application are not valid. In that case application must set the client
+    * params (See {@link #setRcsClientConfiguration}) and re register the
+    * callback.
+    * See {@link ImsException#getCode()} for a more detailed reason.
+    */
+    @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION})
     public void registerRcsProvisioningChangedCallback(
             @NonNull @CallbackExecutor Executor executor,
             @NonNull RcsProvisioningCallback callback) throws ImsException {
@@ -1459,13 +1477,22 @@
      * removed, ESIM swap, etc...), this callback will automatically be
      * removed. If this method is called for an inactive subscription, it
      * will result in a no-op.
+     * <p> Requires Permission:
+     * <ul>
+     *     <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li>
+     *     <li>{@link android.Manifest.permission#PERFORM_IMS_SINGLE_REGISTRATION},</li>
+     *     <li>or that the caller has carrier privileges (see
+     *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+     * </ul>
+     *
      * @param callback The existing {@link RcsProvisioningCallback} to be
      * removed.
      * @see #registerRcsProvisioningChangedCallback
      * @throws IllegalArgumentException if the subscription associated with this callback is
      * invalid.
      */
-    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION})
     public void unregisterRcsProvisioningChangedCallback(
             @NonNull RcsProvisioningCallback callback) {
         try {
@@ -1480,7 +1507,7 @@
      * Reconfiguration triggered by the RCS application. Most likely cause
      * is the 403 forbidden to a HTTP request.
      */
-    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION)
     public void triggerRcsReconfiguration() {
         try {
             getITelephony().triggerRcsReconfiguration(mSubId);
diff --git a/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java b/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java
index 5eb75e7..bdf628b 100644
--- a/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java
+++ b/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java
@@ -21,6 +21,7 @@
 import android.annotation.StringDef;
 import android.annotation.SystemApi;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -39,6 +40,15 @@
 public final class RcsContactPresenceTuple implements Parcelable {
 
     /**
+     * The service ID used to indicate that service discovery via presence is available.
+     * <p>
+     * See RCC.07 v5.0 specification for more information.
+     * @hide
+     */
+    public static final String SERVICE_ID_PRESENCE =
+            "org.3gpp.urn:urn-7:3gpp-application.ims.iari.rcse.dp";
+
+    /**
      * The service ID used to indicate that MMTEL service is available.
      * <p>
      * See the GSMA RCC.07 specification for more information.
@@ -329,6 +339,13 @@
         public @NonNull @DuplexMode List<String> getUnsupportedDuplexModes() {
             return Collections.unmodifiableList(mUnsupportedDuplexModeList);
         }
+
+        @Override
+        public String toString() {
+            return "servCaps{" + "a=" + mIsAudioCapable + ", v=" + mIsVideoCapable
+                    + ", supported=" + mSupportedDuplexModeList + ", unsupported="
+                    + mUnsupportedDuplexModeList + '}';
+        }
     }
 
     /**
@@ -487,4 +504,36 @@
     public @Nullable ServiceCapabilities getServiceCapabilities() {
         return mServiceCapabilities;
     }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder("{");
+        if (Build.IS_ENG) {
+            builder.append("u=");
+            builder.append(mContactUri);
+        } else {
+            builder.append("u=");
+            builder.append(mContactUri != null ? "XXX" : "null");
+        }
+        builder.append(", id=");
+        builder.append(mServiceId);
+        builder.append(", v=");
+        builder.append(mServiceVersion);
+        builder.append(", s=");
+        builder.append(mStatus);
+        if (mTimestamp != null) {
+            builder.append(", timestamp=");
+            builder.append(mTimestamp);
+        }
+        if (mServiceDescription != null) {
+            builder.append(", servDesc=");
+            builder.append(mServiceDescription);
+        }
+        if (mServiceCapabilities != null) {
+            builder.append(", servCaps=");
+            builder.append(mServiceCapabilities);
+        }
+        builder.append("}");
+        return builder.toString();
+    }
 }
diff --git a/telephony/java/android/telephony/ims/RcsContactUceCapability.java b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
index fe85502..9299fed 100644
--- a/telephony/java/android/telephony/ims/RcsContactUceCapability.java
+++ b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
@@ -21,6 +21,7 @@
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -344,4 +345,39 @@
     public @NonNull Uri getContactUri() {
         return mContactUri;
     }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder("RcsContactUceCapability");
+        if (mCapabilityMechanism == CAPABILITY_MECHANISM_PRESENCE) {
+            builder.append("(presence) {");
+        } else if (mCapabilityMechanism == CAPABILITY_MECHANISM_OPTIONS) {
+            builder.append("(options) {");
+        } else {
+            builder.append("(?) {");
+        }
+        if (Build.IS_ENG) {
+            builder.append("uri=");
+            builder.append(mContactUri);
+        } else {
+            builder.append("uri (isNull)=");
+            builder.append(mContactUri != null ? "XXX" : "null");
+        }
+        builder.append(", sourceType=");
+        builder.append(mSourceType);
+        builder.append(", requestResult=");
+        builder.append(mRequestResult);
+
+        if (mCapabilityMechanism == CAPABILITY_MECHANISM_PRESENCE) {
+            builder.append(", presenceTuples={");
+            builder.append(mPresenceTuples);
+            builder.append("}");
+        } else if (mCapabilityMechanism == CAPABILITY_MECHANISM_OPTIONS) {
+            builder.append(", featureTags={");
+            builder.append(mFeatureTags);
+            builder.append("}");
+        }
+
+        return builder.toString();
+    }
 }
diff --git a/telephony/java/android/telephony/ims/RtpHeaderExtension.java b/telephony/java/android/telephony/ims/RtpHeaderExtension.java
index f9ab701..8815cef 100644
--- a/telephony/java/android/telephony/ims/RtpHeaderExtension.java
+++ b/telephony/java/android/telephony/ims/RtpHeaderExtension.java
@@ -134,4 +134,19 @@
         result = 31 * result + Arrays.hashCode(mExtensionData);
         return result;
     }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("RtpHeaderExtension{mLocalIdentifier=");
+        sb.append(mLocalIdentifier);
+        sb.append(", mData=");
+        for (byte b : mExtensionData) {
+            sb.append(Integer.toBinaryString(b));
+            sb.append("b_");
+        }
+        sb.append("}");
+
+        return sb.toString();
+    }
 }
diff --git a/telephony/java/android/telephony/ims/RtpHeaderExtensionType.java b/telephony/java/android/telephony/ims/RtpHeaderExtensionType.java
index e1d39c2..af4e2347 100644
--- a/telephony/java/android/telephony/ims/RtpHeaderExtensionType.java
+++ b/telephony/java/android/telephony/ims/RtpHeaderExtensionType.java
@@ -133,4 +133,16 @@
     public int hashCode() {
         return Objects.hash(mLocalIdentifier, mUri);
     }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("RtpHeaderExtensionType{mLocalIdentifier=");
+        sb.append(mLocalIdentifier);
+        sb.append(", mUri=");
+        sb.append(mUri);
+        sb.append("}");
+
+        return sb.toString();
+    }
 }
diff --git a/telephony/java/android/telephony/ims/SipDelegateManager.java b/telephony/java/android/telephony/ims/SipDelegateManager.java
index 04421c9..171842b 100644
--- a/telephony/java/android/telephony/ims/SipDelegateManager.java
+++ b/telephony/java/android/telephony/ims/SipDelegateManager.java
@@ -275,7 +275,8 @@
      * @see CarrierConfigManager.Ims#KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL
      * @see PackageManager#FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION
      */
-    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION})
     public boolean isSupported() throws ImsException {
         try {
             IImsRcsController controller = mBinderCache.getBinder();
@@ -317,7 +318,7 @@
      * @throws ImsException Thrown if there was a problem communicating with the ImsService
      * associated with this SipDelegateManager. See {@link ImsException#getCode()}.
      */
-    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION)
     public void createSipDelegate(@NonNull DelegateRequest request, @NonNull Executor executor,
             @NonNull DelegateConnectionStateCallback dc,
             @NonNull DelegateConnectionMessageCallback mc) throws ImsException {
@@ -351,7 +352,7 @@
      * @param delegateConnection The SipDelegateConnection to destroy.
      * @param reason The reason for why this SipDelegateConnection was destroyed.
      */
-    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION)
     public void destroySipDelegate(@NonNull SipDelegateConnection delegateConnection,
             @SipDelegateDestroyReason int reason) {
 
@@ -392,6 +393,7 @@
      *         this condition. May be {@code null} if there was no reason String provided from the
      *         network.
      */
+    @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION)
     public void triggerFullNetworkRegistration(@NonNull SipDelegateConnection connection,
             @IntRange(from = 100, to = 699) int sipCode, @Nullable String sipReason) {
         if (connection == null) {
diff --git a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java
index 4967e5d..6295548 100644
--- a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java
+++ b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java
@@ -25,7 +25,6 @@
 import android.telephony.ims.RcsUceAdapter;
 import android.telephony.ims.feature.ImsFeature;
 import android.telephony.ims.feature.RcsFeature;
-import android.util.Log;
 
 import java.util.List;
 
@@ -44,30 +43,12 @@
          * Respond to a remote capability request from the contact specified with the
          * capabilities of this device.
          * @param ownCapabilities The capabilities of this device.
-         * @hide
-         */
-        default void onRespondToCapabilityRequest(
-                @NonNull RcsContactUceCapability ownCapabilities) {}
-
-        /**
-         * Respond to a remote capability request from the contact specified with the
-         * capabilities of this device.
-         * @param ownCapabilities The capabilities of this device.
          * @param isBlocked Whether or not the user has blocked the number requesting the
          *         capabilities of this device. If true, the device should respond to the OPTIONS
          *         request with a 200 OK response and no capabilities.
          */
-        default void onRespondToCapabilityRequest(@NonNull RcsContactUceCapability ownCapabilities,
-                boolean isBlocked) {
-            Log.w("CapabilityExchangeEventListener", "implement "
-                    + "onRespondToCapabilityRequest(RcsContactUceCapability, boolean) instead!");
-            // Fall back to old implementation
-            if (isBlocked) {
-                onRespondToCapabilityRequestWithError(200, "OK");
-            } else {
-                onRespondToCapabilityRequest(ownCapabilities);
-            }
-        }
+        void onRespondToCapabilityRequest(@NonNull RcsContactUceCapability ownCapabilities,
+                boolean isBlocked);
 
         /**
          * Respond to a remote capability request from the contact specified with the
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index cc050be..34984e0 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -37,6 +37,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
+import java.util.Arrays;
 import java.util.HashMap;
 
 /**
@@ -368,7 +369,13 @@
     }
 
     private void onNotifyRcsAutoConfigurationReceived(byte[] config, boolean isCompressed) {
-        mRcsConfigData = isCompressed ? RcsConfig.decompressGzip(config) : config;
+        // cache uncompressed config
+        config = isCompressed ? RcsConfig.decompressGzip(config) : config;
+        if (Arrays.equals(mRcsConfigData, config)) {
+            return;
+        }
+        mRcsConfigData = config;
+
         // can be null in testing
         if (mRcsCallbacks != null) {
             mRcsCallbacks.broadcastAction(c -> {
diff --git a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
index 5f8e93d..8ad40ed 100644
--- a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
@@ -57,10 +57,10 @@
                 } else if (listener != null && mListener == null) {
                     mListener = listener;
                 } else {
-                    // Fail fast here instead of silently overwriting the listener to another
-                    // listener due to another connection connecting.
-                    throw new IllegalStateException("ImsEcbmImplBase: Listener already set by "
-                            + "another connection.");
+                    // Warn that the listener is being replaced while active
+                    Log.w(TAG, "setListener is being called when there is already an active "
+                            + "listener");
+                    mListener = listener;
                 }
             }
         }
diff --git a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
index 8e961ac..ec1c7b3 100644
--- a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
@@ -62,10 +62,10 @@
                 } else if (listener != null && mListener == null) {
                     mListener = listener;
                 } else {
-                    // Fail fast here instead of silently overwriting the listener to another
-                    // listener due to another connection connecting.
-                    throw new IllegalStateException("ImsMultiEndpointImplBase: Listener already"
-                            + " set by another connection.");
+                    // Warn that the listener is being replaced while active
+                    Log.w(TAG, "setListener is being called when there is already an active "
+                            + "listener");
+                    mListener = listener;
                 }
             }
         }
diff --git a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
index 83b89aa..eb3e8ed 100644
--- a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
@@ -224,11 +224,10 @@
                 } else if (listener != null && mUtListener == null) {
                     mUtListener = new ImsUtListener(listener);
                 } else {
-                    // This is a limitation of the current API surface, there can only be one
-                    // listener connected. Fail fast instead of silently overwriting the other
-                    // listener.
-                    throw new IllegalStateException("ImsUtImplBase#setListener: listener already "
-                            + "set by another connected interface!");
+                    // Warn that the listener is being replaced while active
+                    Log.w(TAG, "setListener is being called when there is already an active "
+                            + "listener");
+                    mUtListener = new ImsUtListener(listener);
                 }
             }
 
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 1d04953..e87f3d9 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2055,6 +2055,11 @@
     int setImsProvisioningString(int subId, int key, String value);
 
     /**
+     * Start emergency callback mode for testing.
+     */
+    void startEmergencyCallbackMode();
+
+    /**
      * Update Emergency Number List for Test Mode.
      */
     void updateEmergencyNumberListTestMode(int action, in EmergencyNumber num);
@@ -2320,6 +2325,16 @@
     void triggerRcsReconfiguration(int subId);
 
     /**
+     * Enables or disables the test mode for RCS VoLTE single registration.
+     */
+    void setRcsSingleRegistrationTestModeEnabled(boolean enabled);
+
+    /**
+     * Gets the test mode for RCS VoLTE single registration.
+     */
+    boolean getRcsSingleRegistrationTestModeEnabled();
+
+    /**
      * Overrides the config of RCS VoLTE single registration enabled for the device.
      */
     void setDeviceSingleRegistrationEnabledOverride(String enabled);
@@ -2340,6 +2355,11 @@
     void sendDeviceToDeviceMessage(int message, int value);
 
     /**
+     * Sets the specified transport active; only for use through shell.
+     */
+    void setActiveDeviceToDeviceTransport(String transport);
+
+    /**
      * Gets the config of RCS VoLTE single registration enabled for the carrier/subscription.
      */
     boolean getCarrierSingleRegistrationEnabled(int subId);
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index 151187c..3a99f0e0 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -126,6 +126,7 @@
      * connections.<br/>
      * APN_TYPE_ALL is a special type to indicate that this APN entry can
      * service all data connections.
+     * TODO: remove these and use the reference to ApnSetting.TYPE_XXX_STRING instead
      */
     public static final String APN_TYPE_ALL = ApnSetting.TYPE_ALL_STRING;
     /** APN type for default data traffic */
@@ -153,20 +154,8 @@
     public static final String APN_TYPE_MCX = ApnSetting.TYPE_MCX_STRING;
     /** APN type for XCAP */
     public static final String APN_TYPE_XCAP = ApnSetting.TYPE_XCAP_STRING;
-    /** Array of all APN types */
-    public static final String[] APN_TYPES = {APN_TYPE_DEFAULT,
-            APN_TYPE_MMS,
-            APN_TYPE_SUPL,
-            APN_TYPE_DUN,
-            APN_TYPE_HIPRI,
-            APN_TYPE_FOTA,
-            APN_TYPE_IMS,
-            APN_TYPE_CBS,
-            APN_TYPE_IA,
-            APN_TYPE_EMERGENCY,
-            APN_TYPE_MCX,
-            APN_TYPE_XCAP,
-    };
+    // /** APN type for enterprise */
+    // public static final String APN_TYPE_ENTERPRISE = ApnSetting.TYPE_ENTERPRISE_STRING;
 
     public static final int RIL_CARD_MAX_APPS    = 8;
 
diff --git a/test-base/Android.bp b/test-base/Android.bp
index c7c9fc7..9bd639b 100644
--- a/test-base/Android.bp
+++ b/test-base/Android.bp
@@ -19,6 +19,16 @@
 // This contains the junit.framework and android.test classes that were in
 // Android API level 25 excluding those from android.test.runner.
 // Also contains the com.android.internal.util.Predicate[s] classes.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-CPL-1.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_sdk_library {
     name: "android.test.base",
 
@@ -39,6 +49,12 @@
 
     compile_dex: true,
     default_to_stubs: true,
+
+    // Additional hiddenapi annotations are provided in a separate module.
+    // TODO(b/180295980) - investigate whether this can be removed
+    hiddenapi_additional_annotations: [
+        "android.test.base-hiddenapi-annotations",
+    ],
 }
 
 // Build the android.test.base_static library
@@ -81,8 +97,9 @@
 // ===============================================
 // This contains the android.test classes from android.test.base plus
 // the com.android.internal.util.Predicate[s] classes. This is only
-// intended for inclusion in android.test.legacy and must not be used
-// elsewhere.
+// intended for inclusion in android.test.legacy and in
+// android.test.base-hiddenapi-annotations to avoid a dependency cycle and must
+// not be used elsewhere.
 java_library_static {
     name: "android.test.base-minus-junit",
 
diff --git a/test-base/hiddenapi/Android.bp b/test-base/hiddenapi/Android.bp
index c202467..1466590 100644
--- a/test-base/hiddenapi/Android.bp
+++ b/test-base/hiddenapi/Android.bp
@@ -14,19 +14,29 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 // Provided solely to contribute information about which hidden parts of the android.test.base
 // library are used by apps. The source files are stubs of the actual files in ../src which use the
 // UnsupportedAppUsage annotation to tag those methods that are accessible via the hiddenapi.
-// Relies on the convention that modules with name <x>-hiddenapi provide hiddenapi information for
-// module <x> that is on the bootclasspath.
 java_library {
-    name: "android.test.base-hiddenapi",
+    name: "android.test.base-hiddenapi-annotations",
     compile_dex: true,
 
     srcs: ["src/**/*.java"],
 
     libs: [
-        "android.test.base",
+        // Use this instead of `android.test.base` to avoid a dependency cycle
+        // as `android.test.base` depends on this.
+        "android.test.base-minus-junit",
+        "junit",
         "unsupportedappusage",
     ],
 }
diff --git a/test-legacy/Android.mk b/test-legacy/Android.mk
index af26c5b..ce5e4cf 100644
--- a/test-legacy/Android.mk
+++ b/test-legacy/Android.mk
@@ -27,6 +27,9 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := android.test.legacy
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-MIT SPDX-license-identifier-Unicode-DFS
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../NOTICE
 
 LOCAL_SDK_VERSION := current
 
diff --git a/test-mock/Android.bp b/test-mock/Android.bp
index 7d0f92f..a2447d7 100644
--- a/test-mock/Android.bp
+++ b/test-mock/Android.bp
@@ -16,6 +16,15 @@
 
 // Build the android.test.mock library
 // ===================================
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_sdk_library {
     name: "android.test.mock",
 
diff --git a/test-runner/Android.bp b/test-runner/Android.bp
index 1f6db84..fe007e39 100644
--- a/test-runner/Android.bp
+++ b/test-runner/Android.bp
@@ -16,6 +16,16 @@
 
 // Build the android.test.runner library
 // =====================================
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-CPL-1.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_sdk_library {
     name: "android.test.runner",
 
diff --git a/test-runner/tests/Android.bp b/test-runner/tests/Android.bp
index d74cee4..ac21bcb 100644
--- a/test-runner/tests/Android.bp
+++ b/test-runner/tests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworkTestRunnerTests",
 
diff --git a/tests/AccessibilityEventsLogger/Android.bp b/tests/AccessibilityEventsLogger/Android.bp
index ead1656..c403f9b 100644
--- a/tests/AccessibilityEventsLogger/Android.bp
+++ b/tests/AccessibilityEventsLogger/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "AccessibilityEventsLogger",
     srcs: ["**/*.java"],
diff --git a/tests/AccessoryDisplay/common/Android.bp b/tests/AccessoryDisplay/common/Android.bp
index 3ce4c57..fd3af1e 100644
--- a/tests/AccessoryDisplay/common/Android.bp
+++ b/tests/AccessoryDisplay/common/Android.bp
@@ -13,6 +13,15 @@
 // limitations under the License.
 
 // Build the application.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library_static {
     name: "AccessoryDisplayCommon",
     sdk_version: "current",
diff --git a/tests/AccessoryDisplay/sink/Android.bp b/tests/AccessoryDisplay/sink/Android.bp
index 4e50a81..d825c60 100644
--- a/tests/AccessoryDisplay/sink/Android.bp
+++ b/tests/AccessoryDisplay/sink/Android.bp
@@ -13,6 +13,15 @@
 // limitations under the License.
 
 // Build the application.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "AccessoryDisplaySink",
     sdk_version: "current",
diff --git a/tests/AccessoryDisplay/source/Android.bp b/tests/AccessoryDisplay/source/Android.bp
index 6d8087f..6ed752e 100644
--- a/tests/AccessoryDisplay/source/Android.bp
+++ b/tests/AccessoryDisplay/source/Android.bp
@@ -13,6 +13,15 @@
 // limitations under the License.
 
 // Build the application.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "AccessoryDisplaySource",
     sdk_version: "current",
diff --git a/tests/ActivityManagerPerfTests/stub-app/Android.bp b/tests/ActivityManagerPerfTests/stub-app/Android.bp
index a3c1f5b..19225e4 100644
--- a/tests/ActivityManagerPerfTests/stub-app/Android.bp
+++ b/tests/ActivityManagerPerfTests/stub-app/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "ActivityManagerPerfTestsStubApp1",
     static_libs: ["ActivityManagerPerfTestsUtils"],
@@ -65,4 +74,3 @@
         "--auto-add-overlay",
     ],
 }
-
diff --git a/tests/ActivityManagerPerfTests/test-app/Android.bp b/tests/ActivityManagerPerfTests/test-app/Android.bp
index ef9d587..5fd1d5a 100644
--- a/tests/ActivityManagerPerfTests/test-app/Android.bp
+++ b/tests/ActivityManagerPerfTests/test-app/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ActivityManagerPerfTestsTestApp",
     srcs: ["src/**/*.java"],
diff --git a/tests/ActivityManagerPerfTests/tests/Android.bp b/tests/ActivityManagerPerfTests/tests/Android.bp
index 2ae2cc4..c8dbf81 100644
--- a/tests/ActivityManagerPerfTests/tests/Android.bp
+++ b/tests/ActivityManagerPerfTests/tests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ActivityManagerPerfTests",
     srcs: ["src/**/*.java"],
diff --git a/tests/ActivityManagerPerfTests/utils/Android.bp b/tests/ActivityManagerPerfTests/utils/Android.bp
index 766c3ac..99c43c8 100644
--- a/tests/ActivityManagerPerfTests/utils/Android.bp
+++ b/tests/ActivityManagerPerfTests/utils/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_test {
     name: "ActivityManagerPerfTestsUtils",
     sdk_version: "current",
diff --git a/tests/ActivityTests/Android.bp b/tests/ActivityTests/Android.bp
index 0182862..be6096f 100644
--- a/tests/ActivityTests/Android.bp
+++ b/tests/ActivityTests/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ActivityTest",
     srcs: ["**/*.java"],
diff --git a/tests/ActivityViewTest/Android.bp b/tests/ActivityViewTest/Android.bp
index e7b8c8e..95178a0 100644
--- a/tests/ActivityViewTest/Android.bp
+++ b/tests/ActivityViewTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ActivityViewTest",
     srcs: ["src/**/*.java"],
diff --git a/tests/AmSlam/Android.bp b/tests/AmSlam/Android.bp
index a8e575a..cc33d88 100644
--- a/tests/AmSlam/Android.bp
+++ b/tests/AmSlam/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "AmSlam",
     srcs: ["**/*.java"],
diff --git a/tests/ApkVerityTest/Android.bp b/tests/ApkVerityTest/Android.bp
index e2d2eca..4e98f42 100644
--- a/tests/ApkVerityTest/Android.bp
+++ b/tests/ApkVerityTest/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_test_host {
     name: "ApkVerityTest",
     srcs: ["src/**/*.java"],
diff --git a/tests/ApkVerityTest/ApkVerityTestApp/Android.bp b/tests/ApkVerityTest/ApkVerityTestApp/Android.bp
index 69632b2..adf8f9f 100644
--- a/tests/ApkVerityTest/ApkVerityTestApp/Android.bp
+++ b/tests/ApkVerityTest/ApkVerityTestApp/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
   name: "ApkVerityTestApp",
   manifest: "AndroidManifest.xml",
diff --git a/tests/ApkVerityTest/block_device_writer/Android.bp b/tests/ApkVerityTest/block_device_writer/Android.bp
index 8f2d4bc..0b5f0f6 100644
--- a/tests/ApkVerityTest/block_device_writer/Android.bp
+++ b/tests/ApkVerityTest/block_device_writer/Android.bp
@@ -14,6 +14,15 @@
 
 // This is a cc_test just because it supports test_suites. This should be converted to something
 // like cc_binary_test_helper once supported, thus auto_gen_config:false below.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_test {
     // Depending on how the test runs, the executable may be uploaded to different location.
     // Before the bug in the file pusher is fixed, workaround by making the name unique.
diff --git a/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java b/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java
index ab3572b..d96005b 100644
--- a/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java
+++ b/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java
@@ -95,10 +95,13 @@
             new AddFsVerityCertRule(this, CERT_PATH);
 
     private ITestDevice mDevice;
+    private boolean mDmRequireFsVerity;
 
     @Before
     public void setUp() throws DeviceNotAvailableException {
         mDevice = getDevice();
+        mDmRequireFsVerity = "true".equals(
+                mDevice.getProperty("pm.dexopt.dm.require_fsverity"));
 
         uninstallPackage(TARGET_PACKAGE);
     }
@@ -124,7 +127,7 @@
         verifyInstalledFiles(
                 INSTALLED_BASE_APK,
                 INSTALLED_BASE_APK_FSV_SIG);
-        verifyInstalledFilesHaveFsverity();
+        verifyInstalledFilesHaveFsverity(INSTALLED_BASE_APK);
     }
 
     @Test
@@ -151,7 +154,9 @@
                 INSTALLED_BASE_APK_FSV_SIG,
                 INSTALLED_SPLIT_APK,
                 INSTALLED_SPLIT_APK_FSV_SIG);
-        verifyInstalledFilesHaveFsverity();
+        verifyInstalledFilesHaveFsverity(
+                INSTALLED_BASE_APK,
+                INSTALLED_SPLIT_APK);
     }
 
     @Test
@@ -167,7 +172,9 @@
                 INSTALLED_BASE_APK_FSV_SIG,
                 INSTALLED_BASE_DM,
                 INSTALLED_BASE_DM_FSV_SIG);
-        verifyInstalledFilesHaveFsverity();
+        verifyInstalledFilesHaveFsverity(
+                INSTALLED_BASE_APK,
+                INSTALLED_BASE_DM);
     }
 
     @Test
@@ -189,7 +196,11 @@
                 INSTALLED_SPLIT_APK_FSV_SIG,
                 INSTALLED_SPLIT_DM,
                 INSTALLED_SPLIT_DM_FSV_SIG);
-        verifyInstalledFilesHaveFsverity();
+        verifyInstalledFilesHaveFsverity(
+                INSTALLED_BASE_APK,
+                INSTALLED_BASE_DM,
+                INSTALLED_SPLIT_APK,
+                INSTALLED_SPLIT_DM);
     }
 
     @Test
@@ -213,7 +224,9 @@
                 INSTALLED_BASE_APK_FSV_SIG,
                 INSTALLED_SPLIT_APK,
                 INSTALLED_SPLIT_APK_FSV_SIG);
-        verifyInstalledFilesHaveFsverity();
+        verifyInstalledFilesHaveFsverity(
+                INSTALLED_BASE_APK,
+                INSTALLED_SPLIT_APK);
     }
 
     @Test
@@ -250,18 +263,6 @@
                 INSTALLED_BASE_APK,
                 INSTALLED_SPLIT_APK,
                 INSTALLED_SPLIT_APK_FSV_SIG);
-
-    }
-
-    @Test
-    public void testInstallOnlyBaseHasFsvSig()
-            throws DeviceNotAvailableException, FileNotFoundException {
-        new InstallMultiple()
-                .addFileAndSignature(BASE_APK)
-                .addFile(BASE_APK_DM)
-                .addFile(SPLIT_APK)
-                .addFile(SPLIT_APK_DM)
-                .runExpectingFailure();
     }
 
     @Test
@@ -271,18 +272,83 @@
                 .addFile(BASE_APK)
                 .addFileAndSignature(BASE_APK_DM)
                 .addFile(SPLIT_APK)
-                .addFile(SPLIT_APK_DM)
+                .addFileAndSignature(SPLIT_APK_DM)
+                .run();
+        verifyInstalledFiles(
+                INSTALLED_BASE_APK,
+                INSTALLED_BASE_DM,
+                INSTALLED_BASE_DM_FSV_SIG,
+                INSTALLED_SPLIT_APK,
+                INSTALLED_SPLIT_DM,
+                INSTALLED_SPLIT_DM_FSV_SIG);
+        verifyInstalledFilesHaveFsverity(
+                INSTALLED_BASE_DM,
+                INSTALLED_SPLIT_DM);
+    }
+
+    @Test
+    public void testInstallDmWithoutFsvSig_Base()
+            throws DeviceNotAvailableException, FileNotFoundException {
+        InstallMultiple installer = new InstallMultiple()
+                .addFile(BASE_APK)
+                .addFile(BASE_APK_DM)
+                .addFile(SPLIT_APK)
+                .addFileAndSignature(SPLIT_APK_DM);
+        if (mDmRequireFsVerity) {
+            installer.runExpectingFailure();
+        } else {
+            installer.run();
+            verifyInstalledFiles(
+                    INSTALLED_BASE_APK,
+                    INSTALLED_BASE_DM,
+                    INSTALLED_SPLIT_APK,
+                    INSTALLED_SPLIT_DM,
+                    INSTALLED_SPLIT_DM_FSV_SIG);
+            verifyInstalledFilesHaveFsverity(INSTALLED_SPLIT_DM);
+        }
+    }
+
+    @Test
+    public void testInstallDmWithoutFsvSig_Split()
+            throws DeviceNotAvailableException, FileNotFoundException {
+        InstallMultiple installer = new InstallMultiple()
+                .addFile(BASE_APK)
+                .addFileAndSignature(BASE_APK_DM)
+                .addFile(SPLIT_APK)
+                .addFile(SPLIT_APK_DM);
+        if (mDmRequireFsVerity) {
+            installer.runExpectingFailure();
+        } else {
+            installer.run();
+            verifyInstalledFiles(
+                    INSTALLED_BASE_APK,
+                    INSTALLED_BASE_DM,
+                    INSTALLED_BASE_DM_FSV_SIG,
+                    INSTALLED_SPLIT_APK,
+                    INSTALLED_SPLIT_DM);
+            verifyInstalledFilesHaveFsverity(INSTALLED_BASE_DM);
+        }
+    }
+
+    @Test
+    public void testInstallSomeApkIsMissingFsvSig_Base()
+            throws DeviceNotAvailableException, FileNotFoundException {
+        new InstallMultiple()
+                .addFileAndSignature(BASE_APK)
+                .addFileAndSignature(BASE_APK_DM)
+                .addFile(SPLIT_APK)
+                .addFileAndSignature(SPLIT_APK_DM)
                 .runExpectingFailure();
     }
 
     @Test
-    public void testInstallOnlySplitHasFsvSig()
+    public void testInstallSomeApkIsMissingFsvSig_Split()
             throws DeviceNotAvailableException, FileNotFoundException {
         new InstallMultiple()
                 .addFile(BASE_APK)
-                .addFile(BASE_APK_DM)
+                .addFileAndSignature(BASE_APK_DM)
                 .addFileAndSignature(SPLIT_APK)
-                .addFile(SPLIT_APK_DM)
+                .addFileAndSignature(SPLIT_APK_DM)
                 .runExpectingFailure();
     }
 
@@ -383,37 +449,36 @@
         }
     }
 
-    private void verifyInstalledFilesHaveFsverity() throws DeviceNotAvailableException {
+    private void verifyInstalledFilesHaveFsverity(String... filenames)
+            throws DeviceNotAvailableException {
         // Verify that all files are protected by fs-verity
         String apkPath = getApkPath(TARGET_PACKAGE);
         String appDir = apkPath.substring(0, apkPath.lastIndexOf("/"));
         long kTargetOffset = 0;
-        for (String basename : expectRemoteCommandToSucceed("ls " + appDir).split("\n")) {
-            if (basename.endsWith(".apk") || basename.endsWith(".dm")) {
-                String path = appDir + "/" + basename;
-                damageFileAgainstBlockDevice(path, kTargetOffset);
+        for (String basename : filenames) {
+            String path = appDir + "/" + basename;
+            damageFileAgainstBlockDevice(path, kTargetOffset);
 
-                // Retry is sometimes needed to pass the test. Package manager may have FD leaks
-                // (see b/122744005 as example) that prevents the file in question to be evicted
-                // from filesystem cache. Forcing GC workarounds the problem.
-                int retry = 5;
-                for (; retry > 0; retry--) {
-                    BlockDeviceWriter.dropCaches(mDevice);
-                    if (!BlockDeviceWriter.canReadByte(mDevice, path, kTargetOffset)) {
-                        break;
-                    }
-                    try {
-                        CLog.d("lsof: " + expectRemoteCommandToSucceed("lsof " + apkPath));
-                        Thread.sleep(1000);
-                        String pid = expectRemoteCommandToSucceed("pidof system_server");
-                        mDevice.executeShellV2Command("kill -10 " + pid);  // force GC
-                    } catch (InterruptedException e) {
-                        Thread.currentThread().interrupt();
-                        return;
-                    }
+            // Retry is sometimes needed to pass the test. Package manager may have FD leaks
+            // (see b/122744005 as example) that prevents the file in question to be evicted
+            // from filesystem cache. Forcing GC workarounds the problem.
+            int retry = 5;
+            for (; retry > 0; retry--) {
+                BlockDeviceWriter.dropCaches(mDevice);
+                if (!BlockDeviceWriter.canReadByte(mDevice, path, kTargetOffset)) {
+                    break;
                 }
-                assertTrue("Read from " + path + " should fail", retry > 0);
+                try {
+                    CLog.d("lsof: " + expectRemoteCommandToSucceed("lsof " + apkPath));
+                    Thread.sleep(1000);
+                    String pid = expectRemoteCommandToSucceed("pidof system_server");
+                    mDevice.executeShellV2Command("kill -10 " + pid);  // force GC
+                } catch (InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                    return;
+                }
             }
+            assertTrue("Read from " + path + " should fail", retry > 0);
         }
     }
 
diff --git a/tests/ApkVerityTest/testdata/Android.bp b/tests/ApkVerityTest/testdata/Android.bp
index c10b0ce..ccfc4c9 100644
--- a/tests/ApkVerityTest/testdata/Android.bp
+++ b/tests/ApkVerityTest/testdata/Android.bp
@@ -12,6 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "ApkVerityTestKeyPem",
     srcs: ["ApkVerityTestKey.pem"],
@@ -74,4 +85,3 @@
     srcs: [":ApkVerityTestAppSplitDm"],
     out: ["ApkVerityTestAppSplit.dm.fsv_sig"],
 }
-
diff --git a/tests/AppLaunch/Android.bp b/tests/AppLaunch/Android.bp
index 75db551..f838c5a 100644
--- a/tests/AppLaunch/Android.bp
+++ b/tests/AppLaunch/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "AppLaunch",
     // Only compile source java files in this apk.
diff --git a/tests/AppLaunchWear/Android.bp b/tests/AppLaunchWear/Android.bp
index 8d34b6e..e2fc473 100644
--- a/tests/AppLaunchWear/Android.bp
+++ b/tests/AppLaunchWear/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "AppLaunchWear",
     // Only compile source java files in this apk.
diff --git a/tests/AppResourcesLoaders/Android.bp b/tests/AppResourcesLoaders/Android.bp
index e5739db..d882db8 100644
--- a/tests/AppResourcesLoaders/Android.bp
+++ b/tests/AppResourcesLoaders/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "AppResourcesLoaders",
     srcs: ["**/*.java"],
diff --git a/tests/AppResourcesLoaders/Overlay/Android.bp b/tests/AppResourcesLoaders/Overlay/Android.bp
index 80443f6..b063023 100644
--- a/tests/AppResourcesLoaders/Overlay/Android.bp
+++ b/tests/AppResourcesLoaders/Overlay/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "AppResourcesLoaders_Overlay",
 }
diff --git a/tests/Assist/Android.bp b/tests/Assist/Android.bp
index 216e751..033c140 100644
--- a/tests/Assist/Android.bp
+++ b/tests/Assist/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "Assist",
     srcs: ["**/*.java"],
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/Android.bp b/tests/BackgroundDexOptServiceIntegrationTests/Android.bp
index a85d129..0a45d53 100644
--- a/tests/BackgroundDexOptServiceIntegrationTests/Android.bp
+++ b/tests/BackgroundDexOptServiceIntegrationTests/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "BackgroundDexOptServiceIntegrationTests",
     srcs: ["src/**/*.java"],
diff --git a/tests/BandwidthTests/Android.bp b/tests/BandwidthTests/Android.bp
index 523f522..a7fc89d 100644
--- a/tests/BandwidthTests/Android.bp
+++ b/tests/BandwidthTests/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "BandwidthEnforcementTest",
     platform_apis: true,
diff --git a/tests/BatteryStatsPerfTest/Android.bp b/tests/BatteryStatsPerfTest/Android.bp
index 58ccec7..5233a5b 100644
--- a/tests/BatteryStatsPerfTest/Android.bp
+++ b/tests/BatteryStatsPerfTest/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "BatteryStatsPerfTests",
     srcs: ["src/**/*.java"],
diff --git a/tests/BatteryWaster/Android.bp b/tests/BatteryWaster/Android.bp
index 4698910..1fa4f82 100644
--- a/tests/BatteryWaster/Android.bp
+++ b/tests/BatteryWaster/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "BatteryWaster",
     srcs: ["**/*.java"],
diff --git a/tests/BiDiTests/Android.bp b/tests/BiDiTests/Android.bp
index c659e8c..79ae41f 100644
--- a/tests/BiDiTests/Android.bp
+++ b/tests/BiDiTests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "BiDiTests",
     // Only compile source java files in this apk.
diff --git a/tests/BlobStoreTestUtils/Android.bp b/tests/BlobStoreTestUtils/Android.bp
index 53d3638..c4faf7f 100644
--- a/tests/BlobStoreTestUtils/Android.bp
+++ b/tests/BlobStoreTestUtils/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library {
   name: "BlobStoreTestUtils",
   srcs: ["src/**/*.java"],
@@ -21,4 +30,4 @@
     "androidx.test.ext.junit",
   ],
   sdk_version: "test_current",
-}
\ No newline at end of file
+}
diff --git a/tests/BootImageProfileTest/Android.bp b/tests/BootImageProfileTest/Android.bp
index 1b097a8..9fb5aa2 100644
--- a/tests/BootImageProfileTest/Android.bp
+++ b/tests/BootImageProfileTest/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_test_host {
     name: "BootImageProfileTest",
     srcs: ["src/**/*.java"],
diff --git a/tests/BrowserPowerTest/Android.bp b/tests/BrowserPowerTest/Android.bp
index 1d358cb..a8a9897 100644
--- a/tests/BrowserPowerTest/Android.bp
+++ b/tests/BrowserPowerTest/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "BrowserPowerTests",
     libs: [
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp b/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp
index 125deb5..b889b0d 100644
--- a/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp
@@ -13,6 +13,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_test_library {
     name: "libsmartcamera_jni",
     sdk_version: "14",
diff --git a/tests/CameraPrewarmTest/Android.bp b/tests/CameraPrewarmTest/Android.bp
index eaf453b..07c4923 100644
--- a/tests/CameraPrewarmTest/Android.bp
+++ b/tests/CameraPrewarmTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "CameraPrewarmTest",
     srcs: ["**/*.java"],
diff --git a/tests/Codegen/Android.bp b/tests/Codegen/Android.bp
index 966c560..ddbf168 100644
--- a/tests/Codegen/Android.bp
+++ b/tests/Codegen/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "CodegenTests",
     srcs: [
diff --git a/tests/Compatibility/Android.bp b/tests/Compatibility/Android.bp
index c14e705..c58c99e 100644
--- a/tests/Compatibility/Android.bp
+++ b/tests/Compatibility/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "AppCompatibilityTest",
     static_libs: ["androidx.test.rules"],
diff --git a/tests/CoreTests/android/Android.bp b/tests/CoreTests/android/Android.bp
index 24134e8..e2f194b 100644
--- a/tests/CoreTests/android/Android.bp
+++ b/tests/CoreTests/android/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "LegacyCoreTests",
     srcs: ["**/*.java"],
diff --git a/tests/DataIdleTest/Android.bp b/tests/DataIdleTest/Android.bp
index 19656ce..f9509cc 100644
--- a/tests/DataIdleTest/Android.bp
+++ b/tests/DataIdleTest/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "DataIdleTest",
     platform_apis: true,
diff --git a/tests/DozeTest/Android.bp b/tests/DozeTest/Android.bp
index f1be029..36ea91a 100644
--- a/tests/DozeTest/Android.bp
+++ b/tests/DozeTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "DozeTest",
     // Only compile source java files in this apk.
diff --git a/tests/DpiTest/Android.bp b/tests/DpiTest/Android.bp
index 7d6a78b..52bb08b 100644
--- a/tests/DpiTest/Android.bp
+++ b/tests/DpiTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "DensityTest",
     srcs: ["**/*.java"],
diff --git a/tests/DynamicCodeLoggerIntegrationTests/Android.mk b/tests/DynamicCodeLoggerIntegrationTests/Android.mk
index 2d58ce8..bfb5b07 100644
--- a/tests/DynamicCodeLoggerIntegrationTests/Android.mk
+++ b/tests/DynamicCodeLoggerIntegrationTests/Android.mk
@@ -22,6 +22,9 @@
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_MODULE := DynamicCodeLoggerTestLibrary
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
 LOCAL_SRC_FILES := $(call all-java-files-under, src/com/android/dcl)
 
 include $(BUILD_JAVA_LIBRARY)
@@ -35,6 +38,9 @@
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_MODULE := DynamicCodeLoggerNativeTestLibrary
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
 LOCAL_SRC_FILES := src/cpp/com_android_dcl_Jni.cpp
 LOCAL_HEADER_LIBRARIES := jni_headers
 LOCAL_SDK_VERSION := 28
@@ -48,6 +54,9 @@
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_MODULE := DynamicCodeLoggerNativeExecutable
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
 LOCAL_SRC_FILES := src/cpp/test_executable.cpp
 
 include $(BUILD_EXECUTABLE)
diff --git a/tests/FeatureSplit/base/Android.bp b/tests/FeatureSplit/base/Android.bp
index ab25464..89c26d2 100644
--- a/tests/FeatureSplit/base/Android.bp
+++ b/tests/FeatureSplit/base/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "FeatureSplitBase",
     srcs: ["**/*.java"],
diff --git a/tests/FeatureSplit/feature1/Android.bp b/tests/FeatureSplit/feature1/Android.bp
index 706a4f5..2f8aa8b 100644
--- a/tests/FeatureSplit/feature1/Android.bp
+++ b/tests/FeatureSplit/feature1/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FeatureSplit1",
     srcs: ["**/*.java"],
diff --git a/tests/FeatureSplit/feature2/Android.bp b/tests/FeatureSplit/feature2/Android.bp
index a363482..2a5c432 100644
--- a/tests/FeatureSplit/feature2/Android.bp
+++ b/tests/FeatureSplit/feature2/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FeatureSplit2",
     srcs: ["**/*.java"],
diff --git a/tests/FixVibrateSetting/Android.bp b/tests/FixVibrateSetting/Android.bp
index 5608a2b..bd7c701 100644
--- a/tests/FixVibrateSetting/Android.bp
+++ b/tests/FixVibrateSetting/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "FixVibrateSetting",
     srcs: ["**/*.java"],
diff --git a/tests/FlickerTests/Android.bp b/tests/FlickerTests/Android.bp
index 0792e8b..217a72b 100644
--- a/tests/FlickerTests/Android.bp
+++ b/tests/FlickerTests/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FlickerTests",
     srcs: ["src/**/*.java", "src/**/*.kt"],
diff --git a/tests/FlickerTests/OWNERS b/tests/FlickerTests/OWNERS
index f35a318..b556101 100644
--- a/tests/FlickerTests/OWNERS
+++ b/tests/FlickerTests/OWNERS
@@ -1,2 +1,3 @@
+# Bug component: 909476
 include /services/core/java/com/android/server/wm/OWNERS
 natanieljr@google.com
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
index c5447c1..a8b7b05 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
@@ -17,579 +17,230 @@
 package com.android.server.wm.flicker
 
 import android.platform.helpers.IAppHelper
-import com.android.server.wm.flicker.dsl.EventLogAssertionBuilder
-import com.android.server.wm.flicker.dsl.EventLogAssertionBuilderLegacy
-import com.android.server.wm.flicker.dsl.LayersAssertionBuilder
-import com.android.server.wm.flicker.dsl.LayersAssertionBuilderLegacy
-import com.android.server.wm.flicker.dsl.WmAssertionBuilder
-import com.android.server.wm.flicker.dsl.WmAssertionBuilderLegacy
 import com.android.server.wm.flicker.helpers.WindowUtils
 import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper.Companion.NAV_BAR_LAYER_NAME
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper.Companion.NAV_BAR_WINDOW_NAME
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper.Companion.STATUS_BAR_LAYER_NAME
 import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper.Companion.STATUS_BAR_WINDOW_NAME
 
-const val APP_PAIR_SPLIT_DIVIDER = "AppPairSplitDivider"
-const val DOCKED_STACK_DIVIDER = "DockedStackDivider"
 const val WALLPAPER_TITLE = "Wallpaper"
 
-@JvmOverloads
-fun WmAssertionBuilder.statusBarWindowIsAlwaysVisible(bugId: Int = 0) {
-    all("statusBarWindowIsAlwaysVisible", bugId) {
+fun FlickerTestParameter.statusBarWindowIsAlwaysVisible() {
+    assertWm {
+        this.showsAboveAppWindow(NAV_BAR_LAYER_NAME)
+    }
+}
+
+fun FlickerTestParameter.navBarWindowIsAlwaysVisible() {
+    assertWm {
         this.showsAboveAppWindow(NAV_BAR_LAYER_NAME)
     }
 }
 
 @JvmOverloads
-fun WmAssertionBuilder.navBarWindowIsAlwaysVisible(bugId: Int = 0) {
-    all("navBarWindowIsAlwaysVisible", bugId) {
-        this.showsAboveAppWindow(NAV_BAR_LAYER_NAME)
-    }
-}
-
-fun WmAssertionBuilder.visibleWindowsShownMoreThanOneConsecutiveEntry(
-    ignoreWindows: List<String> = emptyList(),
-    bugId: Int = 0
+fun FlickerTestParameter.visibleWindowsShownMoreThanOneConsecutiveEntry(
+    ignoreWindows: List<String> = emptyList()
 ) {
-    all("visibleWindowsShownMoreThanOneConsecutiveEntry", bugId) {
+    assertWm {
         this.visibleWindowsShownMoreThanOneConsecutiveEntry(ignoreWindows)
     }
 }
 
-fun WmAssertionBuilder.launcherReplacesAppWindowAsTopWindow(testApp: IAppHelper, bugId: Int = 0) {
-    all("launcherReplacesAppWindowAsTopWindow", bugId) {
-        this.showsAppWindowOnTop(testApp.getPackage())
-                .then()
-                .showsAppWindowOnTop("Launcher")
-    }
-}
-
-fun WmAssertionBuilder.wallpaperWindowBecomesVisible(bugId: Int = 0) {
-    all("wallpaperWindowBecomesVisible", bugId) {
-        this.hidesBelowAppWindow(WALLPAPER_TITLE)
-                .then()
-                .showsBelowAppWindow(WALLPAPER_TITLE)
-    }
-}
-
-fun WmAssertionBuilder.wallpaperWindowBecomesInvisible(bugId: Int = 0) {
-    all("wallpaperWindowBecomesInvisible", bugId) {
-        this.showsBelowAppWindow("Wallpaper")
-                .then()
-                .hidesBelowAppWindow("Wallpaper")
-    }
-}
-
-fun WmAssertionBuilder.appWindowAlwaysVisibleOnTop(
-    packageName: String,
-    bugId: Int = 0
-) {
-    all("appWindowAlwaysVisibleOnTop", bugId) {
-        this.showsAppWindowOnTop(packageName)
-    }
-}
-
-fun WmAssertionBuilder.appWindowBecomesVisible(appName: String, bugId: Int = 0) {
-    all("appWindowBecomesVisible", bugId) {
-        this.hidesAppWindow(appName)
-                .then()
-                .showsAppWindow(appName)
-    }
-}
-
-fun WmAssertionBuilder.appWindowBecomesInVisible(appName: String, bugId: Int = 0) {
-    all("appWindowBecomesInVisible", bugId) {
-        this.showsAppWindow(appName)
-            .then()
-            .hidesAppWindow(appName)
-    }
-}
-
-@JvmOverloads
-fun LayersAssertionBuilder.noUncoveredRegions(
-    beginRotation: Int,
-    endRotation: Int = beginRotation,
-    allStates: Boolean = true,
-    bugId: Int = 0
-) {
-    val startingBounds = WindowUtils.getDisplayBounds(beginRotation)
-    val endingBounds = WindowUtils.getDisplayBounds(endRotation)
-    if (allStates) {
-        all("noUncoveredRegions", bugId) {
-            if (startingBounds == endingBounds) {
-                this.coversAtLeastRegion(startingBounds)
-            } else {
-                this.coversAtLeastRegion(startingBounds)
-                        .then()
-                        .coversAtLeastRegion(endingBounds)
-            }
-        }
-    } else {
-        start("noUncoveredRegions_StartingPos") {
-            this.coversAtLeastRegion(startingBounds)
-        }
-        end("noUncoveredRegions_EndingPos") {
-            this.coversAtLeastRegion(endingBounds)
-        }
-    }
-}
-
-@JvmOverloads
-fun LayersAssertionBuilder.navBarLayerIsAlwaysVisible(
-    rotatesScreen: Boolean = false,
-    bugId: Int = 0
-) {
-    if (rotatesScreen) {
-        all("navBarLayerIsAlwaysVisible", bugId) {
-            this.showsLayer(NAV_BAR_LAYER_NAME)
-                    .then()
-                    .hidesLayer(NAV_BAR_LAYER_NAME)
-                    .then()
-                    .showsLayer(NAV_BAR_LAYER_NAME)
-        }
-    } else {
-        all("navBarLayerIsAlwaysVisible", bugId) {
-            this.showsLayer(NAV_BAR_LAYER_NAME)
-        }
-    }
-}
-
-@JvmOverloads
-fun LayersAssertionBuilder.statusBarLayerIsAlwaysVisible(
-    rotatesScreen: Boolean = false,
-    bugId: Int = 0
-) {
-    if (rotatesScreen) {
-        all("statusBarLayerIsAlwaysVisible", bugId) {
-            this.showsLayer(STATUS_BAR_WINDOW_NAME)
-                    .then()
-                    hidesLayer(STATUS_BAR_WINDOW_NAME)
-                    .then()
-                    .showsLayer(STATUS_BAR_WINDOW_NAME)
-        }
-    } else {
-        all("statusBarLayerIsAlwaysVisible", bugId) {
-            this.showsLayer(STATUS_BAR_WINDOW_NAME)
-        }
-    }
-}
-
-@JvmOverloads
-fun LayersAssertionBuilder.navBarLayerRotatesAndScales(
-    beginRotation: Int,
-    endRotation: Int = beginRotation,
-    bugId: Int = 0
-) {
-    val startingPos = WindowUtils.getNavigationBarPosition(beginRotation)
-    val endingPos = WindowUtils.getNavigationBarPosition(endRotation)
-
-    start("navBarLayerRotatesAndScales_StartingPos", bugId) {
-        this.hasVisibleRegion(NAV_BAR_LAYER_NAME, startingPos)
-    }
-    end("navBarLayerRotatesAndScales_EndingPost", bugId) {
-        this.hasVisibleRegion(NAV_BAR_LAYER_NAME, endingPos)
-    }
-
-    /*if (startingPos == endingPos) {
-        all("navBarLayerRotatesAndScales", enabled = false, bugId = 167747321) {
-            this.hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, startingPos)
-        }
-    }*/
-}
-
-@JvmOverloads
-fun LayersAssertionBuilder.statusBarLayerRotatesScales(
-    beginRotation: Int,
-    endRotation: Int = beginRotation,
-    bugId: Int = 0
-) {
-    val startingPos = WindowUtils.getStatusBarPosition(beginRotation)
-    val endingPos = WindowUtils.getStatusBarPosition(endRotation)
-
-    start("statusBarLayerRotatesScales_StartingPos", bugId) {
-        this.hasVisibleRegion(STATUS_BAR_WINDOW_NAME, startingPos)
-    }
-    end("statusBarLayerRotatesScales_EndingPos", bugId) {
-        this.hasVisibleRegion(STATUS_BAR_WINDOW_NAME, endingPos)
-    }
-}
-
-fun LayersAssertionBuilder.visibleLayersShownMoreThanOneConsecutiveEntry(
-    ignoreLayers: List<String> = emptyList(),
-    bugId: Int = 0
-) {
-    all("visibleLayersShownMoreThanOneConsecutiveEntry", bugId) {
-        this.visibleLayersShownMoreThanOneConsecutiveEntry(ignoreLayers)
-    }
-}
-
-fun LayersAssertionBuilder.appLayerReplacesWallpaperLayer(appName: String, bugId: Int = 0) {
-    all("appLayerReplacesWallpaperLayer", bugId) {
-        this.showsLayer("Wallpaper")
-                .then()
-                .replaceVisibleLayer("Wallpaper", appName)
-    }
-}
-
-fun LayersAssertionBuilder.wallpaperLayerReplacesAppLayer(testApp: IAppHelper, bugId: Int = 0) {
-    all("appLayerReplacesWallpaperLayer", bugId) {
-        this.showsLayer(testApp.getPackage())
-                .then()
-                .replaceVisibleLayer(testApp.getPackage(), WALLPAPER_TITLE)
-    }
-}
-
-fun LayersAssertionBuilder.layerAlwaysVisible(packageName: String, bugId: Int = 0) {
-    all("layerAlwaysVisible", bugId) {
-        this.showsLayer(packageName)
-    }
-}
-
-fun LayersAssertionBuilder.layerBecomesVisible(packageName: String, bugId: Int = 0) {
-    all("layerBecomesVisible", bugId) {
-        this.hidesLayer(packageName)
-                .then()
-                .showsLayer(packageName)
-    }
-}
-
-fun LayersAssertionBuilder.layerBecomesInvisible(packageName: String, bugId: Int = 0) {
-    all("layerBecomesInvisible", bugId) {
-        this.showsLayer(packageName)
-                .then()
-                .hidesLayer(packageName)
-    }
-}
-
-fun EventLogAssertionBuilder.focusChanges(vararg windows: String, bugId: Int = 0) {
-    all("focusChanges", bugId) {
-        this.focusChanges(windows)
-    }
-}
-
-fun EventLogAssertionBuilder.focusDoesNotChange(bugId: Int = 0) {
-    all("focusDoesNotChange", bugId) {
-        this.focusDoesNotChange()
-    }
-}
-
-@JvmOverloads
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
-fun WmAssertionBuilderLegacy.statusBarWindowIsAlwaysVisible(
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    all("statusBarWindowIsAlwaysVisible", bugId, enabled) {
-        this.showsAboveAppWindow(STATUS_BAR_WINDOW_NAME)
-    }
-}
-
-@JvmOverloads
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
-fun WmAssertionBuilderLegacy.navBarWindowIsAlwaysVisible(
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    all("navBarWindowIsAlwaysVisible", bugId, enabled) {
-        this.showsAboveAppWindow(NAV_BAR_WINDOW_NAME)
-    }
-}
-
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
-fun WmAssertionBuilderLegacy.visibleWindowsShownMoreThanOneConsecutiveEntry(
-    ignoreWindows: List<String> = emptyList(),
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    all("visibleWindowsShownMoreThanOneConsecutiveEntry", bugId, enabled) {
-        this.visibleWindowsShownMoreThanOneConsecutiveEntry(ignoreWindows)
-    }
-}
-
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
-fun WmAssertionBuilderLegacy.launcherReplacesAppWindowAsTopWindow(
-    testApp: IAppHelper,
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    all("launcherReplacesAppWindowAsTopWindow", bugId, enabled) {
+fun FlickerTestParameter.launcherReplacesAppWindowAsTopWindow(testApp: IAppHelper) {
+    assertWm {
         this.showsAppWindowOnTop(testApp.getPackage())
             .then()
             .showsAppWindowOnTop("Launcher")
     }
 }
 
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
-fun WmAssertionBuilderLegacy.wallpaperWindowBecomesVisible(
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    all("wallpaperWindowBecomesVisible", bugId, enabled) {
+fun FlickerTestParameter.wallpaperWindowBecomesVisible() {
+    assertWm {
         this.hidesBelowAppWindow(WALLPAPER_TITLE)
             .then()
             .showsBelowAppWindow(WALLPAPER_TITLE)
     }
 }
 
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
-fun WmAssertionBuilderLegacy.wallpaperWindowBecomesInvisible(
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    all("wallpaperWindowBecomesInvisible", bugId, enabled) {
-        this.showsBelowAppWindow("Wallpaper")
+fun FlickerTestParameter.wallpaperWindowBecomesInvisible() {
+    assertWm {
+        this.showsBelowAppWindow(WALLPAPER_TITLE)
             .then()
-            .hidesBelowAppWindow("Wallpaper")
+            .hidesBelowAppWindow(WALLPAPER_TITLE)
     }
 }
 
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
-fun WmAssertionBuilderLegacy.appWindowAlwaysVisibleOnTop(
-    packageName: String,
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    all("appWindowAlwaysVisibleOnTop", bugId, enabled) {
+fun FlickerTestParameter.appWindowAlwaysVisibleOnTop(packageName: String) {
+    assertWm {
         this.showsAppWindowOnTop(packageName)
     }
 }
 
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
-fun WmAssertionBuilderLegacy.appWindowBecomesVisible(
-    appName: String,
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    all("appWindowBecomesVisible", bugId, enabled) {
+fun FlickerTestParameter.appWindowBecomesVisible(appName: String) {
+    assertWm {
         this.hidesAppWindow(appName)
             .then()
             .showsAppWindow(appName)
     }
 }
 
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
-fun WmAssertionBuilderLegacy.appWindowBecomesInVisible(
-    appName: String,
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    all("appWindowBecomesInVisible", bugId, enabled) {
+fun FlickerTestParameter.appWindowBecomesInVisible(appName: String) {
+    assertWm {
         this.showsAppWindow(appName)
             .then()
             .hidesAppWindow(appName)
     }
 }
 
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
 @JvmOverloads
-fun LayersAssertionBuilderLegacy.noUncoveredRegions(
+fun FlickerTestParameter.noUncoveredRegions(
     beginRotation: Int,
     endRotation: Int = beginRotation,
-    allStates: Boolean = true,
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
+    allStates: Boolean = true
 ) {
     val startingBounds = WindowUtils.getDisplayBounds(beginRotation)
     val endingBounds = WindowUtils.getDisplayBounds(endRotation)
     if (allStates) {
-        all("noUncoveredRegions", bugId, enabled) {
+        assertLayers {
             if (startingBounds == endingBounds) {
-                this.coversAtLeastRegion(startingBounds)
+                this.coversAtLeast(startingBounds)
             } else {
-                this.coversAtLeastRegion(startingBounds)
+                this.coversAtLeast(startingBounds)
                     .then()
-                    .coversAtLeastRegion(endingBounds)
+                    .coversAtLeast(endingBounds)
             }
         }
     } else {
-        start("noUncoveredRegions_StartingPos") {
-            this.coversAtLeastRegion(startingBounds)
+        assertLayersStart {
+            this.coversAtLeast(startingBounds)
         }
-        end("noUncoveredRegions_EndingPos") {
-            this.coversAtLeastRegion(endingBounds)
+        assertLayersEnd {
+            this.coversAtLeast(endingBounds)
         }
     }
 }
 
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
 @JvmOverloads
-fun LayersAssertionBuilderLegacy.navBarLayerIsAlwaysVisible(
-    rotatesScreen: Boolean = false,
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
+fun FlickerTestParameter.navBarLayerIsAlwaysVisible(rotatesScreen: Boolean = false) {
     if (rotatesScreen) {
-        all("navBarLayerIsAlwaysVisible", bugId, enabled) {
-            this.showsLayer(NAV_BAR_LAYER_NAME)
+        assertLayers {
+            this.isVisible(NAV_BAR_LAYER_NAME)
                 .then()
-                .hidesLayer(NAV_BAR_LAYER_NAME)
+                .isInvisible(NAV_BAR_LAYER_NAME)
                 .then()
-                .showsLayer(NAV_BAR_LAYER_NAME)
+                .isVisible(NAV_BAR_LAYER_NAME)
         }
     } else {
-        all("navBarLayerIsAlwaysVisible", bugId, enabled) {
-            this.showsLayer(NAV_BAR_LAYER_NAME)
+        assertLayers {
+            this.isVisible(NAV_BAR_LAYER_NAME)
         }
     }
 }
 
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
 @JvmOverloads
-fun LayersAssertionBuilderLegacy.statusBarLayerIsAlwaysVisible(
-    rotatesScreen: Boolean = false,
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
+fun FlickerTestParameter.statusBarLayerIsAlwaysVisible(rotatesScreen: Boolean = false) {
     if (rotatesScreen) {
-        all("statusBarLayerIsAlwaysVisible", bugId, enabled) {
-            this.showsLayer(STATUS_BAR_LAYER_NAME)
+        assertLayers {
+            this.isVisible(STATUS_BAR_WINDOW_NAME)
                 .then()
-                .hidesLayer(STATUS_BAR_LAYER_NAME)
+                .isInvisible(STATUS_BAR_WINDOW_NAME)
                 .then()
-                .showsLayer(STATUS_BAR_LAYER_NAME)
+                .isVisible(STATUS_BAR_WINDOW_NAME)
         }
     } else {
-        all("statusBarLayerIsAlwaysVisible", bugId, enabled) {
-            this.showsLayer(STATUS_BAR_LAYER_NAME)
+        assertLayers {
+            this.isVisible(STATUS_BAR_WINDOW_NAME)
         }
     }
 }
 
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
 @JvmOverloads
-fun LayersAssertionBuilderLegacy.navBarLayerRotatesAndScales(
+fun FlickerTestParameter.navBarLayerRotatesAndScales(
     beginRotation: Int,
-    endRotation: Int = beginRotation,
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
+    endRotation: Int = beginRotation
 ) {
     val startingPos = WindowUtils.getNavigationBarPosition(beginRotation)
     val endingPos = WindowUtils.getNavigationBarPosition(endRotation)
 
-    start("navBarLayerRotatesAndScales_StartingPos", bugId, enabled) {
-        this.hasVisibleRegion(NAV_BAR_LAYER_NAME, startingPos)
+    assertLayersStart {
+        this.coversExactly(startingPos, NAV_BAR_LAYER_NAME)
     }
-    end("navBarLayerRotatesAndScales_EndingPost", bugId, enabled) {
-        this.hasVisibleRegion(NAV_BAR_LAYER_NAME, endingPos)
-    }
-
-    if (startingPos == endingPos) {
-        all("navBarLayerRotatesAndScales", enabled = false, bugId = 167747321) {
-            this.hasVisibleRegion(NAV_BAR_LAYER_NAME, startingPos)
-        }
+    assertLayersEnd {
+        this.coversExactly(endingPos, NAV_BAR_LAYER_NAME)
     }
 }
 
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
 @JvmOverloads
-fun LayersAssertionBuilderLegacy.statusBarLayerRotatesScales(
+fun FlickerTestParameter.statusBarLayerRotatesScales(
     beginRotation: Int,
-    endRotation: Int = beginRotation,
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
+    endRotation: Int = beginRotation
 ) {
     val startingPos = WindowUtils.getStatusBarPosition(beginRotation)
     val endingPos = WindowUtils.getStatusBarPosition(endRotation)
 
-    start("statusBarLayerRotatesScales_StartingPos", bugId, enabled) {
-        this.hasVisibleRegion(STATUS_BAR_LAYER_NAME, startingPos)
+    assertLayersStart {
+        this.coversExactly(startingPos, STATUS_BAR_WINDOW_NAME)
     }
-    end("statusBarLayerRotatesScales_EndingPos", bugId, enabled) {
-        this.hasVisibleRegion(STATUS_BAR_LAYER_NAME, endingPos)
+    assertLayersEnd {
+        this.coversExactly(endingPos, STATUS_BAR_WINDOW_NAME)
     }
 }
 
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
-fun LayersAssertionBuilderLegacy.visibleLayersShownMoreThanOneConsecutiveEntry(
-    ignoreLayers: List<String> = kotlin.collections.emptyList(),
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
+@JvmOverloads
+fun FlickerTestParameter.visibleLayersShownMoreThanOneConsecutiveEntry(
+    ignoreLayers: List<String> = emptyList()
 ) {
-    all("visibleLayersShownMoreThanOneConsecutiveEntry", bugId, enabled) {
+    assertLayers {
         this.visibleLayersShownMoreThanOneConsecutiveEntry(ignoreLayers)
     }
 }
 
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
-fun LayersAssertionBuilderLegacy.appLayerReplacesWallpaperLayer(
-    appName: String,
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    all("appLayerReplacesWallpaperLayer", bugId, enabled) {
-        this.showsLayer("Wallpaper")
+fun FlickerTestParameter.appLayerReplacesWallpaperLayer(appName: String) {
+    assertLayers {
+        this.isVisible(WALLPAPER_TITLE)
             .then()
-            .replaceVisibleLayer("Wallpaper", appName)
+            .isInvisible(WALLPAPER_TITLE)
+            .isVisible(appName)
     }
 }
 
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
-fun LayersAssertionBuilderLegacy.wallpaperLayerReplacesAppLayer(
-    testApp: IAppHelper,
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    all("appLayerReplacesWallpaperLayer", bugId, enabled) {
-        this.showsLayer(testApp.getPackage())
+fun FlickerTestParameter.wallpaperLayerReplacesAppLayer(testApp: IAppHelper) {
+    assertLayers {
+        this.isVisible(testApp.getPackage())
             .then()
-            .replaceVisibleLayer(testApp.getPackage(), WALLPAPER_TITLE)
+            .isInvisible(testApp.getPackage())
+            .isVisible(WALLPAPER_TITLE)
     }
 }
 
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
-fun LayersAssertionBuilderLegacy.layerAlwaysVisible(
-    packageName: String,
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    all("layerAlwaysVisible", bugId, enabled) {
-        this.showsLayer(packageName)
+fun FlickerTestParameter.layerAlwaysVisible(packageName: String) {
+    assertLayers {
+        this.isVisible(packageName)
     }
 }
 
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
-fun LayersAssertionBuilderLegacy.layerBecomesVisible(
-    packageName: String,
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    all("layerBecomesVisible", bugId, enabled) {
-        this.hidesLayer(packageName)
+fun FlickerTestParameter.layerBecomesVisible(packageName: String) {
+    assertLayers {
+        this.isInvisible(packageName)
             .then()
-            .showsLayer(packageName)
+            .isVisible(packageName)
     }
 }
 
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
-fun LayersAssertionBuilderLegacy.layerBecomesInvisible(
-    packageName: String,
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    all("layerBecomesInvisible", bugId, enabled) {
-        this.showsLayer(packageName)
+fun FlickerTestParameter.layerBecomesInvisible(packageName: String) {
+    assertLayers {
+        this.isVisible(packageName)
             .then()
-            .hidesLayer(packageName)
+            .isInvisible(packageName)
     }
 }
 
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
-fun EventLogAssertionBuilderLegacy.focusChanges(
-    vararg windows: String,
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    all("focusChanges", bugId, enabled) {
+fun FlickerTestParameter.focusChanges(vararg windows: String) {
+    assertEventLog {
         this.focusChanges(windows)
     }
 }
 
-@Deprecated("Move the assertion into one of the specific blocks (presubmit, postsubmit, flaky)")
-fun EventLogAssertionBuilderLegacy.focusDoesNotChange(
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    all("focusDoesNotChange", bugId, enabled) {
+fun FlickerTestParameter.focusDoesNotChange() {
+    assertEventLog {
         this.focusDoesNotChange()
     }
 }
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
index c507841..fbf18d4 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
@@ -16,11 +16,17 @@
 
 package com.android.server.wm.flicker.close
 
+import android.app.Instrumentation
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
-import com.android.server.wm.flicker.FlickerTestRunner
+import com.android.server.wm.flicker.FlickerBuilderProvider
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.SimpleAppHelper
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
@@ -35,12 +41,12 @@
 import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.flicker.helpers.buildTestTag
-import com.android.server.wm.flicker.helpers.isRotated
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.repetitions
 import com.android.server.wm.flicker.startRotation
+import org.junit.Assume
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -51,86 +57,119 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class CloseAppBackButtonTest(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
+class CloseAppBackButtonTest(private val testSpec: FlickerTestParameter) {
+    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val testApp = SimpleAppHelper(instrumentation)
+
+    @FlickerBuilderProvider
+    fun buildFlicker(): FlickerBuilder {
+        return FlickerBuilder(instrumentation).apply {
+            withTestName { testSpec.name }
+            repeat { testSpec.config.repetitions }
+            setup {
+                test {
+                    device.wakeUpAndGoToHomeScreen()
+                }
+                eachRun {
+                    this.setRotation(testSpec.config.startRotation)
+                    testApp.launchViaIntent(wmHelper)
+                }
+            }
+            transitions {
+                device.pressBack()
+                wmHelper.waitForHomeActivityVisible()
+            }
+            teardown {
+                eachRun {
+                    this.setRotation(Surface.ROTATION_0)
+                }
+                test {
+                    testApp.exit()
+                }
+            }
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun launcherReplacesAppWindowAsTopWindow() =
+        testSpec.launcherReplacesAppWindowAsTopWindow(testApp)
+
+    @Presubmit
+    @Test
+    fun wallpaperWindowBecomesVisible() = testSpec.wallpaperWindowBecomesVisible()
+
+    @Presubmit
+    @Test
+    fun noUncoveredRegions() = testSpec.noUncoveredRegions(testSpec.config.startRotation,
+        Surface.ROTATION_0)
+
+    @Presubmit
+    @Test
+    fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun wallpaperLayerReplacesAppLayer() = testSpec.wallpaperLayerReplacesAppLayer(testApp)
+
+    @Presubmit
+    @Test
+    fun navBarLayerRotatesAndScales() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @FlakyTest
+    @Test
+    fun navBarLayerRotatesAndScales_Flaky() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @Presubmit
+    @Test
+    fun statusBarLayerRotatesScales() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @FlakyTest
+    @Test
+    fun statusBarLayerRotatesScales_Flaky() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @FlakyTest(bugId = 173684672)
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry()
+
+    @FlakyTest(bugId = 173684672)
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry()
+
     companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): List<Array<Any>> {
-            val instrumentation = InstrumentationRegistry.getInstrumentation()
-            val testApp = SimpleAppHelper(instrumentation)
-            return FlickerTestRunnerFactory.getInstance()
-                .buildTest(instrumentation, repetitions = 5) { configuration ->
-                    withTestName { buildTestTag(configuration) }
-                    repeat { configuration.repetitions }
-                    setup {
-                        test {
-                            device.wakeUpAndGoToHomeScreen()
-                        }
-                        eachRun {
-                            this.setRotation(configuration.startRotation)
-                            testApp.launchViaIntent(wmHelper)
-                        }
-                    }
-                    transitions {
-                        device.pressBack()
-                        wmHelper.waitForHomeActivityVisible()
-                    }
-                    teardown {
-                        eachRun {
-                            this.setRotation(Surface.ROTATION_0)
-                        }
-                        test {
-                            testApp.exit()
-                        }
-                    }
-                    assertions {
-                        val isRotated = configuration.startRotation.isRotated()
-
-                        presubmit {
-                            windowManagerTrace {
-                                navBarWindowIsAlwaysVisible()
-                                statusBarWindowIsAlwaysVisible()
-                                launcherReplacesAppWindowAsTopWindow(testApp)
-                                wallpaperWindowBecomesVisible()
-                            }
-
-                            layersTrace {
-                                noUncoveredRegions(configuration.startRotation,
-                                    Surface.ROTATION_0)
-                                navBarLayerIsAlwaysVisible()
-                                statusBarLayerIsAlwaysVisible()
-                                wallpaperLayerReplacesAppLayer(testApp)
-
-                                if (!isRotated) {
-                                    navBarLayerRotatesAndScales(configuration.startRotation,
-                                        Surface.ROTATION_0)
-                                    statusBarLayerRotatesScales(configuration.startRotation,
-                                        Surface.ROTATION_0)
-                                }
-                            }
-                        }
-
-                        flaky {
-                            windowManagerTrace {
-                                visibleWindowsShownMoreThanOneConsecutiveEntry(bugId = 173684672)
-                            }
-
-                            layersTrace {
-                                visibleLayersShownMoreThanOneConsecutiveEntry(bugId = 173684672)
-
-                                if (isRotated) {
-                                    navBarLayerRotatesAndScales(configuration.startRotation,
-                                        Surface.ROTATION_0)
-                                    statusBarLayerRotatesScales(configuration.startRotation,
-                                        Surface.ROTATION_0)
-                                }
-                            }
-                        }
-                    }
-                }
+        fun getParams(): List<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance()
+                .getConfigNonRotationTests(repetitions = 5)
         }
     }
 }
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
index d1c3efe..08d2b7c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
@@ -16,12 +16,17 @@
 
 package com.android.server.wm.flicker.close
 
+import android.app.Instrumentation
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
-import com.android.server.wm.flicker.FlickerTestRunner
+import com.android.server.wm.flicker.FlickerBuilderProvider
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.SimpleAppHelper
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
@@ -36,12 +41,12 @@
 import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.flicker.helpers.buildTestTag
-import com.android.server.wm.flicker.helpers.isRotated
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.repetitions
 import com.android.server.wm.flicker.startRotation
+import org.junit.Assume
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -50,88 +55,121 @@
  * Test app closes by pressing home button.
  * To run this test: `atest FlickerTests:CloseAppHomeButtonTest`
  */
-@Presubmit
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class CloseAppHomeButtonTest(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
+class CloseAppHomeButtonTest(private val testSpec: FlickerTestParameter) {
+    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val testApp = SimpleAppHelper(instrumentation)
+
+    @FlickerBuilderProvider
+    fun buildFlicker(): FlickerBuilder {
+        return FlickerBuilder(instrumentation).apply {
+            withTestName { testSpec.name }
+            repeat { testSpec.config.repetitions }
+            setup {
+                test {
+                    device.wakeUpAndGoToHomeScreen()
+                }
+                eachRun {
+                    testApp.launchViaIntent(wmHelper)
+                    this.setRotation(testSpec.config.startRotation)
+                }
+            }
+            transitions {
+                device.pressHome()
+                wmHelper.waitForHomeActivityVisible()
+            }
+            teardown {
+                eachRun {
+                    this.setRotation(Surface.ROTATION_0)
+                }
+                test {
+                    testApp.exit()
+                }
+            }
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun launcherReplacesAppWindowAsTopWindow() =
+        testSpec.launcherReplacesAppWindowAsTopWindow(testApp)
+
+    @Presubmit
+    @Test
+    fun wallpaperWindowBecomesVisible() = testSpec.wallpaperWindowBecomesVisible()
+
+    @Presubmit
+    @Test
+    fun noUncoveredRegions() = testSpec.noUncoveredRegions(
+        testSpec.config.startRotation, Surface.ROTATION_0)
+
+    @Presubmit
+    @Test
+    fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun wallpaperLayerReplacesAppLayer() = testSpec.wallpaperLayerReplacesAppLayer(testApp)
+
+    @Presubmit
+    @Test
+    fun navBarLayerRotatesAndScales() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @FlakyTest
+    @Test
+    fun navBarLayerRotatesAndScales_Flaky() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @Presubmit
+    @Test
+    fun statusBarLayerRotatesScales() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @FlakyTest
+    @Test
+    fun statusBarLayerRotatesScales_Flaky() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @FlakyTest(bugId = 173689015)
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry()
+
+    @FlakyTest(bugId = 173689015)
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry()
+
     companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): List<Array<Any>> {
-            val instrumentation = InstrumentationRegistry.getInstrumentation()
-            val testApp = SimpleAppHelper(instrumentation)
-            return FlickerTestRunnerFactory.getInstance()
-                .buildTest(instrumentation, repetitions = 5) { configuration ->
-                    withTestName { buildTestTag(configuration) }
-                    repeat { configuration.repetitions }
-                    setup {
-                        test {
-                            device.wakeUpAndGoToHomeScreen()
-                        }
-                        eachRun {
-                            testApp.launchViaIntent(wmHelper)
-                            this.setRotation(configuration.startRotation)
-                        }
-                    }
-                    transitions {
-                        device.pressHome()
-                        wmHelper.waitForHomeActivityVisible()
-                    }
-                    teardown {
-                        eachRun {
-                            this.setRotation(Surface.ROTATION_0)
-                        }
-                        test {
-                            testApp.exit()
-                        }
-                    }
-                    assertions {
-                        val isRotated = configuration.startRotation.isRotated()
-
-                        presubmit {
-                            windowManagerTrace {
-                                navBarWindowIsAlwaysVisible()
-                                statusBarWindowIsAlwaysVisible()
-                                launcherReplacesAppWindowAsTopWindow(testApp)
-                                wallpaperWindowBecomesVisible()
-                            }
-
-                            layersTrace {
-                                noUncoveredRegions(configuration.startRotation,
-                                    Surface.ROTATION_0)
-                                navBarLayerIsAlwaysVisible()
-                                statusBarLayerIsAlwaysVisible()
-                                wallpaperLayerReplacesAppLayer(testApp)
-
-                                if (!isRotated) {
-                                    navBarLayerRotatesAndScales(configuration.startRotation,
-                                        Surface.ROTATION_0)
-                                    statusBarLayerRotatesScales(configuration.startRotation,
-                                        Surface.ROTATION_0)
-                                }
-                            }
-                        }
-
-                        flaky {
-                            windowManagerTrace {
-                                visibleWindowsShownMoreThanOneConsecutiveEntry(bugId = 173689015)
-                            }
-                            layersTrace {
-                                visibleLayersShownMoreThanOneConsecutiveEntry(bugId = 173689015)
-
-                                if (isRotated) {
-                                    navBarLayerRotatesAndScales(configuration.startRotation,
-                                        Surface.ROTATION_0)
-                                    statusBarLayerRotatesScales(configuration.startRotation,
-                                        Surface.ROTATION_0)
-                                }
-                            }
-                        }
-                    }
-                }
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance()
+                .getConfigNonRotationTests(repetitions = 5)
         }
     }
 }
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt
index 323236e..f7e7493 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt
@@ -16,13 +16,9 @@
 
 package com.android.server.wm.flicker.helpers
 
-import android.os.Bundle
 import android.os.RemoteException
-import android.platform.helpers.IAppHelper
 import android.view.Surface
 import com.android.server.wm.flicker.Flicker
-import com.android.server.wm.flicker.endRotation
-import com.android.server.wm.flicker.startRotation
 
 /**
  * Changes the device [rotation] and wait for the rotation animation to complete
@@ -47,128 +43,4 @@
     } catch (e: RemoteException) {
         throw RuntimeException(e)
     }
-}
-
-/**
- * Build a test tag for the test
- * @param testName Name of the transition(s) being tested
- * @param app App being launcher
- * @param beginRotation Initial screen rotation
- * @param endRotation End screen rotation (if any, otherwise use same as initial)
- *
- * @return test tag with pattern <NAME>__<APP>__<BEGIN_ROTATION>-<END_ROTATION>
-</END_ROTATION></BEGIN_ROTATION></APP></NAME> */
-fun buildTestTag(
-    testName: String,
-    app: IAppHelper,
-    beginRotation: Int,
-    endRotation: Int
-): String {
-    return buildTestTag(
-        testName, app.launcherName, beginRotation, endRotation, app2 = null, extraInfo = "")
-}
-
-/**
- * Build a test tag for the test
- * @param testName Name of the transition(s) being tested
- * @param configuration Configuration for the test
- * @param extraInfo Additional information to append to the tag
- *
- * @return test tag with pattern <NAME>__<APP>__<BEGIN_ROTATION>-<END_ROTATION>
-</END_ROTATION></BEGIN_ROTATION></APP></NAME> */
-@JvmOverloads
-fun buildTestTag(
-    testName: String,
-    configuration: Bundle,
-    extraInfo: String = ""
-): String {
-    return buildTestTag(testName,
-        app = null,
-        beginRotation = configuration.startRotation,
-        endRotation = configuration.endRotation,
-        app2 = null,
-        extraInfo = extraInfo)
-}
-
-/**
- * Build a test tag for the test
- * @param configuration Configuration for the test
- * @param extraInfo Additional information to append to the tag
- *
- * @return test tag with pattern <NAME>__<APP>__<BEGIN_ROTATION>-<END_ROTATION>
-</END_ROTATION></BEGIN_ROTATION></APP></NAME> */
-@JvmOverloads
-fun buildTestTag(
-    configuration: Bundle,
-    extraInfo: String = ""
-): String {
-    return buildTestTag(testName = null,
-        app = null,
-        beginRotation = configuration.startRotation,
-        endRotation = configuration.endRotation,
-        app2 = null,
-        extraInfo = extraInfo)
-}
-
-/**
- * Build a test tag for the test
- * @param testName Name of the transition(s) being tested
- * @param app App being launcher
- * @param configuration Configuration for the test
- * @param extraInfo Additional information to append to the tag
- *
- * @return test tag with pattern <NAME>__<APP>__<BEGIN_ROTATION>-<END_ROTATION>
-</END_ROTATION></BEGIN_ROTATION></APP></NAME> */
-@JvmOverloads
-fun buildTestTag(
-    testName: String,
-    app: IAppHelper?,
-    configuration: Bundle,
-    extraInfo: String = ""
-): String {
-    return buildTestTag(testName, app?.launcherName ?: "", configuration.startRotation,
-        configuration.endRotation, app2 = null, extraInfo = extraInfo)
-}
-
-/**
- * Build a test tag for the test
- * @param testName Name of the transition(s) being tested
- * @param app App being launcher
- * @param app2 Second app being launched (if any)
- * @param beginRotation Initial screen rotation
- * @param endRotation End screen rotation (if any, otherwise use same as initial)
- * @param extraInfo Additional information to append to the tag
- *
- * @return test tag with pattern <NAME>__<APP></APP>(S)>__<ROTATION></ROTATION>(S)>[__<EXTRA>]
-</EXTRA></NAME> */
-fun buildTestTag(
-    testName: String?,
-    app: String?,
-    beginRotation: Int,
-    endRotation: Int,
-    app2: String?,
-    extraInfo: String
-): String {
-    var testTag = ""
-    if (testName != null) {
-        testTag += testName
-    }
-    if (app != null) {
-        testTag += "__$app"
-    }
-    if (app2 != null) {
-        testTag += "-$app2"
-    }
-    testTag += "__${Surface.rotationToString(beginRotation)}"
-    if (endRotation != beginRotation) {
-        testTag += "-${Surface.rotationToString(endRotation)}"
-    }
-    if (extraInfo.isNotEmpty()) {
-        testTag += "__$extraInfo"
-    }
-
-    if (testTag.startsWith("__")) {
-        testTag = testTag.drop(2)
-    }
-    return testTag
-}
+}
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
index c7736f8..47eaddf 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
@@ -16,14 +16,19 @@
 
 package com.android.server.wm.flicker.ime
 
+import android.app.Instrumentation
+import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerBuilderProvider
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
-import com.android.server.wm.flicker.helpers.buildTestTag
-import com.android.server.wm.flicker.helpers.isRotated
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
 import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
@@ -37,7 +42,9 @@
 import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import org.junit.Assume
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -48,79 +55,116 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class CloseImeAutoOpenWindowToAppTest(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
+class CloseImeAutoOpenWindowToAppTest(private val testSpec: FlickerTestParameter) {
+    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val testApp = ImeAppAutoFocusHelper(instrumentation, testSpec.config.startRotation)
+
+    @FlickerBuilderProvider
+    fun buildFlicker(): FlickerBuilder {
+        return FlickerBuilder(instrumentation).apply {
+            withTestName { testSpec.name }
+            repeat { testSpec.config.repetitions }
+            setup {
+                test {
+                    device.wakeUpAndGoToHomeScreen()
+                }
+                eachRun {
+                    testApp.launchViaIntent(wmHelper)
+                    testApp.openIME(device, wmHelper)
+                    this.setRotation(testSpec.config.startRotation)
+                }
+            }
+            teardown {
+                test {
+                    testApp.exit()
+                    wmHelper.waitForAppTransitionIdle()
+                    this.setRotation(Surface.ROTATION_0)
+                }
+            }
+            transitions {
+                testApp.closeIME(device, wmHelper)
+            }
+        }
+    }
+
+    @Postsubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Postsubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Postsubmit
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry(listOf(IME_WINDOW_TITLE))
+
+    @Postsubmit
+    @Test
+    fun imeAppWindowIsAlwaysVisible() = testSpec.imeAppWindowIsAlwaysVisible(testApp)
+
+    @Postsubmit
+    @Test
+    fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Postsubmit
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    @Postsubmit
+    @Test
+    fun noUncoveredRegions() = testSpec.noUncoveredRegions(testSpec.config.startRotation)
+
+    @Postsubmit
+    @Test
+    fun imeLayerBecomesInvisible() = testSpec.imeLayerBecomesInvisible()
+
+    @Postsubmit
+    @Test
+    fun imeAppLayerIsAlwaysVisible() = testSpec.imeAppLayerIsAlwaysVisible(testApp)
+
+    @Presubmit
+    @Test
+    fun navBarLayerRotatesAndScales() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation)
+    }
+
+    @FlakyTest
+    @Test
+    fun navBarLayerRotatesAndScales_Flaky() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation)
+    }
+
+    @Presubmit
+    @Test
+    fun statusBarLayerRotatesScales() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation)
+    }
+
+    @FlakyTest
+    @Test
+    fun statusBarLayerRotatesScales_Flaky() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation)
+    }
+
+    @FlakyTest
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry()
 
     companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): List<Array<Any>> {
-            val instrumentation = InstrumentationRegistry.getInstrumentation()
-            return FlickerTestRunnerFactory.getInstance()
-                .buildTest(instrumentation, repetitions = 5) { configuration ->
-                    val testApp = ImeAppAutoFocusHelper(instrumentation,
-                        configuration.startRotation)
-                    withTestName { buildTestTag(configuration) }
-                    repeat { configuration.repetitions }
-                    setup {
-                        test {
-                            device.wakeUpAndGoToHomeScreen()
-                        }
-                        eachRun {
-                            testApp.launchViaIntent(wmHelper)
-                            testApp.openIME(device, wmHelper)
-                            this.setRotation(configuration.startRotation)
-                        }
-                    }
-                    teardown {
-                        test {
-                            testApp.exit()
-                            wmHelper.waitForAppTransitionIdle()
-                            this.setRotation(Surface.ROTATION_0)
-                        }
-                    }
-                    transitions {
-                        testApp.closeIME(device, wmHelper)
-                    }
-                    assertions {
-                        val isRotated = configuration.startRotation.isRotated()
-
-                        postsubmit {
-                            windowManagerTrace {
-                                navBarWindowIsAlwaysVisible()
-                                statusBarWindowIsAlwaysVisible()
-                                visibleWindowsShownMoreThanOneConsecutiveEntry(
-                                    listOf(IME_WINDOW_TITLE))
-                                imeAppWindowIsAlwaysVisible(testApp)
-                            }
-
-                            layersTrace {
-                                navBarLayerIsAlwaysVisible()
-                                statusBarLayerIsAlwaysVisible()
-                                noUncoveredRegions(configuration.startRotation)
-                                imeLayerBecomesInvisible()
-                                imeAppLayerIsAlwaysVisible(testApp)
-                                if (!isRotated) {
-                                    navBarLayerRotatesAndScales(configuration.startRotation)
-                                    statusBarLayerRotatesScales(configuration.startRotation)
-                                }
-                            }
-                        }
-
-                        flaky {
-                            layersTrace {
-                                visibleLayersShownMoreThanOneConsecutiveEntry()
-
-                                if (isRotated) {
-                                    navBarLayerRotatesAndScales(configuration.startRotation)
-                                    statusBarLayerRotatesScales(configuration.startRotation)
-                                }
-                            }
-                        }
-                    }
-                }
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance()
+                .getConfigNonRotationTests(repetitions = 5)
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
index aa24456..26afb79 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
@@ -16,14 +16,18 @@
 
 package com.android.server.wm.flicker.ime
 
+import android.app.Instrumentation
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerBuilderProvider
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
-import com.android.server.wm.flicker.helpers.buildTestTag
-import com.android.server.wm.flicker.helpers.isRotated
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
 import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
@@ -37,7 +41,9 @@
 import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import org.junit.Assume
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -48,93 +54,131 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class CloseImeAutoOpenWindowToHomeTest(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
+class CloseImeAutoOpenWindowToHomeTest(private val testSpec: FlickerTestParameter) {
+    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val testApp = ImeAppAutoFocusHelper(instrumentation, testSpec.config.startRotation)
+
+    @FlickerBuilderProvider
+    fun buildFlicker(): FlickerBuilder {
+        return FlickerBuilder(instrumentation).apply {
+            withTestName { testSpec.name }
+            repeat { testSpec.config.repetitions }
+            setup {
+                test {
+                    device.wakeUpAndGoToHomeScreen()
+                }
+                eachRun {
+                    testApp.launchViaIntent(wmHelper)
+                    testApp.openIME(device, wmHelper)
+                    this.setRotation(testSpec.config.startRotation)
+                }
+            }
+            teardown {
+                test {
+                    testApp.exit()
+                    this.setRotation(Surface.ROTATION_0)
+                }
+            }
+            transitions {
+                device.pressHome()
+                wmHelper.waitForHomeActivityVisible()
+                wmHelper.waitImeWindowGone()
+            }
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry(listOf(IME_WINDOW_TITLE))
+
+    @Presubmit
+    @Test
+    fun imeWindowBecomesInvisible() = testSpec.imeWindowBecomesInvisible()
+
+    @Presubmit
+    @Test
+    fun imeAppWindowBecomesInvisible() = testSpec.imeAppWindowBecomesInvisible(testApp)
+
+    @Presubmit
+    @Test
+    fun noUncoveredRegions() = testSpec.noUncoveredRegions(testSpec.config.startRotation,
+        Surface.ROTATION_0)
+
+    @Presubmit
+    @Test
+    fun imeLayerBecomesInvisible() = testSpec.imeLayerBecomesInvisible()
+
+    @Presubmit
+    @Test
+    fun imeAppLayerBecomesInvisible() = testSpec.imeAppLayerBecomesInvisible(testApp)
+
+    @Presubmit
+    @Test
+    fun navBarLayerRotatesAndScales() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @FlakyTest
+    @Test
+    fun navBarLayerRotatesAndScales_Flaky() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @Presubmit
+    @Test
+    fun statusBarLayerRotatesScales() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @FlakyTest
+    @Test
+    fun statusBarLayerRotatesScales_Flaky() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @Presubmit
+    @Test
+    fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry(listOf(IME_WINDOW_TITLE))
+    }
+
+    @FlakyTest
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry_Flaky() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry(listOf(IME_WINDOW_TITLE))
+    }
 
     companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): List<Array<Any>> {
-            val instrumentation = InstrumentationRegistry.getInstrumentation()
-            return FlickerTestRunnerFactory.getInstance()
-                .buildTest(instrumentation, repetitions = 5) { configuration ->
-                    val testApp = ImeAppAutoFocusHelper(instrumentation,
-                        configuration.startRotation)
-                    withTestName {
-                        buildTestTag(configuration)
-                    }
-                    repeat { configuration.repetitions }
-                    setup {
-                        test {
-                            device.wakeUpAndGoToHomeScreen()
-                        }
-                        eachRun {
-                            testApp.launchViaIntent(wmHelper)
-                            testApp.openIME(device, wmHelper)
-                            this.setRotation(configuration.startRotation)
-                        }
-                    }
-                    teardown {
-                        test {
-                            testApp.exit()
-                            this.setRotation(Surface.ROTATION_0)
-                        }
-                    }
-                    transitions {
-                        device.pressHome()
-                        wmHelper.waitForHomeActivityVisible()
-                        wmHelper.waitImeWindowGone()
-                    }
-                    assertions {
-                        val isRotated = configuration.startRotation.isRotated()
-
-                        presubmit {
-                            windowManagerTrace {
-                                navBarWindowIsAlwaysVisible()
-                                statusBarWindowIsAlwaysVisible()
-                                visibleWindowsShownMoreThanOneConsecutiveEntry(
-                                    listOf(IME_WINDOW_TITLE))
-
-                                imeWindowBecomesInvisible()
-                                imeAppWindowBecomesInvisible(testApp)
-                            }
-
-                            layersTrace {
-                                noUncoveredRegions(configuration.startRotation, Surface.ROTATION_0)
-                                imeLayerBecomesInvisible()
-                                imeAppLayerBecomesInvisible(testApp)
-
-                                if (!isRotated) {
-                                    navBarLayerRotatesAndScales(configuration.startRotation,
-                                        Surface.ROTATION_0)
-                                    statusBarLayerRotatesScales(configuration.startRotation,
-                                        Surface.ROTATION_0)
-                                    navBarLayerIsAlwaysVisible()
-                                    statusBarLayerIsAlwaysVisible()
-                                    visibleLayersShownMoreThanOneConsecutiveEntry(
-                                        listOf(IME_WINDOW_TITLE))
-                                }
-                            }
-                        }
-
-                        flaky {
-                            layersTrace {
-                                if (isRotated) {
-                                    navBarLayerRotatesAndScales(configuration.startRotation,
-                                        Surface.ROTATION_0)
-                                    statusBarLayerRotatesScales(configuration.startRotation,
-                                        Surface.ROTATION_0)
-                                    navBarLayerIsAlwaysVisible()
-                                    statusBarLayerIsAlwaysVisible()
-                                    visibleLayersShownMoreThanOneConsecutiveEntry(
-                                        listOf(IME_WINDOW_TITLE))
-                                }
-                            }
-                        }
-                    }
-                }
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance()
+                .getConfigNonRotationTests(repetitions = 5)
         }
     }
 }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
index 2bd5abb..2c4c627 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
@@ -16,13 +16,17 @@
 
 package com.android.server.wm.flicker.ime
 
+import android.app.Instrumentation
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerBuilderProvider
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.ImeAppHelper
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
 import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
@@ -33,10 +37,10 @@
 import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.repetitions
 import com.android.server.wm.flicker.startRotation
-import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -47,63 +51,97 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class CloseImeWindowToAppTest(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
+class CloseImeWindowToAppTest(private val testSpec: FlickerTestParameter) {
+    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val testApp = ImeAppHelper(instrumentation)
+
+    @FlickerBuilderProvider
+    fun buildFlicker(): FlickerBuilder {
+        return FlickerBuilder(instrumentation).apply {
+            withTestName { testSpec.name }
+            repeat { testSpec.config.repetitions }
+            setup {
+                test {
+                    device.wakeUpAndGoToHomeScreen()
+                    testApp.launchViaIntent()
+                    this.setRotation(testSpec.config.startRotation)
+                }
+                eachRun {
+                    testApp.openIME(device, wmHelper)
+                }
+            }
+            teardown {
+                test {
+                    testApp.exit()
+                    this.setRotation(Surface.ROTATION_0)
+                }
+            }
+            transitions {
+                testApp.closeIME(device, wmHelper)
+            }
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry(listOf(IME_WINDOW_TITLE))
+
+    @Presubmit
+    @Test
+    fun imeAppWindowIsAlwaysVisible() = testSpec.imeAppWindowIsAlwaysVisible(testApp)
+
+    @Presubmit
+    @Test
+    fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun noUncoveredRegions() = testSpec.noUncoveredRegions(testSpec.config.startRotation)
+
+    @Presubmit
+    @Test
+    fun navBarLayerRotatesAndScales() =
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation)
+
+    @Presubmit
+    @Test
+    fun statusBarLayerRotatesScales() =
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation)
+
+    @Presubmit
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry()
+
+    @Presubmit
+    @Test
+    fun imeLayerBecomesInvisible() = testSpec.imeLayerBecomesInvisible()
+
+    @Presubmit
+    @Test
+    fun imeAppLayerIsAlwaysVisible() = testSpec.imeAppLayerIsAlwaysVisible(testApp)
 
     companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): List<Array<Any>> {
-            val instrumentation = InstrumentationRegistry.getInstrumentation()
-            val testApp = ImeAppHelper(instrumentation)
-            return FlickerTestRunnerFactory.getInstance()
-                .buildTest(instrumentation, repetitions = 5) { configuration ->
-                    withTestName { buildTestTag(configuration) }
-                    repeat { configuration.repetitions }
-                    setup {
-                        test {
-                            device.wakeUpAndGoToHomeScreen()
-                            testApp.launchViaIntent()
-                            this.setRotation(configuration.startRotation)
-                        }
-                        eachRun {
-                            testApp.openIME(device, wmHelper)
-                        }
-                    }
-                    teardown {
-                        test {
-                            testApp.exit()
-                            this.setRotation(Surface.ROTATION_0)
-                        }
-                    }
-                    transitions {
-                        testApp.closeIME(device, wmHelper)
-                    }
-                    assertions {
-                        postsubmit {
-                            windowManagerTrace {
-                                navBarWindowIsAlwaysVisible()
-                                statusBarWindowIsAlwaysVisible()
-                                visibleWindowsShownMoreThanOneConsecutiveEntry(
-                                    listOf(IME_WINDOW_TITLE))
-                                imeAppWindowIsAlwaysVisible(testApp)
-                            }
-
-                            layersTrace {
-                                navBarLayerIsAlwaysVisible()
-                                statusBarLayerIsAlwaysVisible()
-                                noUncoveredRegions(configuration.startRotation)
-                                navBarLayerRotatesAndScales(configuration.startRotation)
-                                statusBarLayerRotatesScales(configuration.startRotation)
-                                visibleLayersShownMoreThanOneConsecutiveEntry()
-                                imeLayerBecomesInvisible()
-                                imeAppLayerIsAlwaysVisible(testApp)
-                            }
-                        }
-                    }
-                }
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance()
+                .getConfigNonRotationTests(repetitions = 5)
         }
     }
 }
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
index 7b61bb5..2bcdcd9 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
@@ -16,28 +16,33 @@
 
 package com.android.server.wm.flicker.ime
 
+import android.app.Instrumentation
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerBuilderProvider
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.ImeAppHelper
-import com.android.server.wm.flicker.helpers.buildTestTag
-import com.android.server.wm.flicker.helpers.isRotated
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
 import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.noUncoveredRegions
-import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
-import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.repetitions
 import com.android.server.wm.flicker.startRotation
-import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import org.junit.Assume
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -47,90 +52,118 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class CloseImeWindowToHomeTest(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
+class CloseImeWindowToHomeTest(private val testSpec: FlickerTestParameter) {
+    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val testApp = ImeAppHelper(instrumentation)
+
+    @FlickerBuilderProvider
+    fun buildFlicker(): FlickerBuilder {
+        return FlickerBuilder(instrumentation).apply {
+            withTestName { testSpec.name }
+            repeat { testSpec.config.repetitions }
+            setup {
+                test {
+                    device.wakeUpAndGoToHomeScreen()
+                }
+                eachRun {
+                    testApp.launchViaIntent(wmHelper)
+                    this.setRotation(testSpec.config.startRotation)
+                    testApp.openIME(device, wmHelper)
+                }
+            }
+            transitions {
+                device.pressHome()
+                wmHelper.waitForHomeActivityVisible()
+                wmHelper.waitImeWindowGone()
+            }
+            teardown {
+                eachRun {
+                    device.pressHome()
+                    wmHelper.waitForHomeActivityVisible()
+                }
+                test {
+                    testApp.exit()
+                    this.setRotation(Surface.ROTATION_0)
+                }
+            }
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry(listOf(IME_WINDOW_TITLE))
+
+    @Presubmit
+    @Test
+    fun imeWindowBecomesInvisible() = testSpec.imeWindowBecomesInvisible()
+
+    @Presubmit
+    @Test
+    fun imeAppWindowBecomesInvisible() = testSpec.imeAppWindowBecomesInvisible(testApp)
+
+    @Presubmit
+    @Test
+    fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun noUncoveredRegions() = testSpec.noUncoveredRegions(testSpec.config.startRotation,
+        Surface.ROTATION_0)
+
+    @Presubmit
+    @Test
+    fun imeLayerBecomesInvisible() = testSpec.imeLayerBecomesInvisible()
+
+    @Presubmit
+    @Test
+    fun imeAppLayerBecomesInvisible() = testSpec.imeAppLayerBecomesInvisible(testApp)
+
+    @Presubmit
+    @Test
+    fun navBarLayerRotatesAndScales() =
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation, Surface.ROTATION_0)
+
+    @Presubmit
+    @Test
+    fun statusBarLayerRotatesScales() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @FlakyTest
+    @Test
+    fun statusBarLayerRotatesScales_Flaky() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @FlakyTest
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry(listOf(IME_WINDOW_TITLE))
+
     companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): List<Array<Any>> {
-            val instrumentation = InstrumentationRegistry.getInstrumentation()
-            val testApp = ImeAppHelper(instrumentation)
-            return FlickerTestRunnerFactory.getInstance()
-                .buildTest(instrumentation, repetitions = 5) { configuration ->
-                    withTestName { buildTestTag(configuration) }
-                    repeat { configuration.repetitions }
-                    setup {
-                        test {
-                            device.wakeUpAndGoToHomeScreen()
-                        }
-                        eachRun {
-                            testApp.launchViaIntent(wmHelper)
-                            this.setRotation(configuration.startRotation)
-                            testApp.openIME(device, wmHelper)
-                        }
-                    }
-                    transitions {
-                        device.pressHome()
-                        wmHelper.waitForHomeActivityVisible()
-                        wmHelper.waitImeWindowGone()
-                    }
-                    teardown {
-                        eachRun {
-                            device.pressHome()
-                            wmHelper.waitForHomeActivityVisible()
-                        }
-                        test {
-                            testApp.exit()
-                            this.setRotation(Surface.ROTATION_0)
-                        }
-                    }
-                    assertions {
-                        val isRotated = configuration.startRotation.isRotated()
-
-                        postsubmit {
-                            windowManagerTrace {
-                                navBarWindowIsAlwaysVisible()
-                                statusBarWindowIsAlwaysVisible()
-                                visibleWindowsShownMoreThanOneConsecutiveEntry(
-                                    listOf(IME_WINDOW_TITLE))
-                                imeWindowBecomesInvisible()
-                                imeAppWindowBecomesInvisible(testApp)
-                            }
-
-                            layersTrace {
-                                navBarLayerIsAlwaysVisible()
-                                statusBarLayerIsAlwaysVisible()
-                                imeLayerBecomesInvisible()
-                                imeAppLayerBecomesInvisible(testApp)
-                                noUncoveredRegions(configuration.startRotation,
-                                    Surface.ROTATION_0)
-
-                                if (!isRotated) {
-                                    navBarLayerRotatesAndScales(configuration.startRotation,
-                                        Surface.ROTATION_0)
-                                    statusBarLayerRotatesScales(configuration.startRotation,
-                                        Surface.ROTATION_0)
-                                }
-                            }
-                        }
-
-                        flaky {
-                            layersTrace {
-                                visibleLayersShownMoreThanOneConsecutiveEntry(
-                                    listOf(IME_WINDOW_TITLE))
-
-                                if (isRotated) {
-                                    navBarLayerRotatesAndScales(configuration.startRotation,
-                                        Surface.ROTATION_0)
-                                    statusBarLayerRotatesScales(configuration.startRotation,
-                                        Surface.ROTATION_0)
-                                }
-                            }
-                        }
-                    }
-                }
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance()
+                .getConfigNonRotationTests(repetitions = 5,
+                    supportedRotations = listOf(Surface.ROTATION_0))
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
index cfdd856..3dfa31d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
@@ -17,85 +17,74 @@
 package com.android.server.wm.flicker.ime
 
 import android.platform.helpers.IAppHelper
-import com.android.server.wm.flicker.dsl.LayersAssertionBuilder
-import com.android.server.wm.flicker.dsl.WmAssertionBuilder
+import com.android.server.wm.flicker.FlickerTestParameter
 
 const val IME_WINDOW_TITLE = "InputMethod"
 
-@JvmOverloads
-fun LayersAssertionBuilder.imeLayerBecomesVisible(bugId: Int = 0) {
-    all("imeLayerBecomesVisible", bugId) {
-        this.hidesLayer(IME_WINDOW_TITLE)
-                .then()
-                .showsLayer(IME_WINDOW_TITLE)
+fun FlickerTestParameter.imeLayerBecomesVisible() {
+    assertLayers {
+        this.isInvisible(IME_WINDOW_TITLE)
+            .then()
+            .isVisible(IME_WINDOW_TITLE)
     }
 }
 
-@JvmOverloads
-fun LayersAssertionBuilder.imeLayerBecomesInvisible(bugId: Int = 0) {
-    all("imeLayerBecomesInvisible", bugId) {
-        this.showsLayer(IME_WINDOW_TITLE)
-                .then()
-                .hidesLayer(IME_WINDOW_TITLE)
+fun FlickerTestParameter.imeLayerBecomesInvisible() {
+    assertLayers {
+        this.isVisible(IME_WINDOW_TITLE)
+            .then()
+            .isInvisible(IME_WINDOW_TITLE)
     }
 }
 
-@JvmOverloads
-fun LayersAssertionBuilder.imeAppLayerIsAlwaysVisible(testApp: IAppHelper, bugId: Int = 0) {
-    all("imeAppLayerIsAlwaysVisible", bugId) {
-        this.showsLayer(testApp.getPackage())
+fun FlickerTestParameter.imeAppLayerIsAlwaysVisible(testApp: IAppHelper) {
+    assertLayers {
+        this.isVisible(testApp.getPackage())
     }
 }
 
-@JvmOverloads
-fun WmAssertionBuilder.imeAppWindowIsAlwaysVisible(testApp: IAppHelper, bugId: Int = 0) {
-    all("imeAppWindowIsAlwaysVisible", bugId) {
+fun FlickerTestParameter.imeAppWindowIsAlwaysVisible(testApp: IAppHelper) {
+    assertWm {
         this.showsAppWindowOnTop(testApp.getPackage())
     }
 }
 
-@JvmOverloads
-fun WmAssertionBuilder.imeWindowBecomesVisible(bugId: Int = 0) {
-    all("imeWindowBecomesVisible", bugId) {
+fun FlickerTestParameter.imeWindowBecomesVisible() {
+    assertWm {
         this.hidesNonAppWindow(IME_WINDOW_TITLE)
-                .then()
-                .showsNonAppWindow(IME_WINDOW_TITLE)
+            .then()
+            .showsNonAppWindow(IME_WINDOW_TITLE)
     }
 }
 
-@JvmOverloads
-fun WmAssertionBuilder.imeWindowBecomesInvisible(bugId: Int = 0) {
-    all("imeWindowBecomesInvisible", bugId) {
+fun FlickerTestParameter.imeWindowBecomesInvisible() {
+    assertWm {
         this.showsNonAppWindow(IME_WINDOW_TITLE)
-                .then()
-                .hidesNonAppWindow(IME_WINDOW_TITLE)
+            .then()
+            .hidesNonAppWindow(IME_WINDOW_TITLE)
     }
 }
 
-@JvmOverloads
-fun WmAssertionBuilder.imeAppWindowBecomesVisible(windowName: String, bugId: Int = 0) {
-    all("imeAppWindowBecomesVisible", bugId) {
+fun FlickerTestParameter.imeAppWindowBecomesVisible(windowName: String) {
+    assertWm {
         this.hidesAppWindow(windowName)
-                .then()
-                .showsAppWindow(windowName)
+            .then()
+            .showsAppWindow(windowName)
     }
 }
 
-@JvmOverloads
-fun WmAssertionBuilder.imeAppWindowBecomesInvisible(testApp: IAppHelper, bugId: Int = 0) {
-    all("imeAppWindowBecomesInvisible", bugId) {
+fun FlickerTestParameter.imeAppWindowBecomesInvisible(testApp: IAppHelper) {
+    assertWm {
         this.showsAppWindowOnTop(testApp.getPackage())
-                .then()
-                .appWindowNotOnTop(testApp.getPackage())
+            .then()
+            .appWindowNotOnTop(testApp.getPackage())
     }
 }
 
-@JvmOverloads
-fun LayersAssertionBuilder.imeAppLayerBecomesInvisible(testApp: IAppHelper, bugId: Int = 0) {
-    all("imeAppLayerBecomesInvisible", bugId) {
-        this.skipUntilFirstAssertion()
-                .showsLayer(testApp.getPackage())
-                .then()
-                .hidesLayer(testApp.getPackage())
+fun FlickerTestParameter.imeAppLayerBecomesInvisible(testApp: IAppHelper) {
+    assertLayers {
+        this.isVisible(testApp.getPackage())
+            .then()
+            .isInvisible(testApp.getPackage())
     }
 }
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
index 9e94d6e..6b2b930 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
@@ -16,13 +16,17 @@
 
 package com.android.server.wm.flicker.ime
 
+import android.app.Instrumentation
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerBuilderProvider
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.helpers.ImeAppHelper
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
 import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
@@ -32,14 +36,16 @@
 import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.noUncoveredRegions
 import com.android.server.wm.flicker.appWindowAlwaysVisibleOnTop
-import com.android.server.wm.flicker.helpers.isRotated
+import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.layerAlwaysVisible
 import com.android.server.wm.flicker.repetitions
 import com.android.server.wm.flicker.startRotation
 import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import org.junit.Assume
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -50,80 +56,120 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenImeWindowTest(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
+class OpenImeWindowTest(private val testSpec: FlickerTestParameter) {
+    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val testApp = ImeAppHelper(instrumentation)
+
+    @FlickerBuilderProvider
+    fun buildFlicker(): FlickerBuilder {
+        return FlickerBuilder(instrumentation).apply {
+            withTestName { testSpec.name }
+            repeat { testSpec.config.repetitions }
+            setup {
+                test {
+                    device.wakeUpAndGoToHomeScreen()
+                    testApp.launchViaIntent(wmHelper)
+                    this.setRotation(testSpec.config.startRotation)
+                }
+            }
+            transitions {
+                testApp.openIME(device, wmHelper)
+            }
+            teardown {
+                eachRun {
+                    testApp.closeIME(device, wmHelper)
+                }
+                test {
+                    testApp.exit()
+                    this.setRotation(Surface.ROTATION_0)
+                }
+            }
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun imeWindowBecomesVisible() = testSpec.imeWindowBecomesVisible()
+
+    @Presubmit
+    @Test
+    fun appWindowAlwaysVisibleOnTop() = testSpec.appWindowAlwaysVisibleOnTop(testApp.`package`)
+
+    @Presubmit
+    @Test
+    fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun noUncoveredRegions() = testSpec.noUncoveredRegions(testSpec.config.startRotation)
+
+    @Presubmit
+    @Test
+    fun imeLayerBecomesVisible() = testSpec.imeLayerBecomesVisible()
+
+    @Presubmit
+    @Test
+    fun layerAlwaysVisible() = testSpec.layerAlwaysVisible(testApp.`package`)
+
+    @Presubmit
+    @Test
+    fun navBarLayerRotatesAndScales() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation)
+    }
+
+    @FlakyTest
+    @Test
+    fun navBarLayerRotatesAndScales_Flaky() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation)
+    }
+
+    @Presubmit
+    @Test
+    fun statusBarLayerRotatesScales() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation)
+    }
+
+    @FlakyTest
+    @Test
+    fun statusBarLayerRotatesScales_Flaky() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation)
+    }
+
+    @FlakyTest
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry()
+
+    @FlakyTest
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry()
+
     companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): List<Array<Any>> {
-            val instrumentation = InstrumentationRegistry.getInstrumentation()
-            val testApp = ImeAppHelper(instrumentation)
-            return FlickerTestRunnerFactory.getInstance()
-                .buildTest(instrumentation, repetitions = 5) { configuration ->
-                    withTestName { buildTestTag(configuration) }
-                    repeat { configuration.repetitions }
-                    setup {
-                        test {
-                            device.wakeUpAndGoToHomeScreen()
-                            testApp.launchViaIntent(wmHelper)
-                            this.setRotation(configuration.startRotation)
-                        }
-                    }
-                    transitions {
-                        testApp.openIME(device, wmHelper)
-                    }
-                    teardown {
-                        eachRun {
-                            testApp.closeIME(device, wmHelper)
-                        }
-                        test {
-                            testApp.exit()
-                            this.setRotation(Surface.ROTATION_0)
-                        }
-                    }
-                    assertions {
-                        val isRotated = configuration.startRotation.isRotated()
-
-                        postsubmit {
-                            windowManagerTrace {
-                                navBarWindowIsAlwaysVisible()
-                                statusBarWindowIsAlwaysVisible()
-
-                                imeWindowBecomesVisible()
-                                appWindowAlwaysVisibleOnTop(testApp.`package`)
-                            }
-
-                            layersTrace {
-                                navBarLayerIsAlwaysVisible()
-                                statusBarLayerIsAlwaysVisible()
-                                noUncoveredRegions(configuration.startRotation)
-                                imeLayerBecomesVisible()
-                                layerAlwaysVisible(testApp.`package`)
-
-                                if (!isRotated) {
-                                    navBarLayerRotatesAndScales(configuration.startRotation)
-                                    statusBarLayerRotatesScales(configuration.startRotation)
-                                }
-                            }
-                        }
-
-                        flaky {
-                            windowManagerTrace {
-                                visibleWindowsShownMoreThanOneConsecutiveEntry()
-                            }
-                            layersTrace {
-                                visibleLayersShownMoreThanOneConsecutiveEntry()
-
-                                if (isRotated) {
-                                    navBarLayerRotatesAndScales(configuration.startRotation)
-                                    statusBarLayerRotatesScales(configuration.startRotation)
-                                }
-                            }
-                        }
-                    }
-                }
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance()
+                .getConfigNonRotationTests(repetitions = 5,
+                    supportedRotations = listOf(Surface.ROTATION_0))
         }
     }
 }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
index 2fe49af..0cd5d79 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
@@ -16,14 +16,18 @@
 
 package com.android.server.wm.flicker.ime
 
+import android.app.Instrumentation
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerBuilderProvider
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
 import com.android.server.wm.flicker.helpers.reopenAppFromOverview
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
 import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
@@ -31,18 +35,20 @@
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.wallpaperWindowBecomesInvisible
 import com.android.server.wm.flicker.appLayerReplacesWallpaperLayer
+import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.noUncoveredRegions
 import com.android.server.wm.flicker.repetitions
 import com.android.server.wm.flicker.startRotation
 import com.android.server.wm.flicker.endRotation
-import com.android.server.wm.flicker.helpers.isRotated
 import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.testapp.ActivityOptions
+import org.junit.Assume
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -53,89 +59,132 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ReOpenImeWindowTest(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
+class ReOpenImeWindowTest(private val testSpec: FlickerTestParameter) {
+    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val testApp = ImeAppAutoFocusHelper(instrumentation, testSpec.config.startRotation)
+    private val testAppComponentName = ActivityOptions.IME_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME
+
+    @FlickerBuilderProvider
+    fun buildFlicker(): FlickerBuilder {
+        return FlickerBuilder(instrumentation).apply {
+            withTestName { testSpec.name }
+            repeat { testSpec.config.repetitions }
+            setup {
+                test {
+                    device.wakeUpAndGoToHomeScreen()
+                    testApp.launchViaIntent(wmHelper)
+                    testApp.openIME(device, wmHelper)
+                }
+                eachRun {
+                    device.pressRecentApps()
+                    wmHelper.waitImeWindowGone()
+                    wmHelper.waitForAppTransitionIdle()
+                    this.setRotation(testSpec.config.startRotation)
+                }
+            }
+            transitions {
+                device.reopenAppFromOverview(wmHelper)
+                wmHelper.waitImeWindowShown()
+            }
+            teardown {
+                test {
+                    this.setRotation(Surface.ROTATION_0)
+                    testApp.exit()
+                }
+            }
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry()
+
+    @Presubmit
+    @Test
+    fun wallpaperWindowBecomesInvisible() = testSpec.wallpaperWindowBecomesInvisible()
+
+    @Presubmit
+    @Test
+    fun imeWindowBecomesVisible() = testSpec.imeWindowBecomesVisible()
+
+    @Presubmit
+    @Test
+    fun imeAppWindowBecomesVisible() =
+        testSpec.imeAppWindowBecomesVisible(testAppComponentName.className)
+
+    @Presubmit
+    @Test
+    // During testing the launcher is always in portrait mode
+    fun noUncoveredRegions() = testSpec.noUncoveredRegions(testSpec.config.startRotation,
+        testSpec.config.endRotation)
+
+    @Presubmit
+    @Test
+    fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun imeLayerBecomesVisible() = testSpec.imeLayerBecomesVisible()
+
+    @Presubmit
+    @Test
+    fun appLayerReplacesWallpaperLayer() =
+        testSpec.appLayerReplacesWallpaperLayer(testAppComponentName.className)
+
+    @Presubmit
+    @Test
+    fun navBarLayerRotatesAndScales() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.navBarLayerRotatesAndScales(Surface.ROTATION_0, testSpec.config.endRotation)
+    }
+
+    @FlakyTest
+    @Test
+    fun navBarLayerRotatesAndScales_Flaky() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.navBarLayerRotatesAndScales(Surface.ROTATION_0, testSpec.config.endRotation)
+    }
+
+    @Presubmit
+    @Test
+    fun statusBarLayerRotatesScales() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.statusBarLayerRotatesScales(Surface.ROTATION_0, testSpec.config.endRotation)
+    }
+
+    @FlakyTest
+    @Test
+    fun statusBarLayerRotatesScales_Flaky() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.statusBarLayerRotatesScales(Surface.ROTATION_0, testSpec.config.endRotation)
+    }
+
+    @FlakyTest
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry()
+
     companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): List<Array<Any>> {
-            val instrumentation = InstrumentationRegistry.getInstrumentation()
-            val testAppComponentName = ActivityOptions.IME_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME
-            return FlickerTestRunnerFactory.getInstance()
-                .buildTest(instrumentation, repetitions = 1) { configuration ->
-                    val testApp = ImeAppAutoFocusHelper(instrumentation,
-                        configuration.startRotation)
-                    withTestName { buildTestTag(configuration) }
-                    repeat { configuration.repetitions }
-                    setup {
-                        test {
-                            device.wakeUpAndGoToHomeScreen()
-                            testApp.launchViaIntent(wmHelper)
-                            testApp.openIME(device, wmHelper)
-                        }
-                        eachRun {
-                            device.pressRecentApps()
-                            wmHelper.waitImeWindowGone()
-                            wmHelper.waitForAppTransitionIdle()
-                            this.setRotation(configuration.startRotation)
-                        }
-                    }
-                    transitions {
-                        device.reopenAppFromOverview()
-                        wmHelper.waitImeWindowShown()
-                    }
-                    teardown {
-                        test {
-                            this.setRotation(Surface.ROTATION_0)
-                            testApp.exit()
-                        }
-                    }
-                    assertions {
-                        val isRotated = configuration.startRotation.isRotated()
-
-                        presubmit {
-                            windowManagerTrace {
-                                navBarWindowIsAlwaysVisible()
-                                statusBarWindowIsAlwaysVisible()
-                                visibleWindowsShownMoreThanOneConsecutiveEntry()
-
-                                imeWindowBecomesVisible()
-                                imeAppWindowBecomesVisible(testAppComponentName.className)
-                                wallpaperWindowBecomesInvisible()
-                            }
-
-                            layersTrace {
-                                noUncoveredRegions(Surface.ROTATION_0, configuration.endRotation)
-                                statusBarLayerIsAlwaysVisible()
-                                navBarLayerIsAlwaysVisible()
-                                imeLayerBecomesVisible()
-                                appLayerReplacesWallpaperLayer(testAppComponentName.className)
-
-                                if (!isRotated) {
-                                    navBarLayerRotatesAndScales(Surface.ROTATION_0,
-                                        configuration.endRotation)
-                                    statusBarLayerRotatesScales(Surface.ROTATION_0,
-                                        configuration.endRotation)
-                                }
-                            }
-                        }
-
-                        flaky {
-                            layersTrace {
-                                visibleLayersShownMoreThanOneConsecutiveEntry()
-
-                                if (isRotated) {
-                                    navBarLayerRotatesAndScales(Surface.ROTATION_0,
-                                        configuration.endRotation)
-                                    statusBarLayerRotatesScales(Surface.ROTATION_0,
-                                        configuration.endRotation)
-                                }
-                            }
-                        }
-                    }
-                }
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance()
+                .getConfigNonRotationTests(repetitions = 1)
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/CommonAssertions.kt
index be3fa5f..130860d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/CommonAssertions.kt
@@ -17,12 +17,12 @@
 package com.android.server.wm.flicker.launch
 
 import android.platform.helpers.IAppHelper
-import com.android.server.wm.flicker.dsl.WmAssertionBuilder
+import com.android.server.wm.flicker.FlickerTestParameter
 
-fun WmAssertionBuilder.appWindowReplacesLauncherAsTopWindow(testApp: IAppHelper, bugId: Int = 0) {
-    all("appWindowReplacesLauncherAsTopWindow", bugId) {
+fun FlickerTestParameter.appWindowReplacesLauncherAsTopWindow(testApp: IAppHelper) {
+    assertWm {
         this.showsAppWindowOnTop("Launcher")
-                .then()
-                .showsAppWindowOnTop("Snapshot", testApp.getPackage())
+            .then()
+            .showsAppWindowOnTop("Snapshot", testApp.getPackage())
     }
 }
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
index 0ec0b04..74f002d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
@@ -16,14 +16,17 @@
 
 package com.android.server.wm.flicker.launch
 
+import android.app.Instrumentation
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.endRotation
+import com.android.server.wm.flicker.FlickerBuilderProvider
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.focusChanges
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
 import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
@@ -39,9 +42,11 @@
 import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.wallpaperWindowBecomesInvisible
 import com.android.server.wm.flicker.appLayerReplacesWallpaperLayer
+import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import com.android.server.wm.flicker.helpers.isRotated
+import org.junit.Assume
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -52,85 +57,122 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenAppColdTest(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
+class OpenAppColdTest(private val testSpec: FlickerTestParameter) {
+    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val testApp = SimpleAppHelper(instrumentation)
+
+    @FlickerBuilderProvider
+    fun buildFlicker(): FlickerBuilder {
+        return FlickerBuilder(instrumentation).apply {
+            withTestName { testSpec.name }
+            repeat { testSpec.config.repetitions }
+            setup {
+                test {
+                    device.wakeUpAndGoToHomeScreen()
+                }
+                eachRun {
+                    this.setRotation(testSpec.config.startRotation)
+                }
+            }
+            transitions {
+                testApp.launchViaIntent(wmHelper)
+                // wmHelper.waitForFullScreenApp(testApp.component)
+            }
+            teardown {
+                eachRun {
+                    testApp.exit()
+                    wmHelper.waitForAppTransitionIdle()
+                    this.setRotation(Surface.ROTATION_0)
+                }
+            }
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry()
+
+    @Presubmit
+    @Test
+    fun appWindowReplacesLauncherAsTopWindow() =
+        testSpec.appWindowReplacesLauncherAsTopWindow(testApp)
+
+    @Presubmit
+    @Test
+    fun wallpaperWindowBecomesInvisible() = testSpec.wallpaperWindowBecomesInvisible()
+
+    @Presubmit
+    @Test
+    // During testing the launcher is always in portrait mode
+    fun noUncoveredRegions() = testSpec.noUncoveredRegions(testSpec.config.startRotation,
+        Surface.ROTATION_0)
+
+    @Presubmit
+    @Test
+    fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun appLayerReplacesWallpaperLayer() =
+        testSpec.appLayerReplacesWallpaperLayer(testApp.`package`)
+
+    @Presubmit
+    @Test
+    fun navBarLayerRotatesAndScales() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @FlakyTest
+    @Test
+    fun navBarLayerRotatesAndScales_Flaky() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @Presubmit
+    @Test
+    fun statusBarLayerRotatesScales() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @FlakyTest
+    @Test
+    fun statusBarLayerRotatesScales_Flaky() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @Presubmit
+    @Test
+    fun focusChanges() = testSpec.focusChanges("NexusLauncherActivity", testApp.`package`)
+
+    @FlakyTest
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry()
+
     companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): List<Array<Any>> {
-            val instrumentation = InstrumentationRegistry.getInstrumentation()
-            val testApp = SimpleAppHelper(instrumentation)
-            return FlickerTestRunnerFactory.getInstance()
-                .buildTest(instrumentation) { configuration ->
-                    withTestName { buildTestTag(configuration) }
-                    repeat { configuration.repetitions }
-                    setup {
-                        test {
-                            device.wakeUpAndGoToHomeScreen()
-                        }
-                        eachRun {
-                            this.setRotation(configuration.startRotation)
-                        }
-                    }
-                    transitions {
-                        testApp.open()
-                        wmHelper.waitForFullScreenApp(testApp.component)
-                    }
-                    teardown {
-                        eachRun {
-                            testApp.exit()
-                            wmHelper.waitForAppTransitionIdle()
-                            this.setRotation(Surface.ROTATION_0)
-                        }
-                    }
-                    assertions {
-                        val isRotated = configuration.startRotation.isRotated()
-
-                        presubmit {
-                            windowManagerTrace {
-                                navBarWindowIsAlwaysVisible()
-                                statusBarWindowIsAlwaysVisible()
-                                visibleWindowsShownMoreThanOneConsecutiveEntry()
-                                appWindowReplacesLauncherAsTopWindow(testApp)
-                                wallpaperWindowBecomesInvisible()
-                            }
-
-                            layersTrace {
-                                // During testing the launcher is always in portrait mode
-                                noUncoveredRegions(Surface.ROTATION_0, configuration.endRotation)
-                                navBarLayerIsAlwaysVisible()
-                                statusBarLayerIsAlwaysVisible()
-                                appLayerReplacesWallpaperLayer(testApp.`package`)
-
-                                if (!isRotated) {
-                                    navBarLayerRotatesAndScales(Surface.ROTATION_0,
-                                        configuration.endRotation)
-                                    statusBarLayerRotatesScales(Surface.ROTATION_0,
-                                        configuration.endRotation)
-                                }
-                            }
-
-                            eventLog {
-                                focusChanges("NexusLauncherActivity", testApp.`package`)
-                            }
-                        }
-
-                        flaky {
-                            layersTrace {
-                                visibleLayersShownMoreThanOneConsecutiveEntry()
-
-                                if (isRotated) {
-                                    navBarLayerRotatesAndScales(Surface.ROTATION_0,
-                                        configuration.endRotation)
-                                    statusBarLayerRotatesScales(Surface.ROTATION_0,
-                                        configuration.endRotation)
-                                }
-                            }
-                        }
-                    }
-                }
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests()
         }
     }
 }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
index 84cc8e3..18fac6a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
@@ -16,17 +16,21 @@
 
 package com.android.server.wm.flicker.launch
 
+import android.app.Instrumentation
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
-import com.android.server.wm.flicker.FlickerTestRunner
+import com.android.server.wm.flicker.FlickerBuilderProvider
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.endRotation
 import com.android.server.wm.flicker.focusChanges
 import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.helpers.reopenAppFromOverview
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
 import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
@@ -40,9 +44,11 @@
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.wallpaperWindowBecomesInvisible
 import com.android.server.wm.flicker.appLayerReplacesWallpaperLayer
+import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import com.android.server.wm.flicker.helpers.isRotated
+import org.junit.Assume
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -53,97 +59,133 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenAppFromOverviewTest(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
+class OpenAppFromOverviewTest(private val testSpec: FlickerTestParameter) {
+    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val testApp = SimpleAppHelper(instrumentation)
+
+    @FlickerBuilderProvider
+    fun buildFlicker(): FlickerBuilder {
+        return FlickerBuilder(instrumentation).apply {
+            withTestName { testSpec.name }
+            repeat { testSpec.config.repetitions }
+            setup {
+                test {
+                    device.wakeUpAndGoToHomeScreen()
+                    testApp.launchViaIntent(wmHelper)
+                }
+                eachRun {
+                    device.pressHome()
+                    wmHelper.waitForAppTransitionIdle()
+                    device.pressRecentApps()
+                    wmHelper.waitForAppTransitionIdle()
+                    this.setRotation(testSpec.config.startRotation)
+                }
+            }
+            transitions {
+                device.reopenAppFromOverview(wmHelper)
+                wmHelper.waitForFullScreenApp(testApp.component)
+            }
+            teardown {
+                test {
+                    testApp.exit()
+                }
+            }
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Test
+    fun appWindowReplacesLauncherAsTopWindow() =
+        testSpec.appWindowReplacesLauncherAsTopWindow(testApp)
+
+    @Test
+    fun wallpaperWindowBecomesInvisible() = testSpec.wallpaperWindowBecomesInvisible()
+
+    @Presubmit
+    @Test
+    fun appLayerReplacesWallpaperLayer() =
+        testSpec.appLayerReplacesWallpaperLayer(testApp.`package`)
+
+    @Presubmit
+    @Test
+    fun navBarLayerRotatesAndScales() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @Presubmit
+    @Test
+    fun statusBarLayerRotatesScales() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @Presubmit
+    @Test
+    fun statusBarLayerIsAlwaysVisible() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.statusBarLayerIsAlwaysVisible()
+    }
+
+    @Presubmit
+    @Test
+    fun navBarLayerIsAlwaysVisible() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.navBarLayerIsAlwaysVisible()
+    }
+
+    @Presubmit
+    @Test
+    fun focusChanges() = testSpec.focusChanges("NexusLauncherActivity", testApp.`package`)
+
+    @Presubmit
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry()
+    }
+
+    @FlakyTest
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry_Flaky() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry()
+    }
+
+    @Presubmit
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry()
+    }
+
+    @FlakyTest
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry_Flaky() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry()
+    }
+
+    @Presubmit
+    @Test
+    fun noUncoveredRegions() = testSpec.noUncoveredRegions(Surface.ROTATION_0,
+        testSpec.config.endRotation)
+
     companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): List<Array<Any>> {
-            val instrumentation = InstrumentationRegistry.getInstrumentation()
-            val testApp = SimpleAppHelper(instrumentation)
-            return FlickerTestRunnerFactory.getInstance()
-                .buildTest(instrumentation, repetitions = 5) { configuration ->
-                    withTestName { buildTestTag(configuration) }
-                    repeat { configuration.repetitions }
-                    setup {
-                        test {
-                            device.wakeUpAndGoToHomeScreen()
-                            testApp.launchViaIntent(wmHelper)
-                        }
-                        eachRun {
-                            device.pressHome()
-                            wmHelper.waitForAppTransitionIdle()
-                            device.pressRecentApps()
-                            wmHelper.waitForAppTransitionIdle()
-                            this.setRotation(configuration.startRotation)
-                        }
-                    }
-                    transitions {
-                        device.reopenAppFromOverview()
-                        wmHelper.waitForFullScreenApp(testApp.component)
-                    }
-                    teardown {
-                        test {
-                            testApp.exit()
-                        }
-                    }
-                    assertions {
-                        val isRotated = configuration.startRotation.isRotated()
-
-                        presubmit {
-                            windowManagerTrace {
-                                navBarWindowIsAlwaysVisible()
-                                statusBarWindowIsAlwaysVisible()
-                                appWindowReplacesLauncherAsTopWindow(testApp)
-                                wallpaperWindowBecomesInvisible()
-                            }
-
-                            layersTrace {
-                                appLayerReplacesWallpaperLayer(testApp.`package`)
-
-                                if (!isRotated) {
-                                    navBarLayerRotatesAndScales(Surface.ROTATION_0,
-                                        configuration.endRotation)
-                                    statusBarLayerRotatesScales(Surface.ROTATION_0,
-                                        configuration.endRotation)
-                                } else {
-                                    statusBarLayerIsAlwaysVisible()
-                                    navBarLayerIsAlwaysVisible()
-                                }
-                            }
-
-                            eventLog {
-                                focusChanges("NexusLauncherActivity", testApp.`package`)
-                            }
-                        }
-
-                        postsubmit {
-                            windowManagerTrace {
-                                visibleWindowsShownMoreThanOneConsecutiveEntry()
-                            }
-                        }
-
-                        flaky {
-                            layersTrace {
-                                visibleLayersShownMoreThanOneConsecutiveEntry()
-                                noUncoveredRegions(Surface.ROTATION_0, configuration.endRotation,
-                                    bugId = 141361128)
-
-                                if (isRotated) {
-                                    navBarLayerRotatesAndScales(Surface.ROTATION_0,
-                                        configuration.endRotation)
-                                    statusBarLayerRotatesScales(Surface.ROTATION_0,
-                                        configuration.endRotation)
-                                } else {
-                                    statusBarLayerIsAlwaysVisible()
-                                    navBarLayerIsAlwaysVisible()
-                                }
-                            }
-                        }
-                    }
-                }
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance()
+                .getConfigNonRotationTests(repetitions = 5)
         }
     }
 }
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
index 1f375a5..386dafc5 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
@@ -16,14 +16,17 @@
 
 package com.android.server.wm.flicker.launch
 
+import android.app.Instrumentation
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.endRotation
+import com.android.server.wm.flicker.FlickerBuilderProvider
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.focusChanges
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
 import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
@@ -36,12 +39,13 @@
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
-import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.wallpaperWindowBecomesInvisible
 import com.android.server.wm.flicker.appLayerReplacesWallpaperLayer
+import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import com.android.server.wm.flicker.helpers.isRotated
+import org.junit.Assume
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -52,89 +56,122 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenAppWarmTest(testSpec: FlickerTestRunnerFactory.TestSpec) : FlickerTestRunner(testSpec) {
+class OpenAppWarmTest(private val testSpec: FlickerTestParameter) {
+    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val testApp = SimpleAppHelper(instrumentation)
+
+    @FlickerBuilderProvider
+    fun buildFlicker(): FlickerBuilder {
+        return FlickerBuilder(instrumentation).apply {
+            withTestName { testSpec.name }
+            repeat { testSpec.config.repetitions }
+            setup {
+                test {
+                    device.wakeUpAndGoToHomeScreen()
+                    testApp.launchViaIntent(wmHelper)
+                    // wmHelper.waitForFullScreenApp(testApp.component)
+                }
+                eachRun {
+                    device.pressHome()
+                    wmHelper.waitForHomeActivityVisible()
+                    this.setRotation(testSpec.config.startRotation)
+                }
+            }
+            transitions {
+                testApp.launchViaIntent(wmHelper)
+                wmHelper.waitForFullScreenApp(testApp.component)
+            }
+            teardown {
+                eachRun {
+                    this.setRotation(Surface.ROTATION_0)
+                }
+                test {
+                    testApp.exit()
+                }
+            }
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry()
+
+    @Presubmit
+    @Test
+    fun appWindowReplacesLauncherAsTopWindow() =
+        testSpec.appWindowReplacesLauncherAsTopWindow(testApp)
+
+    @Presubmit
+    @Test
+    fun wallpaperWindowBecomesInvisible() = testSpec.wallpaperWindowBecomesInvisible()
+
+    @Presubmit
+    @Test
+    // During testing the launcher is always in portrait mode
+    fun noUncoveredRegions() = testSpec.noUncoveredRegions(testSpec.config.startRotation,
+        Surface.ROTATION_0)
+
+    @Presubmit
+    @Test
+    fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun appLayerReplacesWallpaperLayer() =
+        testSpec.appLayerReplacesWallpaperLayer(testApp.`package`)
+
+    @Presubmit
+    @Test
+    fun navBarLayerRotatesAndScales() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @FlakyTest
+    @Test
+    fun navBarLayerRotatesAndScales_Flaky() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @Presubmit
+    @Test
+    fun statusBarLayerRotatesScales() {
+        Assume.assumeFalse(testSpec.isRotated)
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @FlakyTest
+    @Test
+    fun statusBarLayerRotatesScales_Flaky() {
+        Assume.assumeTrue(testSpec.isRotated)
+        testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation, Surface.ROTATION_0)
+    }
+
+    @Presubmit
+    @Test
+    fun focusChanges() = testSpec.focusChanges("NexusLauncherActivity", testApp.`package`)
+
     companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): List<Array<Any>> {
-            val instrumentation = InstrumentationRegistry.getInstrumentation()
-            val testApp = SimpleAppHelper(instrumentation)
-            return FlickerTestRunnerFactory.getInstance()
-                .buildTest(instrumentation) { configuration ->
-                    withTestName { buildTestTag(configuration) }
-                    repeat { configuration.repetitions }
-                    setup {
-                        test {
-                            device.wakeUpAndGoToHomeScreen()
-                            testApp.open()
-                            wmHelper.waitForFullScreenApp(testApp.component)
-                        }
-                        eachRun {
-                            device.pressHome()
-                            wmHelper.waitForHomeActivityVisible()
-                            this.setRotation(configuration.startRotation)
-                        }
-                    }
-                    transitions {
-                        testApp.open()
-                        wmHelper.waitForFullScreenApp(testApp.component)
-                    }
-                    teardown {
-                        eachRun {
-                            this.setRotation(Surface.ROTATION_0)
-                        }
-                        test {
-                            testApp.exit()
-                        }
-                    }
-                    assertions {
-                        val isRotated = configuration.startRotation.isRotated()
-
-                        presubmit {
-                            windowManagerTrace {
-                                navBarWindowIsAlwaysVisible()
-                                statusBarWindowIsAlwaysVisible()
-                                visibleWindowsShownMoreThanOneConsecutiveEntry()
-
-                                appWindowReplacesLauncherAsTopWindow(testApp)
-                                wallpaperWindowBecomesInvisible()
-                            }
-
-                            layersTrace {
-                                // During testing the launcher is always in portrait mode
-                                noUncoveredRegions(Surface.ROTATION_0, configuration.endRotation)
-                                navBarLayerIsAlwaysVisible()
-                                statusBarLayerIsAlwaysVisible()
-                                appLayerReplacesWallpaperLayer(testApp.`package`)
-
-                                if (!isRotated) {
-                                    navBarLayerRotatesAndScales(Surface.ROTATION_0,
-                                        configuration.endRotation)
-                                    statusBarLayerRotatesScales(Surface.ROTATION_0,
-                                        configuration.endRotation)
-                                }
-                            }
-
-                            eventLog {
-                                focusChanges("NexusLauncherActivity", testApp.`package`)
-                            }
-                        }
-
-                        flaky {
-                            layersTrace {
-                                visibleLayersShownMoreThanOneConsecutiveEntry()
-
-                                if (isRotated) {
-                                    navBarLayerRotatesAndScales(Surface.ROTATION_0,
-                                        configuration.endRotation)
-                                    statusBarLayerRotatesScales(Surface.ROTATION_0,
-                                        configuration.endRotation)
-                                }
-                            }
-                        }
-                    }
-                }
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests()
         }
     }
 }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
index 7bfdd96..20e4b88 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
@@ -16,29 +16,28 @@
 
 package com.android.server.wm.flicker.rotation
 
-import android.os.Bundle
+import android.platform.test.annotations.Presubmit
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.endRotation
 import com.android.server.wm.flicker.focusDoesNotChange
 import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import com.android.server.wm.flicker.helpers.StandardAppHelper
-import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.noUncoveredRegions
 import com.android.server.wm.flicker.startRotation
-import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
-import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -49,78 +48,103 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class ChangeAppRotationTest(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : RotationTransition(InstrumentationRegistry.getInstrumentation()) {
-        override val testApp: StandardAppHelper
-            get() = SimpleAppHelper(instrumentation)
-
-        override fun getAppLaunchParams(configuration: Bundle): Map<String, String> = emptyMap()
-
-        private const val SCREENSHOT_LAYER = "RotationLayer"
-
-        @Parameterized.Parameters(name = "{0}1}")
-        @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
-                withTestName { buildTestTag(configuration) }
-                assertions {
-                    presubmit {
-                        windowManagerTrace {
-                            navBarWindowIsAlwaysVisible()
-                            statusBarWindowIsAlwaysVisible()
-                            visibleWindowsShownMoreThanOneConsecutiveEntry()
-                        }
-
-                        layersTrace {
-                            noUncoveredRegions(configuration.startRotation,
-                                configuration.endRotation, allStates = false)
-
-                            all("screenshotLayerBecomesInvisible") {
-                                this.showsLayer(testApp.getPackage())
-                                    .then()
-                                    .showsLayer(SCREENSHOT_LAYER)
-                                    .then()
-                                    .showsLayer(testApp.getPackage())
-                            }
-                        }
-                    }
-
-                    flaky {
-                        layersTrace {
-                            navBarLayerIsAlwaysVisible(bugId = 140855415)
-                            statusBarLayerIsAlwaysVisible(bugId = 140855415)
-                            navBarLayerRotatesAndScales(configuration.startRotation,
-                                configuration.endRotation, bugId = 140855415)
-                            statusBarLayerRotatesScales(configuration.startRotation,
-                                configuration.endRotation, bugId = 140855415)
-                            visibleLayersShownMoreThanOneConsecutiveEntry(bugId = 140855415)
-
-                            val startingPos = WindowUtils.getDisplayBounds(
-                                configuration.startRotation)
-                            val endingPos = WindowUtils.getDisplayBounds(
-                                configuration.endRotation)
-
-                            start("appLayerRotates_StartingPos", bugId = 140855415) {
-                                this.hasVisibleRegion(testApp.getPackage(), startingPos)
-                            }
-
-                            end("appLayerRotates_EndingPos", bugId = 140855415) {
-                                this.hasVisibleRegion(testApp.getPackage(), endingPos)
-                            }
-                        }
-
-                        eventLog {
-                            focusDoesNotChange(bugId = 151179149)
-                        }
-                    }
+    testSpec: FlickerTestParameter
+) : RotationTransition(testSpec) {
+    override val testApp = SimpleAppHelper(instrumentation)
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = {
+            super.transition(this, it)
+            setup {
+                test {
+                    testApp.launchViaIntent(wmHelper)
                 }
             }
+        }
 
-            return FlickerTestRunnerFactory.getInstance()
-                .buildRotationTest(instrumentation, transition, testSpec, repetitions = 5)
+    @Presubmit
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @Presubmit
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry()
+
+    @Presubmit
+    @Test
+    fun noUncoveredRegions() = testSpec.noUncoveredRegions(testSpec.config.startRotation,
+        testSpec.config.endRotation, allStates = false)
+
+    @Presubmit
+    @Test
+    fun screenshotLayerBecomesInvisible() {
+        testSpec.assertLayers {
+            this.isVisible(testApp.getPackage())
+                .then()
+                .isVisible(SCREENSHOT_LAYER)
+                .then()
+                .isVisible(testApp.getPackage())
+        }
+    }
+
+    @FlakyTest(bugId = 140855415)
+    @Test
+    fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @FlakyTest(bugId = 140855415)
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    @FlakyTest(bugId = 140855415)
+    @Test
+    fun navBarLayerRotatesAndScales() = testSpec.navBarLayerRotatesAndScales(
+        testSpec.config.startRotation, testSpec.config.endRotation)
+
+    @FlakyTest(bugId = 140855415)
+    @Test
+    fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales(
+        testSpec.config.startRotation, testSpec.config.endRotation)
+
+    @FlakyTest(bugId = 140855415)
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry()
+
+    @FlakyTest(bugId = 140855415)
+    @Test
+    fun appLayerRotates_StartingPos() {
+        testSpec.assertLayersStart {
+            this.coversExactly(startingPos, testApp.getPackage())
+        }
+    }
+
+    @FlakyTest(bugId = 140855415)
+    @Test
+    fun appLayerRotates_EndingPos() {
+        testSpec.assertLayersEnd {
+            this.coversExactly(endingPos, testApp.getPackage())
+        }
+    }
+
+    @FlakyTest(bugId = 151179149)
+    @Test
+    fun focusDoesNotChange() = testSpec.focusDoesNotChange()
+
+    companion object {
+        private const val SCREENSHOT_LAYER = "RotationLayer"
+
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance()
+                .getConfigRotationTests(repetitions = 5)
         }
     }
 }
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
index b871e94..c391112 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
@@ -17,39 +17,50 @@
 package com.android.server.wm.flicker.rotation
 
 import android.app.Instrumentation
-import android.os.Bundle
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.server.wm.flicker.FlickerBuilderProvider
+import com.android.server.wm.flicker.FlickerTestParameter
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.endRotation
 import com.android.server.wm.flicker.helpers.StandardAppHelper
+import com.android.server.wm.flicker.helpers.WindowUtils
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
 import com.android.server.wm.flicker.repetitions
 import com.android.server.wm.flicker.startRotation
 
-abstract class RotationTransition(protected val instrumentation: Instrumentation) {
-    abstract val testApp: StandardAppHelper
-    abstract fun getAppLaunchParams(configuration: Bundle): Map<String, String>
+abstract class RotationTransition(protected val testSpec: FlickerTestParameter) {
+    protected abstract val testApp: StandardAppHelper
 
-    protected open val transition: FlickerBuilder.(Bundle) -> Unit
-        get() = { configuration ->
-            repeat { configuration.repetitions }
-            setup {
-                test {
-                    device.wakeUpAndGoToHomeScreen()
-                    val extras = getAppLaunchParams(configuration)
-                    testApp.launchViaIntent(wmHelper, stringExtras = extras)
-                }
-                eachRun {
-                    this.setRotation(configuration.startRotation)
-                }
+    protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    protected val startingPos get() = WindowUtils.getDisplayBounds(testSpec.config.startRotation)
+    protected val endingPos get() = WindowUtils.getDisplayBounds(testSpec.config.endRotation)
+
+    protected open val transition: FlickerBuilder.(Map<String, Any?>) -> Unit = {
+        withTestName { testSpec.name }
+        repeat { testSpec.config.repetitions }
+        setup {
+            test {
+                device.wakeUpAndGoToHomeScreen()
             }
-            teardown {
-                test {
-                    testApp.exit()
-                }
-            }
-            transitions {
-                this.setRotation(configuration.endRotation)
+            eachRun {
+                this.setRotation(testSpec.config.startRotation)
             }
         }
+        teardown {
+            test {
+                testApp.exit()
+            }
+        }
+        transitions {
+            this.setRotation(testSpec.config.endRotation)
+        }
+    }
+
+    @FlickerBuilderProvider
+    fun buildFlicker(): FlickerBuilder {
+        return FlickerBuilder(instrumentation).apply {
+            transition(testSpec.config)
+        }
+    }
 }
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
index 7861464..fc5bcc7 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
@@ -16,32 +16,31 @@
 
 package com.android.server.wm.flicker.rotation
 
-import android.os.Bundle
+import android.platform.test.annotations.Presubmit
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
-import com.android.server.wm.flicker.endRotation
-import com.android.server.wm.flicker.focusDoesNotChange
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.appWindowAlwaysVisibleOnTop
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.endRotation
+import com.android.server.wm.flicker.focusDoesNotChange
 import com.android.server.wm.flicker.helpers.SeamlessRotationAppHelper
-import com.android.server.wm.flicker.helpers.StandardAppHelper
 import com.android.server.wm.flicker.layerAlwaysVisible
-import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.noUncoveredRegions
-import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
-import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.startRotation
 import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.testapp.ActivityOptions
+import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -52,116 +51,119 @@
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class SeamlessAppRotationTest(
-    testSpec: FlickerTestRunnerFactory.TestSpec
-) : FlickerTestRunner(testSpec) {
-    companion object : RotationTransition(InstrumentationRegistry.getInstrumentation()) {
-        override val testApp: StandardAppHelper
-            get() = SeamlessRotationAppHelper(instrumentation)
+    testSpec: FlickerTestParameter
+) : RotationTransition(testSpec) {
+    override val testApp = SeamlessRotationAppHelper(instrumentation)
 
-        override fun getAppLaunchParams(configuration: Bundle): Map<String, String> = mapOf(
-            ActivityOptions.EXTRA_STARVE_UI_THREAD to configuration.starveUiThread.toString()
-        )
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = {
+            super.transition(this, it)
+            setup {
+                test {
+                    testApp.launchViaIntent(wmHelper,
+                        stringExtras = mapOf(
+                            ActivityOptions.EXTRA_STARVE_UI_THREAD to it.starveUiThread.toString())
+                    )
+                }
+            }
+        }
 
-        private val testFactory = FlickerTestRunnerFactory.getInstance()
+    @Presubmit
+    @Test
+    fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry()
 
-        private val Bundle.starveUiThread
-            get() = this.getBoolean(ActivityOptions.EXTRA_STARVE_UI_THREAD, false)
+    @Presubmit
+    @Test
+    fun appWindowAlwaysVisibleOnTop() = testSpec.appWindowAlwaysVisibleOnTop(testApp.`package`)
 
-        private fun Bundle.createConfig(starveUiThread: Boolean): Bundle {
-            val config = this.deepCopy()
-            config.putBoolean(ActivityOptions.EXTRA_STARVE_UI_THREAD, starveUiThread)
+    @Presubmit
+    @Test
+    fun layerAlwaysVisible() = testSpec.layerAlwaysVisible(testApp.`package`)
+
+    @FlakyTest(bugId = 140855415)
+    @Test
+    fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+    @FlakyTest(bugId = 140855415)
+    @Test
+    fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+    @FlakyTest(bugId = 140855415)
+    @Test
+    fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+    @FlakyTest(bugId = 140855415)
+    @Test
+    fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+    @FlakyTest(bugId = 147659548)
+    @Test
+    fun noUncoveredRegions() = testSpec.noUncoveredRegions(testSpec.config.startRotation,
+        testSpec.config.endRotation, allStates = false)
+
+    @FlakyTest
+    @Test
+    fun navBarLayerRotatesAndScales() = testSpec.navBarLayerRotatesAndScales(
+        testSpec.config.startRotation, testSpec.config.endRotation)
+
+    @FlakyTest
+    @Test
+    fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales(
+        testSpec.config.startRotation, testSpec.config.endRotation)
+
+    @FlakyTest
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        testSpec.visibleLayersShownMoreThanOneConsecutiveEntry()
+
+    @FlakyTest(bugId = 147659548)
+    @Test
+    fun appLayerRotates() {
+        testSpec.assertLayers {
+            this.coversExactly(startingPos, testApp.`package`)
+        }
+    }
+
+    @FlakyTest(bugId = 151179149)
+    @Test
+    fun focusDoesNotChange() = testSpec.focusDoesNotChange()
+
+    companion object {
+        private val testFactory = FlickerTestParameterFactory.getInstance()
+
+        private val Map<String, Any?>.starveUiThread
+            get() = this.getOrDefault(ActivityOptions.EXTRA_STARVE_UI_THREAD, false) as Boolean
+
+        private fun FlickerTestParameter.createConfig(
+            starveUiThread: Boolean
+        ): MutableMap<String, Any?> {
+            val config = this.config.toMutableMap()
+            config[ActivityOptions.EXTRA_STARVE_UI_THREAD] = starveUiThread
             return config
         }
 
         @JvmStatic
-        private fun getConfigurations(): List<Bundle> {
-            return testFactory.getConfigRotationTests().flatMap {
+        private fun getConfigurations(): List<FlickerTestParameter> {
+            return testFactory.getConfigRotationTests(repetitions = 2).flatMap {
                 val defaultRun = it.createConfig(starveUiThread = false)
                 val busyUiRun = it.createConfig(starveUiThread = true)
-                listOf(defaultRun, busyUiRun)
+                listOf(
+                    FlickerTestParameter(defaultRun),
+                    FlickerTestParameter(busyUiRun,
+                        name = "${FlickerTestParameter.defaultName(busyUiRun)}_BUSY_UI_THREAD"
+                    )
+                )
             }
         }
 
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val configurations = getConfigurations()
-            val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
-                withTestName {
-                    val extra = if (configuration.starveUiThread) {
-                        "BUSY_UI_THREAD"
-                    } else {
-                        ""
-                    }
-                    buildTestTag(configuration, extraInfo = extra)
-                }
-                assertions {
-                    val startingBounds = WindowUtils.getDisplayBounds(configuration.startRotation)
-                    val endingBounds = WindowUtils.getDisplayBounds(configuration.endRotation)
-
-                    presubmit {
-                        windowManagerTrace {
-                            visibleWindowsShownMoreThanOneConsecutiveEntry()
-                            appWindowAlwaysVisibleOnTop(testApp.`package`)
-                        }
-
-                        layersTrace {
-                            layerAlwaysVisible(testApp.`package`)
-                        }
-                    }
-
-                    flaky {
-                        windowManagerTrace {
-                            navBarWindowIsAlwaysVisible(bugId = 140855415)
-                            statusBarWindowIsAlwaysVisible(bugId = 140855415)
-                        }
-
-                        layersTrace {
-                            navBarLayerIsAlwaysVisible(bugId = 140855415)
-                            statusBarLayerIsAlwaysVisible(bugId = 140855415)
-                            noUncoveredRegions(configuration.startRotation,
-                                configuration.endRotation, allStates = false, bugId = 147659548)
-                            navBarLayerRotatesAndScales(configuration.startRotation,
-                                configuration.endRotation)
-                            statusBarLayerRotatesScales(configuration.startRotation,
-                                configuration.endRotation)
-                            visibleLayersShownMoreThanOneConsecutiveEntry()
-
-                            all("appLayerRotates", bugId = 147659548) {
-                                if (startingBounds == endingBounds) {
-                                    this.hasVisibleRegion(
-                                        testApp.`package`, startingBounds)
-                                } else {
-                                    this.hasVisibleRegion(testApp.`package`,
-                                        startingBounds)
-                                        .then()
-                                        .hasVisibleRegion(testApp.`package`,
-                                            endingBounds)
-                                }
-                            }
-
-                            all("noUncoveredRegions", bugId = 147659548) {
-                                if (startingBounds == endingBounds) {
-                                    this.coversAtLeastRegion(startingBounds)
-                                } else {
-                                    this.coversAtLeastRegion(startingBounds)
-                                        .then()
-                                        .coversAtLeastRegion(endingBounds)
-                                }
-                            }
-                        }
-
-                        eventLog {
-                            focusDoesNotChange(bugId = 151179149)
-                        }
-                    }
-                }
-            }
-
-            return testFactory.buildRotationTest(instrumentation, transition, testSpec,
-                deviceConfigurations = configurations, repetitions = 2)
+        fun getParams(): Collection<FlickerTestParameter> {
+            return getConfigurations()
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/FlickerTests/test-apps/flickerapp/Android.bp b/tests/FlickerTests/test-apps/flickerapp/Android.bp
index 5027797..78660c0 100644
--- a/tests/FlickerTests/test-apps/flickerapp/Android.bp
+++ b/tests/FlickerTests/test-apps/flickerapp/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FlickerTestApp",
     srcs: ["**/*.java"],
diff --git a/tests/FrameworkPerf/Android.bp b/tests/FrameworkPerf/Android.bp
index a259ebd..9be3ab7 100644
--- a/tests/FrameworkPerf/Android.bp
+++ b/tests/FrameworkPerf/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworkPerf",
     srcs: ["**/*.java"],
diff --git a/tests/GamePerformance/Android.bp b/tests/GamePerformance/Android.bp
index 02908d3..f250a1b 100644
--- a/tests/GamePerformance/Android.bp
+++ b/tests/GamePerformance/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "GamePerformance",
     // Don't include this package in any target
diff --git a/tests/GridLayoutTest/Android.bp b/tests/GridLayoutTest/Android.bp
index b4b5ba5..71d884c 100644
--- a/tests/GridLayoutTest/Android.bp
+++ b/tests/GridLayoutTest/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "GridLayoutTest",
     srcs: ["**/*.java"],
diff --git a/tests/HierarchyViewerTest/Android.bp b/tests/HierarchyViewerTest/Android.bp
index 814c883..9c5d1c0 100644
--- a/tests/HierarchyViewerTest/Android.bp
+++ b/tests/HierarchyViewerTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "HierarchyViewerTest",
     srcs: ["**/*.java"],
diff --git a/tests/HugeBackup/Android.bp b/tests/HugeBackup/Android.bp
index b44c457..7d4e52a 100644
--- a/tests/HugeBackup/Android.bp
+++ b/tests/HugeBackup/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "HugeBackup",
     // Only compile source java files in this apk.
diff --git a/tests/HwAccelerationTest/Android.bp b/tests/HwAccelerationTest/Android.bp
index 37d3f5d..7606322 100644
--- a/tests/HwAccelerationTest/Android.bp
+++ b/tests/HwAccelerationTest/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "HwAccelerationTest",
     srcs: ["**/*.java"],
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index c6c67fe..62ccb1a0 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -400,6 +400,15 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="StretchySurfaceViewActivity"
+                  android:label="SurfaceView/Stretchy Movement"
+                  android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="com.android.test.hwui.TEST"/>
+            </intent-filter>
+        </activity>
+
         <activity android:name="GetBitmapSurfaceViewActivity"
              android:label="SurfaceView/GetBitmap with Camera source"
              android:exported="true">
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java
index 818d899..65d7363 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java
@@ -19,8 +19,13 @@
 import android.app.Activity;
 import android.content.Context;
 import android.graphics.Canvas;
+import android.graphics.PointF;
+import android.graphics.RecordingCanvas;
+import android.graphics.Rect;
+import android.graphics.RectF;
 import android.graphics.RenderNode;
 import android.os.Bundle;
+import android.view.MotionEvent;
 import android.widget.LinearLayout;
 import android.widget.ProgressBar;
 import android.widget.ScrollView;
@@ -38,7 +43,46 @@
         ProgressBar spinner = new ProgressBar(this, null, android.R.attr.progressBarStyleLarge);
         layout.addView(spinner);
 
-        ScrollView scrollingThing = new ScrollView(this);
+        ScrollView scrollingThing = new ScrollView(this) {
+            int setting = 0;
+            PointF opts[] = new PointF[] {
+                    new PointF(0, 0),
+                    new PointF(0, -1f),
+                    new PointF(1f, 0),
+                    new PointF(0, 1f),
+                    new PointF(-1f, 0),
+                    new PointF(-1f, 1f),
+            };
+            {
+                setWillNotDraw(false);
+            }
+
+            @Override
+            public boolean onTouchEvent(MotionEvent ev) {
+                if (ev.getActionMasked() == MotionEvent.ACTION_UP) {
+                    setting = (setting + 1) % opts.length;
+                    invalidate();
+                }
+                return super.onTouchEvent(ev);
+            }
+
+            @Override
+            protected void onDraw(Canvas canvas) {
+                super.onDraw(canvas);
+                RenderNode node = ((RecordingCanvas) canvas).mNode;
+                PointF dir = opts[setting];
+                float maxStretchAmount = 100f;
+                // Although we could do this in a single call, the real one won't be - so mimic that
+                if (dir.x != 0f) {
+                    node.stretch(0f, 0f, (float) getWidth(), (float) getHeight(),
+                            dir.x, 0f, maxStretchAmount);
+                }
+                if (dir.y != 0f) {
+                    node.stretch(0f, 0f, (float) getWidth(), (float) getHeight(),
+                            0f, dir.y, maxStretchAmount);
+                }
+            }
+        };
         scrollingThing.addView(new MyPositionReporter(this));
         layout.addView(scrollingThing);
 
@@ -49,6 +93,11 @@
         RenderNode mNode;
         int mCurrentCount = 0;
         int mTranslateY = 0;
+        Rect mPosition = new Rect();
+        RectF mStretchArea = new RectF();
+        float mStretchX = 0.0f;
+        float mStretchY = 0.0f;
+        float mStretchMax = 0.0f;
 
         MyPositionReporter(Context c) {
             super(c);
@@ -78,18 +127,36 @@
             canvas.drawRenderNode(mNode);
         }
 
+        void updateText() {
+            setText(String.format("%d: Position %s, stretch area %s, vec %f,%f, amount %f",
+                    mCurrentCount, mPosition.toShortString(), mStretchArea.toShortString(),
+                    mStretchX, mStretchY, mStretchMax));
+        }
+
         @Override
         public void positionChanged(long frameNumber, int left, int top, int right, int bottom) {
-            post(() -> {
+            getHandler().postAtFrontOfQueue(() -> {
                 mCurrentCount++;
-                setText(String.format("%d: Position [%d, %d, %d, %d]", mCurrentCount,
-                        left, top, right, bottom));
+                mPosition.set(left, top, right, bottom);
+                updateText();
+            });
+        }
+
+        @Override
+        public void applyStretch(long frameNumber, float left, float top, float right, float bottom,
+                float vecX, float vecY, float maxStretch) {
+            getHandler().postAtFrontOfQueue(() -> {
+                mStretchArea.set(left, top, right, bottom);
+                mStretchX = vecX;
+                mStretchY = vecY;
+                mStretchMax = maxStretch;
+                updateText();
             });
         }
 
         @Override
         public void positionLost(long frameNumber) {
-            post(() -> {
+            getHandler().postAtFrontOfQueue(() -> {
                 mCurrentCount++;
                 setText(mCurrentCount + " No position");
             });
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/StretchySurfaceViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/StretchySurfaceViewActivity.java
new file mode 100644
index 0000000..d604244
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/StretchySurfaceViewActivity.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.animation.ObjectAnimator;
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RecordingCanvas;
+import android.graphics.RenderNode;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.SurfaceHolder;
+import android.view.SurfaceHolder.Callback;
+import android.view.SurfaceView;
+import android.view.animation.LinearInterpolator;
+import android.widget.FrameLayout;
+
+public class StretchySurfaceViewActivity extends Activity implements Callback {
+    SurfaceView mSurfaceView;
+    ObjectAnimator mAnimator;
+
+    class MySurfaceView extends SurfaceView {
+        boolean mSlow;
+        boolean mScaled;
+        int mToggle = 0;
+
+        public MySurfaceView(Context context) {
+            super(context);
+            setOnClickListener(v -> {
+                mToggle = (mToggle + 1) % 4;
+                mSlow = (mToggle & 0x2) != 0;
+                mScaled = (mToggle & 0x1) != 0;
+
+                mSurfaceView.setScaleX(mScaled ? 1.6f : 1f);
+                mSurfaceView.setScaleY(mScaled ? 0.8f : 1f);
+
+                setTitle("Slow=" + mSlow + ", scaled=" + mScaled);
+                invalidate();
+            });
+            setWillNotDraw(false);
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+            super.draw(canvas);
+            if (mSlow) {
+                try {
+                    Thread.sleep(16);
+                } catch (InterruptedException e) {}
+            }
+        }
+
+        public void setMyTranslationY(float ty) {
+            setTranslationY(ty);
+            if (mSlow) {
+                invalidate();
+            }
+        }
+
+        public float getMyTranslationY() {
+            return getTranslationY();
+        }
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        FrameLayout content = new FrameLayout(this) {
+            {
+                setWillNotDraw(false);
+            }
+
+            @Override
+            protected void onDraw(Canvas canvas) {
+                Paint paint = new Paint();
+                paint.setAntiAlias(true);
+                paint.setColor(Color.RED);
+                paint.setStyle(Paint.Style.STROKE);
+                paint.setStrokeWidth(10f);
+                canvas.drawLine(0f, 0f, getWidth(), getHeight(), paint);
+                super.onDraw(canvas);
+
+                RenderNode node = ((RecordingCanvas) canvas).mNode;
+                node.stretch(0f, 0f, getWidth(), getHeight() / 2f, 0f, 1f, 400f);
+            }
+        };
+
+        mSurfaceView = new MySurfaceView(this);
+        mSurfaceView.getHolder().addCallback(this);
+
+        final float density = getResources().getDisplayMetrics().density;
+        int size = (int) (200 * density);
+
+        content.addView(mSurfaceView, new FrameLayout.LayoutParams(
+                size, size, Gravity.CENTER_HORIZONTAL | Gravity.TOP));
+        mAnimator = ObjectAnimator.ofFloat(mSurfaceView, "myTranslationY",
+                0, size);
+        mAnimator.setRepeatMode(ObjectAnimator.REVERSE);
+        mAnimator.setRepeatCount(ObjectAnimator.INFINITE);
+        mAnimator.setDuration(1000);
+        mAnimator.setInterpolator(new LinearInterpolator());
+        setContentView(content);
+    }
+
+    @Override
+    public void surfaceCreated(SurfaceHolder holder) {
+    }
+
+    @Override
+    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+        Canvas canvas = holder.lockCanvas();
+        canvas.drawColor(Color.WHITE);
+
+        Paint paint = new Paint();
+        paint.setAntiAlias(true);
+        paint.setColor(Color.GREEN);
+        paint.setStyle(Paint.Style.STROKE);
+        paint.setStrokeWidth(10f);
+        canvas.drawLine(0, 0, width, height, paint);
+
+        holder.unlockCanvasAndPost(canvas);
+    }
+
+    @Override
+    public void surfaceDestroyed(SurfaceHolder holder) {
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mAnimator.start();
+    }
+
+    @Override
+    protected void onPause() {
+        mAnimator.pause();
+        super.onPause();
+    }
+}
diff --git a/tests/Input/Android.bp b/tests/Input/Android.bp
index a72b07c..335c8d0 100644
--- a/tests/Input/Android.bp
+++ b/tests/Input/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "InputTests",
     srcs: ["src/**/*.kt"],
diff --git a/tests/Input/src/com/android/test/input/ViewFrameInfoTest.kt b/tests/Input/src/com/android/test/input/ViewFrameInfoTest.kt
index f919a3e..c19e5cc 100644
--- a/tests/Input/src/com/android/test/input/ViewFrameInfoTest.kt
+++ b/tests/Input/src/com/android/test/input/ViewFrameInfoTest.kt
@@ -62,15 +62,12 @@
     fun testUpdateFrameInfoFromViewFrameInfo() {
         val frameInfo = FrameInfo()
         // By default, all values should be zero
-        assertThat(frameInfo.frameInfo[FrameInfo.OLDEST_INPUT_EVENT]).isEqualTo(0)
-        assertThat(frameInfo.frameInfo[FrameInfo.NEWEST_INPUT_EVENT]).isEqualTo(0)
+        // TODO(b/169866723): Use InputEventAssigner and assert INPUT_EVENT_ID
         assertThat(frameInfo.frameInfo[FrameInfo.FLAGS]).isEqualTo(0)
         assertThat(frameInfo.frameInfo[FrameInfo.DRAW_START]).isEqualTo(0)
 
         // The values inside FrameInfo should match those from ViewFrameInfo after we update them
         mViewFrameInfo.populateFrameInfo(frameInfo)
-        assertThat(frameInfo.frameInfo[FrameInfo.OLDEST_INPUT_EVENT]).isEqualTo(10)
-        assertThat(frameInfo.frameInfo[FrameInfo.NEWEST_INPUT_EVENT]).isEqualTo(20)
         assertThat(frameInfo.frameInfo[FrameInfo.FLAGS]).isEqualTo(
                 FrameInfo.FLAG_WINDOW_LAYOUT_CHANGED)
         assertThat(frameInfo.frameInfo[FrameInfo.DRAW_START]).isGreaterThan(mTimeStarted)
diff --git a/tests/Internal/Android.bp b/tests/Internal/Android.bp
index 9da17db..ef45864 100644
--- a/tests/Internal/Android.bp
+++ b/tests/Internal/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "InternalTests",
     proto: {
diff --git a/tests/JankBench/Android.bp b/tests/JankBench/Android.bp
index 166639d..39dd197 100644
--- a/tests/JankBench/Android.bp
+++ b/tests/JankBench/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "JankBench",
     manifest: "app/src/main/AndroidManifest.xml",
diff --git a/tests/JobSchedulerPerfTests/Android.bp b/tests/JobSchedulerPerfTests/Android.bp
index 2ae8c33..eb9b2f6 100644
--- a/tests/JobSchedulerPerfTests/Android.bp
+++ b/tests/JobSchedulerPerfTests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "JobSchedulerPerfTests",
     srcs: ["src/**/*.java"],
diff --git a/tests/JobSchedulerTestApp/Android.bp b/tests/JobSchedulerTestApp/Android.bp
index bac0220..893a983 100644
--- a/tests/JobSchedulerTestApp/Android.bp
+++ b/tests/JobSchedulerTestApp/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "JobSchedulerTestApp",
     srcs: ["src/**/*.java"],
diff --git a/tests/LargeAssetTest/Android.bp b/tests/LargeAssetTest/Android.bp
index 499e6a0..2a6de77 100644
--- a/tests/LargeAssetTest/Android.bp
+++ b/tests/LargeAssetTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "LargeAssetTest",
     srcs: ["**/*.java"],
diff --git a/tests/LegacyAssistant/Android.bp b/tests/LegacyAssistant/Android.bp
index fef924d..ab8ef88 100644
--- a/tests/LegacyAssistant/Android.bp
+++ b/tests/LegacyAssistant/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "LegacyAssistant",
     srcs: ["**/*.java"],
diff --git a/tests/LocalizationTest/Android.bp b/tests/LocalizationTest/Android.bp
index c4bfcb1..4e0b0a8 100644
--- a/tests/LocalizationTest/Android.bp
+++ b/tests/LocalizationTest/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "LocalizationTest",
     srcs: ["java/**/*.kt"],
diff --git a/tests/LocationTracker/Android.bp b/tests/LocationTracker/Android.bp
index f0075a9..538687c 100644
--- a/tests/LocationTracker/Android.bp
+++ b/tests/LocationTracker/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "LocationTracker",
     srcs: ["**/*.java"],
diff --git a/tests/LotsOfApps/Android.bp b/tests/LotsOfApps/Android.bp
index 68b9f88..5f6c089 100644
--- a/tests/LotsOfApps/Android.bp
+++ b/tests/LotsOfApps/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "LotsOfApps",
     srcs: ["**/*.java"],
diff --git a/tests/LowStorageTest/Android.bp b/tests/LowStorageTest/Android.bp
index e72e4a5..6dcf39d 100644
--- a/tests/LowStorageTest/Android.bp
+++ b/tests/LowStorageTest/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "lowstoragetest",
     certificate: "platform",
diff --git a/tests/ManagedProfileLifecycleStressTest/Android.bp b/tests/ManagedProfileLifecycleStressTest/Android.bp
index 639ce3c..3ef6322 100644
--- a/tests/ManagedProfileLifecycleStressTest/Android.bp
+++ b/tests/ManagedProfileLifecycleStressTest/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_test_host {
     name: "ManagedProfileLifecycleStressTest",
     srcs: ["src/**/*.java"],
diff --git a/tests/ManagedProfileLifecycleStressTest/app/DummyDPC/Android.bp b/tests/ManagedProfileLifecycleStressTest/app/DummyDPC/Android.bp
index 1f47b03..7a9b6cf 100644
--- a/tests/ManagedProfileLifecycleStressTest/app/DummyDPC/Android.bp
+++ b/tests/ManagedProfileLifecycleStressTest/app/DummyDPC/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "DummyDPC",
     defaults: ["cts_defaults"],
diff --git a/tests/MemoryUsage/Android.bp b/tests/MemoryUsage/Android.bp
index aeb5338..e30a0a7 100644
--- a/tests/MemoryUsage/Android.bp
+++ b/tests/MemoryUsage/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "MemoryUsage",
     // Only compile source java files in this apk.
diff --git a/tests/MirrorSurfaceTest/Android.bp b/tests/MirrorSurfaceTest/Android.bp
index e359c64..1368f26 100644
--- a/tests/MirrorSurfaceTest/Android.bp
+++ b/tests/MirrorSurfaceTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "MirrorSurfaceTest",
     srcs: ["src/**/*.java"],
diff --git a/tests/NativeProcessesMemoryTest/Android.bp b/tests/NativeProcessesMemoryTest/Android.bp
index f2625bf..b7160e9 100644
--- a/tests/NativeProcessesMemoryTest/Android.bp
+++ b/tests/NativeProcessesMemoryTest/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_test_host {
     name: "native-processes-memory-test",
     srcs: ["src/**/*.java"],
diff --git a/tests/NetworkSecurityConfigTest/Android.bp b/tests/NetworkSecurityConfigTest/Android.bp
index cf8ca57..473eadb 100644
--- a/tests/NetworkSecurityConfigTest/Android.bp
+++ b/tests/NetworkSecurityConfigTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "NetworkSecurityConfigTests",
     certificate: "platform",
diff --git a/tests/NullHomeTest/Android.bp b/tests/NullHomeTest/Android.bp
index fc71d0d..d8799a87 100644
--- a/tests/NullHomeTest/Android.bp
+++ b/tests/NullHomeTest/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "NullHomeTest",
     srcs: ["src/**/*.java"],
diff --git a/tests/OdmApps/Android.bp b/tests/OdmApps/Android.bp
index d86f9cc..de86498 100644
--- a/tests/OdmApps/Android.bp
+++ b/tests/OdmApps/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_test_host {
     name: "OdmAppsTest",
     srcs: ["src/**/*.java"],
diff --git a/tests/OdmApps/app/Android.bp b/tests/OdmApps/app/Android.bp
index 5eb8590..a33a1cf 100644
--- a/tests/OdmApps/app/Android.bp
+++ b/tests/OdmApps/app/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "TestOdmApp",
     test_suites: ["device-tests"],
diff --git a/tests/OdmApps/priv-app/Android.bp b/tests/OdmApps/priv-app/Android.bp
index 9dd477cf..7527729 100644
--- a/tests/OdmApps/priv-app/Android.bp
+++ b/tests/OdmApps/priv-app/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "TestOdmPrivApp",
     test_suites: ["device-tests"],
diff --git a/tests/OneMedia/Android.bp b/tests/OneMedia/Android.bp
index 11e12f35..5c73177 100644
--- a/tests/OneMedia/Android.bp
+++ b/tests/OneMedia/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "OneMedia",
     srcs: [
diff --git a/tests/PackageWatchdog/Android.bp b/tests/PackageWatchdog/Android.bp
index 0b75039..1e1dc84 100644
--- a/tests/PackageWatchdog/Android.bp
+++ b/tests/PackageWatchdog/Android.bp
@@ -13,6 +13,15 @@
 // limitations under the License.
 
 // PackageWatchdogTest
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "PackageWatchdogTest",
     srcs: ["src/**/*.java"],
diff --git a/tests/PackageWatchdog/TEST_MAPPING b/tests/PackageWatchdog/TEST_MAPPING
new file mode 100644
index 0000000..6494a27
--- /dev/null
+++ b/tests/PackageWatchdog/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "PackageWatchdogTest"
+    }
+  ]
+}
diff --git a/tests/PlatformCompatGating/Android.bp b/tests/PlatformCompatGating/Android.bp
index 7d918cc..f0f9c4b 100644
--- a/tests/PlatformCompatGating/Android.bp
+++ b/tests/PlatformCompatGating/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "PlatformCompatGating",
     // Only compile source java files in this apk.
diff --git a/tests/PlatformCompatGating/test-rules/Android.bp b/tests/PlatformCompatGating/test-rules/Android.bp
index 10fa2dc..5f91f9d0 100644
--- a/tests/PlatformCompatGating/test-rules/Android.bp
+++ b/tests/PlatformCompatGating/test-rules/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library {
     name: "platform-compat-test-rules",
     srcs: ["src/**/*.java"],
@@ -23,4 +32,4 @@
         "truth-prebuilt",
         "core-compat-test-rules"
     ],
-}
\ No newline at end of file
+}
diff --git a/tests/ProtoInputStreamTests/Android.bp b/tests/ProtoInputStreamTests/Android.bp
index ecc40566..0029080 100644
--- a/tests/ProtoInputStreamTests/Android.bp
+++ b/tests/ProtoInputStreamTests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ProtoInputStreamTests",
     proto: {
diff --git a/tests/RemoteDisplayProvider/Android.bp b/tests/RemoteDisplayProvider/Android.bp
index 6c7798f..55732d1 100644
--- a/tests/RemoteDisplayProvider/Android.bp
+++ b/tests/RemoteDisplayProvider/Android.bp
@@ -13,6 +13,15 @@
 // limitations under the License.
 
 // Build the application.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "RemoteDisplayProviderTest",
     sdk_version: "system_current",
diff --git a/tests/RenderThreadTest/Android.bp b/tests/RenderThreadTest/Android.bp
index 1659776..b18b04e 100644
--- a/tests/RenderThreadTest/Android.bp
+++ b/tests/RenderThreadTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "RenderThreadTest",
     // Only compile source java files in this apk.
diff --git a/tests/RollbackTest/Android.bp b/tests/RollbackTest/Android.bp
index 7dd003e..6e1cef4 100644
--- a/tests/RollbackTest/Android.bp
+++ b/tests/RollbackTest/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "RollbackTest",
     manifest: "RollbackTest/AndroidManifest.xml",
@@ -96,6 +105,7 @@
   key: "com.android.apex.apkrollback.test.key",
   apps: ["TestAppAv1"],
   installable: false,
+  updatable: false,
 }
 
 apex {
@@ -106,6 +116,7 @@
   key: "com.android.apex.apkrollback.test.key",
   apps: ["TestAppAv2"],
   installable: false,
+  updatable: false,
 }
 
 apex {
@@ -116,4 +127,5 @@
   key: "com.android.apex.apkrollback.test.key",
   apps: ["TestAppACrashingV2"],
   installable: false,
-}
\ No newline at end of file
+  updatable: false,
+}
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
index 0508125..0bb0337 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -35,7 +35,6 @@
 import com.android.cts.install.lib.Install;
 import com.android.cts.install.lib.InstallUtils;
 import com.android.cts.install.lib.TestApp;
-import com.android.cts.install.lib.Uninstall;
 import com.android.cts.rollback.lib.Rollback;
 import com.android.cts.rollback.lib.RollbackUtils;
 import com.android.internal.R;
@@ -89,7 +88,6 @@
      */
     @Test
     public void testBadApkOnly_Phase1_Install() throws Exception {
-        Uninstall.packages(TestApp.A);
         assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
 
         Install.single(TestApp.A1).commit();
@@ -149,7 +147,6 @@
      */
     @Test
     public void testNativeWatchdogTriggersRollback_Phase1_Install() throws Exception {
-        Uninstall.packages(TestApp.A);
         Install.single(TestApp.A1).commit();
         assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
 
@@ -183,7 +180,6 @@
      */
     @Test
     public void testNativeWatchdogTriggersRollbackForAll_Phase1_InstallA() throws Exception {
-        Uninstall.packages(TestApp.A);
         Install.single(TestApp.A1).commit();
         assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
 
@@ -201,7 +197,6 @@
                 TestApp.A)).isNotNull();
 
         // Install another package with rollback
-        Uninstall.packages(TestApp.B);
         Install.single(TestApp.B1).commit();
         assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1);
 
@@ -238,7 +233,6 @@
 
     @Test
     public void testPreviouslyAbandonedRollbacks_Phase1_InstallAndAbandon() throws Exception {
-        Uninstall.packages(TestApp.A);
         Install.single(TestApp.A1).commit();
         assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
 
@@ -265,7 +259,6 @@
     public void testPreviouslyAbandonedRollbacks_Phase3_VerifyRollback() throws Exception {
         assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
         InstallUtils.processUserData(TestApp.A);
-        Uninstall.packages(TestApp.A);
     }
 
     private static String getModuleMetadataPackageName() {
@@ -301,7 +294,6 @@
 
     @Test
     public void testRollbackDataPolicy_Phase1_Install() throws Exception {
-        Uninstall.packages(TestApp.A, TestApp.B, TestApp.C);
         Install.multi(TestApp.A1, TestApp.B1, TestApp.C1).commit();
         // Write user data version = 1
         InstallUtils.processUserData(TestApp.A);
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
index 65fb7b6c..304567a3 100644
--- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -99,10 +99,16 @@
                 "/data/apex/active/" + APK_IN_APEX_TESTAPEX_NAME + "*.apex");
         runPhase("expireRollbacks");
         mLogger.start(getDevice());
+        getDevice().uninstallPackage("com.android.cts.install.lib.testapp.A");
+        getDevice().uninstallPackage("com.android.cts.install.lib.testapp.B");
+        getDevice().uninstallPackage("com.android.cts.install.lib.testapp.C");
     }
 
     @After
     public void tearDown() throws Exception {
+        getDevice().uninstallPackage("com.android.cts.install.lib.testapp.A");
+        getDevice().uninstallPackage("com.android.cts.install.lib.testapp.B");
+        getDevice().uninstallPackage("com.android.cts.install.lib.testapp.C");
         mLogger.stop();
         runPhase("expireRollbacks");
         deleteFiles("/system/apex/" + APK_IN_APEX_TESTAPEX_NAME + "*.apex",
@@ -283,7 +289,6 @@
      */
     @Test
     public void testRollbackApexWithApk() throws Exception {
-        getDevice().uninstallPackage("com.android.cts.install.lib.testapp.A");
         pushTestApex();
         runPhase("testRollbackApexWithApk_Phase1_Install");
         getDevice().reboot();
@@ -297,7 +302,6 @@
      */
     @Test
     public void testRollbackApexWithApkCrashing() throws Exception {
-        getDevice().uninstallPackage("com.android.cts.install.lib.testapp.A");
         pushTestApex();
 
         // Install an apex with apk that crashes
diff --git a/tests/SerialChat/Android.bp b/tests/SerialChat/Android.bp
index 3c18035..8719e010 100644
--- a/tests/SerialChat/Android.bp
+++ b/tests/SerialChat/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "SerialChat",
     srcs: ["**/*.java"],
diff --git a/tests/ServiceCrashTest/Android.bp b/tests/ServiceCrashTest/Android.bp
index 40a377d..fb98b763 100644
--- a/tests/ServiceCrashTest/Android.bp
+++ b/tests/ServiceCrashTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ServiceCrashTest",
     // Only compile source java files in this apk.
diff --git a/tests/SharedLibrary/client/Android.bp b/tests/SharedLibrary/client/Android.bp
index dbf6dc9..6eab7c2 100644
--- a/tests/SharedLibrary/client/Android.bp
+++ b/tests/SharedLibrary/client/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "SharedLibraryClient",
     srcs: ["**/*.java"],
diff --git a/tests/SharedLibrary/lib/Android.bp b/tests/SharedLibrary/lib/Android.bp
index f69d388..0595cb1 100644
--- a/tests/SharedLibrary/lib/Android.bp
+++ b/tests/SharedLibrary/lib/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "SharedLibrary",
     srcs: ["**/*.java"],
diff --git a/tests/ShowWhenLockedApp/Android.bp b/tests/ShowWhenLockedApp/Android.bp
index dba564c..f24834a 100644
--- a/tests/ShowWhenLockedApp/Android.bp
+++ b/tests/ShowWhenLockedApp/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "ShowWhenLocked",
     srcs: ["**/*.java"],
diff --git a/tests/SilkFX/Android.bp b/tests/SilkFX/Android.bp
index 92e3efa..088d9a2 100644
--- a/tests/SilkFX/Android.bp
+++ b/tests/SilkFX/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "SilkFX",
     srcs: ["**/*.java", "**/*.kt"],
diff --git a/tests/SmokeTest/Android.bp b/tests/SmokeTest/Android.bp
index bc45ee6..4c853e3 100644
--- a/tests/SmokeTest/Android.bp
+++ b/tests/SmokeTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "SmokeTestApp",
     // This builds "SmokeTestApp"
diff --git a/tests/SmokeTest/tests/Android.bp b/tests/SmokeTest/tests/Android.bp
index ceb2d19..5542dd0 100644
--- a/tests/SmokeTest/tests/Android.bp
+++ b/tests/SmokeTest/tests/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "SmokeTest",
     // Include all test java files.
diff --git a/tests/SmokeTestApps/Android.bp b/tests/SmokeTestApps/Android.bp
index 0feb0004..3505fe1 100644
--- a/tests/SmokeTestApps/Android.bp
+++ b/tests/SmokeTestApps/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "SmokeTestTriggerApps",
     srcs: ["src/**/*.java"],
diff --git a/tests/SoundTriggerTestApp/Android.bp b/tests/SoundTriggerTestApp/Android.bp
index d3a1300..09f1e10 100644
--- a/tests/SoundTriggerTestApp/Android.bp
+++ b/tests/SoundTriggerTestApp/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "SoundTriggerTestApp",
     srcs: ["**/*.java"],
diff --git a/tests/Split/Android.bp b/tests/Split/Android.bp
index d8c89ba..727b202 100644
--- a/tests/Split/Android.bp
+++ b/tests/Split/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "Split",
     srcs: ["**/*.java"],
diff --git a/tests/StagedInstallTest/Android.bp b/tests/StagedInstallTest/Android.bp
index 3a40696..2e57467 100644
--- a/tests/StagedInstallTest/Android.bp
+++ b/tests/StagedInstallTest/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "StagedInstallInternalTestApp",
     manifest: "app/AndroidManifest.xml",
@@ -41,4 +50,3 @@
     test_suites: ["general-tests"],
     test_config: "StagedInstallInternalTest.xml",
 }
-
diff --git a/tests/StatusBar/Android.bp b/tests/StatusBar/Android.bp
index 0b650ed..2fad051 100644
--- a/tests/StatusBar/Android.bp
+++ b/tests/StatusBar/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "StatusBarTest",
     srcs: ["**/*.java"],
diff --git a/tests/SurfaceComposition/Android.bp b/tests/SurfaceComposition/Android.bp
index 53e4d52..f5aba8f5 100644
--- a/tests/SurfaceComposition/Android.bp
+++ b/tests/SurfaceComposition/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "SurfaceComposition",
     // Don't include this package in any target
diff --git a/tests/SurfaceControlViewHostTest/Android.bp b/tests/SurfaceControlViewHostTest/Android.bp
index e4e0600..0127ba5 100644
--- a/tests/SurfaceControlViewHostTest/Android.bp
+++ b/tests/SurfaceControlViewHostTest/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "SurfaceControlViewHostTest",
     srcs: ["**/*.java"],
diff --git a/tests/SurfaceViewBufferTests/Android.bp b/tests/SurfaceViewBufferTests/Android.bp
index 48031de..dc75f00 100644
--- a/tests/SurfaceViewBufferTests/Android.bp
+++ b/tests/SurfaceViewBufferTests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "SurfaceViewBufferTests",
     srcs: ["**/*.java","**/*.kt"],
diff --git a/tests/SystemMemoryTest/device/Android.bp b/tests/SystemMemoryTest/device/Android.bp
index 2bf0fec..d7cec1a 100644
--- a/tests/SystemMemoryTest/device/Android.bp
+++ b/tests/SystemMemoryTest/device/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test_helper_app {
     name: "SystemMemoryTestDevice",
     sdk_version: "current",
diff --git a/tests/SystemMemoryTest/host/Android.bp b/tests/SystemMemoryTest/host/Android.bp
index 3bb5489..7974462 100644
--- a/tests/SystemMemoryTest/host/Android.bp
+++ b/tests/SystemMemoryTest/host/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_test_host {
     name: "system-memory-test",
     srcs: ["src/**/*.java"],
diff --git a/tests/SystemUIDemoModeController/Android.bp b/tests/SystemUIDemoModeController/Android.bp
index 1e4c437..d952cf6 100644
--- a/tests/SystemUIDemoModeController/Android.bp
+++ b/tests/SystemUIDemoModeController/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "DemoModeController",
     srcs: ["**/*.java"],
diff --git a/tests/TaskOrganizerTest/Android.bp b/tests/TaskOrganizerTest/Android.bp
index 91900626..9b72d35 100644
--- a/tests/TaskOrganizerTest/Android.bp
+++ b/tests/TaskOrganizerTest/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "TaskOrganizerTest",
     srcs: ["**/*.java","**/*.kt"],
diff --git a/tests/TelephonyCommonTests/Android.bp b/tests/TelephonyCommonTests/Android.bp
index 4f7569d..a9fbfd9 100644
--- a/tests/TelephonyCommonTests/Android.bp
+++ b/tests/TelephonyCommonTests/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "TelephonyCommonTests",
     srcs: [
diff --git a/tests/TouchLatency/Android.bp b/tests/TouchLatency/Android.bp
index 1174bcb0..3a9e240 100644
--- a/tests/TouchLatency/Android.bp
+++ b/tests/TouchLatency/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "TouchLatency",
     manifest: "app/src/main/AndroidManifest.xml",
diff --git a/tests/TransformTest/Android.bp b/tests/TransformTest/Android.bp
index fd7aaeb..f58fe8f 100644
--- a/tests/TransformTest/Android.bp
+++ b/tests/TransformTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "TransformTest",
     srcs: ["**/*.java"],
diff --git a/tests/TransitionTests/Android.bp b/tests/TransitionTests/Android.bp
index 57f19e3..4daa5b8 100644
--- a/tests/TransitionTests/Android.bp
+++ b/tests/TransitionTests/Android.bp
@@ -1,3 +1,14 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "TransitionTests",
     // Only compile source java files in this apk.
diff --git a/tests/TtsTests/Android.bp b/tests/TtsTests/Android.bp
index b137523..b7aa5d4 100644
--- a/tests/TtsTests/Android.bp
+++ b/tests/TtsTests/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "TtsTests",
     srcs: ["**/*.java"],
diff --git a/tests/UiBench/Android.bp b/tests/UiBench/Android.bp
index e0608e2..0d2f2ef 100644
--- a/tests/UiBench/Android.bp
+++ b/tests/UiBench/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "UiBench",
     sdk_version: "current",
diff --git a/tests/UpdatableSystemFontTest/Android.bp b/tests/UpdatableSystemFontTest/Android.bp
index 43a5078..ee24d48 100644
--- a/tests/UpdatableSystemFontTest/Android.bp
+++ b/tests/UpdatableSystemFontTest/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_test_host {
     name: "UpdatableSystemFontTest",
     srcs: ["src/**/*.java"],
diff --git a/tests/UpdatableSystemFontTest/testdata/Android.bp b/tests/UpdatableSystemFontTest/testdata/Android.bp
index 1296699..f744d5d 100644
--- a/tests/UpdatableSystemFontTest/testdata/Android.bp
+++ b/tests/UpdatableSystemFontTest/testdata/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "UpdatableSystemFontTestKeyPem",
     srcs: ["UpdatableSystemFontTestKey.pem"],
diff --git a/tests/UsageReportingTest/Android.bp b/tests/UsageReportingTest/Android.bp
index 0bac5a2..dfce070 100644
--- a/tests/UsageReportingTest/Android.bp
+++ b/tests/UsageReportingTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "UsageReportingTest",
     // Only compile source java files in this apk.
diff --git a/tests/UsageStatsPerfTests/Android.bp b/tests/UsageStatsPerfTests/Android.bp
index 3991fb8..0e372a3 100644
--- a/tests/UsageStatsPerfTests/Android.bp
+++ b/tests/UsageStatsPerfTests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "UsageStatsPerfTests",
     srcs: ["src/**/*.java"],
diff --git a/tests/UsageStatsTest/Android.bp b/tests/UsageStatsTest/Android.bp
index 0808b05..afb266b 100644
--- a/tests/UsageStatsTest/Android.bp
+++ b/tests/UsageStatsTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "UsageStatsTest",
     // Only compile source java files in this apk.
diff --git a/tests/UsbHostExternalManagmentTest/AoapTestDevice/Android.bp b/tests/UsbHostExternalManagmentTest/AoapTestDevice/Android.bp
index c7e9df0..9133bae 100644
--- a/tests/UsbHostExternalManagmentTest/AoapTestDevice/Android.bp
+++ b/tests/UsbHostExternalManagmentTest/AoapTestDevice/Android.bp
@@ -16,6 +16,15 @@
 
 //#################################################
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "AoapTestDeviceApp",
     srcs: ["src/**/*.java"],
diff --git a/tests/UsbHostExternalManagmentTest/AoapTestHost/Android.bp b/tests/UsbHostExternalManagmentTest/AoapTestHost/Android.bp
index 6fa58cb..6893002 100644
--- a/tests/UsbHostExternalManagmentTest/AoapTestHost/Android.bp
+++ b/tests/UsbHostExternalManagmentTest/AoapTestHost/Android.bp
@@ -16,6 +16,15 @@
 
 //#################################################
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "AoapTestHostApp",
     srcs: ["src/**/*.java"],
diff --git a/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/Android.bp b/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/Android.bp
index edd4205..2fca4d3 100644
--- a/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/Android.bp
+++ b/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/Android.bp
@@ -17,6 +17,15 @@
 //#################################################
 
 // TODO: should this be android_helper_test_app?
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "UsbHostExternalManagementTestApp",
     srcs: ["src/**/*.java"],
diff --git a/tests/UsbManagerTests/Android.bp b/tests/UsbManagerTests/Android.bp
index a03c6e2..97fbf5b 100644
--- a/tests/UsbManagerTests/Android.bp
+++ b/tests/UsbManagerTests/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "UsbManagerTests",
     srcs: ["src/**/*.java"],
diff --git a/tests/UsbManagerTests/lib/Android.bp b/tests/UsbManagerTests/lib/Android.bp
index 3c5d91b..994484c 100644
--- a/tests/UsbManagerTests/lib/Android.bp
+++ b/tests/UsbManagerTests/lib/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "UsbManagerTestLib",
     srcs: ["src/**/*.java"],
diff --git a/tests/UsbTests/Android.bp b/tests/UsbTests/Android.bp
index 7c2be9b..9328b67 100644
--- a/tests/UsbTests/Android.bp
+++ b/tests/UsbTests/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "UsbTests",
     srcs: ["**/*.java"],
diff --git a/tests/UsesFeature2Test/Android.bp b/tests/UsesFeature2Test/Android.bp
index a1b77d0..624e4ec 100644
--- a/tests/UsesFeature2Test/Android.bp
+++ b/tests/UsesFeature2Test/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "UsesFeature2Test",
     srcs: ["**/*.java"],
diff --git a/tests/VectorDrawableTest/Android.bp b/tests/VectorDrawableTest/Android.bp
index 13f318e..9da7c5f 100644
--- a/tests/VectorDrawableTest/Android.bp
+++ b/tests/VectorDrawableTest/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "VectorDrawableTest",
     srcs: ["**/*.java"],
diff --git a/tests/VoiceEnrollment/Android.bp b/tests/VoiceEnrollment/Android.bp
index e43b38c..b5d62bb 100644
--- a/tests/VoiceEnrollment/Android.bp
+++ b/tests/VoiceEnrollment/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "VoiceEnrollment",
     srcs: ["**/*.java"],
diff --git a/tests/VoiceInteraction/Android.bp b/tests/VoiceInteraction/Android.bp
index 7059473..1aa7faf 100644
--- a/tests/VoiceInteraction/Android.bp
+++ b/tests/VoiceInteraction/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "VoiceInteraction",
     srcs: ["**/*.java"],
diff --git a/tests/WallpaperTest/Android.bp b/tests/WallpaperTest/Android.bp
index f68b6ec..b009af2 100644
--- a/tests/WallpaperTest/Android.bp
+++ b/tests/WallpaperTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "WallpaperTest",
     srcs: ["src/**/*.java"],
diff --git a/tests/WindowAnimationJank/Android.bp b/tests/WindowAnimationJank/Android.bp
index 50b2297..ed86aa5 100644
--- a/tests/WindowAnimationJank/Android.bp
+++ b/tests/WindowAnimationJank/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "WindowAnimationJank",
     srcs: ["src/**/*.java"],
diff --git a/tests/WindowInsetsTests/Android.bp b/tests/WindowInsetsTests/Android.bp
index 7272152..b1f4819 100644
--- a/tests/WindowInsetsTests/Android.bp
+++ b/tests/WindowInsetsTests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "WindowInsetsTests",
     srcs: ["src/**/*.java"],
@@ -24,4 +33,3 @@
         "com.google.android.material_material",
     ],
 }
-
diff --git a/tests/appwidgets/AppWidgetHostTest/Android.bp b/tests/appwidgets/AppWidgetHostTest/Android.bp
index 24b7613..a3838e5 100644
--- a/tests/appwidgets/AppWidgetHostTest/Android.bp
+++ b/tests/appwidgets/AppWidgetHostTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "AppWidgetHostTest",
     srcs: ["**/*.java"],
diff --git a/tests/appwidgets/AppWidgetProviderTest/Android.bp b/tests/appwidgets/AppWidgetProviderTest/Android.bp
index a1a5991..a9ee7ad 100644
--- a/tests/appwidgets/AppWidgetProviderTest/Android.bp
+++ b/tests/appwidgets/AppWidgetProviderTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "AppWidgetProvider",
     srcs: ["**/*.java"],
diff --git a/tests/backup/Android.mk b/tests/backup/Android.mk
index e9618300..9b155c9 100644
--- a/tests/backup/Android.mk
+++ b/tests/backup/Android.mk
@@ -24,6 +24,9 @@
 LOCAL_CFLAGS := -Wall -Werror
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE := backup_helper_test
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 LOCAL_SHARED_LIBRARIES := libandroidfw libutils
 
diff --git a/tests/benchmarks/Android.bp b/tests/benchmarks/Android.bp
index f16ddb9..f87ca2e 100644
--- a/tests/benchmarks/Android.bp
+++ b/tests/benchmarks/Android.bp
@@ -15,6 +15,15 @@
 // build framework base core benchmarks
 // ============================================================
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library {
     name: "networkStatsFactory-benchmarks",
     installable: true,
diff --git a/tests/benchmarks/internal/Android.bp b/tests/benchmarks/internal/Android.bp
index 9c34eaf..74ed7a3 100644
--- a/tests/benchmarks/internal/Android.bp
+++ b/tests/benchmarks/internal/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "InternalBenchTests",
     srcs: ["src/**/*.java"],
@@ -23,4 +32,3 @@
     platform_apis: true,
     certificate: "platform"
 }
-
diff --git a/tests/libs-permissions/Android.bp b/tests/libs-permissions/Android.bp
index 66a1f83..a8ce8a4 100644
--- a/tests/libs-permissions/Android.bp
+++ b/tests/libs-permissions/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library {
     name: "com.android.test.libs.product",
     installable: true,
diff --git a/tests/net/Android.bp b/tests/net/Android.bp
index ffde68e..8122495 100644
--- a/tests/net/Android.bp
+++ b/tests/net/Android.bp
@@ -1,6 +1,15 @@
 //########################################################################
 // Build FrameworksNetTests package
 //########################################################################
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_defaults {
     name: "FrameworksNetTests-jni-defaults",
     jni_libs: [
diff --git a/tests/net/common/Android.bp b/tests/net/common/Android.bp
index c271f49..babb81c 100644
--- a/tests/net/common/Android.bp
+++ b/tests/net/common/Android.bp
@@ -16,6 +16,15 @@
 
 // Tests in this folder are included both in unit tests and CTS.
 // They must be fast and stable, and exercise public or test APIs.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library {
     name: "FrameworksNetCommonTests",
     srcs: ["java/**/*.java", "java/**/*.kt"],
diff --git a/tests/net/common/java/android/net/CaptivePortalDataTest.kt b/tests/net/common/java/android/net/CaptivePortalDataTest.kt
index ad5bbf2..18a9331 100644
--- a/tests/net/common/java/android/net/CaptivePortalDataTest.kt
+++ b/tests/net/common/java/android/net/CaptivePortalDataTest.kt
@@ -55,14 +55,14 @@
             .build()
 
     private val dataFromPasspoint = CaptivePortalData.Builder()
-            .setUserPortalUrl(Uri.parse("https://tc.example.com/passpoint"),
-                    CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
-            .setVenueInfoUrl(Uri.parse("https://venue.example.com/passpoint"),
-                    CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
             .setCaptive(true)
             .apply {
                 if (SdkLevel.isAtLeastS()) {
                     setVenueFriendlyName("venue friendly name")
+                    setUserPortalUrl(Uri.parse("https://tc.example.com/passpoint"),
+                            CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
+                    setVenueInfoUrl(Uri.parse("https://venue.example.com/passpoint"),
+                            CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
                 }
             }
             .build()
@@ -96,28 +96,28 @@
         if (SdkLevel.isAtLeastS()) {
             assertNotEqualsAfterChange { it.setVenueFriendlyName("another friendly name") }
             assertNotEqualsAfterChange { it.setVenueFriendlyName(null) }
-        }
 
-        assertEquals(dataFromPasspoint, CaptivePortalData.Builder(dataFromPasspoint).build())
-        assertNotEqualsAfterChange { it.setUserPortalUrl(
-                Uri.parse("https://tc.example.com/passpoint")) }
-        assertNotEqualsAfterChange { it.setUserPortalUrl(
-                Uri.parse("https://tc.example.com/passpoint"),
-                CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) }
-        assertNotEqualsAfterChange { it.setUserPortalUrl(
-                Uri.parse("https://tc.example.com/other"),
-                CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) }
-        assertNotEqualsAfterChange { it.setUserPortalUrl(
-                Uri.parse("https://tc.example.com/passpoint"),
-                CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) }
-        assertNotEqualsAfterChange { it.setVenueInfoUrl(
-                Uri.parse("https://venue.example.com/passpoint")) }
-        assertNotEqualsAfterChange { it.setVenueInfoUrl(
-                Uri.parse("https://venue.example.com/other"),
-                CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) }
-        assertNotEqualsAfterChange { it.setVenueInfoUrl(
-                Uri.parse("https://venue.example.com/passpoint"),
-                CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) }
+            assertEquals(dataFromPasspoint, CaptivePortalData.Builder(dataFromPasspoint).build())
+            assertNotEqualsAfterChange { it.setUserPortalUrl(
+                    Uri.parse("https://tc.example.com/passpoint")) }
+            assertNotEqualsAfterChange { it.setUserPortalUrl(
+                    Uri.parse("https://tc.example.com/passpoint"),
+                    CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) }
+            assertNotEqualsAfterChange { it.setUserPortalUrl(
+                    Uri.parse("https://tc.example.com/other"),
+                    CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) }
+            assertNotEqualsAfterChange { it.setUserPortalUrl(
+                    Uri.parse("https://tc.example.com/passpoint"),
+                    CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) }
+            assertNotEqualsAfterChange { it.setVenueInfoUrl(
+                    Uri.parse("https://venue.example.com/passpoint")) }
+            assertNotEqualsAfterChange { it.setVenueInfoUrl(
+                    Uri.parse("https://venue.example.com/other"),
+                    CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) }
+            assertNotEqualsAfterChange { it.setVenueInfoUrl(
+                    Uri.parse("https://venue.example.com/passpoint"),
+                    CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) }
+        }
     }
 
     @Test
diff --git a/tests/net/common/java/android/net/NetworkStackTest.java b/tests/net/common/java/android/net/NetworkStackTest.java
index a99aa01..f8f9c72 100644
--- a/tests/net/common/java/android/net/NetworkStackTest.java
+++ b/tests/net/common/java/android/net/NetworkStackTest.java
@@ -15,20 +15,8 @@
  */
 package android.net;
 
-import static android.Manifest.permission.NETWORK_STACK;
-import static android.content.pm.PackageManager.PERMISSION_DENIED;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
-import static android.net.NetworkStack.checkNetworkStackPermission;
-import static android.net.NetworkStack.checkNetworkStackPermissionOr;
-
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.when;
 
-import android.content.Context;
 import android.os.Build;
 import android.os.IBinder;
 
@@ -46,44 +34,15 @@
 
 @RunWith(AndroidJUnit4.class)
 public class NetworkStackTest {
-    private static final String [] OTHER_PERMISSION = {"otherpermission1", "otherpermission2"};
-
     @Rule
     public DevSdkIgnoreRule mDevSdkIgnoreRule = new DevSdkIgnoreRule();
 
-    @Mock Context mCtx;
     @Mock private IBinder mConnectorBinder;
 
     @Before public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
     }
 
-    @Test
-    public void testCheckNetworkStackPermission() throws Exception {
-        when(mCtx.checkCallingOrSelfPermission(eq(NETWORK_STACK))).thenReturn(PERMISSION_GRANTED);
-        when(mCtx.checkCallingOrSelfPermission(eq(PERMISSION_MAINLINE_NETWORK_STACK)))
-                .thenReturn(PERMISSION_DENIED);
-        checkNetworkStackPermission(mCtx);
-        checkNetworkStackPermissionOr(mCtx, OTHER_PERMISSION);
-
-        when(mCtx.checkCallingOrSelfPermission(eq(NETWORK_STACK))).thenReturn(PERMISSION_DENIED);
-        when(mCtx.checkCallingOrSelfPermission(eq(PERMISSION_MAINLINE_NETWORK_STACK)))
-                .thenReturn(PERMISSION_GRANTED);
-        checkNetworkStackPermission(mCtx);
-        checkNetworkStackPermissionOr(mCtx, OTHER_PERMISSION);
-
-        when(mCtx.checkCallingOrSelfPermission(any())).thenReturn(PERMISSION_DENIED);
-
-        try {
-            checkNetworkStackPermissionOr(mCtx, OTHER_PERMISSION);
-        } catch (SecurityException e) {
-            // Expect to get a SecurityException
-            return;
-        }
-
-        fail("Expect fail but permission granted.");
-    }
-
     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
     public void testGetService() {
         NetworkStack.setServiceForTest(mConnectorBinder);
diff --git a/tests/net/common/java/android/net/NetworkStateSnapshotTest.kt b/tests/net/common/java/android/net/NetworkStateSnapshotTest.kt
new file mode 100644
index 0000000..56b56ef
--- /dev/null
+++ b/tests/net/common/java/android/net/NetworkStateSnapshotTest.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net
+
+import android.net.ConnectivityManager.TYPE_NONE
+import android.net.ConnectivityManager.TYPE_WIFI
+import android.net.InetAddresses.parseNumericAddress
+import android.net.NetworkCapabilities.TRANSPORT_WIFI
+import android.os.Build
+import androidx.test.filters.SmallTest
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
+import com.android.testutils.assertParcelSane
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.net.Inet4Address
+import java.net.Inet6Address
+
+private const val TEST_IMSI = "imsi1"
+private const val TEST_SSID = "SSID1"
+private const val TEST_NETID = 123
+
+private val TEST_IPV4_GATEWAY = parseNumericAddress("192.168.222.3") as Inet4Address
+private val TEST_IPV6_GATEWAY = parseNumericAddress("2001:db8::1") as Inet6Address
+private val TEST_IPV4_LINKADDR = LinkAddress("192.168.222.123/24")
+private val TEST_IPV6_LINKADDR = LinkAddress("2001:db8::123/64")
+private val TEST_IFACE = "fake0"
+private val TEST_LINK_PROPERTIES = LinkProperties().apply {
+    interfaceName = TEST_IFACE
+    addLinkAddress(TEST_IPV4_LINKADDR)
+    addLinkAddress(TEST_IPV6_LINKADDR)
+
+    // Add default routes
+    addRoute(RouteInfo(IpPrefix(parseNumericAddress("0.0.0.0"), 0), TEST_IPV4_GATEWAY))
+    addRoute(RouteInfo(IpPrefix(parseNumericAddress("::"), 0), TEST_IPV6_GATEWAY))
+}
+
+private val TEST_CAPABILITIES = NetworkCapabilities().apply {
+    addTransportType(TRANSPORT_WIFI)
+    setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false)
+    setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true)
+    setSSID(TEST_SSID)
+}
+
+@SmallTest
+@RunWith(DevSdkIgnoreRunner::class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+class NetworkStateSnapshotTest {
+
+    @Test
+    fun testParcelUnparcel() {
+        val emptySnapshot = NetworkStateSnapshot(LinkProperties(), NetworkCapabilities(),
+                Network(TEST_NETID), null, TYPE_NONE)
+        val snapshot = NetworkStateSnapshot(
+                TEST_LINK_PROPERTIES, TEST_CAPABILITIES, Network(TEST_NETID), TEST_IMSI, TYPE_WIFI)
+        assertParcelSane(emptySnapshot, 5)
+        assertParcelSane(snapshot, 5)
+    }
+}
diff --git a/tests/net/deflake/Android.bp b/tests/net/deflake/Android.bp
index b1b0171..58ece37 100644
--- a/tests/net/deflake/Android.bp
+++ b/tests/net/deflake/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_test_host {
     name: "FrameworksNetDeflakeTest",
     srcs: ["src/**/*.kt"],
diff --git a/tests/net/integration/Android.bp b/tests/net/integration/Android.bp
index 69742b9..56f9df7 100644
--- a/tests/net/integration/Android.bp
+++ b/tests/net/integration/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworksNetIntegrationTests",
     platform_apis: true,
@@ -26,7 +35,7 @@
         "android.test.mock",
     ],
     static_libs: [
-        "TestNetworkStackLib",
+        "NetworkStackApiStableLib",
         "androidx.test.ext.junit",
         "frameworks-net-integration-testutils",
         "kotlin-reflect",
diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
index 083c8c8..9ed55f0 100644
--- a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
+++ b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
@@ -38,6 +38,7 @@
 import android.os.ConditionVariable
 import android.os.IBinder
 import android.os.INetworkManagementService
+import android.os.SystemConfigManager
 import android.os.UserHandle
 import android.testing.TestableContext
 import android.util.Log
@@ -57,6 +58,7 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.AdditionalAnswers
+import org.mockito.ArgumentMatchers.anyString
 import org.mockito.Mock
 import org.mockito.Mockito.any
 import org.mockito.Mockito.anyInt
@@ -94,6 +96,8 @@
     private lateinit var netd: INetd
     @Mock
     private lateinit var dnsResolver: IDnsResolver
+    @Mock
+    private lateinit var systemConfigManager: SystemConfigManager
     @Spy
     private var context = TestableContext(realContext)
 
@@ -151,6 +155,11 @@
         doReturn(UserHandle.ALL).`when`(asUserCtx).user
         doReturn(asUserCtx).`when`(context).createContextAsUser(eq(UserHandle.ALL), anyInt())
         doNothing().`when`(context).sendStickyBroadcast(any(), any())
+        doReturn(Context.SYSTEM_CONFIG_SERVICE).`when`(context)
+                .getSystemServiceName(SystemConfigManager::class.java)
+        doReturn(systemConfigManager).`when`(context)
+                .getSystemService(Context.SYSTEM_CONFIG_SERVICE)
+        doReturn(IntArray(0)).`when`(systemConfigManager).getSystemPermissionUids(anyString())
 
         networkStackClient = TestNetworkStackClient(realContext)
         networkStackClient.init()
diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
index dc9e587..e1da3d0 100644
--- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
+++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
@@ -84,6 +85,7 @@
         final String typeName = ConnectivityManager.getNetworkTypeName(type);
         mNetworkCapabilities = (ncTemplate != null) ? ncTemplate : new NetworkCapabilities();
         mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
+        mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
         mNetworkCapabilities.addTransportType(transport);
         switch (transport) {
             case TRANSPORT_ETHERNET:
diff --git a/tests/net/java/android/net/NetworkIdentityTest.kt b/tests/net/java/android/net/NetworkIdentityTest.kt
new file mode 100644
index 0000000..eb2b85c
--- /dev/null
+++ b/tests/net/java/android/net/NetworkIdentityTest.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net
+
+import android.net.NetworkIdentity.OEM_NONE
+import android.net.NetworkIdentity.OEM_PAID
+import android.net.NetworkIdentity.OEM_PRIVATE
+import android.net.NetworkIdentity.getOemBitfield
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import kotlin.test.assertEquals
+
+@RunWith(JUnit4::class)
+class NetworkIdentityTest {
+    @Test
+    fun testGetOemBitfield() {
+        val oemNone = NetworkCapabilities().apply {
+            setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID, false)
+            setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE, false)
+        }
+        val oemPaid = NetworkCapabilities().apply {
+            setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID, true)
+            setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE, false)
+        }
+        val oemPrivate = NetworkCapabilities().apply {
+            setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID, false)
+            setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE, true)
+        }
+        val oemAll = NetworkCapabilities().apply {
+            setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID, true)
+            setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE, true)
+        }
+
+        assertEquals(getOemBitfield(oemNone), OEM_NONE)
+        assertEquals(getOemBitfield(oemPaid), OEM_PAID)
+        assertEquals(getOemBitfield(oemPrivate), OEM_PRIVATE)
+        assertEquals(getOemBitfield(oemAll), OEM_PAID or OEM_PRIVATE)
+    }
+}
diff --git a/tests/net/java/android/net/NetworkTemplateTest.kt b/tests/net/java/android/net/NetworkTemplateTest.kt
index 1f8f6f3..27224c2 100644
--- a/tests/net/java/android/net/NetworkTemplateTest.kt
+++ b/tests/net/java/android/net/NetworkTemplateTest.kt
@@ -20,14 +20,23 @@
 import android.net.ConnectivityManager.TYPE_MOBILE
 import android.net.ConnectivityManager.TYPE_WIFI
 import android.net.NetworkIdentity.SUBTYPE_COMBINED
+import android.net.NetworkIdentity.OEM_NONE;
+import android.net.NetworkIdentity.OEM_PAID;
+import android.net.NetworkIdentity.OEM_PRIVATE;
 import android.net.NetworkIdentity.buildNetworkIdentity
 import android.net.NetworkStats.DEFAULT_NETWORK_ALL
 import android.net.NetworkStats.METERED_ALL
 import android.net.NetworkStats.ROAMING_ALL
+import android.net.NetworkTemplate.MATCH_ETHERNET
 import android.net.NetworkTemplate.MATCH_MOBILE
+import android.net.NetworkTemplate.MATCH_MOBILE_WILDCARD
 import android.net.NetworkTemplate.MATCH_WIFI
+import android.net.NetworkTemplate.MATCH_WIFI_WILDCARD
 import android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA
 import android.net.NetworkTemplate.NETWORK_TYPE_ALL
+import android.net.NetworkTemplate.OEM_MANAGED_ALL
+import android.net.NetworkTemplate.OEM_MANAGED_NO
+import android.net.NetworkTemplate.OEM_MANAGED_YES
 import android.net.NetworkTemplate.buildTemplateMobileWithRatType
 import android.telephony.TelephonyManager
 import com.android.testutils.assertParcelSane
@@ -37,9 +46,11 @@
 import org.junit.runners.JUnit4
 import org.mockito.Mockito.mock
 import org.mockito.MockitoAnnotations
+import kotlin.test.assertEquals
 import kotlin.test.assertFalse
 import kotlin.test.assertNotEquals
 import kotlin.test.assertTrue
+import kotlin.test.fail
 
 private const val TEST_IMSI1 = "imsi1"
 private const val TEST_IMSI2 = "imsi2"
@@ -57,15 +68,20 @@
     private fun buildNetworkState(
         type: Int,
         subscriberId: String? = null,
-        ssid: String? = null
+        ssid: String? = null,
+        oemManaged: Int = OEM_NONE,
     ): NetworkState {
         val lp = LinkProperties()
         val caps = NetworkCapabilities().apply {
             setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false)
             setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true)
             setSSID(ssid)
+            setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID,
+                    (oemManaged and OEM_PAID) == OEM_PAID)
+            setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE,
+                    (oemManaged and OEM_PRIVATE) == OEM_PRIVATE)
         }
-        return NetworkState(type, lp, caps, mock(Network::class.java), subscriberId, ssid)
+        return NetworkState(type, lp, caps, mock(Network::class.java), subscriberId)
     }
 
     private fun NetworkTemplate.assertMatches(ident: NetworkIdentity) =
@@ -136,11 +152,15 @@
     @Test
     fun testParcelUnparcel() {
         val templateMobile = NetworkTemplate(MATCH_MOBILE, TEST_IMSI1, null, null, METERED_ALL,
-                ROAMING_ALL, DEFAULT_NETWORK_ALL, TelephonyManager.NETWORK_TYPE_LTE)
+                ROAMING_ALL, DEFAULT_NETWORK_ALL, TelephonyManager.NETWORK_TYPE_LTE,
+                OEM_MANAGED_ALL)
         val templateWifi = NetworkTemplate(MATCH_WIFI, null, null, TEST_SSID1, METERED_ALL,
-                ROAMING_ALL, DEFAULT_NETWORK_ALL, 0)
-        assertParcelSane(templateMobile, 8)
-        assertParcelSane(templateWifi, 8)
+                ROAMING_ALL, DEFAULT_NETWORK_ALL, 0, OEM_MANAGED_ALL)
+        val templateOem = NetworkTemplate(MATCH_MOBILE, null, null, null, METERED_ALL,
+                ROAMING_ALL, DEFAULT_NETWORK_ALL, 0, OEM_MANAGED_YES)
+        assertParcelSane(templateMobile, 9)
+        assertParcelSane(templateWifi, 9)
+        assertParcelSane(templateOem, 9)
     }
 
     // Verify NETWORK_TYPE_* constants in NetworkTemplate do not conflict with
@@ -152,4 +172,81 @@
             assertNotEquals(NETWORK_TYPE_5G_NSA, ratType)
         }
     }
+
+    @Test
+    fun testOemNetworkConstants() {
+        val constantValues = arrayOf(OEM_MANAGED_YES, OEM_MANAGED_ALL, OEM_MANAGED_NO,
+                OEM_PAID, OEM_PRIVATE, OEM_PAID or OEM_PRIVATE)
+
+        // Verify that "not OEM managed network" constants are equal.
+        assertEquals(OEM_MANAGED_NO, OEM_NONE);
+
+        // Verify the constants don't conflict.
+        assertEquals(constantValues.size, constantValues.distinct().count())
+    }
+
+    /**
+     * Helper to enumerate and assert OEM managed wifi and mobile {@code NetworkTemplate}s match
+     * their the appropriate OEM managed {@code NetworkIdentity}s.
+     *
+     * @param networkType {@code TYPE_MOBILE} or {@code TYPE_WIFI}
+     * @param matchType A match rule from {@code NetworkTemplate.MATCH_*} corresponding to the
+     *         networkType.
+     * @param subscriberId To be populated with {@code TEST_IMSI*} only if networkType is
+     *         {@code TYPE_MOBILE}. May be left as null when matchType is
+     *         {@link NetworkTemplate.MATCH_MOBILE_WILDCARD}.
+     * @param templateSsid Top be populated with {@code TEST_SSID*} only if networkType is
+     *         {@code TYPE_WIFI}. May be left as null when matchType is
+     *         {@link NetworkTemplate.MATCH_WIFI_WILDCARD}.
+     * @param identSsid If networkType is {@code TYPE_WIFI}, this value must *NOT* be null. Provide
+     *         one of {@code TEST_SSID*}.
+     */
+    private fun matchOemManagedIdent(networkType: Int, matchType:Int, subscriberId: String? = null,
+            templateSsid: String? = null, identSsid: String? = null) {
+        val oemManagedStates = arrayOf(OEM_NONE, OEM_PAID, OEM_PRIVATE, OEM_PAID or OEM_PRIVATE)
+        // A null subscriberId needs a null matchSubscriberIds argument as well.
+        val matchSubscriberIds = if (subscriberId == null) null else arrayOf(subscriberId)
+
+        val templateOemYes = NetworkTemplate(matchType, subscriberId, matchSubscriberIds,
+                templateSsid, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
+                OEM_MANAGED_YES)
+        val templateOemAll = NetworkTemplate(matchType, subscriberId, matchSubscriberIds,
+                templateSsid, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
+                OEM_MANAGED_ALL)
+
+        for (identityOemManagedState in oemManagedStates) {
+            val ident = buildNetworkIdentity(mockContext, buildNetworkState(networkType,
+                    subscriberId, identSsid, identityOemManagedState), /*defaultNetwork=*/false,
+                    /*subType=*/0)
+
+            // Create a template with each OEM managed type and match it against the NetworkIdentity
+            for (templateOemManagedState in oemManagedStates) {
+                val template = NetworkTemplate(matchType, subscriberId, matchSubscriberIds,
+                        templateSsid, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL,
+                        NETWORK_TYPE_ALL, templateOemManagedState)
+                if (identityOemManagedState == templateOemManagedState) {
+                    template.assertMatches(ident)
+                } else {
+                    template.assertDoesNotMatch(ident)
+                }
+            }
+            // OEM_MANAGED_ALL ignores OEM state.
+            templateOemAll.assertMatches(ident)
+            if (identityOemManagedState == OEM_NONE) {
+                // OEM_MANAGED_YES matches everything except OEM_NONE.
+                templateOemYes.assertDoesNotMatch(ident)
+            } else {
+                templateOemYes.assertMatches(ident)
+            }
+        }
+    }
+
+    @Test
+    fun testOemManagedMatchesIdent() {
+        matchOemManagedIdent(TYPE_MOBILE, MATCH_MOBILE, subscriberId = TEST_IMSI1)
+        matchOemManagedIdent(TYPE_MOBILE, MATCH_MOBILE_WILDCARD)
+        matchOemManagedIdent(TYPE_WIFI, MATCH_WIFI, templateSsid = TEST_SSID1,
+                identSsid = TEST_SSID1)
+        matchOemManagedIdent(TYPE_WIFI, MATCH_WIFI_WILDCARD, identSsid = TEST_SSID1)
+    }
 }
diff --git a/tests/net/java/android/net/VpnTransportInfoTest.java b/tests/net/java/android/net/VpnTransportInfoTest.java
index 866f38c..d04c87b 100644
--- a/tests/net/java/android/net/VpnTransportInfoTest.java
+++ b/tests/net/java/android/net/VpnTransportInfoTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/tests/net/java/android/net/util/MultinetworkPolicyTrackerTest.kt b/tests/net/java/android/net/util/MultinetworkPolicyTrackerTest.kt
new file mode 100644
index 0000000..9b0cfa9
--- /dev/null
+++ b/tests/net/java/android/net/util/MultinetworkPolicyTrackerTest.kt
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.util
+
+import android.content.Context
+import android.content.res.Resources
+import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_HANDOVER
+import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_PERFORMANCE
+import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_RELIABILITY
+import android.net.util.MultinetworkPolicyTracker.ActiveDataSubscriptionIdChangedListener
+import android.provider.Settings
+import android.provider.Settings.Global.NETWORK_AVOID_BAD_WIFI
+import android.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE
+import android.telephony.SubscriptionInfo
+import android.telephony.SubscriptionManager
+import android.telephony.TelephonyManager
+import android.test.mock.MockContentResolver
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.R
+import com.android.internal.util.test.FakeSettingsProvider
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.argThat
+import org.mockito.Mockito.any
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+
+/**
+ * Tests for [MultinetworkPolicyTracker].
+ *
+ * Build, install and run with:
+ * atest android.net.util.MultinetworkPolicyTrackerTest
+ */
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class MultinetworkPolicyTrackerTest {
+    private val resources = mock(Resources::class.java).also {
+        doReturn(0).`when`(it).getInteger(R.integer.config_networkAvoidBadWifi)
+    }
+    private val telephonyManager = mock(TelephonyManager::class.java)
+    private val subscriptionManager = mock(SubscriptionManager::class.java).also {
+        doReturn(null).`when`(it).getActiveSubscriptionInfo(anyInt())
+    }
+    private val resolver = MockContentResolver().apply {
+        addProvider(Settings.AUTHORITY, FakeSettingsProvider()) }
+    private val context = mock(Context::class.java).also {
+        doReturn(Context.TELEPHONY_SERVICE).`when`(it)
+                .getSystemServiceName(TelephonyManager::class.java)
+        doReturn(telephonyManager).`when`(it).getSystemService(Context.TELEPHONY_SERVICE)
+        doReturn(subscriptionManager).`when`(it)
+                .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)
+        doReturn(resolver).`when`(it).contentResolver
+        doReturn(resources).`when`(it).resources
+        doReturn(it).`when`(it).createConfigurationContext(any())
+        Settings.Global.putString(resolver, NETWORK_AVOID_BAD_WIFI, "1")
+    }
+    private val tracker = MultinetworkPolicyTracker(context, null /* handler */)
+
+    private fun assertMultipathPreference(preference: Int) {
+        Settings.Global.putString(resolver, NETWORK_METERED_MULTIPATH_PREFERENCE,
+                preference.toString())
+        tracker.updateMeteredMultipathPreference()
+        assertEquals(preference, tracker.meteredMultipathPreference)
+    }
+
+    @Test
+    fun testUpdateMeteredMultipathPreference() {
+        assertMultipathPreference(MULTIPATH_PREFERENCE_HANDOVER)
+        assertMultipathPreference(MULTIPATH_PREFERENCE_RELIABILITY)
+        assertMultipathPreference(MULTIPATH_PREFERENCE_PERFORMANCE)
+    }
+
+    @Test
+    fun testUpdateAvoidBadWifi() {
+        Settings.Global.putString(resolver, NETWORK_AVOID_BAD_WIFI, "0")
+        assertTrue(tracker.updateAvoidBadWifi())
+        assertFalse(tracker.avoidBadWifi)
+
+        doReturn(1).`when`(resources).getInteger(R.integer.config_networkAvoidBadWifi)
+        assertTrue(tracker.updateAvoidBadWifi())
+        assertTrue(tracker.avoidBadWifi)
+    }
+
+    @Test
+    fun testOnActiveDataSubscriptionIdChanged() {
+        val testSubId = 1000
+        val subscriptionInfo = SubscriptionInfo(testSubId, ""/* iccId */, 1/* iccId */,
+                "TMO"/* displayName */, "TMO"/* carrierName */, 1/* nameSource */, 1/* iconTint */,
+                "123"/* number */, 1/* roaming */, null/* icon */, "310"/* mcc */, "210"/* mnc */,
+                ""/* countryIso */, false/* isEmbedded */, null/* nativeAccessRules */,
+                "1"/* cardString */)
+        doReturn(subscriptionInfo).`when`(subscriptionManager).getActiveSubscriptionInfo(testSubId)
+
+        // Modify avoidBadWifi and meteredMultipathPreference settings value and local variables in
+        // MultinetworkPolicyTracker should be also updated after subId changed.
+        Settings.Global.putString(resolver, NETWORK_AVOID_BAD_WIFI, "0")
+        Settings.Global.putString(resolver, NETWORK_METERED_MULTIPATH_PREFERENCE,
+                MULTIPATH_PREFERENCE_PERFORMANCE.toString())
+
+        val listenerCaptor = ArgumentCaptor.forClass(
+                ActiveDataSubscriptionIdChangedListener::class.java)
+        verify(telephonyManager, times(1))
+                .registerPhoneStateListener(any(), listenerCaptor.capture())
+        val listener = listenerCaptor.value
+        listener.onActiveDataSubscriptionIdChanged(testSubId)
+
+        // Check it get resource value with test sub id.
+        verify(subscriptionManager, times(1)).getActiveSubscriptionInfo(testSubId)
+        verify(context).createConfigurationContext(argThat { it.mcc == 310 && it.mnc == 210 })
+
+        // Check if avoidBadWifi and meteredMultipathPreference values have been updated.
+        assertFalse(tracker.avoidBadWifi)
+        assertEquals(MULTIPATH_PREFERENCE_PERFORMANCE, tracker.meteredMultipathPreference)
+    }
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 1358410..1cfc3f9 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -53,6 +53,7 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
@@ -84,6 +85,11 @@
 import static android.net.NetworkPolicyManager.RULE_NONE;
 import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
 import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
+import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
+import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
+import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
+import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
+import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_UNINITIALIZED;
 import static android.net.RouteInfo.RTN_UNREACHABLE;
 import static android.os.Process.INVALID_UID;
 import static android.system.OsConstants.IPPROTO_TCP;
@@ -233,6 +239,7 @@
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
 import android.os.SystemClock;
+import android.os.SystemConfigManager;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -355,6 +362,7 @@
     private static final long TIMESTAMP = 1234L;
 
     private static final int NET_ID = 110;
+    private static final int OEM_PREF_ANY_NET_ID = -1;
     // Set a non-zero value to verify the flow to set tcp init rwnd value.
     private static final int TEST_TCP_INIT_RWND = 60;
 
@@ -424,7 +432,7 @@
     @Mock EthernetManager mEthernetManager;
     @Mock NetworkPolicyManager mNetworkPolicyManager;
     @Mock KeyStore mKeyStore;
-    @Mock IOnSetOemNetworkPreferenceListener mOnSetOemNetworkPreferenceListener;
+    @Mock SystemConfigManager mSystemConfigManager;
 
     private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
             ArgumentCaptor.forClass(ResolverParamsParcel.class);
@@ -521,6 +529,7 @@
             if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
             if (Context.ETHERNET_SERVICE.equals(name)) return mEthernetManager;
             if (Context.NETWORK_POLICY_SERVICE.equals(name)) return mNetworkPolicyManager;
+            if (Context.SYSTEM_CONFIG_SERVICE.equals(name)) return mSystemConfigManager;
             return super.getSystemService(name);
         }
 
@@ -994,10 +1003,12 @@
         // Used to collect the networks requests managed by this factory. This is a duplicate of
         // the internal information stored in the NetworkFactory (which is private).
         private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
+        private final HandlerThread mHandlerSendingRequests;
 
         public MockNetworkFactory(Looper looper, Context context, String logTag,
-                NetworkCapabilities filter) {
+                NetworkCapabilities filter, HandlerThread threadSendingRequests) {
             super(looper, context, logTag, filter);
+            mHandlerSendingRequests = threadSendingRequests;
         }
 
         public int getMyRequestCount() {
@@ -1051,7 +1062,8 @@
         public void terminate() {
             super.terminate();
             // Make sure there are no remaining requests unaccounted for.
-            assertNull(mRequestHistory.poll(TIMEOUT_MS, r -> true));
+            HandlerUtils.waitForIdle(mHandlerSendingRequests, TIMEOUT_MS);
+            assertNull(mRequestHistory.poll(0, r -> true));
         }
 
         // Trigger releasing the request as unfulfillable
@@ -1424,6 +1436,7 @@
         applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
         when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
                 .thenReturn(applicationInfo);
+        when(mSystemConfigManager.getSystemPermissionUids(anyString())).thenReturn(new int[0]);
 
         // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
         // http://b/25897652 .
@@ -1609,10 +1622,13 @@
         }
         switch (transport) {
             case TRANSPORT_WIFI:
-                assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
+                assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
                 break;
             case TRANSPORT_CELLULAR:
-                assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
+                assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+                break;
+            case TRANSPORT_ETHERNET:
+                assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
                 break;
             default:
                 break;
@@ -1621,6 +1637,7 @@
         assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
         assertEquals(transportToLegacyType(transport),
                 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
+        assertNotNull(mCm.getActiveNetworkInfoForUid(Process.myUid()));
         // Test getNetworkCapabilities(Network)
         assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
         assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
@@ -2158,6 +2175,24 @@
         }
     }
 
+    static void expectOnLost(TestNetworkAgentWrapper network, TestNetworkCallback ... callbacks) {
+        for (TestNetworkCallback c : callbacks) {
+            c.expectCallback(CallbackEntry.LOST, network);
+        }
+    }
+
+    static void expectAvailableCallbacksUnvalidatedWithSpecifier(TestNetworkAgentWrapper network,
+            NetworkSpecifier specifier, TestNetworkCallback ... callbacks) {
+        for (TestNetworkCallback c : callbacks) {
+            c.expectCallback(CallbackEntry.AVAILABLE, network);
+            c.expectCapabilitiesThat(network, (nc) ->
+                    !nc.hasCapability(NET_CAPABILITY_VALIDATED)
+                            && Objects.equals(specifier, nc.getNetworkSpecifier()));
+            c.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, network);
+            c.expectCallback(CallbackEntry.BLOCKED_STATUS, network);
+        }
+    }
+
     @Test
     public void testStateChangeNetworkCallbacks() throws Exception {
         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
@@ -2753,7 +2788,8 @@
         if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
                 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
                 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
-                capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
+                capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP
+                || capability == NET_CAPABILITY_ENTERPRISE) {
             assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
         } else {
             assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
@@ -2761,10 +2797,14 @@
 
         NetworkCapabilities filter = new NetworkCapabilities();
         filter.addCapability(capability);
+        // Add NOT_VCN_MANAGED capability into filter unconditionally since some request will add
+        // NOT_VCN_MANAGED automatically but not for NetworkCapabilities,
+        // see {@code NetworkCapabilities#deduceNotVcnManagedCapability} for more details.
+        filter.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
         handlerThread.start();
         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
-                mServiceContext, "testFactory", filter);
+                mServiceContext, "testFactory", filter, mCsHandlerThread);
         testFactory.setScoreFilter(40);
         ConditionVariable cv = testFactory.getNetworkStartedCV();
         testFactory.register();
@@ -2852,6 +2892,7 @@
         tryNetworkFactoryRequests(NET_CAPABILITY_IA);
         tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
         tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
+        tryNetworkFactoryRequests(NET_CAPABILITY_ENTERPRISE);
         tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
         tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
@@ -2872,7 +2913,7 @@
         // does not crash.
         for (int i = 0; i < 100; i++) {
             final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
-                    mServiceContext, "testFactory", filter);
+                    mServiceContext, "testFactory", filter, mCsHandlerThread);
             // Register the factory and don't be surprised when the default request arrives.
             testFactory.register();
             testFactory.expectRequestAdd();
@@ -3521,11 +3562,9 @@
     /**
      * Verify request matching behavior with network specifiers.
      *
-     * Note: this test is somewhat problematic since it involves removing capabilities from
-     * agents - i.e. agents rejecting requests which they previously accepted. This is flagged
-     * as a WTF bug in
-     * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but
-     * does work.
+     * This test does not check updating the specifier on a live network because the specifier is
+     * immutable and this triggers a WTF in
+     * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)}.
      */
     @Test
     public void testNetworkSpecifier() throws Exception {
@@ -3610,60 +3649,49 @@
 
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(false);
-        cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, null /* specifier */,
+                cEmpty1, cEmpty2, cEmpty3, cEmpty4);
         assertNoCallbacks(cFoo, cBar);
 
+        mWiFiNetworkAgent.disconnect();
+        expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4);
+
+        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
-        cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        for (TestNetworkCallback c: emptyCallbacks) {
-            c.expectCapabilitiesThat(mWiFiNetworkAgent,
-                    (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
-        }
-        cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
-                (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
+        mWiFiNetworkAgent.connect(false);
+        expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, nsFoo,
+                cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
+        cBar.assertNoCallback();
         assertEquals(nsFoo,
                 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
-        cFoo.assertNoCallback();
+        assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
 
+        mWiFiNetworkAgent.disconnect();
+        expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
+
+        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
-        cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
-        cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        for (TestNetworkCallback c: emptyCallbacks) {
-            c.expectCapabilitiesThat(mWiFiNetworkAgent,
-                    (caps) -> caps.getNetworkSpecifier().equals(nsBar));
-        }
-        cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
-                (caps) -> caps.getNetworkSpecifier().equals(nsBar));
+        mWiFiNetworkAgent.connect(false);
+        expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, nsBar,
+                cEmpty1, cEmpty2, cEmpty3, cEmpty4, cBar);
+        cFoo.assertNoCallback();
         assertEquals(nsBar,
                 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
-        cBar.assertNoCallback();
 
+        mWiFiNetworkAgent.disconnect();
+        expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cBar);
+        cFoo.assertNoCallback();
+
+        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
-        cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        for (TestNetworkCallback c : emptyCallbacks) {
-            c.expectCapabilitiesThat(mWiFiNetworkAgent,
-                    (caps) -> caps.getNetworkSpecifier() == null);
-        }
-        cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
-                (caps) -> caps.getNetworkSpecifier() == null);
-        cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
-                (caps) -> caps.getNetworkSpecifier() == null);
+        mWiFiNetworkAgent.connect(false);
+        expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, null /* specifier */,
+                cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
         assertNull(
                 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
-        cFoo.assertNoCallback();
-        cBar.assertNoCallback();
 
-        mWiFiNetworkAgent.setNetworkSpecifier(null);
-        cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
-        cBar.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
-        for (TestNetworkCallback c: emptyCallbacks) {
-            c.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mWiFiNetworkAgent);
-        }
-
-        assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
+        mWiFiNetworkAgent.disconnect();
+        expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
     }
 
     /**
@@ -4120,9 +4148,10 @@
         handlerThread.start();
         NetworkCapabilities filter = new NetworkCapabilities()
                 .addTransportType(TRANSPORT_CELLULAR)
+                .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
                 .addCapability(NET_CAPABILITY_INTERNET);
         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
-                mServiceContext, "testFactory", filter);
+                mServiceContext, "testFactory", filter, mCsHandlerThread);
         testFactory.setScoreFilter(40);
 
         // Register the factory and expect it to start looking for a network.
@@ -4170,6 +4199,7 @@
             // ...  and cell data to be torn down after nascent network timeout.
             cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent,
                     mService.mNascentDelayMs + TEST_CALLBACK_TIMEOUT_MS);
+            waitForIdle();
             assertLength(1, mCm.getAllNetworks());
         } finally {
             testFactory.terminate();
@@ -4469,7 +4499,7 @@
                 .addTransportType(TRANSPORT_WIFI)
                 .addCapability(NET_CAPABILITY_INTERNET);
         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
-                mServiceContext, "testFactory", filter);
+                mServiceContext, "testFactory", filter, mCsHandlerThread);
         testFactory.setScoreFilter(40);
 
         // Register the factory and expect it to receive the default request.
@@ -6023,6 +6053,7 @@
                 .addTransportType(TRANSPORT_CELLULAR)
                 .addCapability(NET_CAPABILITY_INTERNET)
                 .addCapability(NET_CAPABILITY_NOT_CONGESTED)
+                .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
                 .setLinkDownstreamBandwidthKbps(10);
         final NetworkCapabilities wifiNc = new NetworkCapabilities()
                 .addTransportType(TRANSPORT_WIFI)
@@ -6031,6 +6062,7 @@
                 .addCapability(NET_CAPABILITY_NOT_ROAMING)
                 .addCapability(NET_CAPABILITY_NOT_CONGESTED)
                 .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
+                .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
                 .setLinkUpstreamBandwidthKbps(20);
         mCellNetworkAgent.setNetworkCapabilities(cellNc, true /* sendToConnectivityService */);
         mWiFiNetworkAgent.setNetworkCapabilities(wifiNc, true /* sendToConnectivityService */);
@@ -6818,6 +6850,7 @@
                 .thenReturn(UserHandle.getUid(RESTRICTED_USER, VPN_UID));
 
         final Intent addedIntent = new Intent(ACTION_USER_ADDED);
+        addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER));
         addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);
 
         // Send a USER_ADDED broadcast for it.
@@ -6828,7 +6861,7 @@
         callback.expectCapabilitiesThat(mMockVpn, (caps)
                 -> caps.getUids().size() == 2
                 && caps.getUids().contains(new UidRange(uid, uid))
-                && caps.getUids().contains(UidRange.createForUser(RESTRICTED_USER))
+                && caps.getUids().contains(createUidRange(RESTRICTED_USER))
                 && caps.hasTransport(TRANSPORT_VPN)
                 && caps.hasTransport(TRANSPORT_WIFI));
 
@@ -6838,12 +6871,13 @@
         callback.expectCapabilitiesThat(mMockVpn, (caps)
                 -> caps.getUids().size() == 2
                 && caps.getUids().contains(new UidRange(uid, uid))
-                && caps.getUids().contains(UidRange.createForUser(RESTRICTED_USER))
+                && caps.getUids().contains(createUidRange(RESTRICTED_USER))
                 && caps.hasTransport(TRANSPORT_VPN)
                 && !caps.hasTransport(TRANSPORT_WIFI));
 
         // Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user.
         final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
+        removedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER));
         removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);
         processBroadcastForVpn(removedIntent);
 
@@ -6901,6 +6935,7 @@
                 RESTRICTED_USER_INFO));
         // TODO: check that VPN app within restricted profile still has access, etc.
         final Intent addedIntent = new Intent(ACTION_USER_ADDED);
+        addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER));
         addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);
         processBroadcastForVpn(addedIntent);
         assertNull(mCm.getActiveNetworkForUid(uid));
@@ -6911,6 +6946,7 @@
 
         // Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user.
         final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
+        removedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER));
         removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);
         processBroadcastForVpn(removedIntent);
         assertNull(mCm.getActiveNetworkForUid(uid));
@@ -7469,7 +7505,7 @@
         assertNotNull(underlying);
         mMockVpn.setVpnType(VpnManager.TYPE_VPN_LEGACY);
         // The legacy lockdown VPN only supports userId 0.
-        final Set<UidRange> ranges = Collections.singleton(UidRange.createForUser(PRIMARY_USER));
+        final Set<UidRange> ranges = Collections.singleton(createUidRange(PRIMARY_USER));
         mMockVpn.registerAgent(ranges);
         mMockVpn.setUnderlyingNetworks(new Network[]{underlying});
         mMockVpn.connect(true);
@@ -7505,6 +7541,7 @@
         // Send a USER_UNLOCKED broadcast so CS starts LockdownVpnTracker.
         final int userId = UserHandle.getUserId(Process.myUid());
         final Intent addedIntent = new Intent(ACTION_USER_UNLOCKED);
+        addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(userId));
         addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
         processBroadcastForVpn(addedIntent);
 
@@ -7718,19 +7755,13 @@
             mWiFiNetworkAgent.removeCapability(testCap);
             callbackWithCap.expectAvailableCallbacksValidated(mCellNetworkAgent);
             callbackWithoutCap.expectCapabilitiesWithout(testCap, mWiFiNetworkAgent);
-            // TODO: Test default network changes for NOT_VCN_MANAGED once the default request has
-            //  it.
-            if (testCap == NET_CAPABILITY_TRUSTED) {
-                verify(mMockNetd).networkSetDefault(eq(mCellNetworkAgent.getNetwork().netId));
-                reset(mMockNetd);
-            }
+            verify(mMockNetd).networkSetDefault(eq(mCellNetworkAgent.getNetwork().netId));
+            reset(mMockNetd);
 
             mCellNetworkAgent.removeCapability(testCap);
             callbackWithCap.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
             callbackWithoutCap.assertNoCallback();
-            if (testCap == NET_CAPABILITY_TRUSTED) {
-                verify(mMockNetd).networkClearDefault();
-            }
+            verify(mMockNetd).networkClearDefault();
 
             mCm.unregisterNetworkCallback(callbackWithCap);
             mCm.unregisterNetworkCallback(callbackWithoutCap);
@@ -8205,8 +8236,8 @@
         reset(mNetworkManagementService);
         mCellNetworkAgent.connect(true);
         networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
-                eq(NetworkCapabilities.TRANSPORT_CELLULAR));
+        verify(mMockNetd, times(1)).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(),
+                eq(Integer.toString(TRANSPORT_CELLULAR)));
 
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         final LinkProperties wifiLp = new LinkProperties();
@@ -8214,25 +8245,27 @@
         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
 
         // Network switch
-        reset(mNetworkManagementService);
         mWiFiNetworkAgent.connect(true);
         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
-        verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
-                eq(NetworkCapabilities.TRANSPORT_WIFI));
-        verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
+        verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(),
+                eq(Integer.toString(TRANSPORT_WIFI)));
+        verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
+                eq(Integer.toString(TRANSPORT_CELLULAR)));
 
         // Disconnect wifi and switch back to cell
-        reset(mNetworkManagementService);
+        reset(mMockNetd);
         mWiFiNetworkAgent.disconnect();
         networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         assertNoCallbacks(networkCallback);
-        verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
-        verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
-                eq(NetworkCapabilities.TRANSPORT_CELLULAR));
+        verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(),
+                eq(Integer.toString(TRANSPORT_WIFI)));
+        verify(mMockNetd, times(1)).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(),
+                eq(Integer.toString(TRANSPORT_CELLULAR)));
 
         // reconnect wifi
+        reset(mMockNetd);
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         wifiLp.setInterfaceName(WIFI_IFNAME);
         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
@@ -8240,9 +8273,12 @@
         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+        verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(),
+                eq(Integer.toString(TRANSPORT_WIFI)));
+        verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
+                eq(Integer.toString(TRANSPORT_CELLULAR)));
 
         // Disconnect cell
-        reset(mNetworkManagementService);
         reset(mMockNetd);
         mCellNetworkAgent.disconnect();
         networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
@@ -8250,17 +8286,18 @@
         // sent as network being switched. Ensure rule removal for cell will not be triggered
         // unexpectedly before network being removed.
         waitForIdle();
-        verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
+        verify(mMockNetd, times(0)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
+                eq(Integer.toString(TRANSPORT_CELLULAR)));
         verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
         verify(mMockDnsResolver, times(1))
                 .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
 
         // Disconnect wifi
         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
-        reset(mNetworkManagementService);
         mWiFiNetworkAgent.disconnect();
         b.expectBroadcast();
-        verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
+        verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(),
+                eq(Integer.toString(TRANSPORT_WIFI)));
 
         // Clean up
         mCm.unregisterNetworkCallback(networkCallback);
@@ -8381,7 +8418,7 @@
         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
         // The uid range needs to cover the test app so the network is visible to it.
-        final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(PRIMARY_USER));
+        final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER));
         mMockVpn.establish(lp, VPN_UID, vpnRange);
         assertVpnUidRangesUpdated(true, vpnRange, VPN_UID);
 
@@ -8409,7 +8446,7 @@
         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
         // The uid range needs to cover the test app so the network is visible to it.
-        final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(PRIMARY_USER));
+        final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER));
         mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
         assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID);
 
@@ -8425,7 +8462,7 @@
         lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
         // The uid range needs to cover the test app so the network is visible to it.
-        final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(PRIMARY_USER));
+        final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER));
         mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
         assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID);
 
@@ -8440,7 +8477,7 @@
         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
         // The uid range needs to cover the test app so the network is visible to it.
-        final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(PRIMARY_USER));
+        final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER));
         mMockVpn.establish(lp, VPN_UID, vpnRange);
         assertVpnUidRangesUpdated(true, vpnRange, VPN_UID);
 
@@ -8492,7 +8529,7 @@
         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
         // The uid range needs to cover the test app so the network is visible to it.
-        final UidRange vpnRange = UidRange.createForUser(PRIMARY_USER);
+        final UidRange vpnRange = createUidRange(PRIMARY_USER);
         final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
         mMockVpn.establish(lp, VPN_UID, vpnRanges);
         assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
@@ -8691,7 +8728,7 @@
 
     private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
             throws Exception {
-        final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(PRIMARY_USER));
+        final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER));
         mMockVpn.setVpnType(vpnType);
         mMockVpn.establish(new LinkProperties(), vpnOwnerUid, vpnRange);
         assertVpnUidRangesUpdated(true, vpnRange, vpnOwnerUid);
@@ -9250,7 +9287,7 @@
         lp.setInterfaceName("tun0");
         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
-        final UidRange vpnRange = UidRange.createForUser(PRIMARY_USER);
+        final UidRange vpnRange = createUidRange(PRIMARY_USER);
         Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
         mMockVpn.establish(lp, VPN_UID, vpnRanges);
         assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
@@ -9431,7 +9468,7 @@
     }
 
     private void mockGetApplicationInfo(@NonNull final String packageName, @NonNull final int uid)
-            throws PackageManager.NameNotFoundException {
+            throws Exception {
         final ApplicationInfo applicationInfo = new ApplicationInfo();
         applicationInfo.uid = uid;
         when(mPackageManager.getApplicationInfo(eq(packageName), anyInt()))
@@ -9451,7 +9488,7 @@
 
     private OemNetworkPreferences createDefaultOemNetworkPreferences(
             @OemNetworkPreferences.OemNetworkPreference final int preference)
-            throws PackageManager.NameNotFoundException {
+            throws Exception {
         // Arrange PackageManager mocks
         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
 
@@ -9465,7 +9502,7 @@
     public void testOemNetworkRequestFactoryPreferenceUninitializedThrowsError()
             throws PackageManager.NameNotFoundException {
         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
-                OemNetworkPreferences.OEM_NETWORK_PREFERENCE_UNINITIALIZED;
+                OEM_NETWORK_PREFERENCE_UNINITIALIZED;
 
         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
         assertThrows(IllegalArgumentException.class,
@@ -9476,13 +9513,13 @@
 
     @Test
     public void testOemNetworkRequestFactoryPreferenceOemPaid()
-            throws PackageManager.NameNotFoundException {
+            throws Exception {
         // Expectations
         final int expectedNumOfNris = 1;
         final int expectedNumOfRequests = 3;
 
         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
-                OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
+                OEM_NETWORK_PREFERENCE_OEM_PAID;
 
         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
         final ArraySet<ConnectivityService.NetworkRequestInfo> nris =
@@ -9505,13 +9542,13 @@
 
     @Test
     public void testOemNetworkRequestFactoryPreferenceOemPaidNoFallback()
-            throws PackageManager.NameNotFoundException {
+            throws Exception {
         // Expectations
         final int expectedNumOfNris = 1;
         final int expectedNumOfRequests = 2;
 
         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
-                OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
+                OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
 
         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
         final ArraySet<ConnectivityService.NetworkRequestInfo> nris =
@@ -9531,13 +9568,13 @@
 
     @Test
     public void testOemNetworkRequestFactoryPreferenceOemPaidOnly()
-            throws PackageManager.NameNotFoundException {
+            throws Exception {
         // Expectations
         final int expectedNumOfNris = 1;
         final int expectedNumOfRequests = 1;
 
         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
-                OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
+                OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
 
         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
         final ArraySet<ConnectivityService.NetworkRequestInfo> nris =
@@ -9554,13 +9591,13 @@
 
     @Test
     public void testOemNetworkRequestFactoryPreferenceOemPrivateOnly()
-            throws PackageManager.NameNotFoundException {
+            throws Exception {
         // Expectations
         final int expectedNumOfNris = 1;
         final int expectedNumOfRequests = 1;
 
         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
-                OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
+                OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
 
         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
         final ArraySet<ConnectivityService.NetworkRequestInfo> nris =
@@ -9578,7 +9615,7 @@
 
     @Test
     public void testOemNetworkRequestFactoryCreatesCorrectNumOfNris()
-            throws PackageManager.NameNotFoundException {
+            throws Exception {
         // Expectations
         final int expectedNumOfNris = 2;
 
@@ -9588,8 +9625,8 @@
         mockGetApplicationInfo(testPackageName2, TEST_PACKAGE_UID);
 
         // Build OemNetworkPreferences object
-        final int testOemPref = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
-        final int testOemPref2 = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
+        final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
+        final int testOemPref2 = OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
                 .addNetworkPreference(testPackageName2, testOemPref2)
@@ -9605,7 +9642,7 @@
 
     @Test
     public void testOemNetworkRequestFactoryCorrectlySetsUids()
-            throws PackageManager.NameNotFoundException {
+            throws Exception {
         // Arrange PackageManager mocks
         final String testPackageName2 = "com.google.apps.dialer";
         final int testPackageNameUid2 = 456;
@@ -9613,8 +9650,8 @@
         mockGetApplicationInfo(testPackageName2, testPackageNameUid2);
 
         // Build OemNetworkPreferences object
-        final int testOemPref = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
-        final int testOemPref2 = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
+        final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
+        final int testOemPref2 = OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
                 .addNetworkPreference(testPackageName2, testOemPref2)
@@ -9636,7 +9673,7 @@
 
     @Test
     public void testOemNetworkRequestFactoryAddsPackagesToCorrectPreference()
-            throws PackageManager.NameNotFoundException {
+            throws Exception {
         // Expectations
         final int expectedNumOfNris = 1;
         final int expectedNumOfAppUids = 2;
@@ -9648,7 +9685,7 @@
         mockGetApplicationInfo(testPackageName2, testPackageNameUid2);
 
         // Build OemNetworkPreferences object
-        final int testOemPref = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
+        final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
                 .addNetworkPreference(testPackageName2, testOemPref)
@@ -9666,8 +9703,6 @@
     @Test
     public void testSetOemNetworkPreferenceNullListenerAndPrefParamThrowsNpe() {
         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
-        @OemNetworkPreferences.OemNetworkPreference final int networkPref =
-                OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
 
         // Act on ConnectivityService.setOemNetworkPreference()
         assertThrows(NullPointerException.class,
@@ -9678,15 +9713,641 @@
 
     @Test
     public void testSetOemNetworkPreferenceFailsForNonAutomotive()
-            throws PackageManager.NameNotFoundException, RemoteException {
+            throws Exception {
         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
-                OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
+                OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
 
         // Act on ConnectivityService.setOemNetworkPreference()
         assertThrows(UnsupportedOperationException.class,
                 () -> mService.setOemNetworkPreference(
                         createDefaultOemNetworkPreferences(networkPref),
-                        mOnSetOemNetworkPreferenceListener));
+                        new TestOemListenerCallback()));
+    }
+
+    private void setOemNetworkPreferenceAgentConnected(final int transportType,
+            final boolean connectAgent) throws Exception {
+        switch(transportType) {
+            // Corresponds to a metered cellular network. Will be used for the default network.
+            case TRANSPORT_CELLULAR:
+                if (!connectAgent) {
+                    mCellNetworkAgent.disconnect();
+                    break;
+                }
+                mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+                mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
+                mCellNetworkAgent.connect(true);
+                break;
+            // Corresponds to a restricted ethernet network with OEM_PAID/OEM_PRIVATE.
+            case TRANSPORT_ETHERNET:
+                if (!connectAgent) {
+                    stopOemManagedNetwork();
+                    break;
+                }
+                startOemManagedNetwork(true);
+                break;
+            // Corresponds to unmetered Wi-Fi.
+            case TRANSPORT_WIFI:
+                if (!connectAgent) {
+                    mWiFiNetworkAgent.disconnect();
+                    break;
+                }
+                mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+                mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+                mWiFiNetworkAgent.connect(true);
+                break;
+            default:
+                throw new AssertionError("Unsupported transport type passed in.");
+
+        }
+        waitForIdle();
+    }
+
+    private void startOemManagedNetwork(final boolean isOemPaid) throws Exception {
+        mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
+        mEthernetNetworkAgent.addCapability(
+                isOemPaid ? NET_CAPABILITY_OEM_PAID : NET_CAPABILITY_OEM_PRIVATE);
+        mEthernetNetworkAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
+        mEthernetNetworkAgent.connect(true);
+    }
+
+    private void stopOemManagedNetwork() {
+        mEthernetNetworkAgent.disconnect();
+        waitForIdle();
+    }
+
+    private void verifyMultipleDefaultNetworksTracksCorrectly(
+            final int expectedOemRequestsSize,
+            @NonNull final Network expectedDefaultNetwork,
+            @NonNull final Network expectedPerAppNetwork) {
+        // The current test setup assumes two tracked default network requests; one for the default
+        // network and the other for the OEM network preference being tested. This will be validated
+        // each time to confirm it doesn't change under test.
+        final int expectedDefaultNetworkRequestsSize = 2;
+        assertEquals(expectedDefaultNetworkRequestsSize, mService.mDefaultNetworkRequests.size());
+        for (final ConnectivityService.NetworkRequestInfo defaultRequest
+                : mService.mDefaultNetworkRequests) {
+            final Network defaultNetwork = defaultRequest.getSatisfier() == null
+                    ? null : defaultRequest.getSatisfier().network();
+            // If this is the default request.
+            if (defaultRequest == mService.mDefaultRequest) {
+                assertEquals(
+                        expectedDefaultNetwork,
+                        defaultNetwork);
+                // Make sure this value doesn't change.
+                assertEquals(1, defaultRequest.mRequests.size());
+                continue;
+            }
+            assertEquals(expectedPerAppNetwork, defaultNetwork);
+            assertEquals(expectedOemRequestsSize, defaultRequest.mRequests.size());
+        }
+    }
+
+    private void setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(
+            @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup)
+            throws Exception {
+        final int testPackageNameUid = 123;
+        final String testPackageName = "per.app.defaults.package";
+        setupMultipleDefaultNetworksForOemNetworkPreferenceTest(
+                networkPrefToSetup, testPackageNameUid, testPackageName);
+    }
+
+    private void setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(
+            @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup)
+            throws Exception {
+        final int testPackageNameUid = Process.myUid();
+        final String testPackageName = "per.app.defaults.package";
+        setupMultipleDefaultNetworksForOemNetworkPreferenceTest(
+                networkPrefToSetup, testPackageNameUid, testPackageName);
+    }
+
+    private void setupMultipleDefaultNetworksForOemNetworkPreferenceTest(
+            @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
+            final int testPackageUid, @NonNull final String testPackageName) throws Exception {
+        // Only the default request should be included at start.
+        assertEquals(1, mService.mDefaultNetworkRequests.size());
+
+        final UidRangeParcel[] uidRanges =
+                toUidRangeStableParcels(uidRangesForUid(testPackageUid));
+        setupSetOemNetworkPreferenceForPreferenceTest(
+                networkPrefToSetup, uidRanges, testPackageName);
+    }
+
+    private void setupSetOemNetworkPreferenceForPreferenceTest(
+            @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
+            @NonNull final UidRangeParcel[] uidRanges,
+            @NonNull final String testPackageName)
+            throws Exception {
+        mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
+
+        // These tests work off a single UID therefore using 'start' is valid.
+        mockGetApplicationInfo(testPackageName, uidRanges[0].start);
+
+        // Build OemNetworkPreferences object
+        final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
+                .addNetworkPreference(testPackageName, networkPrefToSetup)
+                .build();
+
+        // Act on ConnectivityService.setOemNetworkPreference()
+        final TestOemListenerCallback mOnSetOemNetworkPreferenceTestListener =
+                new TestOemListenerCallback();
+        mService.setOemNetworkPreference(pref, mOnSetOemNetworkPreferenceTestListener);
+
+        // Verify call returned successfully
+        mOnSetOemNetworkPreferenceTestListener.expectOnComplete();
+    }
+
+    private static class TestOemListenerCallback implements IOnSetOemNetworkPreferenceListener {
+        final CompletableFuture<Object> mDone = new CompletableFuture<>();
+
+        @Override
+        public void onComplete() {
+            mDone.complete(new Object());
+        }
+
+        void expectOnComplete() throws Exception {
+            try {
+                mDone.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+            } catch (TimeoutException e) {
+                fail("Expected onComplete() not received after " + TIMEOUT_MS + " ms");
+            }
+        }
+
+        @Override
+        public IBinder asBinder() {
+            return null;
+        }
+    }
+
+    @Test
+    public void testMultiDefaultGetActiveNetworkIsCorrect() throws Exception {
+        @OemNetworkPreferences.OemNetworkPreference final int networkPref =
+                OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
+        final int expectedOemPrefRequestSize = 1;
+
+        // Setup the test process to use networkPref for their default network.
+        setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
+
+        // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
+        // The active network for the default should be null at this point as this is a retricted
+        // network.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
+        verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
+                null,
+                mEthernetNetworkAgent.getNetwork());
+
+        // Verify that the active network is correct
+        verifyActiveNetwork(TRANSPORT_ETHERNET);
+    }
+
+    @Test
+    public void testMultiDefaultIsActiveNetworkMeteredIsCorrect() throws Exception {
+        @OemNetworkPreferences.OemNetworkPreference final int networkPref =
+                OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
+        final int expectedOemPrefRequestSize = 1;
+
+        // Setup the test process to use networkPref for their default network.
+        setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
+
+        // Returns true by default when no network is available.
+        assertTrue(mCm.isActiveNetworkMetered());
+
+        // Connect to an unmetered restricted network that will only be available to the OEM pref.
+        mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
+        mEthernetNetworkAgent.addCapability(NET_CAPABILITY_OEM_PAID);
+        mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mEthernetNetworkAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
+        mEthernetNetworkAgent.connect(true);
+        waitForIdle();
+
+        verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
+                null,
+                mEthernetNetworkAgent.getNetwork());
+
+        assertFalse(mCm.isActiveNetworkMetered());
+    }
+
+    @Test
+    public void testPerAppDefaultRegisterDefaultNetworkCallback() throws Exception {
+        @OemNetworkPreferences.OemNetworkPreference final int networkPref =
+                OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
+        final int expectedOemPrefRequestSize = 1;
+        final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
+
+        // Register the default network callback before the pref is already set. This means that
+        // the policy will be applied to the callback on setOemNetworkPreference().
+        mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
+        defaultNetworkCallback.assertNoCallback();
+
+        // Setup the test process to use networkPref for their default network.
+        setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
+
+        // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
+        // The active nai for the default is null at this point as this is a restricted network.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
+        verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
+                null,
+                mEthernetNetworkAgent.getNetwork());
+
+        // At this point with a restricted network used, the available callback should trigger
+        defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
+        assertEquals(defaultNetworkCallback.getLastAvailableNetwork(),
+                mEthernetNetworkAgent.getNetwork());
+
+        // Now bring down the default network which should trigger a LOST callback.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
+
+        // At this point, with no network is available, the lost callback should trigger
+        defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
+
+        // Confirm we can unregister without issues.
+        mCm.unregisterNetworkCallback(defaultNetworkCallback);
+    }
+
+    @Test
+    public void testPerAppDefaultRegisterDefaultNetworkCallbackAfterPrefSet() throws Exception {
+        @OemNetworkPreferences.OemNetworkPreference final int networkPref =
+                OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
+        final int expectedOemPrefRequestSize = 1;
+        final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
+
+        // Setup the test process to use networkPref for their default network.
+        setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
+
+        // Register the default network callback after the pref is already set. This means that
+        // the policy will be applied to the callback on requestNetwork().
+        mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
+        defaultNetworkCallback.assertNoCallback();
+
+        // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
+        // The active nai for the default is null at this point as this is a restricted network.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
+        verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
+                null,
+                mEthernetNetworkAgent.getNetwork());
+
+        // At this point with a restricted network used, the available callback should trigger
+        defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
+        assertEquals(defaultNetworkCallback.getLastAvailableNetwork(),
+                mEthernetNetworkAgent.getNetwork());
+
+        // Now bring down the default network which should trigger a LOST callback.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
+
+        // At this point, with no network is available, the lost callback should trigger
+        defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
+
+        // Confirm we can unregister without issues.
+        mCm.unregisterNetworkCallback(defaultNetworkCallback);
+    }
+
+    @Test
+    public void testPerAppDefaultRegisterDefaultNetworkCallbackDoesNotFire() throws Exception {
+        @OemNetworkPreferences.OemNetworkPreference final int networkPref =
+                OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
+        final int expectedOemPrefRequestSize = 1;
+        final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
+        final int userId = UserHandle.getUserId(Process.myUid());
+
+        mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
+        defaultNetworkCallback.assertNoCallback();
+
+        // Setup a process different than the test process to use the default network. This means
+        // that the defaultNetworkCallback won't be tracked by the per-app policy.
+        setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(networkPref);
+
+        // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
+        // The active nai for the default is null at this point as this is a restricted network.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
+        verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
+                null,
+                mEthernetNetworkAgent.getNetwork());
+
+        // As this callback does not have access to the OEM_PAID network, it will not fire.
+        defaultNetworkCallback.assertNoCallback();
+        assertDefaultNetworkCapabilities(userId /* no networks */);
+
+        // Bring up unrestricted cellular. This should now satisfy the default network.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
+        verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
+                mCellNetworkAgent.getNetwork(),
+                mEthernetNetworkAgent.getNetwork());
+
+        // At this point with an unrestricted network used, the available callback should trigger
+        defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        assertEquals(defaultNetworkCallback.getLastAvailableNetwork(),
+                mCellNetworkAgent.getNetwork());
+        assertDefaultNetworkCapabilities(userId, mCellNetworkAgent);
+
+        // Now bring down the per-app network.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
+
+        // Since the callback didn't use the per-app network, no callback should fire.
+        defaultNetworkCallback.assertNoCallback();
+
+        // Now bring down the default network.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
+
+        // As this callback was tracking the default, this should now trigger.
+        defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
+
+        // Confirm we can unregister without issues.
+        mCm.unregisterNetworkCallback(defaultNetworkCallback);
+    }
+
+    private void verifySetOemNetworkPreferenceForPreference(
+            @NonNull final UidRangeParcel[] uidRanges,
+            final int addUidRangesNetId,
+            final int addUidRangesTimes,
+            final int removeUidRangesNetId,
+            final int removeUidRangesTimes,
+            final boolean shouldDestroyNetwork) throws RemoteException {
+        final boolean useAnyIdForAdd = OEM_PREF_ANY_NET_ID == addUidRangesNetId;
+        final boolean useAnyIdForRemove = OEM_PREF_ANY_NET_ID == removeUidRangesNetId;
+
+        // Validate netd.
+        verify(mMockNetd, times(addUidRangesTimes))
+                .networkAddUidRanges(
+                        (useAnyIdForAdd ? anyInt() : eq(addUidRangesNetId)), eq(uidRanges));
+        verify(mMockNetd, times(removeUidRangesTimes))
+                .networkRemoveUidRanges(
+                        (useAnyIdForRemove ? anyInt() : eq(removeUidRangesNetId)), eq(uidRanges));
+        if (shouldDestroyNetwork) {
+            verify(mMockNetd, times(1))
+                    .networkDestroy((useAnyIdForRemove ? anyInt() : eq(removeUidRangesNetId)));
+        }
+        reset(mMockNetd);
+    }
+
+    /**
+     * Test the tracked default requests clear previous OEM requests on setOemNetworkPreference().
+     * @throws Exception
+     */
+    @Test
+    public void testSetOemNetworkPreferenceClearPreviousOemValues() throws Exception {
+        @OemNetworkPreferences.OemNetworkPreference int networkPref =
+                OEM_NETWORK_PREFERENCE_OEM_PAID;
+        final int testPackageUid = 123;
+        final String testPackageName = "com.google.apps.contacts";
+        final UidRangeParcel[] uidRanges =
+                toUidRangeStableParcels(uidRangesForUid(testPackageUid));
+
+        // Validate the starting requests only includes the fallback request.
+        assertEquals(1, mService.mDefaultNetworkRequests.size());
+
+        // Add an OEM default network request to track.
+        setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, testPackageName);
+
+        // Two requests should exist, one for the fallback and one for the pref.
+        assertEquals(2, mService.mDefaultNetworkRequests.size());
+
+        networkPref = OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
+        setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, testPackageName);
+
+        // Two requests should still exist validating the previous per-app request was replaced.
+        assertEquals(2, mService.mDefaultNetworkRequests.size());
+    }
+
+    /**
+     * Test network priority for preference OEM_NETWORK_PREFERENCE_OEM_PAID following in order:
+     * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID -> fallback
+     * @throws Exception
+     */
+    @Test
+    public void testMultilayerForPreferenceOemPaidEvaluatesCorrectly()
+            throws Exception {
+        @OemNetworkPreferences.OemNetworkPreference final int networkPref =
+                OEM_NETWORK_PREFERENCE_OEM_PAID;
+
+        // Arrange PackageManager mocks
+        final int testPackageNameUid = 123;
+        final UidRangeParcel[] uidRanges =
+                toUidRangeStableParcels(uidRangesForUid(testPackageNameUid));
+        setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
+
+        // Verify the starting state. No networks should be connected.
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                false /* shouldDestroyNetwork */);
+
+        // Test lowest to highest priority requests.
+        // Bring up metered cellular. This will satisfy the fallback network.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                false /* shouldDestroyNetwork */);
+
+        // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
+                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+                false /* shouldDestroyNetwork */);
+
+        // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                mWiFiNetworkAgent.getNetwork().netId, 1 /* times */,
+                mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
+                false /* shouldDestroyNetwork */);
+
+        // Disconnecting OEM_PAID should have no effect as it is lower in priority then unmetered.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
+        // netd should not be called as default networks haven't changed.
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                false /* shouldDestroyNetwork */);
+
+        // Disconnecting unmetered should put PANS on lowest priority fallback request.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+                mWiFiNetworkAgent.getNetwork().netId, 0 /* times */,
+                true /* shouldDestroyNetwork */);
+
+        // Disconnecting the fallback network should result in no connectivity.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                mCellNetworkAgent.getNetwork().netId, 0 /* times */,
+                true /* shouldDestroyNetwork */);
+    }
+
+    /**
+     * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK following in order:
+     * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID
+     * @throws Exception
+     */
+    @Test
+    public void testMultilayerForPreferenceOemPaidNoFallbackEvaluatesCorrectly()
+            throws Exception {
+        @OemNetworkPreferences.OemNetworkPreference final int networkPref =
+                OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
+
+        // Arrange PackageManager mocks
+        final int testPackageNameUid = 123;
+        final UidRangeParcel[] uidRanges =
+                toUidRangeStableParcels(uidRangesForUid(testPackageNameUid));
+        setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
+
+        // Verify the starting state. This preference doesn't support using the fallback network
+        // therefore should be on the disconnected network as it has no networks to connect to.
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                false /* shouldDestroyNetwork */);
+
+        // Test lowest to highest priority requests.
+        // Bring up metered cellular. This will satisfy the fallback network.
+        // This preference should not use this network as it doesn't support fallback usage.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                false /* shouldDestroyNetwork */);
+
+        // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
+                mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
+                false /* shouldDestroyNetwork */);
+
+        // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                mWiFiNetworkAgent.getNetwork().netId, 1 /* times */,
+                mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
+                false /* shouldDestroyNetwork */);
+
+        // Disconnecting unmetered should put PANS on OEM_PAID.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
+                mWiFiNetworkAgent.getNetwork().netId, 0 /* times */,
+                true /* shouldDestroyNetwork */);
+
+        // Disconnecting OEM_PAID should result in no connectivity.
+        // OEM_PAID_NO_FALLBACK not supporting a fallback now uses the disconnected network.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
+                mEthernetNetworkAgent.getNetwork().netId, 0 /* times */,
+                true /* shouldDestroyNetwork */);
+    }
+
+    /**
+     * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY following in order:
+     * NET_CAPABILITY_OEM_PAID
+     * This preference should only apply to OEM_PAID networks.
+     * @throws Exception
+     */
+    @Test
+    public void testMultilayerForPreferenceOemPaidOnlyEvaluatesCorrectly()
+            throws Exception {
+        @OemNetworkPreferences.OemNetworkPreference final int networkPref =
+                OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
+
+        // Arrange PackageManager mocks
+        final int testPackageNameUid = 123;
+        final UidRangeParcel[] uidRanges =
+                toUidRangeStableParcels(uidRangesForUid(testPackageNameUid));
+        setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
+
+        // Verify the starting state. This preference doesn't support using the fallback network
+        // therefore should be on the disconnected network as it has no networks to connect to.
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                false /* shouldDestroyNetwork */);
+
+        // Bring up metered cellular. This should not apply to this preference.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                false /* shouldDestroyNetwork */);
+
+        // Bring up unmetered Wi-Fi. This should not apply to this preference.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                false /* shouldDestroyNetwork */);
+
+        // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
+                mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
+                false /* shouldDestroyNetwork */);
+
+        // Disconnecting OEM_PAID should result in no connectivity.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
+                mEthernetNetworkAgent.getNetwork().netId, 0 /* times */,
+                true /* shouldDestroyNetwork */);
+    }
+
+    /**
+     * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY following in order:
+     * NET_CAPABILITY_OEM_PRIVATE
+     * This preference should only apply to OEM_PRIVATE networks.
+     * @throws Exception
+     */
+    @Test
+    public void testMultilayerForPreferenceOemPrivateOnlyEvaluatesCorrectly()
+            throws Exception {
+        @OemNetworkPreferences.OemNetworkPreference final int networkPref =
+                OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
+
+        // Arrange PackageManager mocks
+        final int testPackageNameUid = 123;
+        final UidRangeParcel[] uidRanges =
+                toUidRangeStableParcels(uidRangesForUid(testPackageNameUid));
+        setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
+
+        // Verify the starting state. This preference doesn't support using the fallback network
+        // therefore should be on the disconnected network as it has no networks to connect to.
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                false /* shouldDestroyNetwork */);
+
+        // Bring up metered cellular. This should not apply to this preference.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                false /* shouldDestroyNetwork */);
+
+        // Bring up unmetered Wi-Fi. This should not apply to this preference.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                false /* shouldDestroyNetwork */);
+
+        // Bring up ethernet with OEM_PRIVATE. This will satisfy NET_CAPABILITY_OEM_PRIVATE.
+        startOemManagedNetwork(false);
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
+                mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
+                false /* shouldDestroyNetwork */);
+
+        // Disconnecting OEM_PRIVATE should result in no connectivity.
+        stopOemManagedNetwork();
+        verifySetOemNetworkPreferenceForPreference(uidRanges,
+                mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
+                mEthernetNetworkAgent.getNetwork().netId, 0 /* times */,
+                true /* shouldDestroyNetwork */);
+    }
+
+    private UidRange createUidRange(int userId) {
+        return UidRange.createForUser(UserHandle.of(userId));
     }
 }
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
index c86224a..32c95f1 100644
--- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -16,12 +16,16 @@
 
 package com.android.server;
 
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.net.INetd.IF_STATE_DOWN;
+import static android.net.INetd.IF_STATE_UP;
 import static android.system.OsConstants.AF_INET;
 import static android.system.OsConstants.AF_INET6;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
@@ -36,6 +40,7 @@
 import android.net.ConnectivityManager;
 import android.net.INetd;
 import android.net.InetAddresses;
+import android.net.InterfaceConfigurationParcel;
 import android.net.IpSecAlgorithm;
 import android.net.IpSecConfig;
 import android.net.IpSecManager;
@@ -48,7 +53,6 @@
 import android.net.LinkProperties;
 import android.net.Network;
 import android.os.Binder;
-import android.os.INetworkManagementService;
 import android.os.ParcelFileDescriptor;
 import android.system.Os;
 import android.test.mock.MockContext;
@@ -148,10 +152,17 @@
             }
             throw new SecurityException("Unavailable permission requested");
         }
+
+        @Override
+        public int checkCallingOrSelfPermission(String permission) {
+            if (android.Manifest.permission.NETWORK_STACK.equals(permission)) {
+                return PERMISSION_GRANTED;
+            }
+            throw new UnsupportedOperationException();
+        }
     };
 
     INetd mMockNetd;
-    INetworkManagementService mNetworkManager;
     PackageManager mMockPkgMgr;
     IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig;
     IpSecService mIpSecService;
@@ -181,10 +192,9 @@
     @Before
     public void setUp() throws Exception {
         mMockNetd = mock(INetd.class);
-        mNetworkManager = mock(INetworkManagementService.class);
         mMockPkgMgr = mock(PackageManager.class);
         mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class);
-        mIpSecService = new IpSecService(mMockContext, mNetworkManager, mMockIpSecSrvConfig);
+        mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig);
 
         // Injecting mock netd
         when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd);
@@ -644,7 +654,10 @@
     }
 
     private IpSecTunnelInterfaceResponse createAndValidateTunnel(
-            String localAddr, String remoteAddr, String pkgName) {
+            String localAddr, String remoteAddr, String pkgName) throws Exception {
+        final InterfaceConfigurationParcel config = new InterfaceConfigurationParcel();
+        config.flags = new String[] {IF_STATE_DOWN};
+        when(mMockNetd.interfaceGetCfg(anyString())).thenReturn(config);
         IpSecTunnelInterfaceResponse createTunnelResp =
                 mIpSecService.createTunnelInterface(
                         mSourceAddr, mDestinationAddr, fakeNetwork, new Binder(), pkgName);
@@ -674,7 +687,8 @@
                         anyInt(),
                         anyInt(),
                         anyInt());
-        verify(mNetworkManager).setInterfaceUp(createTunnelResp.interfaceName);
+        verify(mMockNetd).interfaceSetCfg(argThat(
+                config -> Arrays.asList(config.flags).contains(IF_STATE_UP)));
     }
 
     @Test
diff --git a/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java b/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java
index 788e4ef..22a2c94 100644
--- a/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java
@@ -31,7 +31,6 @@
 import android.content.Context;
 import android.os.Binder;
 import android.os.IBinder;
-import android.os.INetworkManagementService;
 import android.os.RemoteException;
 
 import androidx.test.filters.SmallTest;
@@ -62,8 +61,7 @@
     public void setUp() throws Exception {
         mMockContext = mock(Context.class);
         mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class);
-        mIpSecService = new IpSecService(
-                mMockContext, mock(INetworkManagementService.class), mMockIpSecSrvConfig);
+        mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig);
     }
 
     private void assertResourceState(
diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java
index 536e983..f97eabf 100644
--- a/tests/net/java/com/android/server/IpSecServiceTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceTest.java
@@ -42,7 +42,6 @@
 import android.net.IpSecSpiResponse;
 import android.net.IpSecUdpEncapResponse;
 import android.os.Binder;
-import android.os.INetworkManagementService;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.system.ErrnoException;
@@ -116,7 +115,6 @@
     }
 
     Context mMockContext;
-    INetworkManagementService mMockNetworkManager;
     INetd mMockNetd;
     IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig;
     IpSecService mIpSecService;
@@ -124,10 +122,9 @@
     @Before
     public void setUp() throws Exception {
         mMockContext = mock(Context.class);
-        mMockNetworkManager = mock(INetworkManagementService.class);
         mMockNetd = mock(INetd.class);
         mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class);
-        mIpSecService = new IpSecService(mMockContext, mMockNetworkManager, mMockIpSecSrvConfig);
+        mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig);
 
         // Injecting mock netd
         when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd);
@@ -135,7 +132,7 @@
 
     @Test
     public void testIpSecServiceCreate() throws InterruptedException {
-        IpSecService ipSecSrv = IpSecService.create(mMockContext, mMockNetworkManager);
+        IpSecService ipSecSrv = IpSecService.create(mMockContext);
         assertNotNull(ipSecSrv);
     }
 
@@ -608,7 +605,7 @@
     public void testOpenUdpEncapSocketTagsSocket() throws Exception {
         IpSecService.UidFdTagger mockTagger = mock(IpSecService.UidFdTagger.class);
         IpSecService testIpSecService = new IpSecService(
-                mMockContext, mMockNetworkManager, mMockIpSecSrvConfig, mockTagger);
+                mMockContext, mMockIpSecSrvConfig, mockTagger);
 
         IpSecUdpEncapResponse udpEncapResp =
                 testIpSecService.openUdpEncapsulationSocket(0, new Binder());
diff --git a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
index 46c4081..d01dc03 100644
--- a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
@@ -51,6 +51,7 @@
 import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.AdditionalAnswers;
@@ -199,6 +200,9 @@
     }
 
     @Test
+    @Ignore
+    // Ignored because the code under test calls Log.wtf, which crashes the tests on eng builds.
+    // TODO: re-enable after fixing this (e.g., turn Log.wtf into exceptions that this test catches)
     public void testNoInternetNotificationsNotShownForCellular() {
         mManager.showNotification(100, NO_INTERNET, mCellNai, mWifiNai, null, false);
         mManager.showNotification(101, LOST_INTERNET, mCellNai, mWifiNai, null, false);
diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
index 8f5ae97..e4e24b4 100644
--- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -61,6 +61,7 @@
 import android.net.INetd;
 import android.net.UidRange;
 import android.os.Build;
+import android.os.SystemConfigManager;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.SparseIntArray;
@@ -114,6 +115,7 @@
     @Mock private PackageManagerInternal mMockPmi;
     @Mock private UserManager mUserManager;
     @Mock private PermissionMonitor.Dependencies mDeps;
+    @Mock private SystemConfigManager mSystemConfigManager;
 
     private PermissionMonitor mPermissionMonitor;
 
@@ -124,6 +126,11 @@
         when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager);
         when(mUserManager.getUserHandles(eq(true))).thenReturn(
                 Arrays.asList(new UserHandle[] { MOCK_USER1, MOCK_USER2 }));
+        when(mContext.getSystemServiceName(SystemConfigManager.class))
+                .thenReturn(Context.SYSTEM_CONFIG_SERVICE);
+        when(mContext.getSystemService(Context.SYSTEM_CONFIG_SERVICE))
+                .thenReturn(mSystemConfigManager);
+        when(mSystemConfigManager.getSystemPermissionUids(anyString())).thenReturn(new int[0]);
 
         mPermissionMonitor = spy(new PermissionMonitor(mContext, mNetdService, mDeps));
 
@@ -747,4 +754,20 @@
                 GET_PERMISSIONS | MATCH_ANY_USER);
         assertTrue(monitor.hasPermission(systemInfo, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
     }
+
+    @Test
+    public void testUpdateUidPermissionsFromSystemConfig() throws Exception {
+        final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService);
+        when(mPackageManager.getInstalledPackages(anyInt())).thenReturn(new ArrayList<>());
+        when(mSystemConfigManager.getSystemPermissionUids(eq(INTERNET)))
+                .thenReturn(new int[]{ MOCK_UID1, MOCK_UID2 });
+        when(mSystemConfigManager.getSystemPermissionUids(eq(UPDATE_DEVICE_STATS)))
+                .thenReturn(new int[]{ MOCK_UID2 });
+
+        mPermissionMonitor.startMonitoring();
+        mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{ MOCK_UID1 });
+        mNetdServiceMonitor.expectPermission(
+                INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS,
+                new int[]{ MOCK_UID2 });
+    }
 }
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index cffd2d1d..7489a0f 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -21,6 +21,8 @@
 import static android.content.pm.UserInfo.FLAG_PRIMARY;
 import static android.content.pm.UserInfo.FLAG_RESTRICTED;
 import static android.net.ConnectivityManager.NetworkCallback;
+import static android.net.INetd.IF_STATE_DOWN;
+import static android.net.INetd.IF_STATE_UP;
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
@@ -62,6 +64,7 @@
 import android.net.INetd;
 import android.net.Ikev2VpnProfile;
 import android.net.InetAddresses;
+import android.net.InterfaceConfigurationParcel;
 import android.net.IpPrefix;
 import android.net.IpSecManager;
 import android.net.IpSecTunnelInterfaceResponse;
@@ -179,7 +182,8 @@
             mPackages.put(PKGS[i], PKG_UIDS[i]);
         }
     }
-    private static final UidRange PRI_USER_RANGE = UidRange.createForUser(primaryUser.id);
+    private static final UidRange PRI_USER_RANGE =
+            UidRange.createForUser(UserHandle.of(primaryUser.id));
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext;
     @Mock private UserManager mUserManager;
@@ -269,7 +273,7 @@
                 vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, null, null);
 
         assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] {
-                PRI_USER_RANGE, UidRange.createForUser(restrictedProfileA.id)
+                PRI_USER_RANGE, UidRange.createForUser(UserHandle.of(restrictedProfileA.id))
         })), ranges);
     }
 
@@ -872,17 +876,28 @@
                         eq(AppOpsManager.MODE_IGNORED));
     }
 
-    private NetworkCallback triggerOnAvailableAndGetCallback() {
+    private NetworkCallback triggerOnAvailableAndGetCallback() throws Exception {
         final ArgumentCaptor<NetworkCallback> networkCallbackCaptor =
                 ArgumentCaptor.forClass(NetworkCallback.class);
         verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS))
                 .requestNetwork(any(), networkCallbackCaptor.capture());
 
+        // onAvailable() will trigger onDefaultNetworkChanged(), so NetdUtils#setInterfaceUp will be
+        // invoked. Set the return value of INetd#interfaceGetCfg to prevent NullPointerException.
+        final InterfaceConfigurationParcel config = new InterfaceConfigurationParcel();
+        config.flags = new String[] {IF_STATE_DOWN};
+        when(mNetd.interfaceGetCfg(anyString())).thenReturn(config);
         final NetworkCallback cb = networkCallbackCaptor.getValue();
         cb.onAvailable(TEST_NETWORK);
         return cb;
     }
 
+    private void verifyInterfaceSetCfgWithFlags(String flag) throws Exception {
+        // Add a timeout for waiting for interfaceSetCfg to be called.
+        verify(mNetd, timeout(TEST_TIMEOUT_MS)).interfaceSetCfg(argThat(
+                config -> Arrays.asList(config.flags).contains(flag)));
+    }
+
     @Test
     public void testStartPlatformVpnAuthenticationFailed() throws Exception {
         final ArgumentCaptor<IkeSessionCallback> captor =
@@ -894,6 +909,8 @@
         final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), (mVpnProfile));
         final NetworkCallback cb = triggerOnAvailableAndGetCallback();
 
+        verifyInterfaceSetCfgWithFlags(IF_STATE_UP);
+
         // Wait for createIkeSession() to be called before proceeding in order to ensure consistent
         // state
         verify(mIkev2SessionCreator, timeout(TEST_TIMEOUT_MS))
@@ -912,6 +929,8 @@
         final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), mVpnProfile);
         final NetworkCallback cb = triggerOnAvailableAndGetCallback();
 
+        verifyInterfaceSetCfgWithFlags(IF_STATE_UP);
+
         // Wait for createIkeSession() to be called before proceeding in order to ensure consistent
         // state
         verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS)).unregisterNetworkCallback(eq(cb));
diff --git a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
index 435c3c0..505ff9b 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
@@ -17,6 +17,7 @@
 package com.android.server.net;
 
 import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.NetworkIdentity.OEM_NONE;
 import static android.net.NetworkStats.SET_ALL;
 import static android.net.NetworkStats.SET_DEFAULT;
 import static android.net.NetworkStats.TAG_NONE;
@@ -213,7 +214,7 @@
         final NetworkStats.Entry entry = new NetworkStats.Entry();
         final NetworkIdentitySet identSet = new NetworkIdentitySet();
         identSet.add(new NetworkIdentity(TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                TEST_IMSI, null, false, true, true));
+                TEST_IMSI, null, false, true, true, OEM_NONE));
 
         int myUid = Process.myUid();
         int otherUidInSameUser = Process.myUid() + 1;
@@ -468,7 +469,7 @@
         final NetworkStatsCollection large = new NetworkStatsCollection(HOUR_IN_MILLIS);
         final NetworkIdentitySet ident = new NetworkIdentitySet();
         ident.add(new NetworkIdentity(ConnectivityManager.TYPE_MOBILE, -1, TEST_IMSI, null,
-                false, true, true));
+                false, true, true, OEM_NONE));
         large.recordData(ident, UID_ALL, SET_ALL, TAG_NONE, TIME_A, TIME_B,
                 new NetworkStats.Entry(12_730_893_164L, 1, 0, 0, 0));
 
diff --git a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
index 291efc7..9fa1c50 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
@@ -17,6 +17,7 @@
 package com.android.server.net;
 
 import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.NetworkIdentity.OEM_NONE;
 import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
 import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
 import static android.net.NetworkStats.METERED_NO;
@@ -220,7 +221,7 @@
         identSet.add(new NetworkIdentity(
                 TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
                 IMSI_1, null /* networkId */, false /* roaming */, true /* metered */,
-                true /* defaultNetwork */));
+                true /* defaultNetwork */, OEM_NONE));
         return identSet;
     }
 
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index 214c82d..54d6fb9 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -21,6 +21,9 @@
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.ConnectivityManager.TYPE_VPN;
 import static android.net.ConnectivityManager.TYPE_WIFI;
+import static android.net.NetworkIdentity.OEM_NONE;
+import static android.net.NetworkIdentity.OEM_PAID;
+import static android.net.NetworkIdentity.OEM_PRIVATE;
 import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
 import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
 import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
@@ -40,7 +43,10 @@
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
 import static android.net.NetworkStatsHistory.FIELD_ALL;
+import static android.net.NetworkTemplate.MATCH_MOBILE_WILDCARD;
 import static android.net.NetworkTemplate.NETWORK_TYPE_ALL;
+import static android.net.NetworkTemplate.OEM_MANAGED_NO;
+import static android.net.NetworkTemplate.OEM_MANAGED_YES;
 import static android.net.NetworkTemplate.buildTemplateMobileAll;
 import static android.net.NetworkTemplate.buildTemplateMobileWithRatType;
 import static android.net.NetworkTemplate.buildTemplateWifi;
@@ -643,6 +649,116 @@
         assertUidTotal(template5g, UID_RED, 5L, 13L, 31L, 9L, 2);
     }
 
+    @Test
+    public void testMobileStatsOemManaged() throws Exception {
+        final NetworkTemplate templateOemPaid = new NetworkTemplate(MATCH_MOBILE_WILDCARD,
+                /*subscriberId=*/null, /*matchSubscriberIds=*/null, /*networkId=*/null,
+                METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_PAID);
+
+        final NetworkTemplate templateOemPrivate = new NetworkTemplate(MATCH_MOBILE_WILDCARD,
+                /*subscriberId=*/null, /*matchSubscriberIds=*/null, /*networkId=*/null,
+                METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_PRIVATE);
+
+        final NetworkTemplate templateOemAll = new NetworkTemplate(MATCH_MOBILE_WILDCARD,
+                /*subscriberId=*/null, /*matchSubscriberIds=*/null, /*networkId=*/null,
+                METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
+                OEM_PAID | OEM_PRIVATE);
+
+        final NetworkTemplate templateOemYes = new NetworkTemplate(MATCH_MOBILE_WILDCARD,
+                /*subscriberId=*/null, /*matchSubscriberIds=*/null, /*networkId=*/null,
+                METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_YES);
+
+        final NetworkTemplate templateOemNone = new NetworkTemplate(MATCH_MOBILE_WILDCARD,
+                /*subscriberId=*/null, /*matchSubscriberIds=*/null, /*networkId=*/null,
+                METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_NO);
+
+        // OEM_PAID network comes online.
+        NetworkState[] states = new NetworkState[]{buildOemManagedMobileState(IMSI_1, false,
+                new int[]{NetworkCapabilities.NET_CAPABILITY_OEM_PAID})};
+        expectNetworkStatsSummary(buildEmptyStats());
+        expectNetworkStatsUidDetail(buildEmptyStats());
+        mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
+
+        // Create some traffic.
+        incrementCurrentTime(MINUTE_IN_MILLIS);
+        expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
+                .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE,
+                        36L, 41L, 24L, 96L, 0L)));
+        forcePollAndWaitForIdle();
+
+        // OEM_PRIVATE network comes online.
+        states = new NetworkState[]{buildOemManagedMobileState(IMSI_1, false,
+                new int[]{NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE})};
+        expectNetworkStatsSummary(buildEmptyStats());
+        expectNetworkStatsUidDetail(buildEmptyStats());
+        mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
+
+        // Create some traffic.
+        incrementCurrentTime(MINUTE_IN_MILLIS);
+        expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
+                .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE,
+                        49L, 71L, 72L, 48L, 0L)));
+        forcePollAndWaitForIdle();
+
+        // OEM_PAID + OEM_PRIVATE network comes online.
+        states = new NetworkState[]{buildOemManagedMobileState(IMSI_1, false,
+                new int[]{NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE,
+                          NetworkCapabilities.NET_CAPABILITY_OEM_PAID})};
+        expectNetworkStatsSummary(buildEmptyStats());
+        expectNetworkStatsUidDetail(buildEmptyStats());
+        mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
+
+        // Create some traffic.
+        incrementCurrentTime(MINUTE_IN_MILLIS);
+        expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
+                .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE,
+                        57L, 86L, 83L, 93L, 0L)));
+        forcePollAndWaitForIdle();
+
+        // OEM_NONE network comes online.
+        states = new NetworkState[]{buildOemManagedMobileState(IMSI_1, false, new int[]{})};
+        expectNetworkStatsSummary(buildEmptyStats());
+        expectNetworkStatsUidDetail(buildEmptyStats());
+        mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
+
+        // Create some traffic.
+        incrementCurrentTime(MINUTE_IN_MILLIS);
+        expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
+                .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE,
+                        29L, 73L, 34L, 31L, 0L)));
+        forcePollAndWaitForIdle();
+
+        // Verify OEM_PAID template gets only relevant stats.
+        assertUidTotal(templateOemPaid, UID_RED, 36L, 41L, 24L, 96L, 0);
+
+        // Verify OEM_PRIVATE template gets only relevant stats.
+        assertUidTotal(templateOemPrivate, UID_RED, 49L, 71L, 72L, 48L, 0);
+
+        // Verify OEM_PAID + OEM_PRIVATE template gets only relevant stats.
+        assertUidTotal(templateOemAll, UID_RED, 57L, 86L, 83L, 93L, 0);
+
+        // Verify OEM_NONE sees only non-OEM managed stats.
+        assertUidTotal(templateOemNone, UID_RED, 29L, 73L, 34L, 31L, 0);
+
+        // Verify OEM_MANAGED_YES sees all OEM managed stats.
+        assertUidTotal(templateOemYes, UID_RED,
+                36L + 49L + 57L,
+                41L + 71L + 86L,
+                24L + 72L + 83L,
+                96L + 48L + 93L, 0);
+
+        // Verify ALL_MOBILE template gets both OEM managed and non-OEM managed stats.
+        assertUidTotal(sTemplateImsi1, UID_RED,
+                36L + 49L + 57L + 29L,
+                41L + 71L + 86L + 73L,
+                24L + 72L + 83L + 34L,
+                96L + 48L + 93L + 31L, 0);
+    }
+
     // TODO: support per IMSI state
     private void setMobileRatTypeAndWaitForIdle(int ratType) {
         when(mNetworkStatsSubscriptionsMonitor.getRatTypeForSubscriberId(anyString()))
@@ -1461,7 +1577,7 @@
         capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true);
         capabilities.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
         capabilities.setSSID(TEST_SSID);
-        return new NetworkState(TYPE_WIFI, prop, capabilities, WIFI_NETWORK, null, TEST_SSID);
+        return new NetworkState(TYPE_WIFI, prop, capabilities, WIFI_NETWORK, null);
     }
 
     private static NetworkState buildMobile3gState(String subscriberId) {
@@ -1475,8 +1591,7 @@
         capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false);
         capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, !isRoaming);
         capabilities.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
-        return new NetworkState(
-                TYPE_MOBILE, prop, capabilities, MOBILE_NETWORK, subscriberId, null);
+        return new NetworkState(TYPE_MOBILE, prop, capabilities, MOBILE_NETWORK, subscriberId);
     }
 
     private NetworkStats buildEmptyStats() {
@@ -1486,7 +1601,21 @@
     private static NetworkState buildVpnState() {
         final LinkProperties prop = new LinkProperties();
         prop.setInterfaceName(TUN_IFACE);
-        return new NetworkState(TYPE_VPN, prop, new NetworkCapabilities(), VPN_NETWORK, null, null);
+        return new NetworkState(TYPE_VPN, prop, new NetworkCapabilities(), VPN_NETWORK, null);
+    }
+
+    private static NetworkState buildOemManagedMobileState(String subscriberId, boolean isRoaming,
+                int[] oemNetCapabilities) {
+        final LinkProperties prop = new LinkProperties();
+        prop.setInterfaceName(TEST_IFACE);
+        final NetworkCapabilities capabilities = new NetworkCapabilities();
+        capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false);
+        capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, !isRoaming);
+        for (int nc : oemNetCapabilities) {
+            capabilities.setCapability(nc, true);
+        }
+        capabilities.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+        return new NetworkState(TYPE_MOBILE, prop, capabilities, MOBILE_NETWORK, subscriberId);
     }
 
     private long getElapsedRealtime() {
diff --git a/tests/net/jni/Android.bp b/tests/net/jni/Android.bp
index 9225ffb..22a04f5 100644
--- a/tests/net/jni/Android.bp
+++ b/tests/net/jni/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_library_shared {
     name: "libnetworkstatsfactorytestjni",
 
diff --git a/tests/net/smoketest/Android.bp b/tests/net/smoketest/Android.bp
index 84ae2b5..1535f3d 100644
--- a/tests/net/smoketest/Android.bp
+++ b/tests/net/smoketest/Android.bp
@@ -9,6 +9,15 @@
 //
 // TODO: remove this hack when there is a better solution for jni_libs that includes
 // dependent libraries.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworksNetSmokeTests",
     defaults: ["FrameworksNetTests-jni-defaults"],
@@ -19,4 +28,4 @@
         "mockito-target-minus-junit4",
         "services.core",
     ],
-}
\ No newline at end of file
+}
diff --git a/tests/notification/Android.bp b/tests/notification/Android.bp
index f05edaf..1c1b5a2 100644
--- a/tests/notification/Android.bp
+++ b/tests/notification/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "NotificationTests",
     // Include all test java files.
diff --git a/tests/permission/Android.bp b/tests/permission/Android.bp
index bd07009..d06809b 100644
--- a/tests/permission/Android.bp
+++ b/tests/permission/Android.bp
@@ -1,12 +1,26 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworkPermissionTests",
     // Include all test java files.
     srcs: ["src/**/*.java"],
     libs: [
         "android.test.runner",
-        "telephony-common",
         "android.test.base",
+        "telephony-common",
     ],
-    static_libs: ["junit"],
+    static_libs: [
+        "androidx.test.runner",
+        "junit",
+        "platform-test-annotations",
+    ],
     platform_apis: true,
+    test_suites: ["device-tests"],
 }
diff --git a/tests/permission/AndroidManifest.xml b/tests/permission/AndroidManifest.xml
index b19bf00..9ff5fb3 100644
--- a/tests/permission/AndroidManifest.xml
+++ b/tests/permission/AndroidManifest.xml
@@ -24,9 +24,10 @@
 
     <!--
     The test declared in this instrumentation can be run via this command
-    "adb shell am instrument -w com.android.framework.permission.tests/android.test.InstrumentationTestRunner"
+    $ adb shell am instrument \
+       -w com.android.framework.permission.tests/androidx.test.runner.AndroidJUnitRunner
     -->
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.framework.permission.tests"
                      android:label="Tests for private API framework permissions"/>
 
diff --git a/tests/permission/src/com/android/framework/permission/tests/VibratorManagerServicePermissionTest.java b/tests/permission/src/com/android/framework/permission/tests/VibratorManagerServicePermissionTest.java
index 0f920b3..fe68543 100644
--- a/tests/permission/src/com/android/framework/permission/tests/VibratorManagerServicePermissionTest.java
+++ b/tests/permission/src/com/android/framework/permission/tests/VibratorManagerServicePermissionTest.java
@@ -16,69 +16,135 @@
 
 package com.android.framework.permission.tests;
 
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static junit.framework.Assert.fail;
+
+import android.Manifest;
 import android.content.Context;
 import android.os.Binder;
 import android.os.CombinedVibrationEffect;
-import android.os.IBinder;
 import android.os.IVibratorManagerService;
+import android.os.IVibratorStateListener;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.VibrationAttributes;
 import android.os.VibrationEffect;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.platform.test.annotations.Presubmit;
 
-import junit.framework.TestCase;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
 
 
 /**
  * Verify that Hardware apis cannot be called without required permissions.
  */
-@SmallTest
-public class VibratorManagerServicePermissionTest extends TestCase {
+@Presubmit
+@RunWith(JUnit4.class)
+public class VibratorManagerServicePermissionTest {
+
+    private static final String PACKAGE_NAME = "com.android.framework.permission.tests";
+    private static final CombinedVibrationEffect EFFECT =
+            CombinedVibrationEffect.createSynced(
+                    VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE));
+    private static final VibrationAttributes ATTRS = new VibrationAttributes.Builder()
+            .setUsage(VibrationAttributes.USAGE_ALARM)
+            .build();
+
+    @Rule
+    public ExpectedException exceptionRule = ExpectedException.none();
 
     private IVibratorManagerService mVibratorService;
 
-    @Override
-    protected void setUp() throws Exception {
+    @Before
+    public void setUp() throws Exception {
         mVibratorService = IVibratorManagerService.Stub.asInterface(
                 ServiceManager.getService(Context.VIBRATOR_MANAGER_SERVICE));
     }
 
-    /**
-     * Test that calling {@link android.os.IVibratorManagerService#vibrate(int, String,
-     * CombinedVibrationEffect, VibrationAttributes, String, IBinder)} requires permissions.
-     * <p>Tests permission:
-     * {@link android.Manifest.permission#VIBRATE}
-     */
-    public void testVibrate() throws RemoteException {
-        try {
-            CombinedVibrationEffect effect =
-                    CombinedVibrationEffect.createSynced(
-                            VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE));
-            VibrationAttributes attrs = new VibrationAttributes.Builder()
-                    .setUsage(VibrationAttributes.USAGE_ALARM)
-                    .build();
-            mVibratorService.vibrate(Process.myUid(), null, effect, attrs,
-                    "testVibrate", new Binder());
-            fail("vibrate did not throw SecurityException as expected");
-        } catch (SecurityException e) {
-            // expected
-        }
+    @After
+    public void cleanUp() {
+        getInstrumentation().getUiAutomation().dropShellPermissionIdentity();
     }
 
-    /**
-     * Test that calling {@link android.os.IVibratorManagerService#cancelVibrate(IBinder)} requires
-     * permissions.
-     * <p>Tests permission:
-     * {@link android.Manifest.permission#VIBRATE}
-     */
-    public void testCancelVibrate() throws RemoteException {
-        try {
-            mVibratorService.cancelVibrate(new Binder());
-            fail("cancelVibrate did not throw SecurityException as expected");
-        } catch (SecurityException e) {
-            // expected
-        }
+    @Test
+    public void testIsVibratingFails() throws RemoteException {
+        expectSecurityException("ACCESS_VIBRATOR_STATE");
+        mVibratorService.isVibrating(1);
+    }
+
+    @Test
+    public void testRegisterVibratorStateListenerFails() throws RemoteException {
+        expectSecurityException("ACCESS_VIBRATOR_STATE");
+        IVibratorStateListener listener = new IVibratorStateListener.Stub() {
+            @Override
+            public void onVibrating(boolean vibrating) {
+                fail("Listener callback was not expected.");
+            }
+        };
+        mVibratorService.registerVibratorStateListener(1, listener);
+    }
+
+    @Test
+    public void testUnregisterVibratorStateListenerFails() throws RemoteException {
+        expectSecurityException("ACCESS_VIBRATOR_STATE");
+        mVibratorService.unregisterVibratorStateListener(1, null);
+    }
+
+    @Test
+    public void testSetAlwaysOnEffectFails() throws RemoteException {
+        expectSecurityException("VIBRATE_ALWAYS_ON");
+        mVibratorService.setAlwaysOnEffect(Process.myUid(), PACKAGE_NAME, 1, EFFECT, ATTRS);
+    }
+
+    @Test
+    public void testVibrateWithoutPermissionFails() throws RemoteException {
+        expectSecurityException("VIBRATE");
+        mVibratorService.vibrate(Process.myUid(), PACKAGE_NAME, EFFECT, ATTRS, "testVibrate",
+                new Binder());
+    }
+
+    @Test
+    public void testVibrateWithVibratePermissionAndSameProcessUidIsAllowed()
+            throws RemoteException {
+        getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
+                Manifest.permission.VIBRATE);
+        mVibratorService.vibrate(Process.myUid(), PACKAGE_NAME, EFFECT, ATTRS, "testVibrate",
+                new Binder());
+    }
+
+    @Test
+    public void testVibrateWithVibratePermissionAndDifferentUidsFails() throws RemoteException {
+        expectSecurityException("UPDATE_APP_OPS_STATS");
+        getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
+                Manifest.permission.VIBRATE);
+        mVibratorService.vibrate(Process.SYSTEM_UID, "android", EFFECT, ATTRS, "testVibrate",
+                new Binder());
+    }
+
+    @Test
+    public void testVibrateWithAllPermissionsAndDifferentUidsIsAllowed() throws RemoteException {
+        getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
+                Manifest.permission.VIBRATE,
+                Manifest.permission.UPDATE_APP_OPS_STATS);
+        mVibratorService.vibrate(Process.SYSTEM_UID, "android", EFFECT, ATTRS, "testVibrate",
+                new Binder());
+    }
+
+    @Test
+    public void testCancelVibrateFails() throws RemoteException {
+        expectSecurityException("VIBRATE");
+        mVibratorService.cancelVibrate(new Binder());
+    }
+
+    private void expectSecurityException(String expectedPermission) {
+        exceptionRule.expect(SecurityException.class);
+        exceptionRule.expectMessage("permission." + expectedPermission);
     }
 }
diff --git a/tests/privapp-permissions/Android.bp b/tests/privapp-permissions/Android.bp
index b661850..082b08dea 100644
--- a/tests/privapp-permissions/Android.bp
+++ b/tests/privapp-permissions/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_app {
     name: "PrivAppPermissionTest",
     sdk_version: "current",
diff --git a/tests/testables/Android.bp b/tests/testables/Android.bp
index eb6811c..c0e3d63 100644
--- a/tests/testables/Android.bp
+++ b/tests/testables/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library {
     name: "testables",
     srcs: ["src/**/*.java"],
diff --git a/tests/testables/tests/Android.bp b/tests/testables/tests/Android.bp
index e1a58be..ba323d3 100644
--- a/tests/testables/tests/Android.bp
+++ b/tests/testables/tests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "TestablesTests",
     platform_apis: true,
diff --git a/tests/utils/StubIME/Android.bp b/tests/utils/StubIME/Android.bp
index 668c92c..d86068c 100644
--- a/tests/utils/StubIME/Android.bp
+++ b/tests/utils/StubIME/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "StubIME",
     srcs: ["src/**/*.java"],
diff --git a/tests/utils/hostutils/Android.bp b/tests/utils/hostutils/Android.bp
index c9ad702..05f3c74 100644
--- a/tests/utils/hostutils/Android.bp
+++ b/tests/utils/hostutils/Android.bp
@@ -13,6 +13,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library_host {
     name: "frameworks-base-hostutils",
 
diff --git a/tests/utils/testutils/Android.bp b/tests/utils/testutils/Android.bp
index a6625ab..af9786b 100644
--- a/tests/utils/testutils/Android.bp
+++ b/tests/utils/testutils/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library {
     name: "frameworks-base-testutils",
 
diff --git a/tests/vcn/Android.bp b/tests/vcn/Android.bp
index 1dedc19..41f73cd 100644
--- a/tests/vcn/Android.bp
+++ b/tests/vcn/Android.bp
@@ -2,6 +2,15 @@
 // Build FrameworksVcnTests package
 //########################################################################
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworksVcnTests",
     srcs: [
diff --git a/tests/vcn/java/android/net/vcn/VcnManagerTest.java b/tests/vcn/java/android/net/vcn/VcnManagerTest.java
index 1a90fc3..66590c9 100644
--- a/tests/vcn/java/android/net/vcn/VcnManagerTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnManagerTest.java
@@ -16,12 +16,15 @@
 
 package android.net.vcn;
 
+import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
+
 import static androidx.test.InstrumentationRegistry.getContext;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.notNull;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -33,6 +36,7 @@
 import android.net.LinkProperties;
 import android.net.NetworkCapabilities;
 import android.net.vcn.VcnManager.VcnStatusCallback;
+import android.net.vcn.VcnManager.VcnStatusCallbackBinder;
 import android.net.vcn.VcnManager.VcnUnderlyingNetworkPolicyListener;
 import android.os.ParcelUuid;
 
@@ -40,11 +44,15 @@
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 
+import java.net.UnknownHostException;
 import java.util.UUID;
 import java.util.concurrent.Executor;
 
 public class VcnManagerTest {
     private static final ParcelUuid SUB_GROUP = new ParcelUuid(new UUID(0, 0));
+    private static final int[] UNDERLYING_NETWORK_CAPABILITIES = {
+        NetworkCapabilities.NET_CAPABILITY_IMS, NetworkCapabilities.NET_CAPABILITY_INTERNET
+    };
     private static final Executor INLINE_EXECUTOR = Runnable::run;
 
     private IVcnManagementService mMockVcnManagementService;
@@ -144,14 +152,8 @@
     public void testRegisterVcnStatusCallback() throws Exception {
         mVcnManager.registerVcnStatusCallback(SUB_GROUP, INLINE_EXECUTOR, mMockStatusCallback);
 
-        ArgumentCaptor<IVcnStatusCallback> captor =
-                ArgumentCaptor.forClass(IVcnStatusCallback.class);
         verify(mMockVcnManagementService)
-                .registerVcnStatusCallback(eq(SUB_GROUP), captor.capture(), any());
-
-        IVcnStatusCallback callbackWrapper = captor.getValue();
-        callbackWrapper.onEnteredSafeMode();
-        verify(mMockStatusCallback).onEnteredSafeMode();
+                .registerVcnStatusCallback(eq(SUB_GROUP), notNull(), any());
     }
 
     @Test(expected = IllegalStateException.class)
@@ -195,4 +197,27 @@
     public void testUnregisterNullVcnStatusCallback() throws Exception {
         mVcnManager.unregisterVcnStatusCallback(null);
     }
+
+    @Test
+    public void testVcnStatusCallbackBinder() throws Exception {
+        IVcnStatusCallback cbBinder =
+                new VcnStatusCallbackBinder(INLINE_EXECUTOR, mMockStatusCallback);
+
+        cbBinder.onEnteredSafeMode();
+        verify(mMockStatusCallback).onEnteredSafeMode();
+
+        cbBinder.onVcnStatusChanged(VCN_STATUS_CODE_ACTIVE);
+        verify(mMockStatusCallback).onVcnStatusChanged(VCN_STATUS_CODE_ACTIVE);
+
+        cbBinder.onGatewayConnectionError(
+                UNDERLYING_NETWORK_CAPABILITIES,
+                VcnManager.VCN_ERROR_CODE_NETWORK_ERROR,
+                UnknownHostException.class.getName(),
+                "exception_message");
+        verify(mMockStatusCallback)
+                .onGatewayConnectionError(
+                        eq(UNDERLYING_NETWORK_CAPABILITIES),
+                        eq(VcnManager.VCN_ERROR_CODE_NETWORK_ERROR),
+                        any(UnknownHostException.class));
+    }
 }
diff --git a/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkPolicyTest.java b/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkPolicyTest.java
index 3ba0a1f..a674425 100644
--- a/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkPolicyTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkPolicyTest.java
@@ -46,6 +46,6 @@
 
     @Test
     public void testParcelUnparcel() {
-        assertParcelSane(SAMPLE_NETWORK_POLICY, 2);
+        assertParcelSane(SAMPLE_NETWORK_POLICY, 1);
     }
 }
diff --git a/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkSpecifierTest.java b/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkSpecifierTest.java
new file mode 100644
index 0000000..2110d6e
--- /dev/null
+++ b/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkSpecifierTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.vcn;
+
+import static com.android.testutils.ParcelUtils.assertParcelSane;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.net.TelephonyNetworkSpecifier;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class VcnUnderlyingNetworkSpecifierTest {
+    private static final int[] TEST_SUB_IDS = new int[] {1, 2, 3, 5};
+
+    @Test
+    public void testGetSubIds() {
+        final VcnUnderlyingNetworkSpecifier specifier =
+                new VcnUnderlyingNetworkSpecifier(TEST_SUB_IDS);
+
+        assertEquals(TEST_SUB_IDS, specifier.getSubIds());
+    }
+
+    @Test
+    public void testParceling() {
+        final VcnUnderlyingNetworkSpecifier specifier =
+                new VcnUnderlyingNetworkSpecifier(TEST_SUB_IDS);
+        assertParcelSane(specifier, 1);
+    }
+
+    @Test
+    public void testCanBeSatisfiedByTelephonyNetworkSpecifier() {
+        final TelephonyNetworkSpecifier telSpecifier =
+                new TelephonyNetworkSpecifier(TEST_SUB_IDS[0]);
+
+        final VcnUnderlyingNetworkSpecifier specifier =
+                new VcnUnderlyingNetworkSpecifier(TEST_SUB_IDS);
+        assertTrue(specifier.canBeSatisfiedBy(telSpecifier));
+    }
+}
diff --git a/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeTrafficSelectorUtilsTest.java b/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeTrafficSelectorUtilsTest.java
new file mode 100644
index 0000000..28cf38a
--- /dev/null
+++ b/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeTrafficSelectorUtilsTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.vcn.persistablebundleutils;
+
+import static org.junit.Assert.assertEquals;
+
+import android.net.InetAddresses;
+import android.net.ipsec.ike.IkeTrafficSelector;
+import android.os.PersistableBundle;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.net.InetAddress;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class IkeTrafficSelectorUtilsTest {
+    private static final int START_PORT = 16;
+    private static final int END_PORT = 65520;
+
+    private static final InetAddress IPV4_START_ADDRESS =
+            InetAddresses.parseNumericAddress("192.0.2.100");
+    private static final InetAddress IPV4_END_ADDRESS =
+            InetAddresses.parseNumericAddress("192.0.2.101");
+
+    private static final InetAddress IPV6_START_ADDRESS =
+            InetAddresses.parseNumericAddress("2001:db8:2::100");
+    private static final InetAddress IPV6_END_ADDRESS =
+            InetAddresses.parseNumericAddress("2001:db8:2::101");
+
+    private static void verifyPersistableBundleEncodeDecodeIsLossless(IkeTrafficSelector ts) {
+        final PersistableBundle bundle = IkeTrafficSelectorUtils.toPersistableBundle(ts);
+        final IkeTrafficSelector resultTs = IkeTrafficSelectorUtils.fromPersistableBundle(bundle);
+        assertEquals(ts, resultTs);
+    }
+
+    @Test
+    public void testPersistableBundleEncodeDecodeIsLosslessIpv4Ts() throws Exception {
+        verifyPersistableBundleEncodeDecodeIsLossless(
+                new IkeTrafficSelector(START_PORT, END_PORT, IPV4_START_ADDRESS, IPV4_END_ADDRESS));
+    }
+
+    @Test
+    public void testPersistableBundleEncodeDecodeIsLosslessIpv6Ts() throws Exception {
+        verifyPersistableBundleEncodeDecodeIsLossless(
+                new IkeTrafficSelector(START_PORT, END_PORT, IPV6_START_ADDRESS, IPV6_END_ADDRESS));
+    }
+}
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index 124ec30..9b500a7 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -43,7 +43,6 @@
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -59,6 +58,7 @@
 import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
 import android.net.vcn.VcnConfig;
 import android.net.vcn.VcnConfigTest;
+import android.net.vcn.VcnManager;
 import android.net.vcn.VcnUnderlyingNetworkPolicy;
 import android.net.wifi.WifiInfo;
 import android.os.IBinder;
@@ -75,7 +75,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.util.LocationPermissionChecker;
-import com.android.server.VcnManagementService.VcnSafeModeCallback;
+import com.android.server.VcnManagementService.VcnCallback;
 import com.android.server.VcnManagementService.VcnStatusCallbackInfo;
 import com.android.server.vcn.TelephonySubscriptionTracker;
 import com.android.server.vcn.Vcn;
@@ -156,8 +156,8 @@
     private final LocationPermissionChecker mLocationPermissionChecker =
             mock(LocationPermissionChecker.class);
 
-    private final ArgumentCaptor<VcnSafeModeCallback> mSafeModeCallbackCaptor =
-            ArgumentCaptor.forClass(VcnSafeModeCallback.class);
+    private final ArgumentCaptor<VcnCallback> mVcnCallbackCaptor =
+            ArgumentCaptor.forClass(VcnCallback.class);
 
     private final VcnManagementService mVcnMgmtSvc;
 
@@ -721,7 +721,7 @@
         verify(mMockPolicyListener).onPolicyChanged();
     }
 
-    private void verifyVcnSafeModeCallback(
+    private void verifyVcnCallback(
             @NonNull ParcelUuid subGroup, @NonNull TelephonySubscriptionSnapshot snapshot)
             throws Exception {
         verify(mMockDeps)
@@ -730,22 +730,22 @@
                         eq(subGroup),
                         eq(TEST_VCN_CONFIG),
                         eq(snapshot),
-                        mSafeModeCallbackCaptor.capture());
+                        mVcnCallbackCaptor.capture());
 
         mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
 
-        VcnSafeModeCallback safeModeCallback = mSafeModeCallbackCaptor.getValue();
-        safeModeCallback.onEnteredSafeMode();
+        VcnCallback vcnCallback = mVcnCallbackCaptor.getValue();
+        vcnCallback.onEnteredSafeMode();
 
         verify(mMockPolicyListener).onPolicyChanged();
     }
 
     @Test
-    public void testVcnSafeModeCallbackOnEnteredSafeMode() throws Exception {
+    public void testVcnCallbackOnEnteredSafeMode() throws Exception {
         TelephonySubscriptionSnapshot snapshot =
                 triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1));
 
-        verifyVcnSafeModeCallback(TEST_UUID_1, snapshot);
+        verifyVcnCallback(TEST_UUID_1, snapshot);
     }
 
     private void triggerVcnStatusCallbackOnEnteredSafeMode(
@@ -771,7 +771,7 @@
         // Trigger systemReady() to set up LocationPermissionChecker
         mVcnMgmtSvc.systemReady();
 
-        verifyVcnSafeModeCallback(subGroup, snapshot);
+        verifyVcnCallback(subGroup, snapshot);
     }
 
     @Test
@@ -783,7 +783,7 @@
                 true /* hasPermissionsforSubGroup */,
                 true /* hasLocationPermission */);
 
-        verify(mMockStatusCallback, times(1)).onEnteredSafeMode();
+        verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_SAFE_MODE);
     }
 
     @Test
@@ -795,7 +795,8 @@
                 false /* hasPermissionsforSubGroup */,
                 true /* hasLocationPermission */);
 
-        verify(mMockStatusCallback, never()).onEnteredSafeMode();
+        verify(mMockStatusCallback, never())
+                .onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_SAFE_MODE);
     }
 
     @Test
@@ -807,7 +808,8 @@
                 true /* hasPermissionsforSubGroup */,
                 false /* hasLocationPermission */);
 
-        verify(mMockStatusCallback, never()).onEnteredSafeMode();
+        verify(mMockStatusCallback, never())
+                .onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_SAFE_MODE);
     }
 
     @Test
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
index b62a0b8..69c21b9 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -20,6 +20,9 @@
 import static android.net.IpSecManager.DIRECTION_OUT;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.vcn.VcnManager.VCN_ERROR_CODE_CONFIG_ERROR;
+import static android.net.vcn.VcnManager.VCN_ERROR_CODE_INTERNAL_ERROR;
+import static android.net.vcn.VcnManager.VCN_ERROR_CODE_NETWORK_ERROR;
 
 import static com.android.server.vcn.VcnGatewayConnection.VcnChildSessionConfiguration;
 import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession;
@@ -39,6 +42,11 @@
 import android.net.LinkProperties;
 import android.net.NetworkAgent;
 import android.net.NetworkCapabilities;
+import android.net.ipsec.ike.exceptions.AuthenticationFailedException;
+import android.net.ipsec.ike.exceptions.IkeException;
+import android.net.ipsec.ike.exceptions.IkeInternalException;
+import android.net.ipsec.ike.exceptions.TemporaryFailureException;
+import android.net.vcn.VcnManager.VcnErrorCode;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -48,6 +56,8 @@
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 
+import java.io.IOException;
+import java.net.UnknownHostException;
 import java.util.Collections;
 
 /** Tests for VcnGatewayConnection.ConnectedState */
@@ -208,6 +218,25 @@
 
         // Since network never validated, verify mSafeModeTimeoutAlarm not canceled
         verifyNoMoreInteractions(mSafeModeTimeoutAlarm);
+
+        // The child session was closed without exception, so verify that the GatewayStatusCallback
+        // was not notified
+        verifyNoMoreInteractions(mGatewayStatusCallback);
+    }
+
+    @Test
+    public void testChildSessionClosedExceptionallyNotifiesGatewayStatusCallback()
+            throws Exception {
+        final IkeInternalException exception = new IkeInternalException(mock(IOException.class));
+        getChildSessionCallback().onClosedExceptionally(exception);
+        mTestLooper.dispatchAll();
+
+        verify(mGatewayStatusCallback)
+                .onGatewayConnectionError(
+                        eq(mConfig.getRequiredUnderlyingCapabilities()),
+                        eq(VCN_ERROR_CODE_INTERNAL_ERROR),
+                        any(),
+                        any());
     }
 
     @Test
@@ -223,5 +252,42 @@
 
         // Since network never validated, verify mSafeModeTimeoutAlarm not canceled
         verifyNoMoreInteractions(mSafeModeTimeoutAlarm);
+
+        // IkeSession closed with no error, so verify that the GatewayStatusCallback was not
+        // notified
+        verifyNoMoreInteractions(mGatewayStatusCallback);
+    }
+
+    private void verifyIkeSessionClosedExceptionalltyNotifiesStatusCallback(
+            IkeException cause, @VcnErrorCode int expectedErrorType) {
+        getIkeSessionCallback().onClosedExceptionally(cause);
+        mTestLooper.dispatchAll();
+
+        verify(mIkeSession).close();
+
+        verify(mGatewayStatusCallback)
+                .onGatewayConnectionError(
+                        eq(mConfig.getRequiredUnderlyingCapabilities()),
+                        eq(expectedErrorType),
+                        any(),
+                        any());
+    }
+
+    @Test
+    public void testIkeSessionClosedExceptionallyAuthenticationFailure() throws Exception {
+        verifyIkeSessionClosedExceptionalltyNotifiesStatusCallback(
+                new AuthenticationFailedException("vcn test"), VCN_ERROR_CODE_CONFIG_ERROR);
+    }
+
+    @Test
+    public void testIkeSessionClosedExceptionallyDnsFailure() throws Exception {
+        verifyIkeSessionClosedExceptionalltyNotifiesStatusCallback(
+                new IkeInternalException(new UnknownHostException()), VCN_ERROR_CODE_NETWORK_ERROR);
+    }
+
+    @Test
+    public void testIkeSessionClosedExceptionallyInternalFailure() throws Exception {
+        verifyIkeSessionClosedExceptionalltyNotifiesStatusCallback(
+                new TemporaryFailureException("vcn test"), VCN_ERROR_CODE_INTERNAL_ERROR);
     }
 }
diff --git a/tests/vcn/java/com/android/server/vcn/VcnTest.java b/tests/vcn/java/com/android/server/vcn/VcnTest.java
index 8e142c0..9d33682 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnTest.java
@@ -34,7 +34,7 @@
 import android.os.ParcelUuid;
 import android.os.test.TestLooper;
 
-import com.android.server.VcnManagementService.VcnSafeModeCallback;
+import com.android.server.VcnManagementService.VcnCallback;
 import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
 import com.android.server.vcn.Vcn.VcnGatewayStatusCallback;
 import com.android.server.vcn.VcnNetworkProvider.NetworkRequestListener;
@@ -56,7 +56,7 @@
     private VcnContext mVcnContext;
     private TelephonySubscriptionSnapshot mSubscriptionSnapshot;
     private VcnNetworkProvider mVcnNetworkProvider;
-    private VcnSafeModeCallback mVcnSafeModeCallback;
+    private VcnCallback mVcnCallback;
     private Vcn.Dependencies mDeps;
 
     private ArgumentCaptor<VcnGatewayStatusCallback> mGatewayStatusCallbackCaptor;
@@ -72,7 +72,7 @@
         mVcnContext = mock(VcnContext.class);
         mSubscriptionSnapshot = mock(TelephonySubscriptionSnapshot.class);
         mVcnNetworkProvider = mock(VcnNetworkProvider.class);
-        mVcnSafeModeCallback = mock(VcnSafeModeCallback.class);
+        mVcnCallback = mock(VcnCallback.class);
         mDeps = mock(Vcn.Dependencies.class);
 
         mTestLooper = new TestLooper();
@@ -104,7 +104,7 @@
                         TEST_SUB_GROUP,
                         mConfig,
                         mSubscriptionSnapshot,
-                        mVcnSafeModeCallback,
+                        mVcnCallback,
                         mDeps);
     }
 
@@ -179,6 +179,6 @@
             verify(gatewayConnection).teardownAsynchronously();
         }
         verify(mVcnNetworkProvider).unregisterListener(requestListener);
-        verify(mVcnSafeModeCallback).onEnteredSafeMode();
+        verify(mVcnCallback).onEnteredSafeMode();
     }
 }
diff --git a/tools/aapt/Android.bp b/tools/aapt/Android.bp
index a594e5b..c75ba71 100644
--- a/tools/aapt/Android.bp
+++ b/tools/aapt/Android.bp
@@ -19,6 +19,23 @@
 // targets here.
 // ==========================================================
 
+package {
+    default_applicable_licenses: ["frameworks_base_tools_aapt_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_base_tools_aapt_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_defaults {
     name: "aapt_defaults",
 
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index 46ae2ec..df727e0 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 toolSources = [
     "cmd/Command.cpp",
     "cmd/Compile.cpp",
diff --git a/tools/aapt2/integration-tests/AutoVersionTest/Android.bp b/tools/aapt2/integration-tests/AutoVersionTest/Android.bp
index 79fb573..bfd3508 100644
--- a/tools/aapt2/integration-tests/AutoVersionTest/Android.bp
+++ b/tools/aapt2/integration-tests/AutoVersionTest/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "AaptAutoVersionTest",
     sdk_version: "current",
diff --git a/tools/aapt2/integration-tests/BasicTest/Android.bp b/tools/aapt2/integration-tests/BasicTest/Android.bp
index a94a01f..7db9d26 100644
--- a/tools/aapt2/integration-tests/BasicTest/Android.bp
+++ b/tools/aapt2/integration-tests/BasicTest/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "AaptBasicTest",
     sdk_version: "current",
diff --git a/tools/aapt2/integration-tests/MergeOnlyTest/LeafLib/Android.mk b/tools/aapt2/integration-tests/MergeOnlyTest/LeafLib/Android.mk
index 7bf8cf8..c084849 100644
--- a/tools/aapt2/integration-tests/MergeOnlyTest/LeafLib/Android.mk
+++ b/tools/aapt2/integration-tests/MergeOnlyTest/LeafLib/Android.mk
@@ -20,9 +20,12 @@
 LOCAL_USE_AAPT2 := true
 LOCAL_AAPT_NAMESPACES := true
 LOCAL_MODULE := AaptTestMergeOnly_LeafLib
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE
 LOCAL_SDK_VERSION := current
 LOCAL_MODULE_TAGS := tests
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 LOCAL_MIN_SDK_VERSION := 21
 LOCAL_AAPT_FLAGS := --merge-only
-include $(BUILD_STATIC_JAVA_LIBRARY)
\ No newline at end of file
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tools/aapt2/integration-tests/MergeOnlyTest/LocalLib/Android.mk b/tools/aapt2/integration-tests/MergeOnlyTest/LocalLib/Android.mk
index ba781c5..699ad79 100644
--- a/tools/aapt2/integration-tests/MergeOnlyTest/LocalLib/Android.mk
+++ b/tools/aapt2/integration-tests/MergeOnlyTest/LocalLib/Android.mk
@@ -20,9 +20,12 @@
 LOCAL_USE_AAPT2 := true
 LOCAL_AAPT_NAMESPACES := true
 LOCAL_MODULE := AaptTestMergeOnly_LocalLib
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE
 LOCAL_SDK_VERSION := current
 LOCAL_MODULE_TAGS := tests
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 LOCAL_MIN_SDK_VERSION := 21
 LOCAL_AAPT_FLAGS := --merge-only
-include $(BUILD_STATIC_JAVA_LIBRARY)
\ No newline at end of file
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk
index c723d90..dd41702 100644
--- a/tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk
+++ b/tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk
@@ -20,6 +20,9 @@
 LOCAL_USE_AAPT2 := true
 LOCAL_AAPT_NAMESPACES := true
 LOCAL_MODULE := AaptTestNamespace_LibOne
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE
 LOCAL_SDK_VERSION := current
 LOCAL_MODULE_TAGS := tests
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
diff --git a/tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk
index 90a7f62..0d11bcb 100644
--- a/tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk
+++ b/tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk
@@ -20,6 +20,9 @@
 LOCAL_USE_AAPT2 := true
 LOCAL_AAPT_NAMESPACES := true
 LOCAL_MODULE := AaptTestNamespace_LibTwo
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE
 LOCAL_SDK_VERSION := current
 LOCAL_MODULE_TAGS := tests
 LOCAL_SRC_FILES := $(call all-java-files-under,src)
diff --git a/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp b/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp
index 9aadff3..80404ee 100644
--- a/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp
+++ b/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
 
     name: "AaptTestStaticLib_App",
diff --git a/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp b/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp
index 4c81813..a84da43 100644
--- a/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp
+++ b/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "AaptTestStaticLib_LibOne",
     sdk_version: "current",
diff --git a/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp
index 7c4f7ed..d386c3a 100644
--- a/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp
+++ b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "AaptTestStaticLib_LibTwo",
     sdk_version: "current",
diff --git a/tools/aapt2/integration-tests/SymlinkTest/Android.bp b/tools/aapt2/integration-tests/SymlinkTest/Android.bp
index 68e6148..1e8cf86 100644
--- a/tools/aapt2/integration-tests/SymlinkTest/Android.bp
+++ b/tools/aapt2/integration-tests/SymlinkTest/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "AaptSymlinkTest",
     sdk_version: "current",
diff --git a/tools/bit/Android.bp b/tools/bit/Android.bp
index a806271..f6aa0fb 100644
--- a/tools/bit/Android.bp
+++ b/tools/bit/Android.bp
@@ -17,6 +17,15 @@
 // ==========================================================
 // Build the host executable: bit
 // ==========================================================
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_binary_host {
     name: "bit",
 
diff --git a/tools/codegen/Android.bp b/tools/codegen/Android.bp
index 677bee2..e53ba3e 100644
--- a/tools/codegen/Android.bp
+++ b/tools/codegen/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_binary_host {
     name: "codegen_cli",
     manifest: "manifest.txt",
diff --git a/tools/dump-coverage/Android.bp b/tools/dump-coverage/Android.bp
index 94356eb..f381773 100644
--- a/tools/dump-coverage/Android.bp
+++ b/tools/dump-coverage/Android.bp
@@ -15,6 +15,15 @@
 //
 
 // Build variants {target,host} x {32,64}
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_library {
     name: "libdumpcoverage",
     srcs: ["dump_coverage.cc"],
diff --git a/tools/fonts/fontchain_linter.py b/tools/fonts/fontchain_linter.py
index f0b7595..e775e1a 100755
--- a/tools/fonts/fontchain_linter.py
+++ b/tools/fonts/fontchain_linter.py
@@ -665,6 +665,51 @@
             assert_font_supports_none_of_chars(record.font, cjk_punctuation, name)
 
 
+def getPostScriptName(font):
+  ttf = open_font(font)
+  nameTable = ttf['name']
+  for name in nameTable.names:
+    if name.nameID == 6 and name.platformID == 3 and name.platEncID == 1 and name.langID == 0x0409:
+      return str(name)
+
+
+def getSuffix(font):
+  file_path, index = font
+  with open(path.join(_fonts_dir, file_path), 'rb') as f:
+    tag = f.read(4)
+    isCollection = tag == b'ttcf'
+
+  ttf = open_font(font)
+  isType1 = ('CFF ' in ttf or 'CFF2' in ttf)
+
+  if isType1:
+    if isCollection:
+      return '.otc'
+    else:
+      return '.otf'
+  else:
+    if isCollection:
+      return '.ttc'
+    else:
+      return '.ttf'
+
+
+def check_canonical_name():
+  for record in _all_fonts:
+    file_name, index = record.font
+
+    if index and index != 0:
+      continue
+
+    psName = getPostScriptName(record.font)
+    assert psName, 'PostScript must be defined'
+
+    suffix = getSuffix(record.font)
+    canonicalName = '%s%s' % (psName, suffix)
+
+    assert file_name == canonicalName, (
+        '%s is not a canonical name. Must be %s' % (file_name, canonicalName))
+
 def main():
     global _fonts_dir
     target_out = sys.argv[1]
@@ -682,6 +727,8 @@
 
     check_cjk_punctuation()
 
+    check_canonical_name()
+
     check_emoji = sys.argv[2]
     if check_emoji == 'true':
         ucd_path = sys.argv[3]
diff --git a/tools/incident_report/Android.bp b/tools/incident_report/Android.bp
index f2d0d0f..fe519c7 100644
--- a/tools/incident_report/Android.bp
+++ b/tools/incident_report/Android.bp
@@ -17,6 +17,15 @@
 // ==========================================================
 // Build the host executable: incident_report
 // ==========================================================
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_binary_host {
     name: "incident_report",
 
diff --git a/tools/incident_section_gen/Android.bp b/tools/incident_section_gen/Android.bp
index 0c7797e..8227b60 100644
--- a/tools/incident_section_gen/Android.bp
+++ b/tools/incident_section_gen/Android.bp
@@ -17,6 +17,15 @@
 // ==========================================================
 // Build the host executable: incident-section-gen
 // ==========================================================
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_binary_host {
     name: "incident-section-gen",
     cflags: [
diff --git a/tools/lock_agent/Android.bp b/tools/lock_agent/Android.bp
index 7b2ca9a..cabe139 100644
--- a/tools/lock_agent/Android.bp
+++ b/tools/lock_agent/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_library {
     name: "liblockagent",
     host_supported: false,
diff --git a/tools/locked_region_code_injection/Android.bp b/tools/locked_region_code_injection/Android.bp
index 5f81a2e..98c0e69 100644
--- a/tools/locked_region_code_injection/Android.bp
+++ b/tools/locked_region_code_injection/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_binary_host {
     name: "lockedregioncodeinjection",
     manifest: "manifest.txt",
diff --git a/tools/obbtool/Android.bp b/tools/obbtool/Android.bp
index f879658..1c50d18 100644
--- a/tools/obbtool/Android.bp
+++ b/tools/obbtool/Android.bp
@@ -4,6 +4,15 @@
 // Opaque Binary Blob (OBB) Tool
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_binary_host {
     name: "obbtool",
 
diff --git a/tools/powermodel/Android.bp b/tools/powermodel/Android.bp
index f597aab..35c1356 100644
--- a/tools/powermodel/Android.bp
+++ b/tools/powermodel/Android.bp
@@ -1,4 +1,13 @@
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library_host {
     name: "powermodel",
     srcs: [
@@ -23,4 +32,3 @@
         "mockito",
     ],
 }
-
diff --git a/tools/powerstats/Android.bp b/tools/powerstats/Android.bp
index af41144..9c58daf0 100644
--- a/tools/powerstats/Android.bp
+++ b/tools/powerstats/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_binary_host {
     name: "PowerStatsServiceProtoParser",
     manifest: "PowerStatsServiceProtoParser_manifest.txt",
diff --git a/tools/preload-check/Android.bp b/tools/preload-check/Android.bp
index aaa6d76..73caac6 100644
--- a/tools/preload-check/Android.bp
+++ b/tools/preload-check/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_test_host {
     name: "PreloadCheck",
     srcs: ["src/**/*.java"],
diff --git a/tools/preload-check/device/Android.bp b/tools/preload-check/device/Android.bp
index f40d8ba..2a866c4 100644
--- a/tools/preload-check/device/Android.bp
+++ b/tools/preload-check/device/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_test_helper_library {
     name: "preload-check-device",
     host_supported: false,
diff --git a/tools/preload/Android.bp b/tools/preload/Android.bp
index 809ee47..fad015a 100644
--- a/tools/preload/Android.bp
+++ b/tools/preload/Android.bp
@@ -1,3 +1,13 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library_host {
     name: "preload",
     srcs: [
diff --git a/tools/preload/loadclass/Android.bp b/tools/preload/loadclass/Android.bp
index 6f12015..ba36061 100644
--- a/tools/preload/loadclass/Android.bp
+++ b/tools/preload/loadclass/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_test {
     name: "loadclass",
     srcs: ["**/*.java"],
diff --git a/tools/processors/intdef_mappings/Android.bp b/tools/processors/intdef_mappings/Android.bp
index e255f7c..82a5dac 100644
--- a/tools/processors/intdef_mappings/Android.bp
+++ b/tools/processors/intdef_mappings/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_plugin {
     name: "intdef-annotation-processor",
 
@@ -30,4 +39,4 @@
     ],
 
     test_suites: ["general-tests"],
-}
\ No newline at end of file
+}
diff --git a/tools/processors/staledataclass/Android.bp b/tools/processors/staledataclass/Android.bp
index 58a7d34..1e50976 100644
--- a/tools/processors/staledataclass/Android.bp
+++ b/tools/processors/staledataclass/Android.bp
@@ -1,4 +1,13 @@
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_plugin {
     name: "staledataclass-annotation-processor",
     processor_class: "android.processor.staledataclass.StaleDataclassProcessor",
diff --git a/tools/processors/view_inspector/Android.bp b/tools/processors/view_inspector/Android.bp
index 069e61f..ea9974f 100644
--- a/tools/processors/view_inspector/Android.bp
+++ b/tools/processors/view_inspector/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_plugin {
     name: "view-inspector-annotation-processor",
 
diff --git a/tools/protologtool/Android.bp b/tools/protologtool/Android.bp
index 0be80d3..039bb4e 100644
--- a/tools/protologtool/Android.bp
+++ b/tools/protologtool/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_library_host {
     name: "protologtool-lib",
     srcs: [
@@ -25,9 +34,13 @@
     srcs: [
         "tests/**/*.kt",
     ],
+    test_options: {
+        unit_test: true,
+    },
     static_libs: [
         "protologtool-lib",
         "junit",
         "mockito",
+        "objenesis",
     ],
 }
diff --git a/tools/sdkparcelables/Android.bp b/tools/sdkparcelables/Android.bp
index 00fb8aa..9d773e4 100644
--- a/tools/sdkparcelables/Android.bp
+++ b/tools/sdkparcelables/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_binary_host {
     name: "sdkparcelables",
     manifest: "manifest.txt",
diff --git a/tools/split-select/Android.bp b/tools/split-select/Android.bp
index ee822b7..c12fc6a 100644
--- a/tools/split-select/Android.bp
+++ b/tools/split-select/Android.bp
@@ -19,6 +19,15 @@
 // targets here.
 // ==========================================================
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_defaults {
     name: "split-select_defaults",
 
diff --git a/tools/streaming_proto/Android.bp b/tools/streaming_proto/Android.bp
index 1390f63..1ec83a3 100644
--- a/tools/streaming_proto/Android.bp
+++ b/tools/streaming_proto/Android.bp
@@ -17,6 +17,15 @@
 // ==========================================================
 // Build the host executable: protoc-gen-javastream
 // ==========================================================
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_defaults {
     name: "protoc-gen-stream-defaults",
     srcs: [
diff --git a/tools/validatekeymaps/Android.bp b/tools/validatekeymaps/Android.bp
index 15b8b41..0423b7a 100644
--- a/tools/validatekeymaps/Android.bp
+++ b/tools/validatekeymaps/Android.bp
@@ -4,6 +4,15 @@
 // Keymap validation tool.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 cc_binary_host {
     name: "validatekeymaps",
 
diff --git a/tools/xmlpersistence/Android.bp b/tools/xmlpersistence/Android.bp
index d58d0dc..0b6dba6 100644
--- a/tools/xmlpersistence/Android.bp
+++ b/tools/xmlpersistence/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 java_binary_host {
     name: "xmlpersistence_cli",
     manifest: "manifest.txt",
diff --git a/wifi/java/Android.bp b/wifi/java/Android.bp
index b35b4be..225e750 100644
--- a/wifi/java/Android.bp
+++ b/wifi/java/Android.bp
@@ -16,6 +16,15 @@
 // updatable), and are generally only called by the Wifi module.
 
 // necessary since we only want the `path` property to only refer to these files
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 filegroup {
     name: "framework-wifi-non-updatable-sources-internal",
     srcs: ["src/**/*.java"],
diff --git a/wifi/tests/Android.bp b/wifi/tests/Android.bp
index 3f5cacf..c9105f7 100644
--- a/wifi/tests/Android.bp
+++ b/wifi/tests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_test {
     name: "FrameworksWifiNonUpdatableApiTests",